đź“– Guide Documents
LLM Function Calling
application() function

application() function

typia
export namespace llm {
  export function application<App extends object>(
    options?: ILlmApplication.IOptions
  ): ILlmApplication;
}

LLM function calling application from a native TypeScript class or interface type.

typia.llm.application<App>() is a function composing LLM (Large Language Model) calling application from a native TypeScript class or interface type. The function returns an ILlmApplication instance, which is a data structure representing a collection of LLM function calling schemas.

If you put LLM function schema instances registered in the ILlmApplication.functions to the LLM provider like OpenAI, the LLM will select a proper function to call with parameter values of the target function in the conversations with the user. This is the "LLM Function Calling".

Let's make A.I. Chatbot super-easily with typia.llm.application<App>() function.

LLM Function Calling

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).

https://platform.openai.com/docs/guides/function-calling (opens in a new tab)

Description Comment

example/src/llm.application.simple.ts
import { ILlmApplication } from "@samchon/openapi";
import typia, { tags } from "typia";
 
const app: ILlmApplication = typia.llm.application<BbsArticleController>();
 
console.log(JSON.stringify(app, null, 2));
 
interface BbsArticleController {
  /**
   * Create a new article.
   *
   * Writes a new article and archives it into the DB.
   *
   * @param input Information of the article to create
   * @returns Newly created article
   */
  create(input: IBbsArticle.ICreate): Promise<IBbsArticle>;
 
  /**
   * Update an article.
   *
   * Updates an article with new content.
   *
   * @param id Target article's {@link IBbsArticle.id}
   * @param input New content to update
   */
  update(
    id: string & tags.Format<"uuid">,
    input: IBbsArticle.IUpdate,
  ): Promise<void>;
 
  /**
   * Erase an article.
   *
   * Erases an article from the DB.
   *
   * @param id Target article's {@link IBbsArticle.id}
   */
  erase(id: string & tags.Format<"uuid">): Promise<void>;
}
 
/**
 * Article entity.
 *
 * `IBbsArticle` is an entity representing an article in the BBS (Bulletin Board System).
 */
interface IBbsArticle extends IBbsArticle.ICreate {
  /**
   * Primary Key.
   */
  id: string & tags.Format<"uuid">;
 
  /**
   * Creation time of the article.
   */
  created_at: string & tags.Format<"date-time">;
 
  /**
   * Last updated time of the article.
   */
  updated_at: string & tags.Format<"date-time">;
}
namespace IBbsArticle {
  /**
   * Information of the article to create.
   */
  export interface ICreate {
    /**
     * Title of the article.
     *
     * Representative title of the article.
     */
    title: string;
 
    /**
     * Content body.
     *
     * Content body of the article writtn in the markdown format.
     */
    body: string;
 
    /**
     * Thumbnail image URI.
     *
     * Thumbnail image URI which can represent the article.
     *
     * If configured as `null`, it means that no thumbnail image in the article.
     */
    thumbnail:
      | null
      | (string & tags.Format<"uri"> & tags.ContentMediaType<"image/*">);
  }
 
  /**
   * Information of the article to update.
   *
   * Only the filled properties will be updated.
   */
  export type IUpdate = Partial<ICreate>;
}

Here is the example code utilizing the typia.llm.application<App>() function.

As you can see, above example code is writing detailed descriptions for every functions and their parameter/return types. Such detailed descriptions are very important to teach the purpose of the function to the LLM (Language Large Model), and LLM actually determines which function to call by the description.

Therefore, don't forget to writing detailed descriptions. It's very import feature for the LLM function calling.

Parameters' Separation

Parameter values from both LLM and Human sides.

When composing parameter arguments through the LLM (Large Language Model) function calling, there can be a case that some parameters (or nested properties) must be composed not by LLM, but by Human. File uploading feature, or sensitive information like secret key (password) cases are the representative examples.

In that case, you can configure the LLM function calling schemas to exclude such Human side parameters (or nested properties) by ILlmApplication.options.separate property. Instead, you have to merge both Human and LLM composed parameters into one by calling the HttpLlm.mergeParameters() before the LLM function call execution.

