ReAct 范式解析

ReAct(Reasoning and Acting) 是一种让 AI 像人类一样"边想边做"的解题范式。它最早由 Google Research 在 2022 年提出,核心在于建立一个"思考→行动→观察"的闭环。与传统大模型容易"一本正经胡说八道"或缺乏实时信息不同,ReAct 允许模型在推理过程中主动调用外部工具并获取反馈,从而有效减少幻觉,让回答更靠谱、更及时。

一、ReAct 范式核心解析:Thought -> Action -> Observation 循环

ReAct 的核心在于 Thought → Action → Observation 的迭代循环,各阶段职责如下:

Thought(思考) :Agent 的内部推理过程,负责意图理解、任务拆解与行动规划。

示例: 面对"帮我查一下北京故宫博物院明天是否开放,并推荐一条3小时内的游览路线"这一提问,Agent 推理:"用户需要两个信息:明日开放状态和短时游览路线。我的训练数据不包含实时闭馆通知,需先查询官方公告;路线规划则需结合开放区域与游客动线数据,可能需要调用地图或旅游平台工具。"

Action(行动) :基于 Thought 的决策输出,通常表现为调用外部工具或执行特定操作。

示例: 依次调用故宫博物院官网 API 查询明日开放状态,再调用高德地图 POI 接口获取当前开放区域的步行导航数据与预计耗时。

Observation(观察) :Action 执行后返回的客观反馈,为下一轮 Thought 提供事实依据。

示例: 官网 API 返回"明日正常开放,8:30-17:00";地图接口返回"中轴线+珍宝馆路线总时长约2.5小时,当前无临时封闭区域"。Agent 据此整合信息,生成最终回复。

二、如何构造ReAct 示列:

1. 核心逻辑:定义循环协议

ReAct 的本质都是让 LLM 进入一个 While 循环。你需要明确定义三个要素:

Thought: 允许模型自由文本输出,用于推理和规划。

Action: 必须严格匹配预定义的工具签名(如 JSON 或特定语法)。

Observation: 由系统自动注入,而非模型生成。

⚠️ 关键原则: Observation 绝不能由 LLM 自己编造。它必须是外部工具执行后的真实返回值,否则 ReAct 就退化成了普通的 CoT(思维链),失去了"接地"的意义。

2. 实现路径:三种主流构造方式

A. 纯 Prompt 构造法(轻量级/原型验证)

直接在 System Prompt 中规定格式,适合快速验证或简单任务。

示列:

markdown 复制代码
你是一个遵循 ReAct 范式的智能助手。请严格按照以下格式回答问题,不要输出任何额外内容。

你可以使用以下工具:
- search_knowledge: 搜索内部知识库,参数为 {"query": "搜索关键词"}
- calculate: 执行数学计算,参数为 {"expression": "数学表达式"}
- get_order_status: 查询订单状态,参数为 {"order_id": "订单号"}

必须严格遵守以下输出格式:
问题:用户提出的原始问题
思考:分析用户需求,规划下一步行动,说明选择该工具的理由
行动:要调用的工具名称,必须是 [search_knowledge, calculate, get_order_status] 中的一个
行动输入:工具的参数,必须是合法的 JSON 格式
观察:工具返回的结果(由系统自动填充,你无需生成)
...(思考/行动/行动输入/观察 可重复多次)
思考:我已掌握足够信息,可以给出最终答案
最终答案:针对原始问题的完整回复

开始!
问题:{用户输入}
思考:

优点: 零代码依赖,任何支持长上下文的 LLM 均可尝试。

缺点: 解析不稳定,容易格式崩坏;无法处理复杂的多轮状态管理。

B. 框架辅助法(生产推荐)

使用 LangChain、LlamaIndex 或 Semantic Kernel 等成熟框架。它们封装了输出解析器和工具绑定机制。

LangChain 示例思路:

java 复制代码
from langchain.agents import create_react_agent, AgentExecutor
from langchain_core.prompts import ChatPromptTemplate

# 1. 定义工具
tools = [search_tool, calculator_tool]

# 2. 使用内置 ReAct Prompt 模板
prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a helpful assistant..."),
    ("placeholder", "{chat_history}"),
    ("human", "{input}"),
    ("placeholder", "{agent_scratchpad}"), # 自动填充历史 T-A-O 轨迹
])

# 3. 创建 Agent 并执行
agent = create_react_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
executor.invoke({"input": "你的问题"})

优点: 自动处理格式解析、错误重试、历史记录拼接;支持流式输出。

注意: 需关注 Token 消耗,agent_scratchpad 会随循环次数线性增长。

C. 微调法(高性能/小模型)

当通用大模型无法稳定遵循 ReAct 格式,或需要在端侧小模型上运行时,使用 ReAct 格式的 SFT 数据进行微调。

数据来源: Self-Instruct、Alpaca-CoT 或自行构建的领域工具调用数据集。

目标: 让模型将 Thought/Action/Observation 内化为原生生成模式,而非依赖冗长的 Prompt 指令。