From 698cd9c631726efca5b2a9f104f398010be03602 Mon Sep 17 00:00:00 2001 From: Emanuel Ferreira <contatoferreirads@gmail.com> Date: Fri, 1 Mar 2024 21:28:02 -0300 Subject: [PATCH] fix: step wise agent + examples (#594) --- .changeset/four-ways-enjoy.md | 5 ++ examples/agent/step_wise_openai.ts | 95 ++++++++++++++++++++++++++ examples/agent/step_wise_query_tool.ts | 64 +++++++++++++++++ examples/agent/step_wise_react.ts | 90 ++++++++++++++++++++++++ packages/core/src/agent/runner/base.ts | 5 +- packages/core/src/agent/types.ts | 4 +- packages/core/src/llm/LLM.ts | 2 +- 7 files changed, 260 insertions(+), 5 deletions(-) create mode 100644 .changeset/four-ways-enjoy.md create mode 100644 examples/agent/step_wise_openai.ts create mode 100644 examples/agent/step_wise_query_tool.ts create mode 100644 examples/agent/step_wise_react.ts diff --git a/.changeset/four-ways-enjoy.md b/.changeset/four-ways-enjoy.md new file mode 100644 index 000000000..fee00e66f --- /dev/null +++ b/.changeset/four-ways-enjoy.md @@ -0,0 +1,5 @@ +--- +"llamaindex": patch +--- + +fix: step wise agent + examples diff --git a/examples/agent/step_wise_openai.ts b/examples/agent/step_wise_openai.ts new file mode 100644 index 000000000..abbc273c5 --- /dev/null +++ b/examples/agent/step_wise_openai.ts @@ -0,0 +1,95 @@ +import { FunctionTool, OpenAIAgent } from "llamaindex"; + +// Define a function to sum two numbers +function sumNumbers({ a, b }: { a: number; b: number }): number { + return a + b; +} + +// Define a function to divide two numbers +function divideNumbers({ a, b }: { a: number; b: number }): number { + return a / b; +} + +// Define the parameters of the sum function as a JSON schema +const sumJSON = { + type: "object", + properties: { + a: { + type: "number", + description: "The first number", + }, + b: { + type: "number", + description: "The second number", + }, + }, + required: ["a", "b"], +}; + +const divideJSON = { + type: "object", + properties: { + a: { + type: "number", + description: "The dividend a to divide", + }, + b: { + type: "number", + description: "The divisor b to divide by", + }, + }, + required: ["a", "b"], +}; + +async function main() { + // Create a function tool from the sum function + const functionTool = new FunctionTool(sumNumbers, { + name: "sumNumbers", + description: "Use this function to sum two numbers", + parameters: sumJSON, + }); + + // Create a function tool from the divide function + const functionTool2 = new FunctionTool(divideNumbers, { + name: "divideNumbers", + description: "Use this function to divide two numbers", + parameters: divideJSON, + }); + + // Create an OpenAIAgent with the function tools + const agent = new OpenAIAgent({ + tools: [functionTool, functionTool2], + verbose: true, + }); + + // Create a task to sum and divide numbers + const task = agent.createTask("How much is 5 + 5? then divide by 2"); + + let count = 0; + + while (true) { + const stepOutput = await agent.runStep(task.taskId); + + console.log(`Runnning step ${count++}`); + console.log(`======== OUTPUT ==========`); + if (stepOutput.output.response) { + console.log(stepOutput.output.response); + } else { + console.log(stepOutput.output.sources); + } + console.log(`==========================`); + + if (stepOutput.isLast) { + const finalResponse = await agent.finalizeResponse( + task.taskId, + stepOutput, + ); + console.log({ finalResponse }); + break; + } + } +} + +main().then(() => { + console.log("Done"); +}); diff --git a/examples/agent/step_wise_query_tool.ts b/examples/agent/step_wise_query_tool.ts new file mode 100644 index 000000000..d7a17295a --- /dev/null +++ b/examples/agent/step_wise_query_tool.ts @@ -0,0 +1,64 @@ +import { + OpenAIAgent, + QueryEngineTool, + SimpleDirectoryReader, + VectorStoreIndex, +} from "llamaindex"; + +async function main() { + // Load the documents + const documents = await new SimpleDirectoryReader().loadData({ + directoryPath: "node_modules/llamaindex/examples", + }); + + // Create a vector index from the documents + const vectorIndex = await VectorStoreIndex.fromDocuments(documents); + + // Create a query engine from the vector index + const abramovQueryEngine = vectorIndex.asQueryEngine(); + + // Create a QueryEngineTool with the query engine + const queryEngineTool = new QueryEngineTool({ + queryEngine: abramovQueryEngine, + metadata: { + name: "abramov_query_engine", + description: "A query engine for the Abramov documents", + }, + }); + + // Create an OpenAIAgent with the function tools + const agent = new OpenAIAgent({ + tools: [queryEngineTool], + verbose: true, + }); + + const task = agent.createTask("What was his salary?"); + + let count = 0; + + while (true) { + const stepOutput = await agent.runStep(task.taskId); + + console.log(`Runnning step ${count++}`); + console.log(`======== OUTPUT ==========`); + if (stepOutput.output.response) { + console.log(stepOutput.output.response); + } else { + console.log(stepOutput.output.sources); + } + console.log(`==========================`); + + if (stepOutput.isLast) { + const finalResponse = await agent.finalizeResponse( + task.taskId, + stepOutput, + ); + console.log({ finalResponse }); + break; + } + } +} + +main().then(() => { + console.log("Done"); +}); diff --git a/examples/agent/step_wise_react.ts b/examples/agent/step_wise_react.ts new file mode 100644 index 000000000..4230db586 --- /dev/null +++ b/examples/agent/step_wise_react.ts @@ -0,0 +1,90 @@ +import { FunctionTool, ReActAgent } from "llamaindex"; + +// Define a function to sum two numbers +function sumNumbers({ a, b }: { a: number; b: number }): number { + return a + b; +} + +// Define a function to divide two numbers +function divideNumbers({ a, b }: { a: number; b: number }): number { + return a / b; +} + +// Define the parameters of the sum function as a JSON schema +const sumJSON = { + type: "object", + properties: { + a: { + type: "number", + description: "The first number", + }, + b: { + type: "number", + description: "The second number", + }, + }, + required: ["a", "b"], +}; + +const divideJSON = { + type: "object", + properties: { + a: { + type: "number", + description: "The dividend", + }, + b: { + type: "number", + description: "The divisor", + }, + }, + required: ["a", "b"], +}; + +async function main() { + // Create a function tool from the sum function + const functionTool = new FunctionTool(sumNumbers, { + name: "sumNumbers", + description: "Use this function to sum two numbers", + parameters: sumJSON, + }); + + // Create a function tool from the divide function + const functionTool2 = new FunctionTool(divideNumbers, { + name: "divideNumbers", + description: "Use this function to divide two numbers", + parameters: divideJSON, + }); + + // Create an OpenAIAgent with the function tools + const agent = new ReActAgent({ + tools: [functionTool, functionTool2], + verbose: true, + }); + + const task = agent.createTask("Divide 16 by 2 then add 20"); + + let count = 0; + + while (true) { + const stepOutput = await agent.runStep(task.taskId); + + console.log(`Runnning step ${count++}`); + console.log(`======== OUTPUT ==========`); + console.log(stepOutput.output); + console.log(`==========================`); + + if (stepOutput.isLast) { + const finalResponse = await agent.finalizeResponse( + task.taskId, + stepOutput, + ); + console.log({ finalResponse }); + break; + } + } +} + +main().then(() => { + console.log("Done"); +}); diff --git a/packages/core/src/agent/runner/base.ts b/packages/core/src/agent/runner/base.ts index 80dfd2f71..532390e0d 100644 --- a/packages/core/src/agent/runner/base.ts +++ b/packages/core/src/agent/runner/base.ts @@ -14,7 +14,7 @@ import { AgentState, BaseAgentRunner, TaskState } from "./types.js"; const validateStepFromArgs = ( taskId: string, - input: string, + input?: string | null, step?: any, kwargs?: any, ): TaskStep | undefined => { @@ -24,6 +24,7 @@ const validateStepFromArgs = ( } return step; } else { + if (!input) return; return new TaskStep(taskId, step, input, kwargs); } }; @@ -194,7 +195,7 @@ export class AgentRunner extends BaseAgentRunner { */ async runStep( taskId: string, - input: string, + input?: string | null, step?: TaskStep, kwargs: any = {}, ): Promise<TaskStepOutput> { diff --git a/packages/core/src/agent/types.ts b/packages/core/src/agent/types.ts index f861a8488..8adc96340 100644 --- a/packages/core/src/agent/types.ts +++ b/packages/core/src/agent/types.ts @@ -161,13 +161,13 @@ export class TaskStep implements ITaskStep { * @param isLast: isLast */ export class TaskStepOutput { - output: unknown; + output: any; taskStep: TaskStep; nextSteps: TaskStep[]; isLast: boolean; constructor( - output: unknown, + output: any, taskStep: TaskStep, nextSteps: TaskStep[], isLast: boolean = false, diff --git a/packages/core/src/llm/LLM.ts b/packages/core/src/llm/LLM.ts index 317fcc1a3..4db929e79 100644 --- a/packages/core/src/llm/LLM.ts +++ b/packages/core/src/llm/LLM.ts @@ -260,7 +260,7 @@ export class OpenAI extends BaseLLM { stream: false, }); - const content = response.choices[0].message?.content ?? ""; + const content = response.choices[0].message?.content ?? null; const kwargsOutput: Record<string, any> = {}; -- GitLab