Skip to content

Commit

Permalink
Merge pull request #1459 from samchon/feat/separate
Browse files Browse the repository at this point in the history
  • Loading branch information
samchon authored Jan 13, 2025
2 parents fcc46de + e62aa2c commit 58ffcf8
Show file tree
Hide file tree
Showing 12 changed files with 147 additions and 50 deletions.
2 changes: 1 addition & 1 deletion benchmark/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
"ts-node": "^10.9.1",
"ts-patch": "^3.3.0",
"tstl": "^3.0.0",
"typescript": "~5.7.2",
"typescript": "~5.7.3",
"uuid": "^8.3.2",
"zod": "^3.19.1"
},
Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "typia",
"version": "7.5.1",
"version": "7.6.0",
"description": "Superfast runtime validators with only one line",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
Expand Down Expand Up @@ -41,7 +41,7 @@
},
"homepage": "https://typia.io",
"dependencies": {
"@samchon/openapi": "^2.3.1",
"@samchon/openapi": "^2.4.0",
"commander": "^10.0.0",
"comment-json": "^4.2.3",
"inquirer": "^8.2.5",
Expand All @@ -50,7 +50,7 @@
},
"peerDependencies": {
"typescript": ">=4.8.0 <5.8.0",
"@samchon/openapi": ">=2.3.0 <3.0.0"
"@samchon/openapi": ">=2.4.0 <3.0.0"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^26.0.1",
Expand All @@ -68,7 +68,7 @@
"rollup": "^4.18.0",
"suppress-warnings": "^1.0.2",
"ts-node": "^10.9.2",
"typescript": "~5.7.2"
"typescript": "~5.7.3"
},
"stackblitz": {
"startCommand": "npm install && npm run test"
Expand Down
54 changes: 27 additions & 27 deletions src/programmers/json/JsonApplicationProgrammer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,33 @@ export namespace JsonApplicationProgrammer {
};
};

export const writeDescription = <Kind extends "summary" | "title">(props: {
description: string | null;
jsDocTags: IJsDocTagInfo[];
kind: Kind;
}): Kind extends "summary"
? { summary?: string; description?: string }
: { title?: string; description?: string } => {
const title: string | undefined = (() => {
const [explicit] = getJsDocTexts({
jsDocTags: props.jsDocTags,
name: props.kind,
});
if (explicit?.length) return explicit;
else if (!props.description?.length) return undefined;

const index: number = props.description.indexOf("\n");
const top: string = (
index === -1 ? props.description : props.description.substring(0, index)
).trim();
return top.endsWith(".") ? top.substring(0, top.length - 1) : undefined;
})();
return {
[props.kind]: title,
description: props.description?.length ? props.description : undefined,
} as any;
};

