Compare commits

..

10 Commits

Author SHA1 Message Date
Kyle Corbitt
80c0d13bb9 warn folks if they use a lower node version 2023-07-14 14:59:33 -07:00
Kyle Corbitt
f7c94be3f6 Merge pull request #44 from OpenPipe/strip-types
Strip types from prompt variants
2023-07-14 14:07:07 -07:00
Kyle Corbitt
c3e85607e0 Strip types from prompt variants
We want Monaco to treat the prompt constructor as Typescript so we get type checks, but we actually want to save the prompt constructor as Javascript so we can run it directly without transpiling.
2023-07-14 14:03:28 -07:00
Kyle Corbitt
cd5927b8f5 Merge pull request #43 from OpenPipe/function-ux
Pseudo function signatures
2023-07-14 14:01:10 -07:00
Kyle Corbitt
731406d1f4 Pseudo function signatures
Show pseudo function signatures in the variant editor box as a UX hint that you're typing in javascript and have access to the scenario.
2023-07-14 13:56:45 -07:00
Kyle Corbitt
3c59e4b774 Merge pull request #42 from OpenPipe/autoformat
implement format on save
2023-07-14 12:56:41 -07:00
Kyle Corbitt
972b1f2333 Merge pull request #41 from OpenPipe/github-actions
CI checks
2023-07-14 11:40:42 -07:00
Kyle Corbitt
7321f3deda CI checks 2023-07-14 11:36:47 -07:00
Kyle Corbitt
2bd41fdfbf Merge pull request #40 from OpenPipe:completion-costs
store model and use to calculate completion costs
2023-07-14 11:07:15 -07:00
Kyle Corbitt
a5378b106b store model and use to calculate completion costs 2023-07-14 11:06:07 -07:00
20 changed files with 547 additions and 153 deletions

51
.github/workflows/ci.yaml vendored Normal file
View File

@@ -0,0 +1,51 @@
name: CI checks
on:
pull_request:
branches: [main]
jobs:
run-checks:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: "20"
- uses: pnpm/action-setup@v2
name: Install pnpm
id: pnpm-install
with:
version: 8.6.1
run_install: false
- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
- uses: actions/cache@v3
name: Setup pnpm cache
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install Dependencies
run: pnpm install
- name: Check types
run: pnpm tsc
- name: Lint
run: SKIP_ENV_VALIDATION=1 pnpm lint
- name: Check prettier
run: pnpm prettier . --check

1
.tool-versions Normal file
View File

@@ -0,0 +1 @@
nodejs 20.2.0

View File