Here is the example separating the parameter schemas.

example/src/llm.application.separate.ts
import { ILlmApplication, ILlmSchema, LlmTypeChecker } from "@samchon/openapi";
import typia, { tags } from "typia";
 
const app: ILlmApplication = typia.llm.application<BbsArticleController>({
  separate: (schema: ILlmSchema) =>
    LlmTypeChecker.isString(schema) && schema.contentMediaType !== undefined,
});
 
console.log(JSON.stringify(app, null, 2));
 
interface BbsArticleController {
  /**
   * Create a new article.
   *
   * Writes a new article and archives it into the DB.
   *
   * @param input Information of the article to create
   * @returns Newly created article
   */
  create(input: IBbsArticle.ICreate): Promise<IBbsArticle>;
 
  /**
   * Update an article.
   *
   * Updates an article with new content.
   *
   * @param id Target article's {@link IBbsArticle.id}
   * @param input New content to update
   */
  update(
    id: string & tags.Format<"uuid">,
    input: IBbsArticle.IUpdate,
  ): Promise<void>;
 
  /**
   * Erase an article.
   *
   * Erases an article from the DB.
   *
   * @param id Target article's {@link IBbsArticle.id}
   */
  erase(id: string & tags.Format<"uuid">): Promise<void>;
}

Function Hiding

Hiding some functions by comment tag.

If you write @hidden or @internal tag onto a function description comment, the function would not participate in the LLM (Large Language Model) function calling application composition. ILlmFunction schema does not be genrated in the ILlmApplication.functions collection.

It's a good feature to hide some internal functions, so that avoiding the LLM function calling.

example/src/llm.application.hideden.ts
import { ILlmApplication } from "@samchon/openapi";
import typia, { tags } from "typia";
 
const app: ILlmApplication = typia.llm.application<BbsArticleController>();
 
console.log(JSON.stringify(app, null, 2));
 
interface BbsArticleController {
  /**
   * Create a new article.
   *
   * Writes a new article and archives it into the DB.
   *
   * @param input Information of the article to create
   * @returns Newly created article
   */
  create(input: IBbsArticle.ICreate): Promise<IBbsArticle>;
 
  /**
   * Update an article.
   *
   * Updates an article with new content.
   *
   * @param id Target article's {@link IBbsArticle.id}
   * @param input New content to update
   * @hidden
   */
  update(
    id: string & tags.Format<"uuid">,
    input: IBbsArticle.IUpdate,
  ): Promise<void>;
 
  /**
   * Erase an article.
   *
   * Erases an article from the DB.
   *
   * @param id Target article's {@link IBbsArticle.id}
   * @internal
   */
  erase(id: string & tags.Format<"uuid">): Promise<void>;
}

Restrictions

LLM schema does not support bigint type, and recursive type either.

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.

example/src/llm.application.bigint.ts
import typia from "typia";
 
typia.llm.application<Controller>();
 
interface Controller {
  plus(X: bigint, y: bigint): bigint;
}

Also, LLM schema does not support reference type that is embodied by the OpenApi.IJsonSchema.IReference type with $ref property. Therefore, if recursive type comes, no way to express it in the LLM schema, and it would be compilation error in the typia.llm.application<App>() function.

example/src/llm.application.bigint.ts
import typia from "typia";
 
typia.llm.application<Controller>();
 
interface Controller {
  plus(item: Recursive): Recursive;
}
 
interface Recursive {
  id: number;
  children: Recursive[];
}

And if you put any type of native classes like Map or Uint8Array, it would also be error, either. By the way, only Date class type is exceptional, and it would be considered as string & Format<"date-time"> type like below.

example/src/llm.application.bigint.ts
import { ILlmApplication } from "@samchon/openapi";
import typia from "typia";
 
const app: ILlmApplication = typia.llm.application<Controller>();
 
console.log(JSON.stringify(app, null, 2));
 
interface Controller {
  now(): Date;
}