application()
function
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
import { ILlmApplication } from "@samchon/openapi";
import typia, { tags } from "typia";
const app: ILlmApplication = typia.llm.application<BbsArticleController>();
console.log(app);
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.
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(app);
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.
import { ILlmApplication } from "@samchon/openapi";
import typia, { tags } from "typia";
const app: ILlmApplication = typia.llm.application<BbsArticleController>();
console.log(app);
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.
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.
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.
import { ILlmApplication } from "@samchon/openapi";
import typia from "typia";
const app: ILlmApplication = typia.llm.application<Controller>();
console.log(app);
interface Controller {
now(): Date;
}