typia 7.0.0-dev.20241114 → 7.0.0-dev.20241122

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +3 -3
  2. package/lib/executable/TypiaSetupWizard.js +1 -1
  3. package/lib/executable/TypiaSetupWizard.js.map +1 -1
  4. package/lib/factories/MetadataFactory.js +1 -1
  5. package/lib/factories/MetadataFactory.js.map +1 -1
  6. package/lib/index.mjs.map +1 -1
  7. package/lib/internal/_isUniqueItems.d.ts +1 -0
  8. package/lib/internal/_isUniqueItems.js +140 -0
  9. package/lib/internal/_isUniqueItems.js.map +1 -0
  10. package/lib/internal/_llmApplicationFinalize.d.ts +1 -1
  11. package/lib/internal/_llmApplicationFinalize.js +14 -6
  12. package/lib/internal/_llmApplicationFinalize.js.map +1 -1
  13. package/lib/llm.d.ts +4 -3
  14. package/lib/programmers/internal/check_array_length.js +8 -11
  15. package/lib/programmers/internal/check_array_length.js.map +1 -1
  16. package/lib/programmers/internal/check_bigint.js +8 -11
  17. package/lib/programmers/internal/check_bigint.js.map +1 -1
  18. package/lib/programmers/internal/check_number.js +8 -11
  19. package/lib/programmers/internal/check_number.js.map +1 -1
  20. package/lib/programmers/internal/check_string.js +8 -11
  21. package/lib/programmers/internal/check_string.js.map +1 -1
  22. package/lib/programmers/llm/LlmApplicationProgrammer.js +149 -104
  23. package/lib/programmers/llm/LlmApplicationProgrammer.js.map +1 -1
  24. package/lib/programmers/llm/LlmSchemaProgrammer.d.ts +7 -2
  25. package/lib/programmers/llm/LlmSchemaProgrammer.js +40 -12
  26. package/lib/programmers/llm/LlmSchemaProgrammer.js.map +1 -1
  27. package/lib/tags/UniqueItems.d.ts +1 -1
  28. package/lib/transformers/features/llm/LlmSchemaTransformer.js +13 -2
  29. package/lib/transformers/features/llm/LlmSchemaTransformer.js.map +1 -1
  30. package/package.json +37 -28
  31. package/src/executable/TypiaSetupWizard.ts +1 -1
  32. package/src/internal/_isUniqueItems.ts +159 -0
  33. package/src/internal/_llmApplicationFinalize.ts +25 -6
  34. package/src/llm.ts +6 -6
  35. package/src/programmers/llm/LlmApplicationProgrammer.ts +175 -155
  36. package/src/programmers/llm/LlmSchemaProgrammer.ts +80 -17
  37. package/src/tags/Format.ts +50 -50
  38. package/src/tags/Type.ts +32 -32
  39. package/src/tags/UniqueItems.ts +1 -1
  40. package/src/transformers/features/llm/LlmSchemaTransformer.ts +40 -6
