目录

一、ReAct 是什么?AI Agent 的核心灵魂

二、为什么必须用 ReAct?大模型的天然短板

三、ReAct 的核心闭环机制

四、两代实现方案的架构对比

1. 古法 ReAct:Prompt 工程 + 字符串解析

实现逻辑

架构缺点

2. 现代 ReAct:Function Call 原生支持

实现逻辑

架构优势

五、企业级 ReAct Agent 系统架构设计

1. 交互层:用户入口

2. 推理调度层:ReAct 核心大脑

3. 工具层:能力执行单元

4. 数据层:日志与沉淀

六、关键设计与参数调优建议

1. 循环控制参数

2. Prompt 设计要点

3. 工具设计规范

4. 容错与降级参数

七、代码实战示例

示例 1:古法 ReAct 极简实现(Python)

示例 2:现代 ReAct(OpenAI Function Call 实现)

八、效果评测与优化方法

1. 核心评测指标

2. 常见问题与优化方向

3. 评测数据集构建

九、总结


一、ReAct 是什么?AI Agent 的核心灵魂

ReAct = Reasoning(推理) + Acting(行动),是 AI Agent 领域最核心的设计模式之一,核心思想是让 AI 模仿人类解决问题的方式:边思考、边行动、边根据结果调整策略,通过「思考→行动→观察→再思考」的闭环循环,逐步完成复杂任务。

和纯对话大模型直接输出答案的模式不同,ReAct 模式下的 AI 不会一次性拍脑袋给出结果,而是像人解题一样:先分析要做什么,再调用工具获取信息或执行操作,看完结果再判断下一步,直到信息足够才输出最终答案。

举个最典型的例子:问「地球和火星的质量加起来是多少」

  • 纯大模型:靠训练数据硬答,数值可能不准,甚至算错加法

  • ReAct 模式的 AI:

    1. 思考:我需要先获取地球和火星的质量,再相加计算

    2. 行动:调用查询工具获取地球质量

    3. 观察:得到地球质量 5.972 × 10²⁴ kg

    4. 再思考:还需要火星质量,继续查询

    5. 行动:调用查询工具获取火星质量

    6. 观察:得到火星质量 6.42 × 10²³ kg

    7. 再思考:现在两个数值都有了,调用计算器求和

    8. 行动:调用计算器计算总和

    9. 观察:得到结果 6.614 × 10²⁴ kg

    10. 结束:输出最终答案

整个过程和人类解决陌生问题的逻辑完全一致,这也是 ReAct 能支撑复杂智能体的核心原因。

二、为什么必须用 ReAct?大模型的天然短板

纯大模型天生存在三个无法彻底解决的短板,而 ReAct 正是针对性的解决方案:

  1. 知识有边界:大模型的训练数据有截止日期,也不可能覆盖所有私有数据、实时信息(比如实时天气、企业内部数据)

  2. 不擅长精确计算与操作:大模型本质是「预测下一个词」,做数学计算、代码执行、API 调用这类精确任务容易出错

  3. 幻觉问题:遇到不确定的内容,大模型容易编造看似合理的错误信息

ReAct 通过引入外部工具,把「闭卷答题」变成了「开卷考试 + 动手操作」,从机制上大幅降低幻觉,同时扩展了 AI 的能力边界 ——AI 不再只能聊天,而是可以真正执行任务。

三、ReAct 的核心闭环机制

标准的 ReAct 循环包含四个核心环节,循环执行直到任务完成:

表格

环节 英文标识 核心作用 示例
思考 Thought 分析当前问题,拆解子任务,决定下一步行动 "要计算总质量,我需要先查地球的质量"
行动 Action 调用指定工具,传入对应参数 调用「星球质量查询」工具,参数为 "地球"
观察 Observation 获取工具执行的返回结果,作为下一轮思考的依据 工具返回:地球质量为 5.972 × 10²⁴ kg
决策 循环 / 结束 判断信息是否充足:充足则输出最终答案,不足则进入下一轮循环 "还缺少火星质量,继续查询"

这个循环的核心价值是分步拆解、逐步验证:复杂任务被拆成一个个单步动作,每一步都有明确的输入输出,出错可以精准定位。

四、两代实现方案的架构对比

ReAct 的核心思想从未改变,但实现方式经历了从「古法手搓」到「标准化原生支持」的演进,可靠性和开发效率提升了一个量级。

1. 古法 ReAct:Prompt 工程 + 字符串解析

这是最早的实现方式,完全靠 Prompt 约束 AI 的输出格式,再用代码解析字符串来调用工具。

实现逻辑
  1. Prompt 约束:在系统提示词里严格规定输出格式,要求 AI 必须按照 Thought → Action → PAUSE 的固定格式回复

  2. 字符串解析:代码用正则表达式匹配 AI 的输出,提取工具名和参数

  3. 工具执行:调用对应工具,把结果包装成 Observation 塞回对话上下文

  4. 循环执行:重复上述过程,直到 AI 输出 Answer 标识

架构缺点
  • 格式脆弱:AI 输出格式稍有偏差(多空格、换标点),正则就匹配失败

  • 复杂参数难处理:嵌套 JSON、多参数的工具,用字符串描述和解析极易出错

  • 维护成本高:每个项目都要自己设计格式、写解析逻辑、处理各种异常

  • 错误处理繁琐:工具不存在、参数错误等问题都要手动写异常捕获和重试逻辑

2. 现代 ReAct:Function Call 原生支持

大模型厂商针对上述痛点,推出了 Function Call(函数调用) 特性,把工具定义和调用格式做了标准化,这也是目前工业界的主流方案。

实现逻辑
  1. 标准化工具定义:用 JSON Schema 格式定义工具的名称、功能描述、参数类型与约束

  2. 结构化调用:AI 不再输出自然语言字符串,而是直接返回结构化的 JSON 调用指令

  3. 框架级解析:大模型服务端 / 开发框架原生支持解析调用指令,无需手写正则

  4. 结果回传:工具执行结果按标准格式回传,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. 常见问题与优化方向

  1. 工具选错 / 参数错:优化工具描述和参数描述,减少歧义;减少单次提供的工具数量,按场景分发工具

  2. 死循环 / 重复调用:增加最大步数限制;在 Prompt 中要求避免重复无效调用;检测重复调用时主动打断

  3. 幻觉问题:强化「基于工具结果回答」的 Prompt 约束;增加答案置信度校验,无依据的内容强制过滤

  4. 上下文溢出:精简工具返回结果;对长对话做摘要压缩;控制最大循环次数

3. 评测数据集构建

  • 覆盖三类任务:单工具简单任务、多工具串联任务、无对应工具的边界任务

  • 标注标准答案和预期工具调用路径,用于自动化对比评测

  • 每次调整 Prompt、工具定义、参数后,回归跑一遍评测集,避免效果倒退

九、总结

ReAct 是 AI 从「聊天机器人」进化为「智能执行者」的核心技术,它通过「思考 - 行动 - 观察」的闭环,让 AI 具备了调用工具、解决复杂任务的能力。

从实现上,古法手搓版适合理解原理,现代 Function Call 版适合生产落地。落地时建议从少量工具、单一场景切入,先跑通核心循环,再通过评测持续优化 Prompt、工具设计和参数,逐步扩展能力边界。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