@samchon/openapi
Version:
OpenAPI definitions and converters for 'typia' and 'nestia'.
262 lines (261 loc) • 10.7 kB
text/typescript
import { OpenApi } from "../OpenApi";
import { IHttpMigrateRoute } from "./IHttpMigrateRoute";
import { ILlmSchema } from "./ILlmSchema";
import { IValidation } from "./IValidation";
/**
* LLM function calling schema from HTTP (OpenAPI) operation.
*
* `IHttpLlmFunction` is a data structure representing a function converted
* from the {@link OpenApi.IOperation OpenAPI operation}, used for the LLM
* (Large Language Model) function calling. It's a typical RPC (Remote Procedure Call)
* structure containing the function {@link name}, {@link parameters}, and
* {@link output return type}.
*
* If you provide this `IHttpLlmFunction` data to the LLM provider like "OpenAI",
* the "OpenAI" will compose a function arguments by analyzing conversations with
* the user. With the LLM composed arguments, you can execute the function through
* {@link LlmFetcher.execute} and get the result.
*
* For reference, different between `IHttpLlmFunction` and its origin source
* {@link OpenApi.IOperation} is, `IHttpLlmFunction` has converted every type schema
* information from {@link OpenApi.IJsonSchema} to {@link ILlmSchemaV3} to escape
* {@link OpenApi.IJsonSchema.IReference reference types}, and downgrade the version
* of the JSON schema to OpenAPI 3.0. It's because LLM function call feature cannot
* understand both reference types and OpenAPI 3.1 specification.
*
* Additionally, the properties' rule is:
*
* - `pathParameters`: Path parameters of {@link OpenApi.IOperation.parameters}
* - `query`: Query parameter of {@link IHttpMigrateRoute.query}
* - `body`: Body parameter of {@link IHttpMigrateRoute.body}
*
* ```typescript
* {
* ...pathParameters,
* query,
* body,
* }
* ```
*
* @reference https://platform.openai.com/docs/guides/function-calling
* @author Jeongho Nam - https://github.com/samchon
*/
export interface IHttpLlmFunction<Model extends ILlmSchema.Model> {
/**
* HTTP method of the endpoint.
*/
method: "get" | "post" | "patch" | "put" | "delete";
/**
* Path of the endpoint.
*/
path: string;
/**
* Representative name of the function.
*
* The `name` is a repsentative name identifying the function in the
* {@link IHttpLlmApplication}. The `name` value is just composed by joining the
* {@link IHttpMigrateRoute.accessor} by underscore `_` character.
*
* Here is the composition rule of the {@link IHttpMigrateRoute.accessor}:
*
* > The `accessor` is composed with the following rules. At first,
* > namespaces are composed by static directory names in the {@link path}.
* > Parametric symbols represented by `:param` or `{param}` cannot be
* > a part of the namespace.
* >
* > Instead, they would be a part of the function name. The function
* > name is composed with the {@link method HTTP method} and parametric
* > symbols like `getByParam` or `postByParam`. If there are multiple
* > path parameters, they would be concatenated by `And` like
* > `getByParam1AndParam2`.
* >
* > For refefence, if the {@link operation}'s {@link method} is `delete`,
* > the function name would be replaced to `erase` instead of `delete`.
* > It is the reason why the `delete` is a reserved keyword in many
* > programming languages.
* >
* > - Example 1
* > - path: `POST /shopping/sellers/sales`
* > - accessor: `shopping.sellers.sales.post`
* > - Example 2
* > - endpoint: `GET /shoppings/sellers/sales/:saleId/reviews/:reviewId/comments/:id
* > - accessor: `shoppings.sellers.sales.reviews.getBySaleIdAndReviewIdAndCommentId`
*
* @maxLength 64
*/
name: string;
/**
* List of parameter types.
*
* If you've configured {@link IHttpLlmApplication.IOptions.keyword} as `true`,
* number of {@link IHttpLlmFunction.parameters} are always 1 and the first
* parameter's type is always {@link ILlmSchemaV3.IObject}. The
* properties' rule is:
*
* - `pathParameters`: Path parameters of {@link IHttpMigrateRoute.parameters}
* - `query`: Query parameter of {@link IHttpMigrateRoute.query}
* - `body`: Body parameter of {@link IHttpMigrateRoute.body}
*
* ```typescript
* {
* ...pathParameters,
* query,
* body,
* }
* ```
*
* Otherwise, the parameters would be multiple, and the sequence of the
* parameters are following below rules:
*
* ```typescript
* [
* ...pathParameters,
* ...(query ? [query] : []),
* ...(body ? [body] : []),
* ]
* ```
*/
parameters: ILlmSchema.ModelParameters[Model];
/**
* Collection of separated parameters.
*
* Filled only when {@link IHttpLlmApplication.IOptions.separate} is configured.
*/
separated?: IHttpLlmFunction.ISeparated<Model>;
/**
* Expected return type.
*
* If the target operation returns nothing (`void`), the `output`
* would be `undefined`.
*/
output?: ILlmSchema.ModelSchema[Model] | undefined;
/**
* Description of the function.
*
* `IHttpLlmFunction.description` is composed by below rule:
*
* 1. Starts from the {@link OpenApi.IOperation.summary} paragraph.
* 2. The next paragraphs are filled with the
* {@link OpenApi.IOperation.description}. By the way, if the first
* paragraph of {@link OpenApi.IOperation.description} is same with the
* {@link OpenApi.IOperation.summary}, it would not be duplicated.
* 3. Parameters' descriptions are added with `@param` tag.
* 4. {@link OpenApi.IOperation.security Security requirements} are added
* with `@security` tag.
* 5. Tag names are added with `@tag` tag.
* 6. If {@link OpenApi.IOperation.deprecated}, `@deprecated` tag is added.
*
* For reference, the `description` is very important property to teach
* the purpose of the function to the LLM (Language Large Model), and
* LLM actually determines which function to call by the description.
*
* Also, when the LLM conversates with the user, the `description` is
* used to explain the function to the user. Therefore, the `description`
* property has the highest priority, and you have to consider it.
*/
description?: string;
/**
* Whether the function is deprecated or not.
*
* If the `deprecated` is `true`, the function is not recommended to use.
*
* LLM (Large Language Model) may not use the deprecated function.
*/
deprecated?: boolean | undefined;
/**
* Category tags for the function.
*
* Same with {@link OpenApi.IOperation.tags} indicating the category of the function.
*/
tags?: string[];
/**
* Validate function of the arguments.
*
* You know what? LLM (Large Language Model) like OpenAI takes a lot of
* mistakes when composing arguments in function calling. Even though
* `number` like simple type is defined in the {@link parameters} schema,
* LLM often fills it just by a `string` typed value.
*
* In that case, you have to give a validation feedback to the LLM by
* using this `validate` function. The `validate` function will return
* detailed information about every type errors about the arguments.
*
* And in my experience, OpenAI's `gpt-4o-mini` model tends to construct
* an invalid function calling arguments at the first trial about 50% of
* the time. However, if correct it through this `validate` function,
* the success rate soars to 99% at the second trial, and I've never
* failed at the third trial.
*
* > If you've {@link separated} parameters, use the
* > {@link IHttpLlmFunction.ISeparated.validate} function instead when
* > validating the LLM composed arguments.
* >
* > In that case, This `validate` function would be meaningful only
* > when you've merged the LLM and human composed arguments by
* > {@link HttpLlm.mergeParameters} function.
*
* @param args Arguments to validate.
* @returns Validation result
*/
validate: (args: unknown) => IValidation<unknown>;
/**
* Get the Swagger operation metadata.
*
* Get the Swagger operation metadata, of the source.
*
* @returns Swagger operation metadata.
*/
operation: () => OpenApi.IOperation;
/**
* Get the migration route metadata.
*
* Get the migration route metadata, of the source.
*
* @returns Migration route metadata.
*/
route: () => IHttpMigrateRoute;
}
export declare namespace IHttpLlmFunction {
/**
* Collection of separated parameters.
*/
interface ISeparated<Model extends ILlmSchema.Model> {
/**
* Parameters that would be composed by the LLM.
*
* Even though no property exists in the LLM side, the `llm` property
* would have at least empty object type.
*/
llm: ILlmSchema.ModelParameters[Model];
/**
* Parameters that would be composed by the human.
*/
human: ILlmSchema.ModelParameters[Model] | null;
/**
* Validate function of the separated arguments.
*
* If LLM part of separated parameters has some properties,
* this `validate` function will be filled for the {@link llm}
* type validation.
*
* > You know what? LLM (Large Language Model) like OpenAI takes a lot of
* > mistakes when composing arguments in function calling. Even though
* > `number` like simple type is defined in the {@link parameters} schema,
* > LLM often fills it just by a `string` typed value.
* >
* > In that case, you have to give a validation feedback to the LLM by
* > using this `validate` function. The `validate` function will return
* > detailed information about every type errors about the arguments.
* >
* > And in my experience, OpenAI's `gpt-4o-mini` model tends to construct
* > an invalid function calling arguments at the first trial about 50% of
* > the time. However, if correct it through this `validate` function,
* > the success rate soars to 99% at the second trial, and I've never
* > failed at the third trial.
*
* @param args Arguments to validate
* @returns Validate result
*/
validate?: ((args: unknown) => IValidation<unknown>) | undefined;
}
}