@@ -0,0 +1,159 @@
1
+ export const _isUniqueItems = (elements: any[]): boolean => {
2
+ // EMTPY OR ONLY ONE
3
+ if (elements.length < 2) return true;
4
+
5
+ // SHALLOW COMPARISON
6
+ if (["boolean", "bigint", "number", "string"].includes(typeof elements[0]))
7
+ return new Set(elements).size === elements.length;
8
+
9
+ // DEEP COMPARISON
10
+ for (let i = 0; i < elements.length; i++)
11
+ for (let j = i + 1; j < elements.length; j++)
12
+ if (equals(new WeakMap())(elements[i], elements[j])) return false;
13
+ return true;
14
+ };
15
+
16
+ const equals = (visited: WeakMap<object, WeakMap<object, boolean>>) => {
17
+ const next = (a: any, b: any): boolean => {
18
+ // SHALLOW EQUAL
19
+ if (a === b) return true;
20
+ else if (typeof a !== typeof b || typeof a !== "object") return false;
21
+ // COMPARE CONTAINERS
22
+ else if (Array.isArray(a))
23
+ return Array.isArray(b) && a.map((x, i) => next(x, b[i])).every((x) => x);
24
+ else if (a instanceof Set)
25
+ return (
26
+ b instanceof Set && a.size === b.size && [...a].every((x) => b.has(x))
27
+ );
28
+ else if (a instanceof Map)
29
+ return (
30
+ b instanceof Map &&
31
+ a.size === b.size &&
32
+ [...a].every(([k, v]) => b.has(k) && next(v, b.get(k)))
33
+ );
34
+ // ATOMIC CLASSES
35
+ else if (a instanceof Boolean)
36
+ return b instanceof Boolean
37
+ ? a.valueOf() === b.valueOf()
38
+ : a.valueOf() === b;
39
+ else if (a instanceof BigInt)
40
+ return b instanceof BigInt ? a === b : a === BigInt(b);
41
+ else if (a instanceof Number)
42
+ return b instanceof Number
43
+ ? a.valueOf() === b.valueOf()
44
+ : a.valueOf() === b;
45
+ else if (a instanceof String)
46
+ return b instanceof String
47
+ ? a.valueOf() === b.valueOf()
48
+ : a.valueOf() === b;
49
+ else if (a instanceof Date)
50
+ return b instanceof Date && a.getTime() === b.getTime();
51
+ // BINARY DATA
52
+ else if (a instanceof Uint8Array)
53
+ return (
54
+ b instanceof Uint8Array &&
55
+ a.length === b.length &&
56
+ a.every((x, i) => x === b[i])
57
+ );
58
+ else if (a instanceof Uint8ClampedArray)
59
+ return (
60
+ b instanceof Uint8ClampedArray &&
61
+ a.length === b.length &&
62
+ a.every((x, i) => x === b[i])
63
+ );
64
+ else if (a instanceof Uint16Array)
65
+ return (
66
+ b instanceof Uint16Array &&
67
+ a.length === b.length &&
68
+ a.every((x, i) => x === b[i])
69
+ );
70
+ else if (a instanceof Uint32Array)
71
+ return (
72
+ b instanceof Uint32Array &&
73
+ a.length === b.length &&
74
+ a.every((x, i) => x === b[i])
75
+ );
76
+ else if (a instanceof BigUint64Array)
77
+ return (
78
+ b instanceof BigUint64Array &&
79
+ a.length === b.length &&
80
+ a.every((x, i) => x === b[i])
81
+ );
82
+ else if (a instanceof Int8Array)
83
+ return (
84
+ b instanceof Int8Array &&
85
+ a.length === b.length &&
86
+ a.every((x, i) => x === b[i])
87
+ );
88
+ else if (a instanceof Int16Array)
89
+ return (
90
+ b instanceof Int16Array &&
91
+ a.length === b.length &&
92
+ a.every((x, i) => x === b[i])
93
+ );
94
+ else if (a instanceof Int32Array)
95
+ return (
96
+ b instanceof Int32Array &&
97
+ a.length === b.length &&
98
+ a.every((x, i) => x === b[i])
99
+ );
100
+ else if (a instanceof BigInt64Array)
101
+ return (
102
+ b instanceof BigInt64Array &&
103
+ a.length === b.length &&
104
+ a.every((x, i) => x === b[i])
105
+ );
106
+ else if (a instanceof Float32Array)
107
+ return (
108
+ b instanceof Float32Array &&
109
+ a.length === b.length &&
110
+ a.every((x, i) => x === b[i])
111
+ );
112
+ else if (a instanceof Float64Array)
113
+ return (
114
+ b instanceof Float64Array &&
115
+ a.length === b.length &&
116
+ a.every((x, i) => x === b[i])
117
+ );
118
+ else if (a instanceof ArrayBuffer) {
119
+ if (!(b instanceof ArrayBuffer) || a.byteLength !== b.byteLength)
120
+ return false;
121
+ const x: Uint8Array = new Uint8Array(a);
122
+ const y: Uint8Array = new Uint8Array(b);
123
+ return x.every((v, i) => v === y[i]);
124
+ } else if (a instanceof SharedArrayBuffer) {
125
+ if (!(b instanceof SharedArrayBuffer) || a.byteLength !== b.byteLength)
126
+ return false;
127
+ const x: Uint8Array = new Uint8Array(a);
128
+ const y: Uint8Array = new Uint8Array(b);
129
+ return x.every((v, i) => v === y[i]);
130
+ } else if (a instanceof DataView) {
131
+ if (!(b instanceof DataView) || a.byteLength !== b.byteLength)
132
+ return false;
133
+ const x: Uint8Array = new Uint8Array(a.buffer);
134
+ const y: Uint8Array = new Uint8Array(b.buffer);
135
+ return x.every((v, i) => v === y[i]);
136
+ } else if (a instanceof File)
137
+ return (
138
+ b instanceof File &&
139
+ a.name === b.name &&
140
+ a.size === b.size &&
141
+ a.type === b.type &&
142
+ next(a.slice(), b.slice())
143
+ );
144
+ // JUST PLAIN OBJECTS
145
+ else if (a !== null && b !== null) {
146
+ if (visited.has(a) && visited.get(a)!.has(b))
147
+ return visited.get(a)!.get(b)!;
148
+ if (!visited.has(a)) visited.set(a, new WeakMap());
149
+ visited.get(a)!.set(b, true);
150
+ const res: boolean =
151
+ Object.keys(a).length === Object.keys(b).length &&
152
+ Object.keys(a).every((x) => next(a[x], b[x]));
153
+ visited.get(a)!.set(b, res);
154
+ return res;
155
+ }
156
+ return false;
157
+ };
158
+ return next;
159
+ };
@@ -3,17 +3,36 @@ import { HttpLlmConverter } from "@samchon/openapi/lib/converters/HttpLlmConvert
3
3
 
