202 lines
4.8 KiB
TypeScript
202 lines
4.8 KiB
TypeScript
/**
|
|
* AG-UI 工具调用示例
|
|
*
|
|
* 展示 Agent 如何调用工具并流式传输参数和结果
|
|
*
|
|
* 参考文档: modules/events.md (行 938-1066)
|
|
*
|
|
* 事件流:
|
|
* 1. ToolCallStart - 工具调用开始
|
|
* 2. ToolCallArgs (多次) - 流式传输参数
|
|
* 3. ToolCallEnd - 参数传输完成
|
|
* 4. ToolCallResult - 工具执行结果
|
|
*/
|
|
|
|
import {
|
|
AbstractAgent,
|
|
RunAgent,
|
|
RunAgentInput,
|
|
EventType,
|
|
BaseEvent,
|
|
} from "@ag-ui/client"
|
|
import { Observable } from "rxjs"
|
|
|
|
/**
|
|
* 工具定义示例
|
|
*/
|
|
interface Tool {
|
|
name: string
|
|
description: string
|
|
parameters: Record<string, unknown>
|
|
}
|
|
|
|
const weatherTool: Tool = {
|
|
name: "get_weather",
|
|
description: "Get current weather for a location",
|
|
parameters: {
|
|
type: "object",
|
|
properties: {
|
|
location: {
|
|
type: "string",
|
|
description: "City name",
|
|
},
|
|
unit: {
|
|
type: "string",
|
|
enum: ["celsius", "fahrenheit"],
|
|
},
|
|
},
|
|
required: ["location"],
|
|
},
|
|
}
|
|
|
|
class ToolCallingAgent extends AbstractAgent {
|
|
run(input: RunAgentInput): RunAgent {
|
|
const { threadId, runId } = input
|
|
|
|
return () =>
|
|
new Observable<BaseEvent>((observer) => {
|
|
observer.next({
|
|
type: EventType.RUN_STARTED,
|
|
threadId,
|
|
runId,
|
|
})
|
|
|
|
// 模拟 Agent 分析用户请求后决定调用工具
|
|
const toolCallId = `tool_${Date.now()}`
|
|
const messageId = `msg_${Date.now()}`
|
|
|
|
// 1. 发送文本消息说明
|
|
observer.next({
|
|
type: EventType.TEXT_MESSAGE_START,
|
|
messageId,
|
|
role: "assistant",
|
|
})
|
|
|
|
observer.next({
|
|
type: EventType.TEXT_MESSAGE_CONTENT,
|
|
messageId,
|
|
delta: "Let me check the weather for you.",
|
|
})
|
|
|
|
observer.next({
|
|
type: EventType.TEXT_MESSAGE_END,
|
|
messageId,
|
|
})
|
|
|
|
// 2. 开始工具调用
|
|
observer.next({
|
|
type: EventType.TOOL_CALL_START,
|
|
toolCallId,
|
|
toolCallName: "get_weather",
|
|
parentMessageId: messageId,
|
|
})
|
|
|
|
// 3. 流式传输参数(分块发送)
|
|
observer.next({
|
|
type: EventType.TOOL_CALL_ARGS,
|
|
toolCallId,
|
|
delta: '{"loc', // 参数片段 1
|
|
})
|
|
|
|
observer.next({
|
|
type: EventType.TOOL_CALL_ARGS,
|
|
toolCallId,
|
|
delta: 'ation":', // 参数片段 2
|
|
})
|
|
|
|
observer.next({
|
|
type: EventType.TOOL_CALL_ARGS,
|
|
toolCallId,
|
|
delta: ' "San Francisco"}', // 参数片段 3
|
|
})
|
|
|
|
// 4. 参数传输完成
|
|
observer.next({
|
|
type: EventType.TOOL_CALL_END,
|
|
toolCallId,
|
|
})
|
|
|
|
// 5. 工具执行结果(模拟)
|
|
setTimeout(() => {
|
|
observer.next({
|
|
type: EventType.TOOL_CALL_RESULT,
|
|
toolCallId,
|
|
content: JSON.stringify({
|
|
location: "San Francisco",
|
|
temperature: "18°C",
|
|
condition: "Partly cloudy",
|
|
}),
|
|
})
|
|
|
|
// 6. 基于工具结果的响应
|
|
const responseMsgId = `msg_${Date.now()}_response`
|
|
observer.next({
|
|
type: EventType.TEXT_MESSAGE_START,
|
|
messageId: responseMsgId,
|
|
role: "assistant",
|
|
})
|
|
|
|
observer.next({
|
|
type: EventType.TEXT_MESSAGE_CONTENT,
|
|
messageId: responseMsgId,
|
|
delta: "The current weather in San Francisco is 18°C and partly cloudy.",
|
|
})
|
|
|
|
observer.next({
|
|
type: EventType.TEXT_MESSAGE_END,
|
|
messageId: responseMsgId,
|
|
})
|
|
|
|
observer.next({
|
|
type: EventType.RUN_FINISHED,
|
|
threadId,
|
|
runId,
|
|
})
|
|
|
|
observer.complete()
|
|
}, 1000)
|
|
})
|
|
}
|
|
}
|
|
|
|
// 使用示例
|
|
const agent = new ToolCallingAgent()
|
|
|
|
agent
|
|
.runAgent({
|
|
runId: "run_tool_example",
|
|
threadId: "thread_123",
|
|
messages: [
|
|
{
|
|
id: "user_1",
|
|
role: "user",
|
|
content: "What's the weather in San Francisco?",
|
|
},
|
|
],
|
|
tools: [weatherTool as any],
|
|
context: [],
|
|
})
|
|
.subscribe({
|
|
next: (event) => {
|
|
switch (event.type) {
|
|
case EventType.TOOL_CALL_START:
|
|
console.log(`[Tool Call] Starting: ${(event as any).toolCallName}`)
|
|
break
|
|
case EventType.TOOL_CALL_ARGS:
|
|
process.stdout.write((event as any).delta)
|
|
break
|
|
case EventType.TOOL_CALL_END:
|
|
console.log("\n[Tool Call] Arguments complete")
|
|
break
|
|
case EventType.TOOL_CALL_RESULT:
|
|
console.log("[Tool Result]", (event as any).content)
|
|
break
|
|
default:
|
|
console.log(`[${event.type}]`)
|
|
}
|
|
},
|
|
complete: () => console.log("Tool call flow completed"),
|
|
})
|
|
|
|
export { ToolCallingAgent, weatherTool }
|