Skip to content

Commit

Permalink
Try<T, E> pattern to LLM related functions
Browse files Browse the repository at this point in the history
  • Loading branch information
samchon committed Dec 1, 2024
1 parent 486d347 commit f13a641
Show file tree
Hide file tree
Showing 44 changed files with 1,000 additions and 610 deletions.
56 changes: 28 additions & 28 deletions examples/function-calling/arguments/claude.sale.input.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,11 @@
"status": null,
"opened_at": null,
"closed_at": null,
"channels": [
{
"code": "samchon",
"category_codes": [
"2in1_laptops",
"windows_tablets"
]
}
],
"content": {
"title": "Surface Pro 9",
"format": "md",
"body": "The Surface Pro 9 is a versatile 2-in-1 device that combines the power of a laptop with the flexibility of a tablet. It features advanced technology, making it suitable for both professional and personal use.\n\n- \"Unleash Your Creativity Anywhere\": The Surface Pro 9 is designed for those who need power and portability, making it perfect for creative professionals and students alike.\n- \"The Ultimate 2-in-1 Experience\": With its detachable keyboard and touchscreen capabilities, the Surface Pro 9 adapts to your needs, whether you're working, studying, or relaxing.\n- \"Stay Connected with 5G\": Experience lightning-fast internet speeds and seamless connectivity, no matter where you are.\n- \"Power Meets Flexibility\": The Surface Pro 9 combines the performance of a laptop with the convenience of a tablet, making it the ideal device for multitasking.\n\nIn summary, the Surface Pro 9 stands out as a powerful and flexible device, perfect for users who require both performance and portability. With its advanced features and sleek design, it is an excellent choice for anyone looking to enhance their productivity and creativity. Whether for work or play, the Surface Pro 9 is ready to meet your needs.",
"files": [],
"thumbnails": [
{
"name": "microsoft-surface-pro-9-thumbnail-1",
Expand All @@ -32,9 +24,25 @@
"extension": "jpeg",
"url": "https://serpapi.com/searches/673d3a37e45f3316ecd8ab3e/images/1be25e6e2b1fb7505946d975aac683f8826bcb8c509672de4a5f8c71f149fdef.jpeg"
}
],
"files": []
]
},
"channels": [
{
"code": "samchon",
"category_codes": [
"electronics",
"2in1_laptops",
"windows_tablets"
]
}
],
"tags": [
"Surface Pro",
"2-in-1",
"Windows",
"Laptop",
"Tablet"
],
"units": [
{
"name": "Surface Pro 9 Entity",
Expand Down Expand Up @@ -92,7 +100,7 @@
],
"stocks": [
{
"name": "Surface Pro 9 (i3/8GB/128GB)",
"name": "Surface Pro 9 - i3/8GB/128GB",
"price": {
"nominal": 1000000,
"real": 899000
Expand All @@ -114,7 +122,7 @@
]
},
{
"name": "Surface Pro 9 (i3/16GB/256GB)",
"name": "Surface Pro 9 - i3/16GB/256GB",
"price": {
"nominal": 1200000,
"real": 1099000
Expand All @@ -136,7 +144,7 @@
]
},
{
"name": "Surface Pro 9 (i3/16GB/512GB)",
"name": "Surface Pro 9 - i3/16GB/512GB",
"price": {
"nominal": 1400000,
"real": 1299000
Expand All @@ -158,7 +166,7 @@
]
},
{
"name": "Surface Pro 9 (i5/16GB/256GB)",
"name": "Surface Pro 9 - i5/16GB/256GB",
"price": {
"nominal": 1500000,
"real": 1399000
Expand All @@ -180,7 +188,7 @@
]
},
{
"name": "Surface Pro 9 (i5/32GB/512GB)",
"name": "Surface Pro 9 - i5/32GB/512GB",
"price": {
"nominal": 1800000,
"real": 1699000
Expand All @@ -202,7 +210,7 @@
]
},
{
"name": "Surface Pro 9 (i7/16GB/512GB)",
"name": "Surface Pro 9 - i7/16GB/512GB",
"price": {
"nominal": 1800000,
"real": 1699000
Expand All @@ -224,7 +232,7 @@
]
},
{
"name": "Surface Pro 9 (i7/32GB/512GB)",
"name": "Surface Pro 9 - i7/32GB/512GB",
"price": {
"nominal": 2000000,
"real": 1899000
Expand Down Expand Up @@ -254,7 +262,7 @@
"options": [],
"stocks": [
{
"name": "Warranty Program",
"name": "Surface Pro 9 Warranty Program",
"price": {
"nominal": 100000,
"real": 89000
Expand All @@ -271,7 +279,7 @@
"options": [],
"stocks": [
{
"name": "Magnetic Keyboard",
"name": "Surface Pro 9 Magnetic Keyboard",
"price": {
"nominal": 200000,
"real": 169000
Expand All @@ -281,13 +289,5 @@
}
]
}
],
"tags": [
"Surface",
"Microsoft",
"2-in-1",
"Laptop",
"Tablet",
"Windows"
]
}
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@samchon/openapi",
"version": "2.0.0-dev.20241201-2",
"version": "2.0.0-dev.20241202",
"description": "OpenAPI definitions and converters for 'typia' and 'nestia'.",
"main": "./lib/index.js",
"module": "./lib/index.mjs",
Expand Down Expand Up @@ -70,6 +70,7 @@
"files": [
"lib",
"src",
"README.md"
"README.md",
"LICENSE"
]
}
15 changes: 11 additions & 4 deletions src/composers/HttpLlmApplicationComposer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,23 @@ export namespace HttpLlmComposer {
const cast = (
s: OpenApi.IJsonSchema,
accessor: string,
): ILlmSchema.ModelSchema[Model] | null =>
LlmSchemaComposer.schema(props.model)({
): ILlmSchema.ModelSchema[Model] | null => {
const result = LlmSchemaComposer.schema(props.model)({
config: props.options as any,
schema: s,
components: props.components,
$defs,
errors: props.errors,
accessor,
refAccessor: `$input.components.schemas`,
}) as ILlmSchema.ModelSchema[Model] | null;
});
if (result.success === false) {
props.errors.push(
...result.error.reasons.map((r) => `${r.accessor}: ${r.message}`),
);
return null;
}
return result.data as ILlmSchema.ModelSchema[Model];
};

const endpoint: string = `$input.paths[${JSON.stringify(props.route.path)}][${JSON.stringify(props.route.method)}]`;
const output: ILlmSchema.ModelSchema[Model] | null | undefined = props.route
Expand Down
78 changes: 43 additions & 35 deletions src/composers/llm/ChatGptSchemaComposer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { OpenApi } from "../../OpenApi";
import { IChatGptSchema } from "../../structures/IChatGptSchema";
import { ILlmFunction } from "../../structures/ILlmFunction";
import { ILlmSchemaV3_1 } from "../../structures/ILlmSchemaV3_1";
import { IOpenApiSchemaError } from "../../structures/IOpenApiSchemaError";
import { IResult } from "../../typings/IResult";
import { ChatGptTypeChecker } from "../../utils/ChatGptTypeChecker";
import { LlmTypeCheckerV3_1 } from "../../utils/LlmTypeCheckerV3_1";
import { OpenApiTypeChecker } from "../../utils/OpenApiTypeChecker";
Expand All @@ -12,64 +14,70 @@ export namespace ChatGptSchemaComposer {
config: IChatGptSchema.IConfig;
components: OpenApi.IComponents;
schema: OpenApi.IJsonSchema.IObject | OpenApi.IJsonSchema.IReference;
errors?: string[];
accessor?: string;
}): IChatGptSchema.IParameters | null => {
const params: ILlmSchemaV3_1.IParameters | null =
refAccessor?: string;
}): IResult<IChatGptSchema.IParameters, IOpenApiSchemaError> => {
const result: IResult<ILlmSchemaV3_1.IParameters, IOpenApiSchemaError> =
LlmSchemaV3_1Composer.parameters({
...props,
config: {
reference: props.config.reference,
constraint: false,
},
validate: validate(props.errors),
validate,
});
if (params === null) return null;
for (const key of Object.keys(params.$defs))
params.$defs[key] = transform(params.$defs[key]);
return transform(params) as IChatGptSchema.IParameters;
if (result.success === false) return result;
for (const key of Object.keys(result.data.$defs))
result.data.$defs[key] = transform(result.data.$defs[key]);
return {
success: true,
data: transform(result.data) as IChatGptSchema.IParameters,
};
};

export const schema = (props: {
config: IChatGptSchema.IConfig;
components: OpenApi.IComponents;
$defs: Record<string, IChatGptSchema>;
schema: OpenApi.IJsonSchema;
errors?: string[];
accessor?: string;
refAccessor?: string;
}): IChatGptSchema | null => {
}): IResult<IChatGptSchema, IOpenApiSchemaError> => {
const oldbie: Set<string> = new Set(Object.keys(props.$defs));
const schema: ILlmSchemaV3_1 | null = LlmSchemaV3_1Composer.schema({
...props,
config: {
reference: props.config.reference,
constraint: false,
},
validate: validate(props.errors),
});
if (schema === null) return null;
const result: IResult<ILlmSchemaV3_1, IOpenApiSchemaError> =
LlmSchemaV3_1Composer.schema({
...props,
config: {
reference: props.config.reference,
constraint: false,
},
validate,
});
if (result.success === false) return result;
for (const key of Object.keys(props.$defs))
if (oldbie.has(key) === false)
props.$defs[key] = transform(props.$defs[key]);
return transform(schema);
return {
success: true,
data: transform(result.data),
};
};

const validate =
(errors: string[] | undefined) =>
(schema: OpenApi.IJsonSchema, accessor: string): boolean => {
if (
OpenApiTypeChecker.isObject(schema) &&
!!schema.additionalProperties
) {
if (errors)
errors.push(
`${accessor}.additionalProperties: ChatGPT does not allow additionalProperties, the dynamic key typed object.`,
);
return false;
}
return true;
};
const validate = (
schema: OpenApi.IJsonSchema,
accessor: string,
): IOpenApiSchemaError.IReason[] => {
if (OpenApiTypeChecker.isObject(schema) && !!schema.additionalProperties)
return [
{
schema: schema,
accessor: `${accessor}.additionalProperties`,
message:
"ChatGPT does not allow additionalProperties, the dynamic key typed object.",
},
];
return [];
};

const transform = (schema: ILlmSchemaV3_1): IChatGptSchema => {
const union: Array<IChatGptSchema> = [];
Expand Down
9 changes: 5 additions & 4 deletions src/composers/llm/ClaudeSchemaComposer.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { OpenApi } from "../../OpenApi";
import { IClaudeSchema } from "../../structures/IClaudeSchema";
import { ILlmFunction } from "../../structures/ILlmFunction";
import { IOpenApiSchemaError } from "../../structures/IOpenApiSchemaError";
import { IResult } from "../../typings/IResult";
import { LlmSchemaV3_1Composer } from "./LlmSchemaV3_1Composer";

export namespace ClaudeSchemaComposer {
export const parameters = (props: {
config: IClaudeSchema.IConfig;
components: OpenApi.IComponents;
schema: OpenApi.IJsonSchema.IObject | OpenApi.IJsonSchema.IReference;
errors?: string[];
accessor?: string;
}): IClaudeSchema.IParameters | null =>
refAccessor?: string;
}): IResult<IClaudeSchema.IParameters, IOpenApiSchemaError> =>
LlmSchemaV3_1Composer.parameters({
...props,
config: {
Expand All @@ -24,10 +26,9 @@ export namespace ClaudeSchemaComposer {
components: OpenApi.IComponents;
$defs: Record<string, IClaudeSchema>;
schema: OpenApi.IJsonSchema;
errors?: string[];
accessor?: string;
refAccessor?: string;
}): IClaudeSchema | null =>
}): IResult<IClaudeSchema, IOpenApiSchemaError> =>
LlmSchemaV3_1Composer.schema({
...props,
config: {
Expand Down
Loading

0 comments on commit f13a641

Please sign in to comment.