从零构建 AI Agent:深入理解 ReAct 模式与工具调用机制
背景
2023 年被称为 AI Agent 元年。从 AutoGPT 的爆火到 LangChain 的兴起,再到各大厂纷纷推出 Agent 平台,AI Agent 已经从实验室走向生产环境。但很多人对 Agent 的理解还停留在"对话机器人"的层面,不清楚它究竟是如何实现自主决策和工具调用的。
本文将深入剖析 AI Agent 的核心机制——ReAct(Reasoning + Acting)模式,并手把手教你从零构建一个具备工具调用能力的 Agent。
核心概念
什么是 ReAct 模式?
ReAct 是一种让大模型"边思考边行动"的范式。它的核心思想非常简单:
思考(Reasoning)→ 行动(Acting)→ 观察(Observation)→ 循环
传统的对话模型是"一次性回答",而 ReAct 模式让模型能够:
- 思考:分析当前任务,决定下一步该做什么
- 行动:调用外部工具获取信息或执行操作
- 观察:获取工具返回的结果
- 循环:基于观察结果继续思考,直到任务完成
工具调用的本质
工具调用的本质是让大模型输出结构化的 JSON 指令,然后由外部系统解析执行。以 OpenAI 的 Function Calling 为例:
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市的天气信息",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称"
}
},
"required": ["city"]
}
}
}
]
response = client.chat.completions.create(
model="gpt-4",
messages=messages,
tools=tools,
tool_choice="auto"
)
当模型决定调用工具时,它会返回一个 tool_calls 字段,包含函数名和参数。你的代码负责执行这个函数,并将结果返回给模型继续对话。
实战案例:构建一个天气查询 Agent
让我们从零构建一个能够查询天气的 Agent,完整展示 ReAct 模式的工作流程。
Step 1:定义工具
const tools = [
{
name: "get_weather",
description: "获取指定城市的实时天气信息",
parameters: {
type: "object",
properties: {
city: {
type: "string",
description: "城市名称,如:北京、上海、深圳"
}
},
required: ["city"]
},
execute: async (params) => {
const response = await fetch(
`https://api.weather.com/v1/current?city=${encodeURIComponent(params.city)}`
);
return await response.json();
}
},
{
name: "search_web",
description: "在网络上搜索信息",
parameters: {
type: "object",
properties: {
query: {
type: "string",
description: "搜索关键词"
}
},
required: ["query"]
},
execute: async (params) => {
const results = await searchAPI(params.query);
return results.slice(0, 5);
}
}
];
Step 2:实现 ReAct 循环
async function runAgent(userMessage) {
const messages = [
{
role: "system",
content: "你是一个智能助手,可以使用工具帮助用户完成任务。"
},
{ role: "user", content: userMessage }
];
let iteration = 0;
const maxIterations = 5;
while (iteration < maxIterations) {
iteration++;
const response = await callLLM(messages);
if (response.toolCalls && response.toolCalls.length > 0) {
for (const toolCall of response.toolCalls) {
const tool = tools.find(t => t.name === toolCall.function.name);
const result = await tool.execute(toolCall.function.arguments);
messages.push({
role: "tool",
content: JSON.stringify(result),
tool_call_id: toolCall.id
});
}
} else {
return response.content;
}
}
return "抱歉,我无法在有限步骤内完成任务。";
}
Step 3:运行示例
const answer = await runAgent("北京今天天气怎么样?适合户外运动吗?");
// Agent 执行流程:
// 1. Thought: 用户想知道北京天气,需要调用 get_weather 工具
// 2. Action: get_weather({city: "北京"})
// 3. Observation: {city:"北京",temperature:22,condition:"晴",humidity:45,wind:"微风"}
// 4. Thought: 已获取天气信息,可以回答用户问题
// 5. Final Answer: 北京今天天气晴朗,气温22度,非常适合户外运动!
最佳实践
1. 工具设计原则
- 单一职责:每个工具只做一件事,便于理解和调试
- 清晰描述:工具描述要准确,让模型知道何时使用
- 参数验证:执行前验证参数,避免无效调用
- 错误处理:工具返回错误信息时,让模型能理解并调整策略
2. 提示词工程
你是一个专业的助手。请严格遵循 ReAct 格式:
Thought: 思考当前状态和下一步行动
Action: 工具调用(JSON 格式)或 "None"
Observation: 工具返回结果(由系统填充)
注意:
- 不要编造信息,必须使用工具获取实时数据
- 如果工具调用失败,尝试其他方案
- 给用户明确、有帮助的回答
3. 迭代次数限制
设置合理的最大迭代次数(通常 5-10 次),防止 Agent 陷入无限循环。复杂任务可以适当增加。
4. 工具结果格式化
工具返回的结果应该清晰、结构化,便于模型理解:
{
"success": true,
"data": {},
"message": "查询成功"
}
常见问题
Q1:模型一直调用错误的工具怎么办?
检查工具描述是否清晰,参数说明是否准确。可以在 system prompt 中添加工具使用示例。
Q2:如何处理需要多个工具组合的场景?
在 ReAct 循环中,模型会自动判断是否需要继续调用工具。确保每个工具都有明确的输入输出格式。
Q3:Agent 执行时间太长怎么办?
- 优化工具执行效率
- 设置超时机制
- 对于复杂任务,考虑拆分成多个子任务
Q4:如何保证工具调用的安全性?
- 敏感操作需要用户确认
- 限制工具的权限范围
- 记录所有工具调用日志
- 对输出进行安全过滤
总结
AI Agent 的核心在于让大模型具备"思考-行动"的循环能力。ReAct 模式通过结构化的思维过程,让模型能够:
- 分解复杂任务
- 调用外部工具获取实时信息
- 根据反馈调整策略
- 最终给出可靠的答案
掌握 ReAct 模式和工具调用机制,是构建实用 AI Agent 的基础。无论是客服机器人、智能助手,还是自动化工作流,都离不开这套核心思想。
下一步,你可以尝试:
- 接入更多类型的工具(数据库、API、文件操作)
- 实现 Agent 记忆和持久化
- 构建多 Agent 协作系统
- 添加自我反思和优化机制
AI Agent 的世界才刚刚开始,期待你构建出更强大的应用!
评论区
登录 后参与评论