UNPKG

typia

Version:

Superfast runtime validators with only one line

247 lines 13.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LlmApplicationProgrammer = void 0; const LlmSchemaComposer_1 = require("@samchon/openapi/lib/composers/LlmSchemaComposer"); const TypeFactory_1 = require("../../factories/TypeFactory"); const Metadata_1 = require("../../schemas/metadata/Metadata"); const ValidateProgrammer_1 = require("../ValidateProgrammer"); const JsonApplicationProgrammer_1 = require("../json/JsonApplicationProgrammer"); const LlmSchemaProgrammer_1 = require("./LlmSchemaProgrammer"); var LlmApplicationProgrammer; (function (LlmApplicationProgrammer) { LlmApplicationProgrammer.validate = (props) => { let top; return (metadata, explore) => { var _a, _b, _c, _d, _e, _f, _g; top !== null && top !== void 0 ? top : (top = metadata); if (explore.top === false) if (explore.object === ((_a = top === null || top === void 0 ? void 0 : top.objects[0]) === null || _a === void 0 ? void 0 : _a.type) && typeof explore.property === "string" && metadata.size() === 1 && metadata.nullable === false && metadata.isRequired() === true && metadata.functions.length === 1) return validateFunction(explore.property, metadata.functions[0]); else return LlmSchemaProgrammer_1.LlmSchemaProgrammer.validate(props)(metadata); const output = []; const validity = metadata.size() === 1 && metadata.objects.length === 1 && metadata.isRequired() === true && metadata.nullable === false; if (validity === false) output.push("LLM application's generic argument must be a class/interface type."); const object = (_b = metadata.objects[0]) === null || _b === void 0 ? void 0 : _b.type; if (object !== undefined) { if (object.properties.some((p) => p.key.isSoleLiteral() === false)) output.push("LLM application does not allow dynamic keys on class/interface type."); let least = false; for (const p of object.properties) { const name = JSON.stringify(p.key.getSoleLiteral()); const value = p.value; if (value.functions.length) { least || (least = true); if (validity === false) { if (value.functions.length !== 1 || value.size() !== 1) output.push(`LLM application's function (${name}) type does not allow union type.`); if (value.isRequired() === false) output.push(`LLM application's function (${name}) type must be required.`); if (value.nullable === true) output.push(`LLM application's function (${name}) type must not be nullable.`); } const description = concatDescription(JsonApplicationProgrammer_1.JsonApplicationProgrammer.writeDescription({ description: (_g = (_c = p.description) !== null && _c !== void 0 ? _c : (_f = (_e = (_d = p.jsDocTags.find((tag) => tag.name === "description")) === null || _d === void 0 ? void 0 : _d.text) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.text) !== null && _g !== void 0 ? _g : null, jsDocTags: p.jsDocTags, kind: "summary", })); if (description !== undefined && description.length > 1024) output.push(`LLM application's function (${name}) description must not exceed 1,024 characters.`); } } if (least === false) output.push("LLM application's target type must have at least a function type."); } return output; }; }; const validateFunction = (name, func) => { var _a; const output = []; const prefix = `LLM application's function (${JSON.stringify(name)})`; if (func.output.size() && func.output.isRequired() === false) output.push(`${prefix} return type cannot be optional (union with undefined).`); if (/^[0-9]/.test((_a = name[0]) !== null && _a !== void 0 ? _a : "") === true) output.push(`${prefix} name cannot start with a number.`); if (/^[a-zA-Z0-9_-]+$/.test(name) === false) output.push(`${prefix} name must contain only alphanumeric characters, underscores, or hyphens.`); if (name.length > 64) output.push(`${prefix} name cannot exceed 64 characters.`); if (func.parameters.length !== 0 && func.parameters.length !== 1) output.push(`${prefix} must have exactly one parameter or no parameters.`); if (func.parameters.length !== 0) { const type = func.parameters[0].type; if (type.size() !== 1 || type.objects.length !== 1) output.push(`${prefix} parameter must be a single object type.`); else { if (type.objects[0].type.properties.some((p) => p.key.isSoleLiteral() === false)) output.push(`${prefix} parameter cannot have dynamic property keys.`); if (type.isRequired() === false) output.push(`${prefix} parameter cannot be optional (union with undefined).`); if (type.nullable === true) output.push(`${prefix} parameter cannot be nullable.`); } } return output; }; LlmApplicationProgrammer.write = (props) => { const metadata = Metadata_1.Metadata.unalias(props.metadata); const functionParameters = Object.fromEntries(metadata.objects[0].type.properties.filter((p) => p.key.isSoleLiteral() && p.value.size() === 1 && p.value.nullable === false && p.value.isRequired() === true && Metadata_1.Metadata.unalias(p.value).functions.length === 1) .filter((p) => p.jsDocTags.find((tag) => tag.name === "hidden" || tag.name === "internal") === undefined) .map((p) => [ p.key.getSoleLiteral(), Metadata_1.Metadata.unalias(p.value).functions[0].parameters[0], ])); const errorMessages = []; const application = JsonApplicationProgrammer_1.JsonApplicationProgrammer.write({ version: "3.1", metadata, filter: (p) => p.jsDocTags.some((tag) => tag.name === "human") === false, }); const functions = application.functions.map((func) => { var _a; return writeFunction({ model: props.model, context: props.context, modulo: props.modulo, className: props.name, config: props.config, components: application.components, function: func, errors: errorMessages, parameter: (_a = functionParameters[func.name]) !== null && _a !== void 0 ? _a : null, }); }); if (functions.some((func) => func === null)) throw new Error("Failed to write LLM application:\n\n" + errorMessages.map((str) => ` - ${str}`).join("\n")); return { model: props.model, options: Object.assign(Object.assign(Object.assign({}, LlmSchemaComposer_1.LlmSchemaComposer.defaultConfig(props.model)), props.config), { separate: null }), functions: functions, }; }; const writeFunction = (props) => { var _a, _b, _c, _d, _e, _f; const parameters = writeParameters(Object.assign(Object.assign({}, props), { accessor: `$input.${props.function.name}.parameters` })); if (parameters === null) return null; const output = writeOutput({ model: props.model, parameters, components: props.components, schema: (_b = (_a = props.function.output) === null || _a === void 0 ? void 0 : _a.schema) !== null && _b !== void 0 ? _b : null, errors: props.errors, accessor: `$input.${props.function.name}.output`, }); if (output === null) return null; else if (output && output.description === undefined && !!((_d = (_c = props.function.output) === null || _c === void 0 ? void 0 : _c.description) === null || _d === void 0 ? void 0 : _d.length)) output.description = props.function.output.description; return { name: props.function.name, parameters, output: (output !== null && output !== void 0 ? output : undefined), description: (() => { var _a, _b; if (!((_a = props.function.summary) === null || _a === void 0 ? void 0 : _a.length) || !((_b = props.function.description) === null || _b === void 0 ? void 0 : _b.length)) return props.function.summary || props.function.description; const summary = props.function.summary.endsWith(".") ? props.function.summary.slice(0, -1) : props.function.summary; return props.function.description.startsWith(summary) ? props.function.description : summary + ".\n\n" + props.function.description; })(), deprecated: props.function.deprecated, tags: props.function.tags, validate: writeValidator({ context: props.context, modulo: props.modulo, parameter: props.parameter, name: props.function.name, className: props.className, equals: (_f = (_e = props.config) === null || _e === void 0 ? void 0 : _e.equals) !== null && _f !== void 0 ? _f : false, }), }; }; const writeParameters = (props) => { var _a, _b, _c, _d, _e, _f; const schema = (_b = (_a = props.function.parameters[0]) === null || _a === void 0 ? void 0 : _a.schema) !== null && _b !== void 0 ? _b : { type: "object", properties: {}, additionalProperties: false, required: [], }; const result = LlmSchemaComposer_1.LlmSchemaComposer.parameters(props.model)({ config: LlmSchemaComposer_1.LlmSchemaComposer.defaultConfig(props.model), components: props.components, schema: Object.assign(Object.assign({}, schema), { title: (_c = schema.title) !== null && _c !== void 0 ? _c : (_d = props.function.parameters[0]) === null || _d === void 0 ? void 0 : _d.title, description: (_e = schema.description) !== null && _e !== void 0 ? _e : (_f = props.function.parameters[0]) === null || _f === void 0 ? void 0 : _f.description }), accessor: props.accessor, }); if (result.success === false) { props.errors.push(...result.error.reasons.map((r) => ` - ${r.accessor}: ${r.message}`)); return null; } return result.value; }; const writeOutput = (props) => { if (props.schema === null) return undefined; const result = LlmSchemaComposer_1.LlmSchemaComposer.schema(props.model)({ config: LlmSchemaComposer_1.LlmSchemaComposer.defaultConfig(props.model), components: props.components, schema: props.schema, $defs: props.parameters.$defs, accessor: props.accessor, }); if (result.success === false) { props.errors.push(...result.error.reasons.map((r) => ` - ${r.accessor}: ${r.message}`)); return null; } return result.value; }; const writeValidator = (props) => { if (props.parameter === null) return ValidateProgrammer_1.ValidateProgrammer.write(Object.assign(Object.assign({}, props), { type: props.context.checker.getTypeFromTypeNode(TypeFactory_1.TypeFactory.keyword("any")), config: { equals: props.equals, }, name: undefined })); const type = props.parameter.tsType; if (type === undefined) // unreachable throw new Error("Failed to write LLM application's function validator. You don't have to call `LlmApplicationOfValidator.write()` function by yourself, but only by the `typia.llm.applicationOfValidate()` function."); return ValidateProgrammer_1.ValidateProgrammer.write(Object.assign(Object.assign({}, props), { type: props.parameter.tsType, config: { equals: props.equals, }, name: props.className ? `Parameters<${props.className}[${JSON.stringify(props.name)}]>[0]` : undefined })); }; })(LlmApplicationProgrammer || (exports.LlmApplicationProgrammer = LlmApplicationProgrammer = {})); const concatDescription = (p) => { var _a, _b, _c; if (!((_a = p.summary) === null || _a === void 0 ? void 0 : _a.length) || !((_b = p.description) === null || _b === void 0 ? void 0 : _b.length)) return (_c = p.summary) !== null && _c !== void 0 ? _c : p.description; const summary = p.summary.endsWith(".") ? p.summary.slice(0, -1) : p.summary; return p.description.startsWith(summary) ? p.description : summary + ".\n\n" + p.description; }; //# sourceMappingURL=LlmApplicationProgrammer.js.map