@@ -3,6 +3,10 @@
"type": "module",
"version": "0.1.0",
"license": "Apache-2.0",
"engines": {
"node": ">=20.0.0",
"pnpm": ">=8.6.1"
},
"scripts": {
"build": "next build",
"dev:next": "next dev",
@@ -14,6 +18,8 @@
"codegen": "tsx src/codegen/export-openai-types.ts"
},
"dependencies": {
"@babel/preset-typescript": "^7.22.5",
"@babel/standalone": "^7.22.9",
"@chakra-ui/next-js": "^2.1.4",
"@chakra-ui/react": "^2.7.1",
"@emotion/react": "^11.11.1",
@@ -63,6 +69,8 @@
},
"devDependencies": {
"@openapi-contrib/openapi-schema-to-json-schema": "^4.0.5",
"@types/babel__core": "^7.20.1",
"@types/babel__standalone": "^7.1.4",
"@types/chroma-js": "^2.4.0",
"@types/cors": "^2.8.13",
"@types/eslint": "^8.37.0",

388
pnpm-lock.yaml generated
View File

@@ -5,6 +5,12 @@ settings:
excludeLinksFromLockfile: false
dependencies:
'@babel/preset-typescript':
specifier: ^7.22.5
version: 7.22.5(@babel/core@7.22.9)
'@babel/standalone':
specifier: ^7.22.9
version: 7.22.9
'@chakra-ui/next-js':
specifier: ^2.1.4
version: 2.1.4(@chakra-ui/react@2.7.1)(@emotion/react@11.11.1)(next@13.4.2)(react@18.2.0)
@@ -91,7 +97,7 @@ dependencies:
version: 4.17.21
next:
specifier: ^13.4.2
version: 13.4.2(react-dom@18.2.0)(react@18.2.0)
version: 13.4.2(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0)
next-auth:
specifier: ^4.22.1
version: 4.22.1(next@13.4.2)(react-dom@18.2.0)(react@18.2.0)
@@ -148,6 +154,12 @@ devDependencies:
'@openapi-contrib/openapi-schema-to-json-schema':
specifier: ^4.0.5
version: 4.0.5
'@types/babel__core':
specifier: ^7.20.1
version: 7.20.1
'@types/babel__standalone':
specifier: ^7.1.4
version: 7.1.4
'@types/chroma-js':
specifier: ^2.4.0
version: 2.4.0
@@ -217,11 +229,114 @@ devDependencies:
packages:
/@ampproject/remapping@2.2.1:
resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==}
engines: {node: '>=6.0.0'}
dependencies:
'@jridgewell/gen-mapping': 0.3.3
'@jridgewell/trace-mapping': 0.3.18
/@babel/code-frame@7.22.5:
resolution: {integrity: sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/highlight': 7.22.5
/@babel/compat-data@7.22.9:
resolution: {integrity: sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==}
engines: {node: '>=6.9.0'}
/@babel/core@7.22.9:
resolution: {integrity: sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==}
engines: {node: '>=6.9.0'}
dependencies:
'@ampproject/remapping': 2.2.1
'@babel/code-frame': 7.22.5
'@babel/generator': 7.22.9
'@babel/helper-compilation-targets': 7.22.9(@babel/core@7.22.9)
'@babel/helper-module-transforms': 7.22.9(@babel/core@7.22.9)
'@babel/helpers': 7.22.6
'@babel/parser': 7.22.7
'@babel/template': 7.22.5
'@babel/traverse': 7.22.8
'@babel/types': 7.22.5
convert-source-map: 1.9.0
debug: 4.3.4
gensync: 1.0.0-beta.2
json5: 2.2.3
semver: 6.3.1
transitivePeerDependencies:
- supports-color
/@babel/generator@7.22.9:
resolution: {integrity: sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.22.5
'@jridgewell/gen-mapping': 0.3.3
'@jridgewell/trace-mapping': 0.3.18
jsesc: 2.5.2
/@babel/helper-annotate-as-pure@7.22.5:
resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.22.5
dev: false
/@babel/helper-compilation-targets@7.22.9(@babel/core@7.22.9):
resolution: {integrity: sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
dependencies:
'@babel/compat-data': 7.22.9
'@babel/core': 7.22.9
'@babel/helper-validator-option': 7.22.5
browserslist: 4.21.9
lru-cache: 5.1.1
semver: 6.3.1
/@babel/helper-create-class-features-plugin@7.22.9(@babel/core@7.22.9):
resolution: {integrity: sha512-Pwyi89uO4YrGKxL/eNJ8lfEH55DnRloGPOseaA8NFNL6jAUnn+KccaISiFazCj5IolPPDjGSdzQzXVzODVRqUQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
dependencies:
'@babel/core': 7.22.9
'@babel/helper-annotate-as-pure': 7.22.5
'@babel/helper-environment-visitor': 7.22.5
'@babel/helper-function-name': 7.22.5
'@babel/helper-member-expression-to-functions': 7.22.5
'@babel/helper-optimise-call-expression': 7.22.5
'@babel/helper-replace-supers': 7.22.9(@babel/core@7.22.9)
'@babel/helper-skip-transparent-expression-wrappers': 7.22.5
'@babel/helper-split-export-declaration': 7.22.6
semver: 6.3.1
dev: false
/@babel/helper-environment-visitor@7.22.5:
resolution: {integrity: sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==}
engines: {node: '>=6.9.0'}
/@babel/helper-function-name@7.22.5:
resolution: {integrity: sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/template': 7.22.5
'@babel/types': 7.22.5
/@babel/helper-hoist-variables@7.22.5:
resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.22.5
/@babel/helper-member-expression-to-functions@7.22.5:
resolution: {integrity: sha512-aBiH1NKMG0H2cGZqspNvsaBe6wNGjbJjuLy29aU+eDZjSbbN53BaxlpB02xm9v34pLTZ1nIQPFYn2qMZoa5BQQ==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.22.5
dev: false
/@babel/helper-module-imports@7.22.5:
@@ -229,17 +344,84 @@ packages:
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.22.5
/@babel/helper-module-transforms@7.22.9(@babel/core@7.22.9):
resolution: {integrity: sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
dependencies:
'@babel/core': 7.22.9
'@babel/helper-environment-visitor': 7.22.5
'@babel/helper-module-imports': 7.22.5
'@babel/helper-simple-access': 7.22.5
'@babel/helper-split-export-declaration': 7.22.6
'@babel/helper-validator-identifier': 7.22.5
/@babel/helper-optimise-call-expression@7.22.5:
resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.22.5
dev: false
/@babel/helper-plugin-utils@7.22.5:
resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==}
engines: {node: '>=6.9.0'}
dev: false
/@babel/helper-replace-supers@7.22.9(@babel/core@7.22.9):
resolution: {integrity: sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
dependencies:
'@babel/core': 7.22.9
'@babel/helper-environment-visitor': 7.22.5
'@babel/helper-member-expression-to-functions': 7.22.5
'@babel/helper-optimise-call-expression': 7.22.5
dev: false
/@babel/helper-simple-access@7.22.5:
resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.22.5
/@babel/helper-skip-transparent-expression-wrappers@7.22.5:
resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.22.5
dev: false
/@babel/helper-split-export-declaration@7.22.6:
resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.22.5
/@babel/helper-string-parser@7.22.5:
resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==}
engines: {node: '>=6.9.0'}
dev: false
/@babel/helper-validator-identifier@7.22.5:
resolution: {integrity: sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==}
engines: {node: '>=6.9.0'}
dev: false
/@babel/helper-validator-option@7.22.5:
resolution: {integrity: sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==}
engines: {node: '>=6.9.0'}
/@babel/helpers@7.22.6:
resolution: {integrity: sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/template': 7.22.5
'@babel/traverse': 7.22.8
'@babel/types': 7.22.5
transitivePeerDependencies:
- supports-color
/@babel/highlight@7.22.5:
resolution: {integrity: sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==}
@@ -248,6 +430,71 @@ packages:
'@babel/helper-validator-identifier': 7.22.5
chalk: 2.4.2
js-tokens: 4.0.0
/@babel/parser@7.22.7:
resolution: {integrity: sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==}
engines: {node: '>=6.0.0'}
hasBin: true
dependencies:
'@babel/types': 7.22.5
/@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.22.9):
resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.22.9
'@babel/helper-plugin-utils': 7.22.5
dev: false
/@babel/plugin-syntax-typescript@7.22.5(@babel/core@7.22.9):
resolution: {integrity: sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.22.9
'@babel/helper-plugin-utils': 7.22.5
dev: false
/@babel/plugin-transform-modules-commonjs@7.22.5(@babel/core@7.22.9):
resolution: {integrity: sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.22.9
'@babel/helper-module-transforms': 7.22.9(@babel/core@7.22.9)
'@babel/helper-plugin-utils': 7.22.5
'@babel/helper-simple-access': 7.22.5
dev: false
/@babel/plugin-transform-typescript@7.22.9(@babel/core@7.22.9):
resolution: {integrity: sha512-BnVR1CpKiuD0iobHPaM1iLvcwPYN2uVFAqoLVSpEDKWuOikoCv5HbKLxclhKYUXlWkX86DoZGtqI4XhbOsyrMg==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.22.9
'@babel/helper-annotate-as-pure': 7.22.5
'@babel/helper-create-class-features-plugin': 7.22.9(@babel/core@7.22.9)
'@babel/helper-plugin-utils': 7.22.5
'@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.22.9)
dev: false
/@babel/preset-typescript@7.22.5(@babel/core@7.22.9):
resolution: {integrity: sha512-YbPaal9LxztSGhmndR46FmAbkJ/1fAsw293tSU+I5E5h+cnJ3d4GTwyUgGYmOXJYdGA+uNePle4qbaRzj2NISQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.22.9
'@babel/helper-plugin-utils': 7.22.5
'@babel/helper-validator-option': 7.22.5
'@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.9)
'@babel/plugin-transform-modules-commonjs': 7.22.5(@babel/core@7.22.9)
'@babel/plugin-transform-typescript': 7.22.9(@babel/core@7.22.9)
dev: false
/@babel/runtime@7.22.5:
@@ -256,6 +503,36 @@ packages:
dependencies:
regenerator-runtime: 0.13.11
/@babel/standalone@7.22.9:
resolution: {integrity: sha512-RRUFpN2WiHaczMqIhmy7VoruvSw+c3NSq6BczondQ6elJXtKzr9cAWWsWWZvtZ/rYFQpoQlch5VxQe4aWTt8LA==}
engines: {node: '>=6.9.0'}
dev: false
/@babel/template@7.22.5:
resolution: {integrity: sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/code-frame': 7.22.5
'@babel/parser': 7.22.7
'@babel/types': 7.22.5
/@babel/traverse@7.22.8:
resolution: {integrity: sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/code-frame': 7.22.5
'@babel/generator': 7.22.9
'@babel/helper-environment-visitor': 7.22.5
'@babel/helper-function-name': 7.22.5
'@babel/helper-hoist-variables': 7.22.5
'@babel/helper-split-export-declaration': 7.22.6
'@babel/parser': 7.22.7
'@babel/types': 7.22.5
debug: 4.3.4
globals: 11.12.0
transitivePeerDependencies:
- supports-color
/@babel/types@7.22.5:
resolution: {integrity: sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==}
engines: {node: '>=6.9.0'}
@@ -263,7 +540,6 @@ packages:
'@babel/helper-string-parser': 7.22.5
'@babel/helper-validator-identifier': 7.22.5
to-fast-properties: 2.0.0
dev: false
/@chakra-ui/accordion@2.2.0(@chakra-ui/system@2.5.8)(framer-motion@10.12.17)(react@18.2.0):
resolution: {integrity: sha512-2IK1iLzTZ22u8GKPPPn65mqJdZidn4AvkgAbv17ISdKA07VHJ8jSd4QF1T5iCXjKfZ0XaXozmhP4kDhjwF2IbQ==}
@@ -661,7 +937,7 @@ packages:
'@chakra-ui/react': 2.7.1(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.6)(framer-motion@10.12.17)(react-dom@18.2.0)(react@18.2.0)
'@emotion/cache': 11.11.0
'@emotion/react': 11.11.1(@types/react@18.2.6)(react@18.2.0)
next: 13.4.2(react-dom@18.2.0)(react@18.2.0)
next: 13.4.2(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0)
react: 18.2.0
dev: false
@@ -1998,17 +2274,14 @@ packages:
'@jridgewell/set-array': 1.1.2
'@jridgewell/sourcemap-codec': 1.4.15
'@jridgewell/trace-mapping': 0.3.18
dev: true
/@jridgewell/resolve-uri@3.1.0:
resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==}
engines: {node: '>=6.0.0'}
dev: true
/@jridgewell/set-array@1.1.2:
resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
engines: {node: '>=6.0.0'}
dev: true
/@jridgewell/source-map@0.3.5:
resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==}
@@ -2019,18 +2292,15 @@ packages:
/@jridgewell/sourcemap-codec@1.4.14:
resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==}
dev: true
/@jridgewell/sourcemap-codec@1.4.15:
resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
dev: true
/@jridgewell/trace-mapping@0.3.18:
resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==}
dependencies:
'@jridgewell/resolve-uri': 3.1.0
'@jridgewell/sourcemap-codec': 1.4.14
dev: true
/@monaco-editor/loader@1.3.3(monaco-editor@0.40.0):
resolution: {integrity: sha512-6KKF4CTzcJiS8BJwtxtfyYt9shBiEv32ateQ9T4UVogwn4HM/uPo9iJd2Dmbkpz8CM6Y0PDUpjnZzCwC+eYo2Q==}
@@ -2312,7 +2582,7 @@ packages:
'@trpc/client': 10.26.0(@trpc/server@10.26.0)
'@trpc/react-query': 10.26.0(@tanstack/react-query@4.29.7)(@trpc/client@10.26.0)(@trpc/server@10.26.0)(react-dom@18.2.0)(react@18.2.0)
'@trpc/server': 10.26.0
next: 13.4.2(react-dom@18.2.0)(react@18.2.0)
next: 13.4.2(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
react-ssr-prepass: 1.5.0(react@18.2.0)
@@ -2338,6 +2608,43 @@ packages:
resolution: {integrity: sha512-+Wt0NFAeflVSNiUnHIDNN3C8jP7XIRmYrcgJ6IsAnm0lK4p/FkpCpeu1aig5qxrgZx30PHNDLZ/3FttVSEW2aQ==}
dev: false
/@types/babel__core@7.20.1:
resolution: {integrity: sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==}
dependencies:
'@babel/parser': 7.22.7
'@babel/types': 7.22.5
'@types/babel__generator': 7.6.4
'@types/babel__template': 7.4.1
'@types/babel__traverse': 7.20.1
dev: true
/@types/babel__generator@7.6.4:
resolution: {integrity: sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==}
dependencies:
'@babel/types': 7.22.5
dev: true
/@types/babel__standalone@7.1.4:
resolution: {integrity: sha512-HijIDmcNl3Wmo0guqjYkQvMzyRCM6zMCkYcdG8f+2X7mPBNa9ikSeaQlWs2Yg18KN1klOJzyupX5BPOf+7ahaw==}
dependencies:
'@babel/core': 7.22.9
transitivePeerDependencies:
- supports-color
dev: true
/@types/babel__template@7.4.1:
resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==}
dependencies:
'@babel/parser': 7.22.7
'@babel/types': 7.22.5
dev: true
/@types/babel__traverse@7.20.1:
resolution: {integrity: sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==}
dependencies:
'@babel/types': 7.22.5
dev: true
/@types/body-parser@1.19.2:
resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==}
dependencies:
@@ -2896,7 +3203,6 @@ packages:
engines: {node: '>=4'}
dependencies:
color-convert: 1.9.3
dev: false
/ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
@@ -3108,7 +3414,6 @@ packages:
electron-to-chromium: 1.4.459
node-releases: 2.0.13
update-browserslist-db: 1.0.11(browserslist@4.21.9)
dev: true
/buffer-from@0.1.2:
resolution: {integrity: sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==}
@@ -3173,7 +3478,6 @@ packages:
ansi-styles: 3.2.1
escape-string-regexp: 1.0.5
supports-color: 5.5.0
dev: false
/chalk@4.1.2:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
@@ -3243,7 +3547,6 @@ packages:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
dependencies:
color-name: 1.1.3
dev: false
/color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
@@ -3253,7 +3556,6 @@ packages:
/color-name@1.1.3:
resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
dev: false
/color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
@@ -3315,7 +3617,6 @@ packages:
/convert-source-map@1.9.0:
resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
dev: false
/cookie-signature@1.0.6:
resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==}
@@ -3563,7 +3864,6 @@ packages:
/electron-to-chromium@1.4.459:
resolution: {integrity: sha512-XXRS5NFv8nCrBL74Rm3qhJjA2VCsRFx0OjHKBMPI0otij56aun8UWiKTDABmd5/7GTR021pA4wivs+Ri6XCElg==}
dev: true
/emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
@@ -3775,7 +4075,6 @@ packages:
/escape-string-regexp@1.0.5:
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
engines: {node: '>=0.8.0'}
dev: false
/escape-string-regexp@4.0.0:
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
@@ -3895,7 +4194,7 @@ packages:
minimatch: 3.1.2
object.values: 1.1.6
resolve: 1.22.2
semver: 6.3.0
semver: 6.3.1
tsconfig-paths: 3.14.2
transitivePeerDependencies:
- eslint-import-resolver-typescript
@@ -3925,7 +4224,7 @@ packages:
minimatch: 3.1.2
object.entries: 1.1.6
object.fromentries: 2.0.6
semver: 6.3.0
semver: 6.3.1
dev: true
/eslint-plugin-react-hooks@4.6.0(eslint@8.40.0):
@@ -3957,7 +4256,7 @@ packages:
object.values: 1.1.6
prop-types: 15.8.1
resolve: 2.0.0-next.4
semver: 6.3.0
semver: 6.3.1
string.prototype.matchall: 4.0.8
dev: true
@@ -4365,6 +4664,10 @@ packages:
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
dev: true
/gensync@1.0.0-beta.2:
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
engines: {node: '>=6.9.0'}
/get-caller-file@2.0.5:
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
engines: {node: 6.* || 8.* || >= 10.*}
@@ -4444,6 +4747,10 @@ packages:
path-is-absolute: 1.0.1
dev: true
/globals@11.12.0:
resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
engines: {node: '>=4'}
/globals@13.20.0:
resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==}
engines: {node: '>=8'}
@@ -4517,7 +4824,6 @@ packages:
/has-flag@3.0.0:
resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
engines: {node: '>=4'}
dev: false
/has-flag@4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
@@ -4917,6 +5223,11 @@ packages:
argparse: 2.0.1
dev: true
/jsesc@2.5.2:
resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
engines: {node: '>=4'}
hasBin: true
/json-parse-even-better-errors@2.3.1:
resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
@@ -4943,7 +5254,6 @@ packages:
resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
engines: {node: '>=6'}
hasBin: true
dev: true
/jsonc-parser@3.2.0:
resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==}
@@ -5036,6 +5346,11 @@ packages:
highlight.js: 10.7.3
dev: false
/lru-cache@5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
dependencies:
yallist: 3.1.1
/lru-cache@6.0.0:
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
engines: {node: '>=10'}
@@ -5195,7 +5510,7 @@ packages:
'@panva/hkdf': 1.1.1
cookie: 0.5.0
jose: 4.14.4
next: 13.4.2(react-dom@18.2.0)(react@18.2.0)
next: 13.4.2(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0)
oauth: 0.9.15
openid-client: 5.4.2
preact: 10.15.1
@@ -5205,7 +5520,7 @@ packages:
uuid: 8.3.2
dev: false
/next@13.4.2(react-dom@18.2.0)(react@18.2.0):
/next@13.4.2(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-aNFqLs3a3nTGvLWlO9SUhCuMUHVPSFQC0+tDNGAsDXqx+WJDFSbvc233gOJ5H19SBc7nw36A9LwQepOJ2u/8Kg==}
engines: {node: '>=16.8.0'}
hasBin: true
@@ -5233,7 +5548,7 @@ packages:
postcss: 8.4.14
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
styled-jsx: 5.1.1(react@18.2.0)
styled-jsx: 5.1.1(@babel/core@7.22.9)(react@18.2.0)
zod: 3.21.4
optionalDependencies:
'@next/swc-darwin-arm64': 13.4.2
@@ -5257,7 +5572,7 @@ packages:
next: '*'
dependencies:
chokidar: 3.5.3
next: 13.4.2(react-dom@18.2.0)(react@18.2.0)
next: 13.4.2(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0)
dev: false
/node-domexception@1.0.0:
@@ -5279,7 +5594,6 @@ packages:
/node-releases@2.0.13:
resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==}
dev: true
/normalize-path@3.0.0:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
@@ -6046,10 +6360,9 @@ packages:
ajv-keywords: 3.5.2(ajv@6.12.6)
dev: true
/semver@6.3.0:
resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==}
/semver@6.3.1:
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
hasBin: true
dev: true
/semver@7.5.2:
resolution: {integrity: sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==}
@@ -6330,7 +6643,7 @@ packages:
acorn: 8.9.0
dev: true
/styled-jsx@5.1.1(react@18.2.0):
/styled-jsx@5.1.1(@babel/core@7.22.9)(react@18.2.0):
resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==}
engines: {node: '>= 12.0.0'}
peerDependencies:
@@ -6343,6 +6656,7 @@ packages:
babel-plugin-macros:
optional: true
dependencies:
'@babel/core': 7.22.9
client-only: 0.0.1
react: 18.2.0
dev: false
@@ -6363,7 +6677,6 @@ packages:
engines: {node: '>=4'}
dependencies:
has-flag: 3.0.0
dev: false
/supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
@@ -6482,7 +6795,6 @@ packages:
/to-fast-properties@2.0.0:
resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
engines: {node: '>=4'}
dev: false
/to-regex-range@5.0.1:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
@@ -6626,7 +6938,6 @@ packages:
browserslist: 4.21.9
escalade: 3.1.1
picocolors: 1.0.0
dev: true
/uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
@@ -7011,6 +7322,9 @@ packages:
engines: {node: '>=10'}
dev: false
/yallist@3.1.1:
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
/yallist@4.0.0:
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}

