diff --git a/.changeset/four-ways-enjoy.md b/.changeset/four-ways-enjoy.md new file mode 100644 index 0000000000000000000000000000000000000000..fee00e66f98cdf349a334870e8b8d2fdc568d49d --- /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 0000000000000000000000000000000000000000..abbc273c5f634dd1d63769887c31a5d19c9a7804 --- /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 0000000000000000000000000000000000000000..d7a17295a54bb72c208bdce5a95aee5c6a158015 --- /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 0000000000000000000000000000000000000000..4230db586f9f33863771f4e89f0bca66fe48785b --- /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 80dfd2f7198217fbfd17487a5424b5e9b0b54d5c..532390e0df92496880a428b76b61e55f905bdbe7 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 f861a84884b27e130f8cd6dc78b4df0faba225bb..8adc96340db5bb7f89e0d041bc64f388aa88d530 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 317fcc1a34be4dc77b2d0a5b4354825d5ac88809..4db929e79904e3a50b80ecf4d1a405ee21b80761 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> = {};