4
4
  export const _llmApplicationFinalize = <Model extends ILlmApplication.Model>(
5
5
  app: ILlmApplication<Model>,
6
- options?: ILlmApplication.IOptions<Model>,
6
+ options?: Partial<ILlmApplication.IOptions<Model>>,
7
7
  ): void => {
8
- app.options = {
9
- separate: options?.separate ?? null,
10
- recursive: app.model === "chatgpt" ? undefined : (3 as any),
11
- };
8
+ app.options = (
9
+ isChatGptOptions(app, options)
10
+ ? ({
11
+ separate: options?.separate ?? null,
12
+ reference: options?.reference ?? false,
13
+ constraint: options?.constraint ?? false,
14
+ } satisfies ILlmApplication.IOptions<"chatgpt">)
15
+ : ({
16
+ separate: (options?.separate ??
17
+ null) as ILlmApplication.ICommonOptions<
18
+ Exclude<Model, "chatgpt">
19
+ >["separate"],
20
+ recursive:
21
+ (options as ILlmApplication.IOptions<"3.0"> | undefined)
22
+ ?.recursive ?? 3,
23
+ } satisfies ILlmApplication.ICommonOptions<Exclude<Model, "chatgpt">>)
24
+ ) as ILlmApplication.IOptions<Model>;
12
25
  if (app.options.separate === null) return;
13
26
  for (const func of app.functions)
14
27
  func.separated = HttpLlmConverter.separateParameters({
15
28
  model: app.model,
16
29
  parameters: func.parameters,
17
- predicate: app.options.separate,
30
+ predicate: app.options
31
+ .separate as ILlmApplication.IOptions<Model>["separate"] as any,
18
32
  });
19
33
  };
34
+
35
+ const isChatGptOptions = <Model extends ILlmApplication.Model>(
36
+ app: ILlmApplication<Model>,
37
+ _options: unknown,
38
+ ): _options is ILlmApplication.IOptions<"chatgpt"> => app.model === "chatgpt";
package/src/llm.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ILlmApplication } from "@samchon/openapi";
1
+ import { IChatGptSchema, ILlmApplication } from "@samchon/openapi";
2
2
 
3
3
  /**
4
4
  * > You must configure the generic argument `App`.
@@ -82,7 +82,7 @@ export function application(
82
82
  */
83
83
  export function application<
84
84
  App extends object,
