typia
Version:
Superfast runtime validators with only one line
247 lines • 13.8 kB
JavaScript
;
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