const collectFunction = <Version extends "3.0" | "3.1">(props: {
version: Version;
name: string;
Expand Down Expand Up @@ -217,33 +244,6 @@ export namespace JsonApplicationProgrammer {
};
}

const writeDescription = <Kind extends "summary" | "title">(props: {
description: string | null;
jsDocTags: IJsDocTagInfo[];
kind: Kind;
}): Kind extends "summary"
? { summary?: string; description?: string }
: { title?: string; description?: string } => {
const title: string | undefined = (() => {
const [explicit] = getJsDocTexts({
jsDocTags: props.jsDocTags,
name: props.kind,
});
if (explicit?.length) return explicit;
else if (!props.description?.length) return undefined;

const index: number = props.description.indexOf("\n");
const top: string = (
index === -1 ? props.description : props.description.substring(0, index)
).trim();
return top.endsWith(".") ? top.substring(0, top.length - 1) : undefined;
})();
return {
[props.kind]: title,
description: props.description?.length ? props.description : undefined,
} as any;
};

const writeDescriptionFromJsDocTag = (props: {
jsDocTags: IJsDocTagInfo[];
name: string;
Expand Down
18 changes: 16 additions & 2 deletions src/programmers/llm/LlmApplicationOfValidateProgrammer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { ILlmApplication, ILlmSchema } from "@samchon/openapi";
import ts from "typescript";

import { TypeFactory } from "../../factories/TypeFactory";

import { ILlmApplicationOfValidate } from "../../schemas/llm/ILlmApplicationOfValidate";
import { Metadata } from "../../schemas/metadata/Metadata";
import { MetadataParameter } from "../../schemas/metadata/MetadataParameter";
Expand Down Expand Up @@ -55,7 +57,7 @@ export namespace LlmApplicationOfValidateProgrammer {
modulo: props.modulo,
className: props.name,
name: func.name,
parameter: parameters[func.name]!,
parameter: parameters[func.name] ?? null,
}),
})),
};
Expand All @@ -64,10 +66,22 @@ export namespace LlmApplicationOfValidateProgrammer {
const writeValidadtor = (props: {
context: ITypiaContext;
modulo: ts.LeftHandSideExpression;
parameter: MetadataParameter;
parameter: MetadataParameter | null;
name: string;
className?: string;
}): ((props: object) => IValidation<unknown>) => {
if (props.parameter === null)
return ValidateProgrammer.write({
...props,
type: props.context.checker.getTypeFromTypeNode(
TypeFactory.keyword("any"),
),
config: {
equals: false,
},
name: undefined,
}) as any;

const type = props.parameter.tsType;
if (type === undefined)
// unreachable
Expand Down
62 changes: 50 additions & 12 deletions src/programmers/llm/LlmApplicationProgrammer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ export namespace LlmApplicationProgrammer {
else return LlmSchemaProgrammer.validate(props)(metadata);

const output: string[] = [];
const valid: boolean =
const validity: boolean =
metadata.size() === 1 &&
metadata.objects.length === 1 &&
metadata.isRequired() === true &&
metadata.nullable === false;
if (valid === false)
if (validity === false)
output.push(
"LLM application's generic arugment must be a class/interface type.",
);
Expand All @@ -60,23 +60,40 @@ export namespace LlmApplicationProgrammer {
);
let least: boolean = false;
for (const p of object.properties) {
const name: string = JSON.stringify(p.key.getSoleLiteral()!);
const value: Metadata = p.value;
if (value.functions.length) {
least ||= true;
if (valid === false) {
if (validity === false) {
if (value.functions.length !== 1 || value.size() !== 1)
output.push(
"LLM application's function type does not allow union type.",
`LLM application's function (${name}) type does not allow union type.`,
);
if (value.isRequired() === false)
output.push(
"LLM application's function type must be required.",
`LLM application's function (${name}) type must be required.`,
);
if (value.nullable === true)
output.push(
"LLM application's function type must not be nullable.",
`LLM application's function (${name}) type must not be nullable.`,
);
}

const description: string | undefined = concatDescription(
JsonApplicationProgrammer.writeDescription({
description:
p.description ??
p.jsDocTags.find((tag) => tag.name === "description")
?.text?.[0]?.text ??
null,
jsDocTags: p.jsDocTags,
kind: "summary",
}),
);
if (description !== undefined && description.length > 1_024)
output.push(
`LLM application's function (${name}) description must not exceed 1,024 characters.`,
);
}
}
if (least === false)
Expand All @@ -96,10 +113,14 @@ export namespace LlmApplicationProgrammer {
`${prefix}'s return type must not be union type with undefined.`,
);
if (/^[0-9]/.test(name[0] ?? "") === true)
output.push(`name must not start with a number.`);
output.push(`${prefix} name must not start with a number.`);
if (/^[a-zA-Z0-9_-]+$/.test(name) === false)
output.push(`name must be alphanumeric with underscore or hypen.`);
if (func.parameters.length !== 1)
output.push(
`${prefix} name must be alphanumeric with underscore or hypen.`,
);
if (name.length > 64)
output.push(`${prefix} name must not exceed 64 characters.`);
if (func.parameters.length !== 0 && func.parameters.length !== 1)
output.push(`${prefix} must have a single parameter.`);
if (func.parameters.length !== 0) {
const type: Metadata = func.parameters[0]!.type;
Expand Down Expand Up @@ -233,9 +254,12 @@ export namespace LlmApplicationProgrammer {
errors: string[];
accessor: string;
}): ILlmSchema.ModelParameters[Model] | null => {
const schema = props.function.parameters[0]?.schema;
if (!schema) return null;

const schema = props.function.parameters[0]?.schema ?? {
type: "object",
properties: {},
additionalProperties: false,
required: [],
};
const result: IResult<
ILlmSchema.ModelParameters[Model],
IOpenApiSchemaError
Expand Down Expand Up @@ -286,4 +310,18 @@ export namespace LlmApplicationProgrammer {
}
return result.value;
};

const concatDescription = (p: {
summary?: string | undefined;
description?: string | undefined;
}): string | undefined => {
if (!p.summary?.length || !p.description?.length)
return p.summary ?? p.description;
const summary: string = p.summary.endsWith(".")
? p.summary.slice(0, -1)
: p.summary;
return p.description.startsWith(summary)
? p.description
: summary + ".\n\n" + p.description;
};
}
2 changes: 1 addition & 1 deletion test-error/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"devDependencies": {
"rimraf": "^5.0.5",
"ts-patch": "^3.3.0",
"typescript": "~5.7.2"
"typescript": "~5.7.3"
},
"dependencies": {
"typia": "../"
Expand Down
19 changes: 19 additions & 0 deletions test-error/src/llm/llm.application.length.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import typia from "typia";

typia.llm.application<
{
_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(p: {
x: number;
y: number;
z: number;
}): void;
},
"chatgpt"
>();

typia.llm.application<{
/**
* aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
*/
something(p: { value: string }): void;
}>();
2 changes: 1 addition & 1 deletion test-esm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"@types/cli": "^0.11.25",
"@types/node": "^22.10.1",
"ts-patch": "^3.3.0",
"typescript": "~5.7.2"
"typescript": "~5.7.3"
},
"dependencies": {
"typia": "../"
Expand Down
2 changes: 1 addition & 1 deletion test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"rimraf": "^5.0.5",
"ts-node": "^10.9.2",
"ts-patch": "^3.3.0",
"typescript": "~5.7.2"
"typescript": "~5.7.3"
},
"dependencies": {
"cli": "^1.0.1",
Expand Down
10 changes: 10 additions & 0 deletions test/src/debug/llm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import typia from "typia";

interface Application {
/**
* Something interesting.
*/
something(): void;
}

typia.llm.applicationOfValidate<Application, "chatgpt">();
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import typia from "typia";

import { TestValidator } from "../../helpers/TestValidator";

export const test_pr_1459_llm_application_empty_parameters = (): void => {
const app = typia.llm.applicationOfValidate<Application, "chatgpt">();
const result = app.functions[0]!.validate({});
TestValidator.equals("success")(result.success)(true);
};

interface Application {
/**
* Something interesting.
*/
something(): void;
}
2 changes: 1 addition & 1 deletion website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"react-dom": "^18.2.0",
"tgrid": "^1.0.3",
"tstl": "^3.0.0",
"typescript": "~5.7.2",
"typescript": "~5.7.3",
"typia": "latest"
},
"devDependencies": {
Expand Down

0 comments on commit 58ffcf8

Please sign in to comment.