Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test cases of failures #92

Merged
merged 1 commit into from
Nov 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions examples/function-calling/arguments/claude.sale.input.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
"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 @@ -24,7 +23,8 @@
"extension": "jpeg",
"url": "https://serpapi.com/searches/673d3a37e45f3316ecd8ab3e/images/1be25e6e2b1fb7505946d975aac683f8826bcb8c509672de4a5f8c71f149fdef.jpeg"
}
]
],
"files": []
},
"channels": [
{
Expand All @@ -35,6 +35,14 @@
]
}
],
"tags": [
"Surface Pro",
"2-in-1",
"Laptop",
"Tablet",
"Windows",
"Microsoft"
],
"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": "Surface Pro 9 Warranty Program",
"name": "Warranty Program",
"price": {
"nominal": 100000,
"real": 89000
Expand All @@ -271,7 +279,7 @@
"options": [],
"stocks": [
{
"name": "Surface Pro 9 Magnetic Keyboard",
"name": "Magnetic Keyboard",
"price": {
"nominal": 200000,
"real": 169000
Expand All @@ -281,13 +289,5 @@
}
]
}
],
"tags": [
"Surface",
"Microsoft",
"2-in-1",
"Laptop",
"Tablet",
"Windows"
]
}
4 changes: 2 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.20241128",
"version": "2.0.0-dev.20241129",
"description": "OpenAPI definitions and converters for 'typia' and 'nestia'.",
"main": "./lib/index.js",
"module": "./lib/index.mjs",
Expand Down Expand Up @@ -63,7 +63,7 @@
"tstl": "^3.0.0",
"typescript": "~5.6.3",
"typescript-transform-paths": "^3.4.7",
"typia": "7.0.0-dev.20241123",
"typia": "^7.0.0-dev.20241128",
"uuid": "^10.0.0"
},
"sideEffects": false,
Expand Down
25 changes: 20 additions & 5 deletions src/converters/ChatGptConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@ export namespace ChatGptConverter {
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 =
LlmConverterV3_1.parameters({
...props,
config: {
reference: props.config.reference,
constraint: false,
},
components: props.components,
schema: props.schema,
});
if (params === null) return null;
for (const key of Object.keys(params.$defs))
Expand All @@ -32,16 +33,30 @@ export namespace ChatGptConverter {
components: OpenApi.IComponents;
$defs: Record<string, IChatGptSchema>;
schema: OpenApi.IJsonSchema;
errors?: string[];
accessor?: string;
refAccessor?: string;
}): IChatGptSchema | null => {
const oldbie: Set<string> = new Set(Object.keys(props.$defs));
const schema: ILlmSchemaV3_1 | null = LlmConverterV3_1.schema({
...props,
config: {
reference: props.config.reference,
constraint: false,
},
components: props.components,
$defs: props.$defs,
schema: props.schema,
validate: (schema, accessor) => {
if (
OpenApiTypeChecker.isObject(schema) &&
!!schema.additionalProperties
) {
if (props.errors)
props.errors.push(
`${accessor}.additionalProperties: ChatGPT does not allow additionalProperties, the dynamic key typed object.`,
);
return false;
}
return true;
},
});
if (schema === null) return null;
for (const key of Object.keys(props.$defs))
Expand Down
12 changes: 7 additions & 5 deletions src/converters/ClaudeConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,32 @@ export namespace ClaudeConverter {
config: IClaudeSchema.IConfig;
components: OpenApi.IComponents;
schema: OpenApi.IJsonSchema.IObject | OpenApi.IJsonSchema.IReference;
errors?: string[];
accessor?: string;
}): IClaudeSchema.IParameters | null =>
LlmConverterV3_1.parameters({
...props,
config: {
reference: props.config.reference,
constraint: true,
},
components: props.components,
schema: props.schema,
});

export const schema = (props: {
config: IClaudeSchema.IConfig;
components: OpenApi.IComponents;
$defs: Record<string, IClaudeSchema>;
schema: OpenApi.IJsonSchema;
errors?: string[];
accessor?: string;
refAccessor?: string;
}): IClaudeSchema | null =>
LlmConverterV3_1.schema({
...props,
config: {
reference: props.config.reference,
constraint: true,
},
components: props.components,
$defs: props.$defs,
schema: props.schema,
});

