From 42d329e00b924900897dd3e3deb84f85ab01e427 Mon Sep 17 00:00:00 2001 From: Jeongho Nam Date: Tue, 28 Jan 2025 23:23:11 +0900 Subject: [PATCH] Documentation of `@nestia/agent` --- packages/agent/package.json | 2 +- packages/agent/src/NestiaAgent.ts | 19 ++- .../src/structures/INestiaAgentConfig.ts | 11 ++ .../src/structures/INestiaAgentController.ts | 92 +++++++++++++++ .../agent/src/structures/INestiaAgentEvent.ts | 3 +- .../src/structures/INestiaAgentOperation.ts | 21 ++++ .../INestiaAgentOperationCollection.ts | 42 +++++++ .../INestiaAgentOperationSelection.ts | 8 ++ .../src/structures/INestiaAgentPrompt.ts | 8 ++ .../agent/src/structures/INestiaAgentProps.ts | 53 ++++++++- .../src/structures/INestiaAgentProvider.ts | 14 +++ .../structures/INestiaAgentSystemPrompt.ts | 111 ++++++++++++++++++ .../src/structures/INestiaAgentTokenUsage.ts | 33 ++++++ website/build/typedoc.js | 2 +- 14 files changed, 414 insertions(+), 5 deletions(-) diff --git a/packages/agent/package.json b/packages/agent/package.json index 73b8d51b1..f983d7bc5 100644 --- a/packages/agent/package.json +++ b/packages/agent/package.json @@ -1,6 +1,6 @@ { "name": "@nestia/agent", - "version": "0.3.9", + "version": "0.3.10", "main": "lib/index.js", "module": "lib/index.mjs", "typings": "lib/index.d.ts", diff --git a/packages/agent/src/NestiaAgent.ts b/packages/agent/src/NestiaAgent.ts index a09ebab2d..70782fc1b 100644 --- a/packages/agent/src/NestiaAgent.ts +++ b/packages/agent/src/NestiaAgent.ts @@ -18,11 +18,28 @@ import { INestiaAgentTokenUsage } from "./structures/INestiaAgentTokenUsage"; /** * Nestia A.I. chatbot agent. * - * `NestiaChatAgent` is a facade class for the A.I. chatbot agent + * `NestiaChatAgent` is a facade class for the super A.I. chatbot agent * which performs the {@link converstate user's conversation function} * with LLM (Large Language Model) function calling and manages the * {@link getPromptHistories prompt histories}. * + * To understand and compose the `NestiaAgent` class exactly, reference + * below types concentrating on the documentation comments please. + * Especially, you have to be careful about the {@link INestiaAgentProps} + * type which is used in the {@link constructor} function. + * + * - Constructors + * - {@link INestiaAgentProps} + * - {@link INestiaAgentProvider} + * - {@link INestiaAgentController} + * - {@link INestiaAgentConfig} + * - {@link INestiaAgentSystemPrompt} + * - Accessors + * - {@link INestiaAgentOperation} + * - {@link INestiaAgentPrompt} + * - {@link INestiaAgentEvent} + * - {@link INestiaAgentTokenUsage} + * * @author Jeongho Nam - https://github.com/samchon */ export class NestiaAgent { diff --git a/packages/agent/src/structures/INestiaAgentConfig.ts b/packages/agent/src/structures/INestiaAgentConfig.ts index a9d341d92..3fbebe106 100644 --- a/packages/agent/src/structures/INestiaAgentConfig.ts +++ b/packages/agent/src/structures/INestiaAgentConfig.ts @@ -3,6 +3,17 @@ import { INestiaAgentSystemPrompt } from "./INestiaAgentSystemPrompt"; /** * Configuration for Nestia Agent. * + * `INestiaAgentConfig` is an interface that defines the configuration + * properties of the {@link NestiaAgent}. With this configuration, you + * can set the user's locale, timezone, and some of system prompts. + * + * Also, you can affect to the LLM function selecing/calling logic by + * configuring additional properties. For an example, if you configure the + * {@link capacity} property, the A.I. chatbot will divide the functions + * into the several groups with the configured capacity and select proper + * functions to call by operating the multiple LLM function selecting + * agents parallelly. + * * @author Jeongho Nam - https://github.com/samchon */ export interface INestiaAgentConfig { diff --git a/packages/agent/src/structures/INestiaAgentController.ts b/packages/agent/src/structures/INestiaAgentController.ts index ea9f919e0..78c2a8248 100644 --- a/packages/agent/src/structures/INestiaAgentController.ts +++ b/packages/agent/src/structures/INestiaAgentController.ts @@ -6,30 +6,122 @@ import { } from "@samchon/openapi"; import { ILlmApplicationOfValidate, ILlmFunctionOfValidate } from "typia"; +/** + * Controller of the Nestia Agent. + * + * `INestiaAgentController` is a type represents a controller of the + * {@link NestiaAgent}, which serves a set of functions to be called + * by A.I. chatbot from LLM function calling. + * + * Also, `INestiaAgentController` is an union type which can specify + * a subtype by checking the {@link protocol} property. + * + * - HTTP server: {@link INestiaAgentController..IHttp} + * - TypeScript class: {@link INestiaAgentController.IClass} + * + * @author Jeongho Nam - https://github.com/samchon + */ export type INestiaAgentController = | INestiaAgentController.IHttp | INestiaAgentController.IClass; export namespace INestiaAgentController { + /** + * HTTP controller. + * + * You can make it by {@link createHttpLlmApplication} function with + * the Swagger or OpenAPI document. + */ export interface IHttp extends IBase<"http", IHttpLlmApplication<"chatgpt">> { + /** + * Connection to the server. + * + * Connection to the API server including the URL and headers. + */ connection: IHttpConnection; + + /** + * Executor of the API function. + * + * @param props Properties of the API function call + * @returns HTTP response of the API function call + */ execute?: (props: { + /** + * Connection to the server. + */ connection: IHttpConnection; + + /** + * Application schema. + */ application: IHttpLlmApplication<"chatgpt">; + + /** + * Function schema. + */ function: IHttpLlmFunction<"chatgpt">; + + /** + * Arguments of the function calling. + * + * It is an object of key-value pairs of the API function's parameters. + * The property keys are composed by below rules: + * + * - parameter names + * - query parameter as an object type if exists + * - body parameter if exists + */ arguments: object; }) => Promise; } + + /** + * TypeScript class controller. + * + * You can make it by `typia.llm.application()` function. + * + * - https://typia.io/docs/llm/application + */ export interface IClass extends IBase<"class", ILlmApplicationOfValidate<"chatgpt">> { + /** + * Executor of the class function. + * + * @param props Properties of the function call. + * @returns Return value of the function call. + */ execute: (props: { + /** + * Target application schema. + */ application: ILlmApplicationOfValidate<"chatgpt">; + + /** + * Target function schema. + */ function: ILlmFunctionOfValidate<"chatgpt">; + + /** + * Arguments of the function calling. + */ arguments: object; }) => Promise; } + interface IBase { + /** + * Protocol discrminator. + */ protocol: Protocol; + + /** + * Name of the controller. + */ name: string; + + /** + * Application schema of function calling. + */ application: Application; } } diff --git a/packages/agent/src/structures/INestiaAgentEvent.ts b/packages/agent/src/structures/INestiaAgentEvent.ts index f0b38aef7..1c786972e 100644 --- a/packages/agent/src/structures/INestiaAgentEvent.ts +++ b/packages/agent/src/structures/INestiaAgentEvent.ts @@ -8,7 +8,8 @@ import { INestiaAgentPrompt } from "./INestiaAgentPrompt"; * Nestia A.I. chatbot event. * * `INestiaAgentEvent` is an union type of all possible events that can - * be emitted by the A.I. chatbot of the {@link NestiaAgent} class. + * be emitted by the A.I. chatbot of the {@link NestiaAgent} class. You + * can discriminate the subtype by checking the {@link type} property. * * @author Jeongho Nam - https://github.com/samchon */ diff --git a/packages/agent/src/structures/INestiaAgentOperation.ts b/packages/agent/src/structures/INestiaAgentOperation.ts index 82364a60a..9c7aee224 100644 --- a/packages/agent/src/structures/INestiaAgentOperation.ts +++ b/packages/agent/src/structures/INestiaAgentOperation.ts @@ -3,16 +3,37 @@ import { ILlmFunctionOfValidate } from "typia"; import { INestiaAgentController } from "./INestiaAgentController"; +/** + * Operation information in the Nestia Agent. + * + * `INestiaAgentOperation` is a type represents an operation that would + * be selected by the A.I. chatbot of {@link NestiaAgent} class to + * perform the LLM (Large Language Model) function calling. + * + * Also, it is an union type that is discriminated by the {@link protocol} + * property. If the protocol value is `http`, it means that the HTTP API + * operation would be called by the A.I. chatbot. Otherwise, if the protocol + * value is `class`, it means that the operation has come from a + * TypeScript class. + * + * @author Jeongho Nam - https://github.com/samchon + */ export type INestiaAgentOperation = | INestiaAgentOperation.IHttp | INestiaAgentOperation.IClass; export namespace INestiaAgentOperation { + /** + * HTTP API operation. + */ export type IHttp = IBase< "http", INestiaAgentController.IHttp, IHttpLlmFunction<"chatgpt"> >; + /** + * TypeScript class operation. + */ export type IClass = IBase< "class", INestiaAgentController.IClass, diff --git a/packages/agent/src/structures/INestiaAgentOperationCollection.ts b/packages/agent/src/structures/INestiaAgentOperationCollection.ts index d28939be8..7fe531261 100644 --- a/packages/agent/src/structures/INestiaAgentOperationCollection.ts +++ b/packages/agent/src/structures/INestiaAgentOperationCollection.ts @@ -1,8 +1,50 @@ import { INestiaAgentOperation } from "./INestiaAgentOperation"; +/** + * Collection of operations used in the Nestia Agent. + * + * `INestiaAgentOperationCollection` is an interface type representing + * a collection of operations for several purposes used in the + * {@link NestiaAgent} internally. + * + * @author Jeongho Nam - https://github.com/samchon + */ export interface INestiaAgentOperationCollection { + /** + * List of every operations. + */ array: INestiaAgentOperation[]; + + /** + * Divided operations. + * + * If you've configured the {@link INestiaAgentConfig.capacity} property, + * the A.I. chatbot ({@link NestiaAgent}) will separate the operations + * into the several groups to divide and conquer and LLM function selecting + * for accuracy. + * + * In that case, this property `divided`'s length would be dtermined by + * dividing the number of operations ({@link array}'s length) by the + * {@link INestiaAgentConfig.capacity}. + * + * Otherwise, if the {@link INestiaAgentConfig.capacity} has not been + * configured, this `divided` property would be the `undefined` value. + */ divided?: INestiaAgentOperation[][] | undefined; + + /** + * Flat dictionary of operations. + * + * Dictionary of operations with their {@link INestiaAgentOperation.name}. + */ flat: Map; + + /** + * Group dictionary of operations. + * + * Dictionary of operations with their + * {@link INestiaAgentOperation.controller.name} and + * {@link INestiaAgentOperation.function.name}. + */ group: Map>; } diff --git a/packages/agent/src/structures/INestiaAgentOperationSelection.ts b/packages/agent/src/structures/INestiaAgentOperationSelection.ts index 0aeab9554..fde5cbd01 100644 --- a/packages/agent/src/structures/INestiaAgentOperationSelection.ts +++ b/packages/agent/src/structures/INestiaAgentOperationSelection.ts @@ -6,6 +6,14 @@ import { INestiaAgentController } from "./INestiaAgentController"; /** * Nestia agent operation selection. * + * `INestiaAgentOperationSelection` is a type represents an operation + * which has been selected by the A.I. chatbot of {@link NestiaAgent} + * class for the LLM (Large Language Model) function calling with + * detailed {@link reason} of the selection (or cancellation). + * + * Also, `INestiaAgentOperationSelection` is an union type that can + * specify a subtype by checking the {@link protocol} property. + * * @author Jeongho Nam - https://github.com/samchon */ export type INestiaAgentOperationSelection = diff --git a/packages/agent/src/structures/INestiaAgentPrompt.ts b/packages/agent/src/structures/INestiaAgentPrompt.ts index e261d85e2..5e8f0efdd 100644 --- a/packages/agent/src/structures/INestiaAgentPrompt.ts +++ b/packages/agent/src/structures/INestiaAgentPrompt.ts @@ -10,6 +10,14 @@ import { INestiaAgentOperationSelection } from "./INestiaAgentOperationSelection * `INestiaChatPrompt` is an union type of all possible prompts that can * be generated by the A.I. chatbot of the {@link NestiaChatAgent} class. * + * In other words, `INestiaChatPrompt` is a type of chat history that + * is occured during the conversation between the user and the A.I. chatbot + * in the {@link NestiaChatAgent} class. + * + * If you want to continue the previous A.I. chatbot session, you can + * accomplish it by assigning the {@link INestiaAgentProps.histories} + * property when creating a new {@link NestiaAgent} instance. + * * @author Jeongho Nam - https://github.com/samchon */ export type INestiaAgentPrompt = diff --git a/packages/agent/src/structures/INestiaAgentProps.ts b/packages/agent/src/structures/INestiaAgentProps.ts index d40415299..5de51139d 100644 --- a/packages/agent/src/structures/INestiaAgentProps.ts +++ b/packages/agent/src/structures/INestiaAgentProps.ts @@ -5,9 +5,60 @@ import { INestiaAgentController } from "./INestiaAgentController"; import { INestiaAgentPrompt } from "./INestiaAgentPrompt"; import { INestiaAgentProvider } from "./INestiaAgentProvider"; +/** + * Properties of the Nestia Agent. + * + * `INestiaAgentProps` is an interface that defines the properties + * of the {@link NestiaAgent.constructor}. In the `INestiaAgentProps`, + * there're everything to prepare to create a Super A.I. chatbot + * performing the LLM (Large Language Model) function calling. + * + * At first, you have to specify the LLM service {@link provider} like + * OpenAI with its API key and client API. And then, you have to define + * the {@link controllers} serving the functions to call. The controllers + * are separated by two protocols; HTTP API and TypeScript class. At last, + * you can {@link config}ure the agent by setting the locale, timezone, + * and some of system prompts. + * + * Additionally, if you want to start from the previous A.I. chatbot + * session, you can accomplish it by assinging the previous prompt + * histories to the {@link histories} property. + * + * @author Jeongho Nam - https://github.com/samchon + */ export interface INestiaAgentProps { - controllers: INestiaAgentController[]; + /** + * LLM service provider. + */ provider: INestiaAgentProvider; + + /** + * Controllers serving functions to call. + */ + controllers: INestiaAgentController[]; + + /** + * Configuration of agent. + * + * Configuration of A.I. chatbot agent including the user's locale, + * timezone, and some of system prompts. Also, you can affect to the + * LLM function selecting/calling logic by configuring additional + * properties. + * + * If you don't configure this property, these values would be default. + * + * - `locale`: your system's locale and timezone + * - `timezone`: your system's timezone + * - `systemPrompt`: default prompts written in markdown + * - https://github.com/samchon/nestia/tree/master/packages/agent/prompts + */ config?: INestiaAgentConfig; + + /** + * Prompt histories. + * + * If you're starting the conversation from an existing session, + * assign the previouis prompt histories to this property. + */ histories?: Primitive[]; } diff --git a/packages/agent/src/structures/INestiaAgentProvider.ts b/packages/agent/src/structures/INestiaAgentProvider.ts index e376831f4..f09dd87ff 100644 --- a/packages/agent/src/structures/INestiaAgentProvider.ts +++ b/packages/agent/src/structures/INestiaAgentProvider.ts @@ -3,10 +3,24 @@ import OpenAI from "openai"; /** * LLM Provider for Nestia Chat. * + * `INestiaAgentProvider` is a type represents an LLM + * (Large Language Model) provider of the {@link NestiaAgent}. + * + * Currently, {@link NestiaAgent} is supporting only one provider OpenAI. + * You can specify the provider by configuring the `type` property as + * `"chatgpt"`. Also, you have to assign the OpenAI API client instance + * to the `api` property, and specify the `model` to use. + * + * If you want to use another LLM provider like Claude or Gemini, + * please write an issue or contribute to `nestia` please. + * * @author Jeongho Nam - https://github.com/samchon */ export type INestiaAgentProvider = INestiaAgentProvider.IChatGpt; export namespace INestiaAgentProvider { + /** + * OpenAI provider. + */ export interface IChatGpt { /** * Discriminator type. diff --git a/packages/agent/src/structures/INestiaAgentSystemPrompt.ts b/packages/agent/src/structures/INestiaAgentSystemPrompt.ts index c0fa4fde1..feace82b5 100644 --- a/packages/agent/src/structures/INestiaAgentSystemPrompt.ts +++ b/packages/agent/src/structures/INestiaAgentSystemPrompt.ts @@ -1,11 +1,122 @@ import { INestiaAgentConfig } from "./INestiaAgentConfig"; import { INestiaAgentPrompt } from "./INestiaAgentPrompt"; +/** + * System prompt collection of the A.I. chatbot. + * + * `INestiaAgentSystemPrompt` is a type represents a collection of system + * prompts that would be used by the A.I. chatbot of {@link NestiaAgent}. + * + * You can customize the system prompt by configuring the + * {@link INestiaAgentConfig.systemPrompt} property when creating a new + * {@link NestiaAgent} instance. + * + * If you don't configure any system prompts, the default system prompts + * would be used which are written in the below directory as markdown + * documents. + * + * - https://github.com/samchon/nestia/tree/master/packages/agent/prompts + * + * @author Jeongho Nam - https://github.com/samchon + */ export interface INestiaAgentSystemPrompt { + /** + * Common system prompt that would be used in every situation. + * + * @param config Configuration of the agent + * @returns The common system prompt + * @default https://github.com/samchon/nestia/blob/master/packages/agent/prompts/common.md + */ common?: (config?: INestiaAgentConfig | undefined) => string; + + /** + * Initialize system prompt. + * + * When the A.I. chatbot has not informed any functions to the agent + * yet because the user has not implied any function calling request yet, + * {@link NestiaAgent} says that it is a circumstance that nothing has + * been initialized yet. + * + * In that case, the `initialize` system prompt would be used. You can + * customize the `initialize` system prompt by assigning this function + * with the given {@link INestiaAgentPrompt histories} parameter. + * + * @param histories Histories of the previous prompts + * @returns initialize system prompt + * @default https://github.com/samchon/nestia/blob/master/packages/agent/prompts/initialize.md + */ initialize?: (histories: INestiaAgentPrompt[]) => string; + + /** + * Select system prompt. + * + * The {@link NestiaAgent} has a process selecting some candidate + * functions to call by asking to the A.I. agent with the previous + * prompt histories. + * + * In that case, this `select` system prompt would be used. You can + * customize it by assigning this function with the given + * {@link INestiaAgentPrompt histories} parameter. + * + * Note that, the `"select"` means only the function selection. It does + * not contain the filling argument or executing the function. It + * literally contains only the selection process. + * + * @param histories Histories of the previous prompts + * @returns select system promopt + * @default https://github.com/samchon/nestia/blob/master/packages/agent/prompts/select.md + */ select?: (histories: INestiaAgentPrompt[]) => string; + + /** + * Cancel system prompt. + * + * The {@link NestiaAgent} has a process canceling some candidate + * functions to call by asking to the A.I. agent with the previous + * prompt histories. + * + * In that case, this `cancel` system prompt would be used. You can + * customize it by assigning this function with the given + * {@link INestiaAgentPrompt histories} parameter. + * + * @param histories Histories of the previous prompts + * @returns cancel system prompt + * @default https://github.com/samchon/nestia/blob/master/packages/agent/prompts/cancel.md + */ cancel?: (histories: INestiaAgentPrompt[]) => string; + + /** + * Execute system prompt. + * + * The {@link NestiaAgent} has a process filling the arguments of some + * selected candidate functions by the LLM (Large Language Model) + * function calling feature with the previous prompt histories, and + * executing the arguments filled function with validation feedback. + * + * In that case, this `execute` system prompt would be used. You can + * customize it by assigning this function with the given + * {@link INestiaAgentPrompt histories} parameter. + * + * @param histories Histories of the previous prompts + * @returns execute system prompt + * https://github.com/samchon/nestia/blob/master/packages/agent/prompts/execute.md + */ execute?: (histories: INestiaAgentPrompt[]) => string; + + /** + * Describe system prompt. + * + * The {@link NestiaAgent} has a process describing the return values of + * the executed functions by requesting to the A.I. agent with the + * previous prompt histories. + * + * In that case, this `describe` system prompt would be used. You can + * customize it by assigning this function with the given + * {@link INestiaAgentPrompt histories} parameter. + * + * @param histories Histories of the previous prompts + * @returns describe system prompt + * @default https://github.com/samchon/nestia/blob/master/packages/agent/prompts/describe.md + */ describe?: (histories: INestiaAgentPrompt.IExecute[]) => string; } diff --git a/packages/agent/src/structures/INestiaAgentTokenUsage.ts b/packages/agent/src/structures/INestiaAgentTokenUsage.ts index 3976a8beb..321a3d613 100644 --- a/packages/agent/src/structures/INestiaAgentTokenUsage.ts +++ b/packages/agent/src/structures/INestiaAgentTokenUsage.ts @@ -1,6 +1,39 @@ +/** + * Token usage information from the A.I. chatbot. + * + * `INestiaAgentTokenUsage` is a structure representing the token usage + * information from the {@link NestiaAgent} class. And you can get the + * token usage information by calling the {@link NestiaAgent.getTokenUsage} + * method. + * + * For reference, `INestiaAgentTokenUsage` provides only the token usage + * information, and does not contain any price or cost information. It is + * because the price or cost can be changed by below reasons. + * + * - Type of {@link INestiaAgentProps.provider LLM provider} + * - {@link INestiaAgentProvider.model} in the LLM provider. + * - Just by a policy change of the LLM provider company. + * + * @author Jeongho Nam - https://github.com/samchon + */ export interface INestiaAgentTokenUsage { + /** + * Total token usage. + */ total: number; + + /** + * Token usage in the prompt. + * + * In other words, it is called as the input token. + */ prompt: INestiaAgentTokenUsage.IPrompt; + + /** + * Token usage in the completion. + * + * In other words, it is called as the output token. + */ completion: INestiaAgentTokenUsage.ICompletion; } export namespace INestiaAgentTokenUsage { diff --git a/website/build/typedoc.js b/website/build/typedoc.js index 4677ce7ba..e3426f603 100644 --- a/website/build/typedoc.js +++ b/website/build/typedoc.js @@ -6,7 +6,7 @@ import { fileURLToPath } from "url"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); -for (const pack of ["benchmark", "core", "e2e", "fetcher"]) { +for (const pack of ["agent", "benchmark", "core", "e2e", "fetcher"]) { const location = `${__dirname}/../../packages/${pack}`; if (fs.existsSync(`${location}/node_modules`) === false) cp.execSync("pnpm install", { cwd: location, stdio: "ignore" });