@samchon/openapi
Version:
Universal OpenAPI to LLM function calling schemas. Transform any Swagger/OpenAPI document into type-safe schemas for OpenAI, Claude, Qwen, and more.
393 lines (392 loc) • 14.5 kB
text/typescript
import { IJsonSchemaAttribute } from "./IJsonSchemaAttribute";
/**
* Type schema info for LLM (Large Language Model) function calling.
*
* ## Overview
*
* `ILlmSchema` is a type schema info for LLM function calling, designed to be
* compatible with multiple LLM providers while following the JSON schema
* specification.
*
* ## Specification
*
* `ILlmSchema` basically follows the JSON schema definition of the OpenAPI v3.1
* specification; {@link OpenApiV3_1.IJsonSchema}.
*
* However, it deviates from the standard JSON schema specification and omits
* many features to ensure compatibility across different LLM providers and
* their function calling requirements.
*
* ## Differences from OpenAPI v3.1
*
* Here is the list of how `ILlmSchema` is different with the OpenAPI v3.1 JSON
* schema:
*
* - Decompose mixed type: {@link OpenApiV3_1.IJsonSchema.IMixed}
* - Resolve nullable property:
* {@link OpenApiV3_1.IJsonSchema.__ISignificant.nullable}
* - Tuple type is banned: {@link OpenApiV3_1.IJsonSchema.ITuple.prefixItems}
* - Constant type is banned: {@link OpenApiV3_1.IJsonSchema.IConstant}
* - Merge {@link OpenApiV3_1.IJsonSchema.IOneOf} to {@link ILlmSchema.IAnyOf}
* - Merge {@link OpenApiV3_1.IJsonSchema.IAllOf} to {@link ILlmSchema.IObject}
* - Merge {@link OpenApiV3_1.IJsonSchema.IRecursiveReference} to
* {@link ILlmSchema.IReference}
*
* ## Differences from OpenApi.IJsonSchema
*
* Compared to {@link OpenApi.IJsonSchema}, the emended JSON schema
* specification:
*
* - {@link ILlmSchema.IAnyOf} instead of {@link OpenApi.IJsonSchema.IOneOf}
* - {@link ILlmSchema.IParameters.$defs} instead of
* {@link OpenApi.IJsonSchema.IComponents.schemas}
* - Do not support {@link OpenApi.IJsonSchema.ITuple} type
* - {@link ILlmSchema.properties} and {@link ILlmSchema.required} are always
* defined
*
* ## Strict Mode
*
* When {@link ILlmSchema.IConfig.strict} mode is enabled, the schema
* transformation follows OpenAI's structured output requirements:
*
* - Every {@link ILlmSchema.IObject.additionalProperties} is forced to `false`
* - Every property in {@link ILlmSchema.IObject.properties} becomes
* {@link ILlmSchema.IObject.required}
* - All constraint properties are removed from the schema and moved to
* {@link IJsonSchemaAttribute.description} in a JSDoc-like format:
*
* - Numeric constraints: `minimum`, `maximum`, `exclusiveMinimum`,
* `exclusiveMaximum`, `multipleOf`
* - String constraints: `minLength`, `maxLength`, `pattern`, `format`,
* `contentMediaType`
* - Array constraints: `minItems`, `maxItems`, `uniqueItems`
* - Example: `@minimum 0`, `@maximum 100`, `@format uuid`
*
* @author Jeongho Nam - https://github.com/samchon
*/
export type ILlmSchema = ILlmSchema.IBoolean | ILlmSchema.IInteger | ILlmSchema.INumber | ILlmSchema.IString | ILlmSchema.IArray | ILlmSchema.IObject | ILlmSchema.IReference | ILlmSchema.IAnyOf | ILlmSchema.INull | ILlmSchema.IUnknown;
export declare namespace ILlmSchema {
/** Configuration for the LLM schema composition. */
interface IConfig {
/**
* Whether to allow reference type in everywhere.
*
* If you configure this property to `false`, most of reference types
* represented by {@link ILlmSchema.IReference} would be escaped to a plain
* type unless recursive type comes.
*
* This is because some LLM models do not understand the reference type
* well, and even the modern version of LLM sometimes occur the
* hallucination.
*
* However, the reference type makes the schema size smaller, so that
* reduces the LLM token cost. Therefore, if you're using the modern version
* of LLM, and want to reduce the LLM token cost, you can configure this
* property to `true`.
*
* @default true
*/
reference: boolean;
/**
* Whether to apply the strict mode.
*
* If you configure this property to `true`, the LLM function calling does
* not allow optional properties and dynamic key typed properties in the
* {@link ILlmSchema.IObject} type. In other words, when strict mode is
* enabled, {@link ILlmSchema.IObject.additionalProperties} is fixed to
* `false`, and every property must be {@link ILlmSchema.IObject.required}.
*
* However, the strict mode actually shows lower performance in practice. If
* you utilize the {@link typia.validate} function and give its validation
* feedback to the LLM, the performance is much better than the strict
* mode.
*
* Therefore, I recommend you to just turn off the strict mode and utilize
* the {@link typia.validate} function instead.
*
* @default false
*/
strict: boolean;
}
/**
* Type for function parameters.
*
* `ILlmSchema.IParameters` defines a function's parameters as a keyword
* object type, where each property represents a named parameter.
*
* It can also be used for structured output metadata to define the expected
* format of LLM responses.
*/
interface IParameters extends Omit<IObject, "additionalProperties"> {
/**
* Collection of the named types.
*
* This record would be filled when {@link IConfig.reference} is `true`, or
* recursive type comes.
*/
$defs: Record<string, ILlmSchema>;
/**
* Additional properties information.
*
* The `additionalProperties` defines the type schema for additional
* properties that are not listed in the {@link properties}.
*
* By the way, it is not allowed at the parameters level.
*/
additionalProperties: false;
}
/** Boolean type info. */
interface IBoolean extends IJsonSchemaAttribute.IBoolean {
/** Enumeration values. */
enum?: Array<boolean>;
/** Default value. */
default?: boolean;
}
/** Integer type info. */
interface IInteger extends IJsonSchemaAttribute.IInteger {
/** Enumeration values. */
enum?: Array<number>;
/**
* Default value.
*
* @type int64
*/
default?: number;
/**
* Minimum value restriction.
*
* @type int64
*/
minimum?: number;
/**
* Maximum value restriction.
*
* @type int64
*/
maximum?: number;
/**
* Exclusive minimum value restriction.
*
* @type int64
*/
exclusiveMinimum?: number;
/**
* Exclusive maximum value restriction.
*
* @type int64
*/
exclusiveMaximum?: number;
/**
* Multiple of value restriction.
*
* @type uint64
* @exclusiveMinimum 0
*/
multipleOf?: number;
}
/** Number (double) type info. */
interface INumber extends IJsonSchemaAttribute.INumber {
/** Enumeration values. */
enum?: Array<number>;
/** Default value. */
default?: number;
/** Minimum value restriction. */
minimum?: number;
/** Maximum value restriction. */
maximum?: number;
/** Exclusive minimum value restriction. */
exclusiveMinimum?: number;
/** Exclusive maximum value restriction. */
exclusiveMaximum?: number;
/**
* Multiple of value restriction.
*
* @exclusiveMinimum 0
*/
multipleOf?: number;
}
/** String type info. */
interface IString extends IJsonSchemaAttribute.IString {
/** Enumeration values. */
enum?: Array<string>;
/** Default value. */
default?: string;
/** Format restriction. */
format?: "binary" | "byte" | "password" | "regex" | "uuid" | "email" | "hostname" | "idn-email" | "idn-hostname" | "iri" | "iri-reference" | "ipv4" | "ipv6" | "uri" | "uri-reference" | "uri-template" | "url" | "date-time" | "date" | "time" | "duration" | "json-pointer" | "relative-json-pointer" | (string & {});
/** Pattern restriction. */
pattern?: string;
/** Content media type restriction. */
contentMediaType?: string;
/**
* Minimum length restriction.
*
* @type uint64
*/
minLength?: number;
/**
* Maximum length restriction.
*
* @type uint64
*/
maxLength?: number;
}
/** Array type info. */
interface IArray extends IJsonSchemaAttribute.IArray {
/**
* Items type info.
*
* The `items` means the type of the array elements. In other words, it is
* the type schema info of the `T` in the TypeScript array type `Array<T>`.
*/
items: ILlmSchema;
/**
* Unique items restriction.
*
* If this property value is `true`, target array must have unique items.
*/
uniqueItems?: boolean;
/**
* Minimum items restriction.
*
* Restriction of minimum number of items in the array.
*
* @type uint64
*/
minItems?: number;
/**
* Maximum items restriction.
*
* Restriction of maximum number of items in the array.
*
* @type uint64
*/
maxItems?: number;
}
/** Object type info. */
interface IObject extends IJsonSchemaAttribute.IObject {
/**
* Properties of the object.
*
* The `properties` means a list of key-value pairs of the object's regular
* properties. The key is the name of the regular property, and the value is
* the type schema info.
*/
properties: Record<string, ILlmSchema>;
/**
* Additional properties' info.
*
* The `additionalProperties` means the type schema info of the additional
* properties that are not listed in the {@link properties}.
*
* If the value is `true`, it means that the additional properties are not
* restricted. They can be any type. Otherwise, if the value is
* {@link ILlmSchema} type, it means that the additional properties must
* follow the type schema info.
*
* - `true`: `Record<string, any>`
* - `ILlmSchema`: `Record<string, T>`
*
* Note: When {@link IConfig.strict} mode is enabled, this property is always
* fixed to `false`, meaning no additional properties are allowed.
*/
additionalProperties?: ILlmSchema | boolean;
/**
* List of required property keys.
*
* The `required` contains a list of property keys from {@link properties}
* that must be provided. Properties not listed in `required` are optional,
* while those listed must be filled.
*
* Below is an example of {@link properties} and `required`:
*
* ```typescript
* interface SomeObject {
* id: string;
* email: string;
* name?: string;
* }
* ```
*
* As you can see, `id` and `email` {@link properties} are {@link required},
* so they are listed in the `required` array.
*
* ```json
* {
* "type": "object",
* "properties": {
* "id": { "type": "string" },
* "email": { "type": "string" },
* "name": { "type": "string" }
* },
* "required": ["id", "email"]
* }
* ```
*/
required: string[];
}
/**
* Reference type directing to named schema.
*
* If {@link IConfig.strict} mode is enabled, its other properties like
* {@link description} would be disabled. Instead, the description would be
* placed in the parent type. For example, if this reference type is used as a
* property of an object, the description would be placed in the object
* place.
*/
interface IReference extends IJsonSchemaAttribute {
/**
* Reference to the named schema.
*
* The `$ref` is a reference to a named schema. The format follows the JSON
* Pointer specification. In OpenAPI, the `$ref` starts with `#/$defs/`
* which indicates the type is stored in the
* {@link ILlmSchema.IParameters.$defs} object.
*
* - `#/$defs/SomeObject`
* - `#/$defs/AnotherObject`
*/
$ref: string;
}
/**
* Union type.
*
* `IAnyOf` represents a union type in TypeScript (`A | B | C`).
*
* For reference, even if your Swagger (or OpenAPI) document defines `oneOf`
* instead of `anyOf`, {@link ILlmSchema} forcibly converts it to the
* `anyOf`-based {@link ILlmSchema.IAnyOf} type.
*/
interface IAnyOf extends IJsonSchemaAttribute {
/** List of the union types. */
anyOf: Exclude<ILlmSchema, ILlmSchema.IAnyOf>[];
/**
* Discriminator info of the union type.
*
* This discriminator is used to determine which type in the union should be
* used based on the value of a specific property.
*/
"x-discriminator"?: IAnyOf.IDiscriminator;
}
namespace IAnyOf {
/** Discriminator info of the union type. */
interface IDiscriminator {
/** Property name for the discriminator. */
propertyName: string;
/**
* Mapping of discriminator values to schema names.
*
* This property is valid only for {@link IReference} typed
* {@link IAnyOf.anyOf} elements. Therefore, the `key` of `mapping` is the
* discriminator value, and the `value` of `mapping` is the schema name
* like `#/components/schemas/SomeObject`.
*/
mapping?: Record<string, string>;
}
}
/** Null type. */
interface INull extends IJsonSchemaAttribute.INull {
}
/** Unknown, the `any` type. */
interface IUnknown extends IJsonSchemaAttribute.IUnknown {
}
}