View File

@@ -26,10 +26,11 @@ model Experiment {
}
model PromptVariant {
id String @id @default(uuid()) @db.Uuid
label String
id String @id @default(uuid()) @db.Uuid
label String
constructFn String
model String @default("gpt-3.5-turbo")
uiId String @default(uuid()) @db.Uuid
visible Boolean @default(true)

View File

@@ -37,10 +37,6 @@ export default function OutputCell({
// if (variant.config === null || Object.keys(variant.config).length === 0)
// disabledReason = "Save your prompt variant to see output";
// const model = getModelName(variant.config as JSONSerializable);
// TODO: Temporarily hardcoding this while we get other stuff working
const model = "gpt-3.5-turbo";
const outputMutation = api.outputs.get.useMutation();
const [output, setOutput] = useState<RouterOutputs["outputs"]["get"]>(null);
@@ -140,7 +136,7 @@ export default function OutputCell({
{ maxLength: 40 },
)}
</SyntaxHighlighter>
<OutputStats model={model} modelOutput={output} scenario={scenario} />
<OutputStats model={variant.model} modelOutput={output} scenario={scenario} />
</Box>
);
}
@@ -150,7 +146,7 @@ export default function OutputCell({
return (
<Flex w="100%" h="100%" direction="column" justifyContent="space-between" whiteSpace="pre-wrap">
{contentToDisplay}
{output && <OutputStats model={model} modelOutput={output} scenario={scenario} />}
{output && <OutputStats model={variant.model} modelOutput={output} scenario={scenario} />}
</Flex>
);
}

View File

@@ -17,7 +17,7 @@ export const OutputStats = ({
modelOutput,
scenario,
}: {
model: SupportedModel | null;
model: SupportedModel | string | null;
modelOutput: ModelOutput;
scenario: Scenario;
}) => {

View File

@@ -1,11 +1,10 @@
import { Box, Button, HStack, Tooltip, useToast } from "@chakra-ui/react";
import { Box, Button, HStack, Tooltip, VStack, useToast } from "@chakra-ui/react";
import { useRef, useEffect, useState, useCallback } from "react";
import { useHandledAsyncCallback, useModifierKeyLabel } from "~/utils/hooks";
import { type PromptVariant } from "./types";
import { api } from "~/utils/api";
import { useAppStore } from "~/state/store";
// import openAITypes from "~/codegen/openai.types.ts.txt";
import { editorBackground } from "~/state/sharedVariantEditor.slice";
export default function VariantConfigEditor(props: { variant: PromptVariant }) {
const monaco = useAppStore.use.sharedVariantEditor.monaco();
const editorRef = useRef<ReturnType<NonNullable<typeof monaco>["editor"]["create"]> | null>(null);
@@ -64,10 +63,17 @@ export default function VariantConfigEditor(props: { variant: PromptVariant }) {
return;
}
await replaceVariant.mutateAsync({
const resp = await replaceVariant.mutateAsync({
id: props.variant.id,
constructFn: currentFn,
});
if (resp.status === "error") {
return toast({
title: "Error saving variant",
description: resp.message,
status: "error",
});
}
await utils.promptVariants.list.invalidate();
@@ -122,21 +128,21 @@ export default function VariantConfigEditor(props: { variant: PromptVariant }) {
/* eslint-disable-next-line react-hooks/exhaustive-deps */
}, [monaco, editorId]);
// useEffect(() => {
// const savedConfigChanged = lastSavedFn !== savedConfig;
// lastSavedFn = savedConfig;
// if (savedConfigChanged && editorRef.current?.getValue() !== savedConfig) {
// editorRef.current?.setValue(savedConfig);
// }
// checkForChanges();
// }, [savedConfig, checkForChanges]);
return (
<Box w="100%" pos="relative">
<div id={editorId} style={{ height: "300px", width: "100%" }}></div>
<VStack
spacing={0}
align="stretch"
fontSize="xs"
fontWeight="bold"
color="gray.600"
py={2}
bgColor={editorBackground}
>
<code>{`function constructPrompt(scenario: Scenario): Prompt {`}</code>
<div id={editorId} style={{ height: "300px", width: "100%" }}></div>
<code>{`return prompt; }`}</code>
</VStack>
{isChanged && (
<HStack pos="absolute" bottom={2} right={2}>
<Button

View File

@@ -75,6 +75,7 @@ export const experimentsRouter = createTRPCRouter({
stream: true,
messages: [{ role: "system", content: "Return 'Ready to go!'" }],
}`,
model: "gpt-3.5-turbo-0613",
},
}),
prisma.testScenario.create({

View File

@@ -6,6 +6,7 @@ import type { Prisma } from "@prisma/client";
import { reevaluateVariant } from "~/server/utils/evaluations";
import { getCompletion } from "~/server/utils/getCompletion";
import { constructPrompt } from "~/server/utils/constructPrompt";
import { type CompletionCreateParams } from "openai/resources/chat";
export const modelOutputsRouter = createTRPCRouter({
get: publicProcedure
@@ -43,7 +44,7 @@ export const modelOutputsRouter = createTRPCRouter({
if (!variant || !scenario) return null;
const prompt = await constructPrompt(variant, scenario);
const prompt = await constructPrompt(variant, scenario.variableValues);
const inputHash = crypto.createHash("sha256").update(JSON.stringify(prompt)).digest("hex");
@@ -65,7 +66,10 @@ export const modelOutputsRouter = createTRPCRouter({
};
} else {
try {
modelResponse = await getCompletion(prompt, input.channel);
modelResponse = await getCompletion(
prompt as unknown as CompletionCreateParams,
input.channel,
);
} catch (e) {
console.error(e);
throw e;

View File

@@ -1,6 +1,10 @@
import { isObject } from "lodash";
import { z } from "zod";
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
import { prisma } from "~/server/db";
import { OpenAIChatModel } from "~/server/types";
import { constructPrompt } from "~/server/utils/constructPrompt";
import userError from "~/server/utils/error";
import { recordExperimentUpdated } from "~/server/utils/recordExperimentUpdated";
import { calculateTokenCost } from "~/utils/calculateTokenCost";
@@ -57,14 +61,10 @@ export const promptVariantsRouter = createTRPCRouter({
},
});
// TODO: fix this
const model = "gpt-3.5-turbo-0613";
// const model = getModelName(variant.config);
const promptTokens = overallTokens._sum?.promptTokens ?? 0;
const overallPromptCost = calculateTokenCost(model, promptTokens);
const overallPromptCost = calculateTokenCost(variant.model, promptTokens);
const completionTokens = overallTokens._sum?.completionTokens ?? 0;
const overallCompletionCost = calculateTokenCost(model, completionTokens, true);
const overallCompletionCost = calculateTokenCost(variant.model, completionTokens, true);
const overallCost = overallPromptCost + overallCompletionCost;
@@ -106,6 +106,7 @@ export const promptVariantsRouter = createTRPCRouter({
label: `Prompt Variant ${largestSortIndex + 2}`,
sortIndex: (lastVariant?.sortIndex ?? 0) + 1,
constructFn: lastVariant?.constructFn ?? "",
model: lastVariant?.model ?? "gpt-3.5-turbo",
},
});
@@ -185,6 +186,27 @@ export const promptVariantsRouter = createTRPCRouter({
throw new Error(`Prompt Variant with id ${input.id} does not exist`);
}
let model = existing.model;
try {
const contructedPrompt = await constructPrompt({ constructFn: input.constructFn }, null);
if (!isObject(contructedPrompt)) {
return userError("Prompt is not an object");
}
if (!("model" in contructedPrompt)) {
return userError("Prompt does not define a model");
}
if (
typeof contructedPrompt.model !== "string" ||
!(contructedPrompt.model in OpenAIChatModel)
) {
return userError("Prompt defines an invalid model");
}
model = contructedPrompt.model;
} catch (e) {
return userError((e as Error).message);
}
// Create a duplicate with only the config changed
const newVariant = await prisma.promptVariant.create({
data: {
@@ -193,11 +215,12 @@ export const promptVariantsRouter = createTRPCRouter({
sortIndex: existing.sortIndex,
uiId: existing.uiId,
constructFn: input.constructFn,
model,
},
});
// Hide anything with the same uiId besides the new one
const hideOldVariantsAction = prisma.promptVariant.updateMany({
const hideOldVariants = prisma.promptVariant.updateMany({
where: {
uiId: existing.uiId,
id: {
@@ -209,12 +232,9 @@ export const promptVariantsRouter = createTRPCRouter({
},
});
await prisma.$transaction([
hideOldVariantsAction,
recordExperimentUpdated(existing.experimentId),
]);
await prisma.$transaction([hideOldVariants, recordExperimentUpdated(existing.experimentId)]);
return newVariant;
return { status: "ok" } as const;
}),
reorder: publicProcedure

View File

@@ -7,9 +7,7 @@ test.skip("constructPrompt", async () => {
constructFn: `prompt = { "fooz": "bar" }`,
},
{
variableValues: {
foo: "bar",
},
foo: "bar",
},
);

View File

@@ -6,10 +6,8 @@ const isolate = new ivm.Isolate({ memoryLimit: 128 });
export async function constructPrompt(
variant: Pick<PromptVariant, "constructFn">,
testScenario: Pick<TestScenario, "variableValues">,
scenario: TestScenario["variableValues"],
): Promise<JSONSerializable> {
const scenario = testScenario.variableValues as JSONSerializable;
const code = `
const scenario = ${JSON.stringify(scenario, null, 2)};
let prompt

View File

@@ -0,0 +1,6 @@
export default function userError(message: string): { status: "error"; message: string } {
return {
status: "error",
message,
};
}

View File

@@ -4,14 +4,11 @@ import { Prisma } from "@prisma/client";
import { streamChatCompletion } from "./openai";
import { wsConnection } from "~/utils/wsConnection";
import { type ChatCompletion, type CompletionCreateParams } from "openai/resources/chat";
import { type JSONSerializable, OpenAIChatModel } from "../types";
import { type OpenAIChatModel } from "../types";
import { env } from "~/env.mjs";
import { countOpenAIChatTokens } from "~/utils/countTokens";
import { getModelName } from "./getModelName";
import { rateLimitErrorMessage } from "~/sharedStrings";
env;
type CompletionResponse = {
output: Prisma.InputJsonValue | typeof Prisma.JsonNull;
statusCode: number;
@@ -22,35 +19,7 @@ type CompletionResponse = {
};
export async function getCompletion(
payload: JSONSerializable,
channel?: string,
): Promise<CompletionResponse> {
const modelName = getModelName(payload);
if (!modelName)
return {
output: Prisma.JsonNull,
statusCode: 400,
errorMessage: "Invalid payload provided",
timeToComplete: 0,
};
if (modelName in OpenAIChatModel) {
return getOpenAIChatCompletion(
payload as unknown as CompletionCreateParams,
env.OPENAI_API_KEY,
channel,
);
}
return {
output: Prisma.JsonNull,
statusCode: 400,
errorMessage: "Invalid model provided",
timeToComplete: 0,
};
}
export async function getOpenAIChatCompletion(
payload: CompletionCreateParams,
apiKey: string,
channel?: string,
): Promise<CompletionResponse> {
// If functions are enabled, disable streaming so that we get the full response with token counts
@@ -60,7 +29,7 @@ export async function getOpenAIChatCompletion(
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`,
Authorization: `Bearer ${env.OPENAI_API_KEY}`,
},
body: JSON.stringify(payload),
});

View File

@@ -1,9 +0,0 @@
import { isObject } from "lodash";
import { type JSONSerializable, type SupportedModel } from "../types";
import { type Prisma } from "@prisma/client";
export function getModelName(config: JSONSerializable | Prisma.JsonValue): SupportedModel | null {
if (!isObject(config)) return null;
if ("model" in config && typeof config.model === "string") return config.model as SupportedModel;
return null;
}

View File

@@ -2,12 +2,9 @@ import { type RouterOutputs } from "~/utils/api";
import { type SliceCreator } from "./store";
import loader from "@monaco-editor/loader";
import openAITypes from "~/codegen/openai.types.ts.txt";
import prettier from "prettier/standalone";
import parserTypescript from "prettier/plugins/typescript";
import formatPromptConstructor from "~/utils/formatPromptConstructor";
// @ts-expect-error for some reason missing from types
import parserEstree from "prettier/plugins/estree";
import { type languages } from "monaco-editor/esm/vs/editor/editor.api";
export const editorBackground = "#fafafa";
export type SharedVariantEditorSlice = {
monaco: null | ReturnType<typeof loader.__getMonacoInstance>;
@@ -17,29 +14,12 @@ export type SharedVariantEditorSlice = {
setScenarios: (scenarios: RouterOutputs["scenarios"]["list"]) => void;
};
const customFormatter: languages.DocumentFormattingEditProvider = {
provideDocumentFormattingEdits: async (model) => {
const val = model.getValue();
console.log("going to format!", val);
const text = await prettier.format(val, {
parser: "typescript",
plugins: [parserTypescript, parserEstree],
// We're showing these in pretty narrow panes so let's keep the print width low
printWidth: 60,
});
return [
{
range: model.getFullModelRange(),
text,
},
];
},
};
export const createVariantEditorSlice: SliceCreator<SharedVariantEditorSlice> = (set, get) => ({
monaco: loader.__getMonacoInstance(),
loadMonaco: async () => {
// We only want to run this client-side
if (typeof window === "undefined") return;
const monaco = await loader.init();
monaco.editor.defineTheme("customTheme", {
@@ -47,7 +27,7 @@ export const createVariantEditorSlice: SliceCreator<SharedVariantEditorSlice> =
inherit: true,
rules: [],
colors: {
"editor.background": "#fafafa",
"editor.background": editorBackground,
},
});
@@ -66,7 +46,16 @@ export const createVariantEditorSlice: SliceCreator<SharedVariantEditorSlice> =
monaco.Uri.parse("file:///openai.types.ts"),
);
monaco.languages.registerDocumentFormattingEditProvider("typescript", customFormatter);
monaco.languages.registerDocumentFormattingEditProvider("typescript", {
provideDocumentFormattingEdits: async (model) => {
return [
{
range: model.getFullModelRange(),
text: await formatPromptConstructor(model.getValue()),
},
];
},
});
set((state) => {
state.sharedVariantEditor.monaco = monaco;

View File

@@ -23,7 +23,7 @@ const openAICompletionTokensToDollars: { [key in OpenAIChatModel]: number } = {
};
export const calculateTokenCost = (
model: SupportedModel | null,
model: SupportedModel | string | null,
numTokens: number,
isCompletion = false,
) => {

View File

@@ -0,0 +1,10 @@
import { expect, test } from "vitest";
import { stripTypes } from "./formatPromptConstructor";
test("stripTypes", () => {
expect(stripTypes(`const foo: string = "bar";`)).toBe(`const foo = "bar";`);
});
test("stripTypes with invalid syntax", () => {
expect(stripTypes(`asdf foo: string = "bar"`)).toBe(`asdf foo: string = "bar"`);
});

View File

@@ -0,0 +1,31 @@
import prettier from "prettier/standalone";
import parserTypescript from "prettier/plugins/typescript";
// @ts-expect-error for some reason missing from types
import parserEstree from "prettier/plugins/estree";
import * as babel from "@babel/standalone";
export function stripTypes(tsCode: string): string {
const options = {
presets: ["typescript"],
filename: "file.ts",
};
try {
const result = babel.transform(tsCode, options);
return result.code ?? tsCode;
} catch (error) {
console.error("Error stripping types", error);
return tsCode;
}
}
export default async function formatPromptConstructor(code: string): Promise<string> {
return await prettier.format(stripTypes(code), {
parser: "typescript",
plugins: [parserTypescript, parserEstree],
// We're showing these in pretty narrow panes so let's keep the print width low
printWidth: 60,
});
}