85
- Model extends ILlmApplication.Model = "3.1",
85
+ Model extends ILlmApplication.Model,
86
86
  >(
87
87
  options?: Partial<Omit<ILlmApplication.IOptions<Model>, "recursive">>,
88
88
  ): ILlmApplication<Model>;
@@ -164,14 +164,14 @@ export function schema(): never;
164
164
  *
165
165
  * @template T Target type
166
166
  * @template Model LLM schema model
167
+ * @param $defs Definitions of named schemas if the model is `chatgpt`
167
168
  * @returns LLM schema
168
169
  * @reference https://platform.openai.com/docs/guides/function-calling
169
170
  * @author Jeongho Nam - https://github.com/samchon
170
171
  */
171
- export function schema<
172
- T,
173
- Model extends ILlmApplication.Model = "3.1",
174
- >(): ILlmApplication.ModelSchema[Model];
172
+ export function schema<T, Model extends ILlmApplication.Model>(
173
+ ...$defs: Model extends "chatgpt" ? [Record<string, IChatGptSchema>] : []
174
+ ): ILlmApplication.ModelSchema[Model];
175
175
 
176
176
  /**
177
177
  * @internal
@@ -1,13 +1,18 @@
1
- import { ILlmApplication } from "@samchon/openapi";
1
+ import { IChatGptSchema, ILlmApplication, OpenApi } from "@samchon/openapi";
2
+ import { ChatGptConverter } from "@samchon/openapi/lib/converters/ChatGptConverter";
3
+ import { GeminiConverter } from "@samchon/openapi/lib/converters/GeminiConverter";
4
+ import { LlmConverterV3 } from "@samchon/openapi/lib/converters/LlmConverterV3";
5
+ import { LlmConverterV3_1 } from "@samchon/openapi/lib/converters/LlmConverterV3_1";
2
6
  import { ILlmFunction } from "@samchon/openapi/lib/structures/ILlmFunction";
3
7
 
4
8
  import { MetadataFactory } from "../../factories/MetadataFactory";
5
9
 
6
- import { IJsDocTagInfo } from "../../schemas/metadata/IJsDocTagInfo";
7
10
  import { Metadata } from "../../schemas/metadata/Metadata";
8
11
  import { MetadataFunction } from "../../schemas/metadata/MetadataFunction";
9
12
  import { MetadataObjectType } from "../../schemas/metadata/MetadataObjectType";
10
13
 
14
+ import { IJsonApplication } from "../../module";
15
+ import { JsonApplicationProgrammer } from "../json/JsonApplicationProgrammer";
11
16
  import { LlmSchemaProgrammer } from "./LlmSchemaProgrammer";
12
17
 
13
18
  export namespace LlmApplicationProgrammer {
@@ -101,175 +106,190 @@ export namespace LlmApplicationProgrammer {
101
106
  if (errors.length)
102
107
  throw new Error("Failed to write LLM application: " + errors.join("\n"));
103
108
 
104
- const object: MetadataObjectType = props.metadata.objects[0]!.type;
109
+ const application: IJsonApplication<"3.1"> =
110
+ JsonApplicationProgrammer.write({
111
+ version: "3.1",
112
+ metadata: props.metadata,
113
+ });
105
114
  return {
106
115
  model: props.model,
107
- functions: object.properties
108
- .filter(
109
- (p) =>
110
- p.value.functions.length === 1 &&
111
- p.value.size() === 1 &&
112
- p.key.isSoleLiteral(),
113
- )
114
- .filter(
115
- (p) => p.jsDocTags.find((tag) => tag.name === "hidden") === undefined,
116
- )
117
- .map((p) =>
118
- writeFunction({
119
- model: props.model,
120
- name: p.key.getSoleLiteral()!,
121
- function: p.value.functions[0]!,
122
- description: p.description,
123
- jsDocTags: p.jsDocTags,
124
- }),
125
- ),
126
- options: {
127
- separate: null,
128
- recursive: props.model === "chatgpt" ? undefined : (3 as any),
129
- },
130
- };
131
- };
132
-
133
- const writeFunction = <Model extends ILlmApplication.Model>(props: {
134
- model: Model;
135
- name: string;
136
- function: MetadataFunction;
137
- description: string | null;
138
- jsDocTags: IJsDocTagInfo[];
139
- }): ILlmFunction<ILlmApplication.ModelSchema[Model]> => {
140
- const deprecated: boolean = props.jsDocTags.some(
141
- (tag) => tag.name === "deprecated",
142
- );
143
- const tags: string[] = props.jsDocTags
144
- .map((tag) =>
145
- tag.name === "tag"
146
- ? (tag.text?.filter((elem) => elem.kind === "text") ?? [])
147
- : [],
148
- )
149
- .flat()
150
- .map((elem) => elem.text)
151
- .map((str) => str.trim().split(" ")[0] ?? "")
152
- .filter((str) => !!str.length);
153
- return {
154
- name: props.name,
155
- parameters: props.function.parameters.map((p) => {
156
- const jsDocTagDescription: string | null = writeDescriptionFromJsDocTag(
157
- {
158
- jsDocTags: p.jsDocTags,
159
- name: "param",
160
- parameter: p.name,
161
- },
162
- );
163
- return writeSchema({
116
+ functions: application.functions.map((func) =>
117
+ writeFunction({
164
118
  model: props.model,
165
- metadata: p.type,
166
- description: jsDocTagDescription ?? p.description,
167
- jsDocTags: jsDocTagDescription ? [] : p.jsDocTags,
168
- });
169
- }),
170
- output:
171
- props.function.output.size() || props.function.output.nullable
172
- ? writeSchema({
173
- model: props.model,
174
- metadata: props.function.output,
175
- description:
176
- writeDescriptionFromJsDocTag({
177
- jsDocTags: props.jsDocTags,
178
- name: "return",
179
- }) ??
180
- writeDescriptionFromJsDocTag({
181
- jsDocTags: props.jsDocTags,
182
- name: "returns",
183
- }),
184
- jsDocTags: [],
185
- })
186
- : undefined,
187
- description: props.description ?? undefined,
188
- deprecated: deprecated || undefined,
189
- tags: tags.length ? tags : undefined,
119
+ components: application.components,
120
+ function: func,
121
+ }),
122
+ ),
123
+ options: (props.model === "chatgpt"
124
+ ? ({
125
+ separate: null,
126
+ reference: false,
127
+ constraint: false,
128
+ } satisfies ILlmApplication.IOptions<"chatgpt">)
129
+ : ({
130
+ separate: null,
131
+ recursive: props.model === "chatgpt" ? undefined : (3 as any),
132
+ } satisfies ILlmApplication.ICommonOptions<
133
+ Exclude<Model, "chatgpt">
134
+ >)) as ILlmApplication.IOptions<Model>,
190
135
  };
191
136
  };
192
137
 
193
- const writeSchema = <Model extends ILlmApplication.Model>(props: {
138
+ const writeFunction = <Model extends ILlmApplication.Model>(props: {
194
139
  model: Model;
195
- metadata: Metadata;
196
- description: string | null;
197
- jsDocTags: IJsDocTagInfo[];
198
- }): ILlmApplication.ModelSchema[Model] => {
199
- const schema: ILlmApplication.ModelSchema[Model] =
200
- LlmSchemaProgrammer.write(props);
201
- const explicit: Pick<
202
- ILlmApplication.ModelSchema[Model],
203
- "title" | "description"
204
- > = writeDescription({
140
+ components: OpenApi.IComponents;
141
+ function: IJsonApplication.IFunction<OpenApi.IJsonSchema>;
142
+ }): ILlmFunction<ILlmApplication.ModelParameters[Model]> => {
143
+ const parameters: ILlmApplication.ModelParameters[Model] =
144
+ writeParameters(props);
145
+ const output: ILlmApplication.ModelSchema[Model] | null = writeOutput({
205
146
  model: props.model,
206
- description: props.description,
207
- jsDocTags: props.jsDocTags,
147
+ parameters,
148
+ components: props.components,
149
+ schema: props.function.output?.schema ?? null,
208
150
  });
151
+ if (
152
+ output &&
153
+ output.description === undefined &&
154
+ !!props.function.output?.description?.length
155
+ )
156
+ output.description = props.function.output.description;
209
157
  return {
210
- ...schema,
211
- ...(!!explicit.title?.length || !!explicit.description?.length
212
- ? explicit
213
- : {}),
158
+ name: props.function.name,
159
+ parameters,
160
+ output: (output ?? undefined) as
161
+ | ILlmApplication.ModelParameters[Model]["properties"][string]
162
+ | undefined,
163
+ description: (() => {
164
+ if (
165
+ !props.function.summary?.length ||
166
+ !props.function.description?.length
167
+ )
168
+ return props.function.summary || props.function.description;
169
+ const summary: string = props.function.summary.endsWith(".")
170
+ ? props.function.summary.slice(0, -1)
171
+ : props.function.summary;
172
+ return props.function.description.startsWith(summary)
173
+ ? props.function.description
174
+ : summary + ".\n\n" + props.function.description;
175
+ })(),
176
+ deprecated: props.function.deprecated,
177
+ tags: props.function.tags,
178
+ strict: true,
214
179
  };
215
180
  };
216
181
 
217
- const writeDescription = <Model extends ILlmApplication.Model>(props: {
182
+ const writeParameters = <Model extends ILlmApplication.Model>(props: {
218
183
  model: Model;
219
- description: string | null;
220
- jsDocTags: IJsDocTagInfo[];
221
- }): Pick<ILlmApplication.ModelSchema[Model], "title" | "description"> => {
222
- const title: string | undefined = (() => {
223
- const [explicit] = getJsDocTexts({
224
- jsDocTags: props.jsDocTags,
225
- name: "title",
226
- });
227
- if (explicit?.length) return explicit;
228
- else if (!props.description?.length) return undefined;
229
-
230
- const index: number = props.description.indexOf("\n");
231
- const top: string = (
232
- index === -1 ? props.description : props.description.substring(0, index)
233
- ).trim();
234
- return top.endsWith(".") ? top.substring(0, top.length - 1) : undefined;
184
+ components: OpenApi.IComponents;
185
+ function: IJsonApplication.IFunction<OpenApi.IJsonSchema>;
186
+ }): ILlmApplication.ModelParameters[Model] => {
187
+ const schema: OpenApi.IJsonSchema.IObject = {
188
+ type: "object",
189
+ properties: Object.fromEntries(
190
+ props.function.parameters.map((p) => [
191
+ p.name,
192
+ {
193
+ ...p.schema,
194
+ title: p.title ?? p.schema.title,
195
+ description: p.description ?? p.schema.description,
196
+ },
197
+ ]),
198
+ ),
199
+ required: props.function.parameters
200
+ .filter((p) => p.required)
201
+ .map((p) => p.name),
202
+ additionalProperties: false,
203
+ };
204
+ const parameters: ILlmApplication.ModelParameters[Model] | null = (() => {
205
+ if (props.model === "chatgpt")
206
+ return ChatGptConverter.parameters({
207
+ options: DEFAULT_CHATGPT_OPTION,
208
+ components: props.components,
209
+ schema,
210
+ });
211
+ else if (props.model === "gemini")
212
+ return GeminiConverter.parameters({
213
+ recursive: DEFAULT_V3_OPTIONS.recursive,
214
+ components: props.components,
215
+ schema,
216
+ }) as ILlmApplication.ModelParameters[Model] | null;
217
+ else if (props.model === "3.0")
218
+ return LlmConverterV3.parameters({
219
+ recursive: DEFAULT_V3_OPTIONS.recursive,
220
+ components: props.components,
221
+ schema,
222
+ }) as ILlmApplication.ModelParameters[Model] | null;
223
+ else if (props.model === "3.1")
224
+ return LlmConverterV3_1.parameters({
225
+ recursive: DEFAULT_V3_OPTIONS.recursive,
226
+ components: props.components,
227
+ schema,
228
+ }) as ILlmApplication.ModelParameters[Model] | null;
229
+ else return null;
235
230
  })();
236
- return {
237
- title: title,
238
- description: props.description?.length ? props.description : undefined,
239
- } as any;
231
+ if (parameters === null)
232
+ throw new Error("Failed to write LLM application parameters.");
233
+ return parameters;
240
234
  };
241
235
 
242
- const writeDescriptionFromJsDocTag = (props: {
243
- jsDocTags: IJsDocTagInfo[];
244
- name: string;
245
- parameter?: string;
246
- }): string | null => {
247
- const parametric: (elem: IJsDocTagInfo) => boolean = props.parameter
248
- ? (tag) =>
249
- tag.text!.find(
250
- (elem) =>
251
- elem.kind === "parameterName" && elem.text === props.parameter,
252
- ) !== undefined
253
- : () => true;
254
- const tag: IJsDocTagInfo | undefined = props.jsDocTags.find(
255
- (tag) => tag.name === props.name && tag.text && parametric(tag),
256
- );
257
- return tag && tag.text
258
- ? (tag.text.find((elem) => elem.kind === "text")?.text ?? null)
259
- : null;
236
+ const writeOutput = <Model extends ILlmApplication.Model>(props: {
237
+ model: Model;
238
+ parameters: ILlmApplication.ModelParameters[Model];
239
+ components: OpenApi.IComponents;
240
+ schema: OpenApi.IJsonSchema | null;
241
+ }): ILlmApplication.ModelSchema[Model] | null => {
242
+ if (props.schema === null) return null;
243
+ const output: ILlmApplication.ModelSchema[Model] | null = (() => {
244
+ if (props.model === "chatgpt") {
245
+ const $defs =
246
+ (props.parameters as IChatGptSchema.IParameters).$defs ?? {};
247
+ const output: IChatGptSchema | null = ChatGptConverter.schema({
248
+ options: DEFAULT_CHATGPT_OPTION,
249
+ components: props.components,
250
+ $defs,
251
+ schema: props.schema,
252
+ });
253
+ if (
254
+ output !== null &&
255
+ (props.parameters as IChatGptSchema.IParameters).$defs ===
256
+ undefined &&
257
+ Object.keys($defs).length !== 0
258
+ )
259
+ (props.parameters as IChatGptSchema.IParameters).$defs = $defs;
260
+ return output;
261
+ } else if (props.model === "gemini")
262
+ return GeminiConverter.schema({
263
+ recursive: DEFAULT_V3_OPTIONS.recursive,
264
+ components: props.components,
265
+ schema: props.schema,
266
+ }) as ILlmApplication.ModelSchema[Model] | null;
267
+ else if (props.model === "3.0")
268
+ return LlmConverterV3.schema({
269
+ recursive: DEFAULT_V3_OPTIONS.recursive,
270
+ components: props.components,
271
+ schema: props.schema,
272
+ }) as ILlmApplication.ModelSchema[Model] | null;
273
+ else if (props.model === "3.1")
274
+ return LlmConverterV3_1.schema({
275
+ recursive: DEFAULT_V3_OPTIONS.recursive,
276
+ components: props.components,
277
+ schema: props.schema,
278
+ }) as ILlmApplication.ModelSchema[Model] | null;
279
+ else return null;
280
+ })();
281
+ if (output === null)
282
+ throw new Error("Failed to write LLM application output.");
283
+ return output;
260
284
  };
261
-
262
- const getJsDocTexts = (props: {
263
- jsDocTags: IJsDocTagInfo[];
264
- name: string;
265
- }): string[] =>
266
- props.jsDocTags
267
- .filter(
268
- (tag) =>
269
- tag.name === props.name &&
270
- tag.text &&
271
- tag.text.find((elem) => elem.kind === "text" && elem.text.length) !==
272
- undefined,
273
- )
274
- .map((tag) => tag.text!.find((elem) => elem.kind === "text")!.text);
275
285
  }
286
+
287
+ const DEFAULT_CHATGPT_OPTION: ILlmApplication.IChatGptOptions = {
288
+ separate: null,
289
+ reference: false,
290
+ constraint: false,
291
+ };
292
+ const DEFAULT_V3_OPTIONS = {
293
+ separate: null,
294
+ recursive: 3,
295
+ } satisfies ILlmApplication.ICommonOptions<"3.0">;