schema() function

typia
export namespace llm {
  // LLM FUNCTION CALLING APPLICATION SCHEMA
  export function application<
    App extends Record<string, any>,
    Model extends ILlmSchema.Model,
    Config extends Partial<ILlmSchema.ModelConfig[Model]> = {},
  >(
    options?: Partial<Pick<ILlmApplication.IOptions<Model>, "separate">>,
  ): ILlmApplication<Model>;
 
  // +VALIDATE FUNCTION EMBEDDED
  export function applicationOfValidate<
    App extends Record<string, any>,
    Model extends ILlmSchema.Model,
    Config extends Partial<ILlmSchema.ModelConfig[Model]> = {},
  >(
    options?: Partial<Pick<ILlmApplicationOfValidate.IOptions<Model>, "separate">>,
  ): ILlmApplicationOfValidate<Model>;
 
  // STRUCTURED OUTPUT
  export function parameters<
    Parameters extends Record<string, any>,
    Model extends ILlmSchema.Model,
    Config extends Partial<ILlmSchema.ModelConfig[Model]> = {},
  >(): ILlmSchema.ModelParameters[Model];
 
  // TYPE SCHEMA
  export function schema<
    T,
    Model extends ILlmSchema.Model,
    Config extends Partial<ILlmSchema.ModelConfig[Model]> = {},
  >(
    ...$defs: Extract<
      ILlmSchema.ModelSchema[Model],
      { $ref: string }
    > extends never
      ? []
      : [Record<string, ILlmSchema.ModelSchema[Model]>]
  ): ILlmSchema.ModelSchema[Model];
}

Type schema in the LLM function calling application.

typia.llm.schema<T, Model>() is a function generating type schema which is used in the LLM (Large Language Model) function calling application schema or structured output, especially composed by the typia.llm.parameters<Parameters, Model>() and typia.llm.application<App, Model>() functions.

Return value type ILlmSchema is similar with the JSON schema definition. However, its detailed specification becomes different by the LLM provider model you’ve chosen. Here is the list of LLM schema definitions of each model. Determine one of them carefully reading the LLM schema definitions.

LLM Function Calling and Structured Output

LLM selects proper function and fill arguments.

In nowadays, most LLM (Large Language Model) like OpenAI are supporting “function calling” feature. The “LLM function calling” means that LLM automatically selects a proper function and fills parameter values from conversation with the user (may by chatting text).

Structured output is another feature of LLM. The “structured output” means that LLM automatically transforms the output conversation into a structured data format like JSON.

Specialization

You can utilize type tags (or validator’s comment tags) to constructing special fields of JSON schema.

If you write any comment on a property, it would fill the IJsonSchema.description value. Also, there’re special comment tags only for JSON schema definition that are different with validator’s comment tags like below.

  • @deprecated
  • @hidden
  • @internal
  • @title {string}
  • @default {value}

Let’s see how those type tags, comment tags and description comments are working with example code.

examples/src/llm-schema.ts
import { IChatGptSchema } from "@samchon/openapi";
import typia, { tags } from "typia";
 
export const schema: IChatGptSchema = typia.llm.schema<Special, "claude">();
 
interface Special {
  /**
   * Deprecated tags are just used for marking.
   *
   * @title Unsigned integer
   * @deprecated
   */
  type: number & tags.Type<"int32">;
 
  /**
   * Internal tagged property never be shown in JSON schema.
   *
   * It even doesn't be shown in other `typia` functions like `assert<T>()`.
   *
   * @internal
   */
  internal: number[];
 
  /**
   * Hidden tagged property never be shown in JSON schema.
   *
   * However, it would be shown in other `typia` functions like `stringify<T>()`.
   *
   * @hidden
   */
  hidden: boolean;
 
  /**
   * You can limit the range of number.
   *
   * @exclusiveMinimum 19
   * @maximum 100
   * @default 30
   */
  number?: number;
 
  /**
   * You can limit the length of string.
   *
   * Also, multiple range conditions are also possible.
   */
  string: string &
    (
      | (tags.MinLength<3> & tags.MaxLength<24>)
      | (tags.MinLength<40> & tags.MaxLength<100>)
    );
 
