完整版:ReAct Agent 从入门到落地:原理、架构、代码实现与评测全指南
目录
2. 现代 ReAct:Function Call 原生支持
示例 2:现代 ReAct(OpenAI Function Call 实现)
一、ReAct 是什么?AI Agent 的核心灵魂
ReAct = Reasoning(推理) + Acting(行动),是 AI Agent 领域最核心的设计模式之一,核心思想是让 AI 模仿人类解决问题的方式:边思考、边行动、边根据结果调整策略,通过「思考→行动→观察→再思考」的闭环循环,逐步完成复杂任务。
和纯对话大模型直接输出答案的模式不同,ReAct 模式下的 AI 不会一次性拍脑袋给出结果,而是像人解题一样:先分析要做什么,再调用工具获取信息或执行操作,看完结果再判断下一步,直到信息足够才输出最终答案。
举个最典型的例子:问「地球和火星的质量加起来是多少」
-
纯大模型:靠训练数据硬答,数值可能不准,甚至算错加法
-
ReAct 模式的 AI:
-
思考:我需要先获取地球和火星的质量,再相加计算
-
行动:调用查询工具获取地球质量
-
观察:得到地球质量 5.972 × 10²⁴ kg
-
再思考:还需要火星质量,继续查询
-
行动:调用查询工具获取火星质量
-
观察:得到火星质量 6.42 × 10²³ kg
-
再思考:现在两个数值都有了,调用计算器求和
-
行动:调用计算器计算总和
-
观察:得到结果 6.614 × 10²⁴ kg
-
结束:输出最终答案
-
整个过程和人类解决陌生问题的逻辑完全一致,这也是 ReAct 能支撑复杂智能体的核心原因。
二、为什么必须用 ReAct?大模型的天然短板
纯大模型天生存在三个无法彻底解决的短板,而 ReAct 正是针对性的解决方案:
-
知识有边界:大模型的训练数据有截止日期,也不可能覆盖所有私有数据、实时信息(比如实时天气、企业内部数据)
-
不擅长精确计算与操作:大模型本质是「预测下一个词」,做数学计算、代码执行、API 调用这类精确任务容易出错
-
幻觉问题:遇到不确定的内容,大模型容易编造看似合理的错误信息
ReAct 通过引入外部工具,把「闭卷答题」变成了「开卷考试 + 动手操作」,从机制上大幅降低幻觉,同时扩展了 AI 的能力边界 ——AI 不再只能聊天,而是可以真正执行任务。
三、ReAct 的核心闭环机制
标准的 ReAct 循环包含四个核心环节,循环执行直到任务完成:
表格
| 环节 | 英文标识 | 核心作用 | 示例 |
|---|---|---|---|
| 思考 | Thought | 分析当前问题,拆解子任务,决定下一步行动 | "要计算总质量,我需要先查地球的质量" |
| 行动 | Action | 调用指定工具,传入对应参数 | 调用「星球质量查询」工具,参数为 "地球" |
| 观察 | Observation | 获取工具执行的返回结果,作为下一轮思考的依据 | 工具返回:地球质量为 5.972 × 10²⁴ kg |
| 决策 | 循环 / 结束 | 判断信息是否充足:充足则输出最终答案,不足则进入下一轮循环 | "还缺少火星质量,继续查询" |
这个循环的核心价值是分步拆解、逐步验证:复杂任务被拆成一个个单步动作,每一步都有明确的输入输出,出错可以精准定位。
四、两代实现方案的架构对比
ReAct 的核心思想从未改变,但实现方式经历了从「古法手搓」到「标准化原生支持」的演进,可靠性和开发效率提升了一个量级。
1. 古法 ReAct:Prompt 工程 + 字符串解析
这是最早的实现方式,完全靠 Prompt 约束 AI 的输出格式,再用代码解析字符串来调用工具。
实现逻辑
-
Prompt 约束:在系统提示词里严格规定输出格式,要求 AI 必须按照
Thought → Action → PAUSE的固定格式回复 -
字符串解析:代码用正则表达式匹配 AI 的输出,提取工具名和参数
-
工具执行:调用对应工具,把结果包装成
Observation塞回对话上下文 -
循环执行:重复上述过程,直到 AI 输出
Answer标识
架构缺点
-
格式脆弱:AI 输出格式稍有偏差(多空格、换标点),正则就匹配失败
-
复杂参数难处理:嵌套 JSON、多参数的工具,用字符串描述和解析极易出错
-
维护成本高:每个项目都要自己设计格式、写解析逻辑、处理各种异常
-
错误处理繁琐:工具不存在、参数错误等问题都要手动写异常捕获和重试逻辑
2. 现代 ReAct:Function Call 原生支持
大模型厂商针对上述痛点,推出了 Function Call(函数调用) 特性,把工具定义和调用格式做了标准化,这也是目前工业界的主流方案。
实现逻辑
-
标准化工具定义:用 JSON Schema 格式定义工具的名称、功能描述、参数类型与约束
-
结构化调用:AI 不再输出自然语言字符串,而是直接返回结构化的 JSON 调用指令
-
框架级解析:大模型服务端 / 开发框架原生支持解析调用指令,无需手写正则
-
结果回传:工具执行结果按标准格式回传,AI 继续推理循环
架构优势
-
可靠性高:大模型针对性训练过 Function Call 能力,格式准确率远高于纯 Prompt 约束
-
开发效率高:框架原生封装了解析、重试、错误处理逻辑,无需重复造轮子
-
支持复杂参数:JSON 天然支持嵌套对象、数组等复杂参数类型,适配各类工具
-
生态完善:主流大模型和 Agent 框架(LangChain、LlamaIndex)全量支持
一句话总结两代方案的差异:核心思想没变,实现方式从「人工字符串约定」升级成了「机器可理解的标准化协议」。
五、企业级 ReAct Agent 系统架构设计
一套可落地的 ReAct 智能体系统,通常分为 4 层架构,各司其职,支持灵活扩展工具和场景:
1. 交互层:用户入口
-
负责接收用户请求,返回最终答案与执行过程
-
常见入口:对话网页、企业 IM(飞书 / 企微)、业务系统插件、API 接口
-
核心能力:流式输出、多轮会话管理、执行过程可视化(展示思考 / 工具调用过程)
2. 推理调度层:ReAct 核心大脑
-
对话上下文管理:维护会话历史、思考过程、工具调用记录,控制上下文窗口长度
-
推理引擎:调用大模型,基于当前上下文生成思考与工具调用指令
-
工具调度器:解析工具调用指令,校验参数合法性,分发到对应工具执行
-
循环控制器:控制最大循环次数,判断任务终止条件,防止死循环
-
异常处理器:工具调用失败、格式错误、超时时的重试与降级逻辑
3. 工具层:能力执行单元
-
工具注册中心:统一管理所有可用工具,包含工具元数据(名称、描述、参数定义)
-
基础工具集:
-
信息查询类:搜索引擎、向量知识库、数据库查询
-
计算执行类:计算器、代码解释器、Shell 执行
-
业务操作类:API 调用、工单创建、消息推送
-
-
工具执行器:负责实际调用工具,处理鉴权、超时、重试
4. 数据层:日志与沉淀
-
会话日志:记录完整的思考、调用、结果全流程,用于调试和复盘
-
效果数据:存储用户反馈、回答准确率、工具调用成功率等指标
-
知识沉淀:优质的工具调用与问答对,可反哺优化 Prompt 与知识库
六、关键设计与参数调优建议
ReAct Agent 的效果和稳定性,很大程度取决于参数和规则设计,以下是经过落地验证的通用建议:
1. 循环控制参数
-
最大循环次数(Max Steps):建议设置 5~10 次。次数太少解决不了复杂任务,太多容易死循环浪费 token
-
终止判断:除了 AI 主动输出答案,建议增加兜底终止:达到最大次数强制结束,给出「任务执行超时,请简化问题」的提示
2. Prompt 设计要点
-
角色与规则明确:清晰定义 Agent 的身份、能力边界、禁止行为
-
输出格式严格约束:古法 ReAct 必须明确格式标记(如 Thought: / Action: / Answer:);Function Call 模式则依赖工具定义的准确性
-
思考引导:提示 AI 先拆解问题再行动,信息不足时继续调用工具,不要强行回答
-
幻觉抑制:明确要求「仅基于工具返回结果回答,不确定的内容说明无法确认」
3. 工具设计规范
-
粒度适中:工具功能单一明确,避免一个工具做太多事。比如「查询星球质量」比「天文数据查询」效果更好
-
描述精准:工具和参数的描述要清晰无歧义,这直接决定 AI 会不会正确调用它
-
返回简洁:工具返回结果尽量精简,只保留核心信息,避免冗余内容挤占上下文窗口
-
数量控制:单次给 AI 的工具建议不超过 10 个,太多工具会干扰 AI 选择,降低调用准确率
4. 容错与降级参数
-
工具调用重试次数:建议 2~3 次,格式错误、调用失败时自动让 AI 重试
-
置信度判断:工具返回结果为空或不相关时,引导 AI 换工具或换参数重试
-
兜底方案:多次循环仍无法解决时,自动引导转人工或给出参考信息,避免错误回答
七、代码实战示例
示例 1:古法 ReAct 极简实现(Python)
核心是 while 循环 + 正则解析,适合理解底层原理:
python
运行
import re
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
# 系统提示词,严格规定输出格式
SYSTEM_PROMPT = """
你是一个会使用工具的AI助手,解决问题时请遵循以下格式:
Thought: 你的思考过程,分析下一步该做什么
Action: 工具名: 参数
PAUSE
如果信息足够回答用户问题,请直接输出:
Answer: 最终答案
可用工具:
- planet_mass: 查询星球质量,参数为星球名称
- calculator: 数学计算,参数为数学表达式
"""
# 模拟工具函数
def planet_mass(planet):
data = {"地球": "5.972e24 kg", "火星": "6.42e23 kg"}
return data.get(planet, "未找到该星球数据")
def calculator(expression):
try:
return str(eval(expression))
except:
return "计算错误"
tools = {
"planet_mass": planet_mass,
"calculator": calculator
}
# 解析 Action 的正则
action_pattern = re.compile(r"Action: (\w+): (.+)")
# ReAct 主循环
def react_agent(user_question):
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_question}
]
max_steps = 5
for _ in range(max_steps):
response = llm.invoke(messages).content
# 判断是否输出最终答案
if "Answer:" in response:
return response.split("Answer:")[-1].strip()
# 解析工具调用
match = action_pattern.search(response)
if not match:
return "AI输出格式错误,无法执行"
tool_name, tool_arg = match.groups()
if tool_name not in tools:
return f"不存在工具:{tool_name}"
# 执行工具,获取观察结果
obs = tools[tool_name](tool_arg.strip())
# 把思考、行动、观察加入上下文
messages.append({"role": "assistant", "content": response})
messages.append({"role": "user", "content": f"Observation: {obs}"})
return "已达到最大执行步数,未能完成任务"
# 测试
if __name__ == "__main__":
question = "地球和火星的质量加起来是多少?"
result = react_agent(question)
print("最终答案:", result)
示例 2:现代 ReAct(OpenAI Function Call 实现)
采用官方原生 Function Call,稳定性更高,是生产环境推荐方案:
python
运行
from openai import OpenAI
import json
client = OpenAI()
# 1. 用 JSON Schema 定义工具
tools = [
{
"type": "function",
"function": {
"name": "get_planet_mass",
"description": "查询指定星球的质量,单位为千克",
"parameters": {
"type": "object",
"properties": {
"planet_name": {
"type": "string",
"description": "星球的中文名称,如地球、火星"
}
},
"required": ["planet_name"]
}
}
},
{
"type": "function",
"function": {
"name": "calculate",
"description": "执行精确的数学计算",
"parameters": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "合法的Python数学表达式,如 5.972e24 + 6.42e23"
}
},
"required": ["expression"]
}
}
}
]
# 2. 实现工具函数
def get_planet_mass(planet_name):
data = {"地球": 5.972e24, "火星": 6.42e23}
return data.get(planet_name, None)
def calculate(expression):
try:
return eval(expression)
except:
return "error"
tool_map = {
"get_planet_mass": get_planet_mass,
"calculate": calculate
}
# 3. ReAct 主循环
def react_agent(question):
messages = [{"role": "user", "content": question}]
max_steps = 5
for _ in range(max_steps):
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=messages,
tools=tools,
temperature=0
)
message = response.choices[0].message
# 没有工具调用,说明要输出最终答案
if not message.tool_calls:
return message.content
# 处理工具调用
messages.append(message)
for tool_call in message.tool_calls:
func_name = tool_call.function.name
func_args = json.loads(tool_call.function.arguments)
# 执行工具
result = tool_map[func_name](**func_args)
# 回传工具结果
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"name": func_name,
"content": str(result)
})
return "执行步数超限,未能完成任务"
# 测试
if __name__ == "__main__":
print(react_agent("地球和火星的质量加起来是多少?"))
八、效果评测与优化方法
1. 核心评测指标
从「能力、稳定性、效率」三个维度量化评估:
表格
| 维度 | 指标 | 定义 | 合格参考 |
|---|---|---|---|
| 能力效果 | 任务完成率 | 成功解决目标问题的比例 | 简单任务≥90%,复杂任务≥70% |
| 能力效果 | 工具调用准确率 | 正确选择工具、传入正确参数的比例 | ≥85% |
| 能力效果 | 幻觉率 | 答案中出现编造内容的比例 | ≤5% |
| 稳定性 | 格式成功率 | 输出格式可被正确解析的比例 | Function Call 模式≥98% |
| 稳定性 | 异常率 | 工具调用失败、循环超时的比例 | ≤5% |
| 效率 | 平均调用步数 | 完成任务平均需要的循环次数 | 简单任务≤3 步 |
| 效率 | 平均响应时长 | 从提问到返回最终答案的时间 | 简单任务≤5 秒 |
2. 常见问题与优化方向
-
工具选错 / 参数错:优化工具描述和参数描述,减少歧义;减少单次提供的工具数量,按场景分发工具
-
死循环 / 重复调用:增加最大步数限制;在 Prompt 中要求避免重复无效调用;检测重复调用时主动打断
-
幻觉问题:强化「基于工具结果回答」的 Prompt 约束;增加答案置信度校验,无依据的内容强制过滤
-
上下文溢出:精简工具返回结果;对长对话做摘要压缩;控制最大循环次数
3. 评测数据集构建
-
覆盖三类任务:单工具简单任务、多工具串联任务、无对应工具的边界任务
-
标注标准答案和预期工具调用路径,用于自动化对比评测
-
每次调整 Prompt、工具定义、参数后,回归跑一遍评测集,避免效果倒退
九、总结
ReAct 是 AI 从「聊天机器人」进化为「智能执行者」的核心技术,它通过「思考 - 行动 - 观察」的闭环,让 AI 具备了调用工具、解决复杂任务的能力。
从实现上,古法手搓版适合理解原理,现代 Function Call 版适合生产落地。落地时建议从少量工具、单一场景切入,先跑通核心循环,再通过评测持续优化 Prompt、工具设计和参数,逐步扩展能力边界。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)