diff --git a/src/programmers/llm/LlmSchemaProgrammer.ts b/src/programmers/llm/LlmSchemaProgrammer.ts index 21ec562cc9..60729a1775 100644 --- a/src/programmers/llm/LlmSchemaProgrammer.ts +++ b/src/programmers/llm/LlmSchemaProgrammer.ts @@ -1,14 +1,39 @@ import { ILlmApplication } from "@samchon/openapi"; import { HttpLlmConverter } from "@samchon/openapi/lib/converters/HttpLlmConverter"; -import { OpenApiV3Converter } from "@samchon/openapi/lib/converters/OpenApiV3Converter"; import { IJsonSchemaCollection } from "../../schemas/json/IJsonSchemaCollection"; import { Metadata } from "../../schemas/metadata/Metadata"; import { AtomicPredicator } from "../helpers/AtomicPredicator"; +import { json_schema_bigint } from "../internal/json_schema_bigint"; +import { json_schema_boolean } from "../internal/json_schema_boolean"; +import { json_schema_native } from "../internal/json_schema_native"; +import { json_schema_number } from "../internal/json_schema_number"; +import { json_schema_string } from "../internal/json_schema_string"; import { JsonSchemasProgrammer } from "../json/JsonSchemasProgrammer"; export namespace LlmSchemaProgrammer { + export const write = (props: { + model: Model; + metadata: Metadata; + }): ILlmApplication.ModelSchema[Model] => { + const collection: IJsonSchemaCollection<"3.1"> = + JsonSchemasProgrammer.write({ + version: "3.1", + metadatas: [props.metadata], + }); + const schema: ILlmApplication.ModelSchema[Model] | null = + HttpLlmConverter.schema({ + model: props.model, + components: collection.components, + schema: collection.schemas[0]!, + recursive: 3, + }); + if (schema === null) + throw new Error("Failed to convert JSON schema to LLM schema."); + return schema; + }; + export const validate = (model: ILlmApplication.Model) => (metadata: Metadata): string[] => { @@ -37,18 +62,8 @@ export namespace LlmSchemaProgrammer { native.name !== "File" ) output.push(`LLM schema does not support ${native.name} type.`); - if (model === "gemini") { - try { - const { - schemas: [schema], - } = JsonSchemasProgrammer.write({ - version: "3.0", - metadatas: [metadata], - }); - if (OpenApiV3Converter.TypeChecker.isOneOf(schema!)) - output.push("Gemini model does not support the union type."); - } catch {} - } + if (model === "gemini" && size(metadata) > 1) + output.push("Gemini model does not support the union type."); // if ( // metadata.aliases.some((a) => a.type.recursive) || // metadata.arrays.some((a) => a.type.recursive) || @@ -58,25 +73,42 @@ export namespace LlmSchemaProgrammer { // output.push("LLM schema does not support recursive type."); return output; }; - - export const write = (props: { - model: Model; - metadata: Metadata; - }): ILlmApplication.ModelSchema[Model] => { - const collection: IJsonSchemaCollection<"3.1"> = - JsonSchemasProgrammer.write({ - version: "3.1", - metadatas: [props.metadata], - }); - const schema: ILlmApplication.ModelSchema[Model] | null = - HttpLlmConverter.schema({ - model: props.model, - components: collection.components, - schema: collection.schemas[0]!, - recursive: 3, - }); - if (schema === null) - throw new Error("Failed to convert JSON schema to LLM schema."); - return schema; - }; } + +const size = (metadata: Metadata): number => + (metadata.escaped ? size(metadata.escaped.returns) : 0) + + metadata.aliases.length + + metadata.objects.length + + metadata.arrays.length + + metadata.tuples.length + + (metadata.maps.length ? 1 : 0) + + (metadata.sets.length ? 1 : 0) + + metadata.atomics + .map((a) => + a.type === "boolean" + ? json_schema_boolean(a).length + : a.type === "bigint" + ? json_schema_bigint(a).length + : a.type === "number" + ? json_schema_number(a).length + : json_schema_string(a).length, + ) + .reduce((a, b) => a + b, 0) + + metadata.constants.filter( + (c) => metadata.atomics.some((a) => a.type === c.type) === false, + ).length + + metadata.templates.length + + metadata.natives + .filter( + (n) => + metadata.atomics.some((a) => a.type === n.name) === false && + metadata.constants.some((c) => c.type === n.name) === false, + ) + .map( + (n) => + json_schema_native({ + components: {}, + native: n, + }).length, + ) + .reduce((a, b) => a + b, 0);