  /**
   * You can limit the pattern of string.
   *
   * @pattern ^[a-z]+$
   */
  pattern: string;
 
  /**
   * You can limit the format of string.
   *
   * @format date-time
   */
  format: string | null;
 
  /**
   * In the Array case, possible to restrict its elements.
   */
  array: Array<string & tags.Format<"uuid">> & tags.MinItems<3>;
}

Customziation

If what you want is not just filling regular properties of LLM schema specification, but to adding custom properties into the JSON schema definition, you can do it through the tags.TagBase.schema property type or tags.JsonSchemaPlugin type.

For reference, the custom property must be started with x- prefix. It’s a rule of LLM schema.

examples/src/llm-schema-custom.ts
import typia, { tags } from "typia";
 
type Monetary<Value extends string> = tags.TagBase<{
  target: "number";
  kind: "monetary";
  value: Value;
  schema: {
    "x-monetary": Value;
  };
}>;
 
type Placeholder<Value extends string> = tags.JsonSchemaPlugin<{
  "x-placeholder": Value;
}>;
 
interface IAccount {
  code: string & Placeholder<"Write you account code please">;
  balance: number & Monetary<"dollar">;
};
 
typia.llm.schema<IAccount, "chatgpt">();

Restrictions

LLM schema does not support bigint type.

LLM schema is based on the JSON schema definition of the OpenAPI v3.0 specification. Therefore, limitations of the JSON schema is also applied to the LLM schema, and the bigint type is not supported in the LLM function calling schema composition.

Also, LLM schema does not support the tuple type, which is represented by the OpenApi.IJsonSchema.ITuple type. It’s no LLM providers are supporting the tuple type, and such tuple type harms the separation option of the typia.llm.application<App, Model>() function. If you need a tuple type, just change the tuple type to a regular object type instead.

src/examples/llm.schema.bigint-and-tuple.ts
import typia from "typia";
 
typia.llm.schema<bigint, "chatgpt">({});
typia.llm.schema<[number, string], "claude">({});

If you’re using Google Gemini (IGeminiSchema) or middle layer schema of ILlmSchemaV3, they do not support the reference type that is embodied by the OpenApi.IJsonSchema.IReference type with $ref property. Therefore, if recursive type comes, no way to express it perfectly in those IGeminiSchema and ILlmSchemaV3. They just repeat the recursive structure 3 times, and remove the recursive type after the 4 depths.

For reference, if the recursive type comes from the array type, it would be zero length array type at the fourth step. Otherwise the recursive type comes from a property and the property is optional, the 4th property would be removed from the object type. At last, if the recursive type is combined as an oneOf type, the type would be removed from there.

src/examples/llm.schema.recursive.ts
import typia, { tags } from "typia";
 
typia.llm.schema<IDepartment, "gemini">();
 
interface IDepartment {
  id: string & tags.Format<"uuid">;
  name: string;
  department: IDepartment[];
}

And OpenAI ChatGPT (IChatGptSchema) and Google Gemini (IGeminiSchema) do not support the OpenApi.IJsonSchema.IObject.additionalProperties type, which represent the dynamic key typed object like Record<string, T> type in the TypeScript. Therefore, if you put the dynamic Record<string, T> type like below, typia.llm.schema<T, "chatgpt">() and typia.llm.schema<T, "gemini"> functions throw the compilation error like below.

Therefore, if you want to utilzie OpenAI hatGPT (IChatGptSchema) or Google Gemini (IGeminiSchema), you have to change the Record<string, T> type to an array of regular object type like below. Note that, as LLM providers do not support the tuple type, you don’t have to define the array type containing the tuple type.

  • recommended: Array<{ key: string, value: T }>
  • not recommended: Array<[string, T]>
src/examples/llm.schema.additionalProperties.ts
import typia from "typia";
 
typia.llm.schema<Record<string, number>, "chatgpt">({});
typia.llm.schema<Record<string, number>, "gemini">();