export const separate = (props: {
Expand Down
83 changes: 54 additions & 29 deletions src/converters/GeminiConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,21 @@ import { ILlmSchemaV3 } from "../structures/ILlmSchemaV3";
import { LlmTypeCheckerV3 } from "../utils/LlmTypeCheckerV3";
import { OpenApiTypeChecker } from "../utils/OpenApiTypeChecker";
import { LlmConverterV3 } from "./LlmConverterV3";
import { LlmParametersFinder } from "./LlmParametersFinder";

export namespace GeminiConverter {
export const parameters = (props: {
config: IGeminiSchema.IConfig;
components: OpenApi.IComponents;
schema: OpenApi.IJsonSchema;
schema: OpenApi.IJsonSchema.IObject | OpenApi.IJsonSchema.IReference;
errors?: string[];
accessor?: string;
}): IGeminiSchema.IParameters | null => {
const entity: OpenApi.IJsonSchema | null =
OpenApiTypeChecker.unreference(props);
if (entity === null || OpenApiTypeChecker.isObject(entity) === false)
return null;
const entity: OpenApi.IJsonSchema.IObject | null =
LlmParametersFinder.find(props);
if (entity === null) return null;
return schema({
config: props.config,
components: props.components,
...props,
schema: entity,
}) as IGeminiSchema.IParameters | null;
};
Expand All @@ -26,39 +27,63 @@ export namespace GeminiConverter {
config: IGeminiSchema.IConfig;
components: OpenApi.IComponents;
schema: OpenApi.IJsonSchema;
errors?: string[];
accessor?: string;
}): IGeminiSchema | null => {
// TRANSFORM TO LLM SCHEMA OF V3.0
const schema: ILlmSchemaV3 | null = LlmConverterV3.schema({
components: props.components,
schema: props.schema,
...props,
config: {
recursive: props.config.recursive,
constraint: false,
},
validate: (next, accessor): boolean => {
if (OpenApiTypeChecker.isObject(next)) {
if (!!next.additionalProperties) {
if (props.errors)
props.errors.push(
`${accessor}.additionalProperties: Gemini does not allow additionalProperties, the dynamic key typed object.`,
);
return false;
}
} else if (OpenApiTypeChecker.isOneOf(next)) {
if (props.errors)
props.errors.push(`${accessor}: Gemini does not allow union type.`);
return false;
}
return true;
},
});
if (schema === null) return null;

let union: boolean = false;
LlmTypeCheckerV3.visit(schema, (v) => {
if (v.title !== undefined) {
if (v.description === undefined) v.description = v.title;
else {
const title: string = v.title.endsWith(".")
? v.title.substring(0, v.title.length - 1)
: v.title;
v.description = v.description.startsWith(title)
? v.description
: `${title}.\n\n${v.description}`;
// SPECIALIZATIONS
LlmTypeCheckerV3.visit({
schema,
closure: (v) => {
if (v.title !== undefined) {
if (v.description === undefined) v.description = v.title;
else {
const title: string = v.title.endsWith(".")
? v.title.substring(0, v.title.length - 1)
: v.title;
v.description = v.description.startsWith(title)
? v.description
: `${title}.\n\n${v.description}`;
}
delete v.title;
}
delete v.title;
}
if (LlmTypeCheckerV3.isOneOf(v)) union = true;
else if (
LlmTypeCheckerV3.isObject(v) &&
v.additionalProperties !== undefined
)
delete (v as Partial<ILlmSchemaV3.IObject>).additionalProperties;
if (
LlmTypeCheckerV3.isObject(v) &&
v.additionalProperties !== undefined
) {
delete (v as Partial<ILlmSchemaV3.IObject>).additionalProperties;
}
},
accessor: props.accessor,
});
return union ? null : schema;

// DO NOT ALLOW UNION TYPE
return schema as IGeminiSchema;
};

export const separate = (props: {
Expand Down
Loading