validate json schema for openai api
This commit is contained in:
@@ -28,6 +28,7 @@ const config = {
|
||||
],
|
||||
"@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }],
|
||||
"@typescript-eslint/no-unsafe-member-access": "off",
|
||||
"@typescript-eslint/no-unsafe-assignment": "off",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
"dev": "next dev",
|
||||
"postinstall": "prisma generate",
|
||||
"lint": "next lint",
|
||||
"start": "next start"
|
||||
"start": "next start",
|
||||
"codegen": "tsx src/codegen/export-openai-schema.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@chakra-ui/next-js": "^2.1.4",
|
||||
@@ -41,6 +42,7 @@
|
||||
"zod": "^3.21.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@openapi-contrib/openapi-schema-to-json-schema": "^4.0.5",
|
||||
"@types/eslint": "^8.37.0",
|
||||
"@types/lodash": "^4.14.195",
|
||||
"@types/node": "^18.16.0",
|
||||
@@ -51,7 +53,8 @@
|
||||
"eslint": "^8.40.0",
|
||||
"eslint-config-next": "^13.4.2",
|
||||
"prisma": "^4.14.0",
|
||||
"typescript": "^5.0.4"
|
||||
"typescript": "^5.0.4",
|
||||
"yaml": "^2.3.1"
|
||||
},
|
||||
"ct3aMetadata": {
|
||||
"initVersion": "7.14.0"
|
||||
|
||||
78
pnpm-lock.yaml
generated
78
pnpm-lock.yaml
generated
@@ -91,6 +91,9 @@ dependencies:
|
||||
version: 3.21.4
|
||||
|
||||
devDependencies:
|
||||
'@openapi-contrib/openapi-schema-to-json-schema':
|
||||
specifier: ^4.0.5
|
||||
version: 4.0.5
|
||||
'@types/eslint':
|
||||
specifier: ^8.37.0
|
||||
version: 8.37.0
|
||||
@@ -124,6 +127,9 @@ devDependencies:
|
||||
typescript:
|
||||
specifier: ^5.0.4
|
||||
version: 5.0.4
|
||||
yaml:
|
||||
specifier: ^2.3.1
|
||||
version: 2.3.1
|
||||
|
||||
packages:
|
||||
|
||||
@@ -1840,6 +1846,15 @@ packages:
|
||||
fastq: 1.15.0
|
||||
dev: true
|
||||
|
||||
/@openapi-contrib/openapi-schema-to-json-schema@4.0.5:
|
||||
resolution: {integrity: sha512-E6s9hfQx125CfGXW5896s0ZtUEecTS69KvqkNDPxKomeZ/Y2rNsG90yO8K47uchXqKw5RhD/rCNcOJ2VODfQiw==}
|
||||
dependencies:
|
||||
'@types/json-schema': 7.0.12
|
||||
'@types/node': 20.3.1
|
||||
fast-deep-equal: 3.1.3
|
||||
openapi-typescript: 5.4.1
|
||||
dev: true
|
||||
|
||||
/@panva/hkdf@1.1.1:
|
||||
resolution: {integrity: sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==}
|
||||
dev: false
|
||||
@@ -2030,6 +2045,10 @@ packages:
|
||||
resolution: {integrity: sha512-BsAaKhB+7X+H4GnSjGhJG9Qi8Tw+inU9nJDwmD5CgOmBLEI6ArdhikpLX7DjbjDRDTbqZzU2LSQNZg8WGPiSZQ==}
|
||||
dev: true
|
||||
|
||||
/@types/node@20.3.1:
|
||||
resolution: {integrity: sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==}
|
||||
dev: true
|
||||
|
||||
/@types/parse-json@4.0.0:
|
||||
resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==}
|
||||
dev: false
|
||||
@@ -2386,7 +2405,6 @@ packages:
|
||||
engines: {node: '>=10.16.0'}
|
||||
dependencies:
|
||||
streamsearch: 1.1.0
|
||||
dev: false
|
||||
|
||||
/call-bind@1.0.2:
|
||||
resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==}
|
||||
@@ -3273,6 +3291,10 @@ packages:
|
||||
define-properties: 1.2.0
|
||||
dev: true
|
||||
|
||||
/globalyzer@0.1.0:
|
||||
resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==}
|
||||
dev: true
|
||||
|
||||
/globby@11.1.0:
|
||||
resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -3296,6 +3318,10 @@ packages:
|
||||
slash: 4.0.0
|
||||
dev: true
|
||||
|
||||
/globrex@0.1.2:
|
||||
resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==}
|
||||
dev: true
|
||||
|
||||
/gopd@1.0.1:
|
||||
resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
|
||||
dependencies:
|
||||
@@ -3713,6 +3739,12 @@ packages:
|
||||
picomatch: 2.3.1
|
||||
dev: true
|
||||
|
||||
/mime@3.0.0:
|
||||
resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/mimic-fn@2.1.0:
|
||||
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -3954,6 +3986,19 @@ packages:
|
||||
is-wsl: 2.2.0
|
||||
dev: true
|
||||
|
||||
/openapi-typescript@5.4.1:
|
||||
resolution: {integrity: sha512-AGB2QiZPz4rE7zIwV3dRHtoUC/CWHhUjuzGXvtmMQN2AFV8xCTLKcZUHLcdPQmt/83i22nRE7+TxXOXkK+gf4Q==}
|
||||
engines: {node: '>= 14.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
js-yaml: 4.1.0
|
||||
mime: 3.0.0
|
||||
prettier: 2.8.8
|
||||
tiny-glob: 0.2.9
|
||||
undici: 5.22.1
|
||||
yargs-parser: 21.1.1
|
||||
dev: true
|
||||
|
||||
/openid-client@5.4.2:
|
||||
resolution: {integrity: sha512-lIhsdPvJ2RneBm3nGBBhQchpe3Uka//xf7WPHTIglery8gnckvW7Bd9IaQzekzXJvWthCMyi/xVEyGW0RFPytw==}
|
||||
dependencies:
|
||||
@@ -4067,6 +4112,12 @@ packages:
|
||||
engines: {node: '>= 0.8.0'}
|
||||
dev: true
|
||||
|
||||
/prettier@2.8.8:
|
||||
resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/pretty-format@3.8.0:
|
||||
resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==}
|
||||
dev: false
|
||||
@@ -4409,7 +4460,6 @@ packages:
|
||||
/streamsearch@1.1.0:
|
||||
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
dev: false
|
||||
|
||||
/string.prototype.matchall@4.0.8:
|
||||
resolution: {integrity: sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==}
|
||||
@@ -4560,6 +4610,13 @@ packages:
|
||||
resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
|
||||
dev: false
|
||||
|
||||
/tiny-glob@0.2.9:
|
||||
resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==}
|
||||
dependencies:
|
||||
globalyzer: 0.1.0
|
||||
globrex: 0.1.2
|
||||
dev: true
|
||||
|
||||
/tiny-invariant@1.3.1:
|
||||
resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==}
|
||||
dev: false
|
||||
@@ -4660,6 +4717,13 @@ packages:
|
||||
which-boxed-primitive: 1.0.2
|
||||
dev: true
|
||||
|
||||
/undici@5.22.1:
|
||||
resolution: {integrity: sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==}
|
||||
engines: {node: '>=14.0'}
|
||||
dependencies:
|
||||
busboy: 1.6.0
|
||||
dev: true
|
||||
|
||||
/untildify@4.0.0:
|
||||
resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -4808,6 +4872,16 @@ packages:
|
||||
engines: {node: '>= 6'}
|
||||
dev: false
|
||||
|
||||
/yaml@2.3.1:
|
||||
resolution: {integrity: sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==}
|
||||
engines: {node: '>= 14'}
|
||||
dev: true
|
||||
|
||||
/yargs-parser@21.1.1:
|
||||
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
|
||||
engines: {node: '>=12'}
|
||||
dev: true
|
||||
|
||||
/yocto-queue@0.1.0:
|
||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
45
src/codegen/export-openai-schema.ts
Normal file
45
src/codegen/export-openai-schema.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import YAML from "yaml";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { openapiSchemaToJsonSchema } from "@openapi-contrib/openapi-schema-to-json-schema";
|
||||
import assert from "assert";
|
||||
|
||||
const OPENAPI_URL =
|
||||
"https://raw.githubusercontent.com/openai/openai-openapi/0c432eb66fd0c758fd8b9bd69db41c1096e5f4db/openapi.yaml";
|
||||
|
||||
const convertOpenApiToJsonSchema = async (url: string) => {
|
||||
// Fetch the openapi document
|
||||
const response = await fetch(url);
|
||||
const openApiYaml = await response.text();
|
||||
|
||||
// Parse the yaml document
|
||||
const openApiDocument = YAML.parse(openApiYaml) as unknown;
|
||||
|
||||
// Convert the openapi schema to json schema
|
||||
const jsonSchema = openapiSchemaToJsonSchema(openApiDocument);
|
||||
|
||||
const modelProperty = jsonSchema.components.schemas.CreateChatCompletionRequest.properties.model;
|
||||
|
||||
assert(modelProperty.oneOf.length === 2, "Expected model to have oneOf length of 2");
|
||||
|
||||
// We need to do a bit of surgery here since the Monaco editor doesn't like
|
||||
// the fact that the schema says `model` can be either a string or an enum,
|
||||
// and displays a warning in the editor. Let's stick with just an enum for
|
||||
// now and drop the string option.
|
||||
modelProperty.type = "string";
|
||||
modelProperty.enum = modelProperty.oneOf[1].enum;
|
||||
modelProperty.oneOf = undefined;
|
||||
|
||||
// Get the directory of the current script
|
||||
const currentDirectory = path.dirname(import.meta.url).replace("file://", "");
|
||||
|
||||
// Write the JSON schema to a file in the current directory
|
||||
fs.writeFileSync(
|
||||
path.join(currentDirectory, "openai.schema.json"),
|
||||
JSON.stringify(jsonSchema, null, 2)
|
||||
);
|
||||
};
|
||||
|
||||
convertOpenApiToJsonSchema(OPENAPI_URL)
|
||||
.then(() => console.log("JSON schema has been written successfully."))
|
||||
.catch((err) => console.error(err));
|
||||
2879
src/codegen/openai.schema.json
Normal file
2879
src/codegen/openai.schema.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -88,7 +88,7 @@ export default function ScenarioEditor({
|
||||
onDrop={onReorder}
|
||||
backgroundColor={isDragTarget ? "gray.100" : "transparent"}
|
||||
>
|
||||
<Stack alignSelf="flex-start" opacity={hovered ? 1 : 0}>
|
||||
<Stack alignSelf="flex-start" opacity={hovered ? 1 : 0} spacing={0}>
|
||||
<Tooltip label="Hide scenario" hasArrow>
|
||||
{/* for some reason the tooltip can't position itself properly relative to the icon without the wrapping box */}
|
||||
<Button
|
||||
|
||||
@@ -2,11 +2,12 @@ import { Box, Button, HStack, Tooltip, useToast } from "@chakra-ui/react";
|
||||
import { useMonaco } from "@monaco-editor/react";
|
||||
import { useRef, useEffect, useState, useCallback, useMemo } from "react";
|
||||
import { useHandledAsyncCallback, useModifierKeyLabel } from "~/utils/hooks";
|
||||
import { PromptVariant } from "./types";
|
||||
import { JSONSerializable } from "~/server/types";
|
||||
import { type PromptVariant } from "./types";
|
||||
import { type JSONSerializable } from "~/server/types";
|
||||
import { api } from "~/utils/api";
|
||||
import openaiSchema from "~/codegen/openai.schema.json";
|
||||
|
||||
let isThemeDefined = false;
|
||||
let isEditorConfigured = false;
|
||||
|
||||
export default function VariantConfigEditor(props: { variant: PromptVariant }) {
|
||||
const monaco = useMonaco();
|
||||
@@ -69,7 +70,7 @@ export default function VariantConfigEditor(props: { variant: PromptVariant }) {
|
||||
|
||||
useEffect(() => {
|
||||
if (monaco) {
|
||||
if (!isThemeDefined) {
|
||||
if (!isEditorConfigured) {
|
||||
monaco.editor.defineTheme("customTheme", {
|
||||
base: "vs",
|
||||
inherit: true,
|
||||
@@ -78,7 +79,21 @@ export default function VariantConfigEditor(props: { variant: PromptVariant }) {
|
||||
"editor.background": "#fafafa",
|
||||
},
|
||||
});
|
||||
isThemeDefined = true;
|
||||
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
|
||||
validate: true,
|
||||
schemas: [
|
||||
{
|
||||
uri: "https://api.openai.com/v1",
|
||||
fileMatch: ["*"],
|
||||
schema: {
|
||||
$schema: "http://json-schema.org/draft-07/schema#",
|
||||
$ref: "#/components/schemas/CreateChatCompletionRequest",
|
||||
components: openaiSchema.components,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
isEditorConfigured = true;
|
||||
}
|
||||
|
||||
const container = document.getElementById(editorId) as HTMLElement;
|
||||
|
||||
Reference in New Issue
Block a user