Skip to content

Commit

Permalink
fix: streaming for ReAct Agent (#798)
Browse files Browse the repository at this point in the history
  • Loading branch information
himself65 authored May 2, 2024
1 parent 1dce275 commit ee719a1
Show file tree
Hide file tree
Showing 9 changed files with 11,964 additions and 8,334 deletions.
5 changes: 5 additions & 0 deletions .changeset/yellow-pigs-reply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"llamaindex": patch
---

fix: streaming for ReAct Agent
62 changes: 7 additions & 55 deletions examples/agent/openai-task.ts
Original file line number Diff line number Diff line change
@@ -1,63 +1,15 @@
import { ChatResponseChunk, FunctionTool, OpenAIAgent } from "llamaindex";
import { ChatResponseChunk, OpenAIAgent } from "llamaindex";
import { ReadableStream } from "node:stream/web";

const functionTool = FunctionTool.from(
() => {
console.log("Getting user id...");
return crypto.randomUUID();
},
{
name: "get_user_id",
description: "Get a random user id",
},
);

const functionTool2 = FunctionTool.from(
({ userId }: { userId: string }) => {
console.log("Getting user info...", userId);
return `Name: Alex; Address: 1234 Main St, CA; User ID: ${userId}`;
},
{
name: "get_user_info",
description: "Get user info",
parameters: {
type: "object",
properties: {
userId: {
type: "string",
description: "The user id",
},
},
required: ["userId"],
},
},
);

const functionTool3 = FunctionTool.from(
({ address }: { address: string }) => {
console.log("Getting weather...", address);
return `${address} is in a sunny location!`;
},
{
name: "get_weather",
description: "Get the current weather for a location",
parameters: {
type: "object",
properties: {
address: {
type: "string",
description: "The address",
},
},
required: ["address"],
},
},
);
import {
getCurrentIDTool,
getUserInfoTool,
getWeatherTool,
} from "./utils/tools";

async function main() {
// Create an OpenAIAgent with the function tools
const agent = new OpenAIAgent({
tools: [functionTool, functionTool2, functionTool3],
tools: [getCurrentIDTool, getUserInfoTool, getWeatherTool],
});

const task = await agent.createTask(
Expand Down
40 changes: 40 additions & 0 deletions examples/agent/react-task.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { ChatResponseChunk, ReActAgent } from "llamaindex";
import { ReadableStream } from "node:stream/web";
import {
getCurrentIDTool,
getUserInfoTool,
getWeatherTool,
} from "./utils/tools";

async function main() {
// Create an OpenAIAgent with the function tools
const agent = new ReActAgent({
tools: [getCurrentIDTool, getUserInfoTool, getWeatherTool],
});

const task = await agent.createTask(
"What is my current address weather based on my profile?",
true,
);

for await (const stepOutput of task) {
const stream = stepOutput.output as ReadableStream<ChatResponseChunk>;
if (stepOutput.isLast) {
for await (const chunk of stream) {
process.stdout.write(chunk.delta);
}
process.stdout.write("\n");
} else {
// handing function call
console.log("handling function call...");
for await (const chunk of stream) {
console.log("debug:", JSON.stringify(chunk.raw));
}
}
console.log("---");
}
}

void main().then(() => {
console.log("Done");
});
54 changes: 54 additions & 0 deletions examples/agent/utils/tools.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { FunctionTool } from "llamaindex";

export const getCurrentIDTool = FunctionTool.from(
() => {
console.log("Getting user id...");
return crypto.randomUUID();
},
{
name: "get_user_id",
description: "Get a random user id",
},
);

export const getUserInfoTool = FunctionTool.from(
({ userId }: { userId: string }) => {
console.log("Getting user info...", userId);
return `Name: Alex; Address: 1234 Main St, CA; User ID: ${userId}`;
},
{
name: "get_user_info",
description: "Get user info",
parameters: {
type: "object",
properties: {
userId: {
type: "string",
description: "The user id",
},
},
required: ["userId"],
},
},
);

export const getWeatherTool = FunctionTool.from(
({ address }: { address: string }) => {
console.log("Getting weather...", address);
return `${address} is in a sunny location!`;
},
{
name: "get_weather",
description: "Get the current weather for a location",
parameters: {
type: "object",
properties: {
address: {
type: "string",
description: "The address",
},
},
required: ["address"],
},
},
);
20 changes: 20 additions & 0 deletions packages/core/e2e/node/react.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,23 @@ await test("react agent", async (t) => {
ok(extractText(response.message.content).includes("72"));
});
});

await test("react agent stream", async (t) => {
await mockLLMEvent(t, "react-agent-stream");
await t.test("get weather", async () => {
const agent = new ReActAgent({
tools: [getWeatherTool],
});

const stream = await agent.chat({
stream: true,
message: "What is the weather like in San Francisco?",
});

let content = "";
for await (const { response } of stream) {
content += response.delta;
}
ok(content.includes("72"));
});
});
Loading

0 comments on commit ee719a1

Please sign in to comment.