Beyond Chatbots:ReAct 框架如何让 LLM 进化成真正的 Agent

AI ReAct Agent

前言

⚠️ 时间线说明: 这篇文章实际上是在《Agent 生产落地:从 demo 到产品的血泪经验》之前完成的,一直躺在草稿箱里忘了发。阅读顺序上,建议先看这篇理解 ReAct 原理,再看那篇的生产实践经验。

想象一下你现在要煮盆饺子。烧水、打料内心独白支配着每一个动作:”水开了,我该下饺子了。”当发现缺少关键调料,内心独白会调整策略:”没辣椒了?我用老干妈代替。”面对技术难点时,这个思维过程会触发外部行动:”我不确定需要煮多久,我需要打开美食APP查下。”

这种边想边做、边做边调整的能力,是人类解决问题的基本方式。但传统的大语言模型(LLM)完全没有这种能力——它们更像一个闭卷考试的学生,只能凭记忆一口气写到底,错了也没法改。

在人工智能领域,传统的大语言模型(LLM)一直像静态黑盒一样运作。虽然这些模型擅长语言模仿,但它们缺乏功能性的”工作记忆”和与世界动态交互的能力。这种隔离滋生了两种系统性失败:“幻觉循环”,即模型自信地编造事实;以及“错误传播”,即单一的逻辑失误会毁掉整个回答。

ReAct(Reason + Act)框架代表了 AI 架构的范式转变。 通过在孤立认知与外部执行之间搭建结构性桥梁,ReAct 将 LLM 从对话者转变为能够规划、执行和自我纠正的自主 Agent。

这篇是我学习 ReAct 的笔记,想把它讲清楚,也给自己留个档。


一、ReAct 到底在解决什么问题

传统的 AI 能力其实是分裂的。要么你用 Chain-of-Thought(CoT)让模型在脑子里一步步推理,要么你用 Action-generation 让模型调用外部工具——但两者各自有坑:

纯推理(CoT)的问题: 模型完全依赖内部参数知识,是个封闭系统。它没法查资料,没法更新自己的认知,结果就是自信满满地编事实(幻觉),而且一步错步步错(错误传播)。

纯行动(Act-only)的问题: 模型可以调用工具,但缺乏显式的长期规划能力。它没法跟踪子目标,也没法系统地探索环境,很容易陷入重复或无意义的操作。

ReAct 的做法是:把两者缝合起来。 推理痕迹帮助模型诱导、跟踪和更新行动计划,处理异常情况;而行动让模型能够对接外部信息源(Wikipedia API、浏览器、数据库)来获取实时信息。

核心机制:反馈循环

ReAct 把 Agent 的活动结构化成一个三段式交替序列:

1
Thought(思考)→ Action(行动)→ Observation(观察)→ Thought(再思考)...
  1. Thought: LLM 用思维链把大任务拆成可管理的小任务,分析数据,决定下一步做什么
  2. Action: 模型输出使用某个预定义工具的意图(比如搜索数据库)。注意:LLM 自己不执行工具,只输出工具名和参数
  3. Observation: 外部系统执行工具,把结果反馈给 LLM

Agent 基于这个观察重新评估进度,生成下一个 Thought。循环往复,直到输出最终答案。

这个循环看起来直白,但效果非常显著。在 HotpotQA 基准测试里,传统 CoT 的幻觉率(编瞎话的概率)是 14%,上了 ReAct 之后直接降到 6%[^1]。

关键洞察:ReAct 不是让模型"更聪明",而是给它一套"查资料→推理→再查资料"的机制,让它有机会认错和修正。

二、五个核心要点:为什么 ReAct 有效

要点 1:推理与行动的协同

ReAct 范式打破了传统上推理与执行的二分。其核心是形式化表达 Â = A ∪ L。在这个等式中,Agent 的行动空间从物理或程序步骤(A)扩展到包含内部的”语言空间”(L)。通过将”思考”视为模型轨迹中的另一种行动类型,ReAct 允许 Agent 生成口头推理痕迹——或称”想法”——与特定任务的动作交错进行。

这种协同使模型能够诱导、跟踪和更新计划,同时实时处理异常。正如 Yao 等人在其奠基性研究中所言:

"这种'行动'与'推理'之间的紧密协同使人类能够快速学习新任务,并在前所未有的情况下进行稳健的决策或推理。"

通过交错这些痕迹,模型使用推理来决定检索什么信息,而由此产生的观察又为后续推理提供基础。

要点 2:通过观察环节打破幻觉循环

传统的思维链(Chain-of-Thought, CoT)提示鼓励模型”一步步思考”,但它完全依赖模型的内部参数知识——一个容易”幻觉”不存在事实的封闭系统。ReAct 通过引入强制的 Observation(观察) 步骤来解决这个问题,将模型锚定在外部现实中。

在知识密集型任务中,ReAct 使用特定的动作词汇——包括 search[entity]lookup[string]finish[answer]——与 Wikipedia 等外部实体交互。这种迭代的 Thought-Action-Observation 循环迫使模型在继续之前根据真实知识库验证其逻辑。结果是统计学上显著的改进:在 HotpotQA 基准测试中,误报率(幻觉事实或逻辑的频率)从标准 CoT 的 14% 暴跌至 ReAct 框架下的 6%[^1]。这种锚定将 Agent 从创意作家转变为可信的调查者。

要点 3:代理技能的效率悖论

ReAct 扩展分析中最深刻的见解之一是:“代理技能”通常比原始模型大小更具参数效率。 我们在”小模型悖论”中看到了突破:教模型如何推理和行动,比强迫它在权重中记忆海量事实更具泛化能力。

数据揭示了一个惊人的层级关系:一个较小的 PaLM-8B 模型,仅在 3,000 条 ReAct 轨迹上微调,就能胜过完全依赖提示的巨大 PaLM-540B 模型。更令人印象深刻的是,微调的 62B 模型超过了 540B 提示版本的性能[^1]。这表明 AI 的未来不在于构建越来越大的记忆数据仓库,而在于提炼模型导航工具集和环境的程序能力。

模型 方式 表现
PaLM-540B Zero-shot 提示 基准线
PaLM-8B ReAct 微调(3,000 轨迹) 超越 540B
PaLM-62B ReAct 微调 大幅超越 540B

数据来源:Yao et al., ReAct: Synergizing Reasoning and Acting in Language Models[^1]

要点 4:可解释性:终于能看懂 AI 在想什么了

传统模型的黑盒问题一直让人头疼。输入一个问题,输出一个答案,中间发生了什么?不知道。

ReAct 的”草稿本(scratchpad)”机制解决了这个问题。每一轮循环的 Thought、Action、Observation 都被记录下来,形成一条完整的”思维链”。

如果出错了,你能精确定位到是哪一步出的问题:

  • 推理错误:模型陷入了重复循环,比如一直问同一个问题
  • 检索错误:外部 API 返回了不相关的信息
  • 行动错误:调用了错误的工具或参数

更有意思的是,这种透明性支持人在回路(Human-in-the-loop)的干预。这有点像你带新人:他在那自言自语分析问题,你说”这一步想偏了”,他马上就能纠正。

ReAct 通过其人类可读的”草稿本”,为 AI 的”黑盒”提供了一个罕见的窗口。Agent 过程的每一步都被记录为想法、行动和观察的序列,提供了以前不可能的诊断水平。

如果 Agent 失败,开发者可以精确定位确切的失败模式——比如模型陷入重复循环的”推理错误”,或外部 API 返回无信息结果的”搜索错误”。这种透明性还促进了“人在回路(Human-in-the-loop)”的纠正。在 ALFWorld 环境(一个基于文本的任务模拟器)中,研究人员证明,人类可以通过简单编辑草稿本上的”想法”来引导失败的 Agent 回到正轨——删除幻觉或添加提示——使 AI 能够立即重新校准其计划[^1]。

示例:ReAct 轨迹

1
2
3
4
5
Thought: 用户询问 2024 年诺贝尔物理学奖得主,我需要确认最新获奖信息。
Action: search[2024 Nobel Prize in Physics winner]
Observation: John J. Hopfield and Geoffrey Hinton were awarded...
Thought: 好的,我已获得准确信息,现在可以回答用户了。
Action: finish[约翰·霍普菲尔德和杰弗里·辛顿]

要点 5:复杂环境的动态规划

虽然标准 LLM 在多步骤任务上挣扎,但 ReAct 在 ALFWorld(合成家庭任务)和 WebShop(拥有 118 万产品的在线购物环境)等交互式环境中表现出色。与遵循 rigid 脚本的”仅行动(Act-only)”Agent 不同,ReAct Agent 利用动态推理将高级目标分解为可管理的子目标。

所以ReAct 的真正威力,在处理多步骤、需要探索的任务时才会显现出来。

ALFWorld 里有个典型任务:”把一个发烫的平底锅放到冷却架上”。这看起来简单,但模型需要:

  • 找到平底锅(可能在灶台上)
  • 判断它是不是”发烫”的状态
  • 找到冷却架(可能在橱柜里)
  • 规划一条合理的移动路径

传统”只行动不思考”的 Agent(Act-only)在这种任务上成功率只有 45%,而 ReAct 能达到 71%[^1]。

ReAct 利用预训练的”常识知识”——例如,知道胡椒罐更可能在橱柜里而不是冰箱里——以手术般的效率探索环境。通过维护其进度的内部记录,ReAct Agent 避免了困扰纯反应式系统的无产出循环。


三、如何构建一个 ReAct Agent

你可以用 LangChain、LangGraph 或 BeeAI 等开源框架快速搭建(比如 LangChain 的 ZERO_SHOT_REACT_DESCRIPTION),也可以从零用纯 Python 手写。下面是手写版本的逻辑拆解:

步骤 1:定义工具集

首先确定模型能用的具体行动。写 Python 函数(计算器、搜索等),然后把它们的签名和描述提取成 LLM 能理解的格式(JSON 或字符串)。

1
2
3
4
5
6
7
8
9
10
11
# 示例工具定义
tools = {
"search": {
"description": "搜索 Wikipedia 获取实体信息",
"parameters": {"entity": "要搜索的关键词"}
},
"calculator": {
"description": "执行数学计算",
"parameters": {"expression": "数学表达式"}
}
}

步骤 2:编写 ReAct 提示词

ReAct Agent 极度依赖特定的提示技巧来结构化输出。系统提示必须:

  • 引导模型一步步思考,交错想法和行动
  • 提供可用工具列表
  • 定义严格的输出格式,通常用标签如 Thought:Action:Action Input:Observation:

提示词模板示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
你是一个能够使用工具的 AI 助手。按以下格式解决问题:

Thought: 分析当前情况,决定下一步行动
Action: 要使用的工具名称(从 [{tool_names}] 中选择)
Action Input: 传递给工具的参数
Observation: 工具执行结果
...(重复 Thought/Action/Observation 直到得出结论)
Thought: 我现在知道最终答案了
Final Answer: 用户的最终答案

可用工具:
{tools}

开始:
Question: {input}

步骤 3:构建执行循环

把提示词和用户问题传给 LLM 后,你需要一个程序循环来处理执行:

  1. 解析输出: 拦截 LLM 的文本输出,提取 Action(工具名)和 Action Input(参数)
  2. 执行工具: 你的 Python 代码调用对应的函数
  3. 返回观察: 把函数结果格式化为 Observation,追加到对话历史
  4. 重复: 把更新后的上下文传回 LLM,让它基于新数据生成下一个 Thought
  5. 终止: 当 LLM 确定有最终答案并使用 “Finish” 动作或输出最终响应标签时,循环结束

伪代码示意:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
max_iterations = 10
history = prompt_template.format(input=user_question)

for i in range(max_iterations):
response = llm.generate(history)

# 解析 Thought/Action/Observation
thought = extract_thought(response)
action = extract_action(response)
action_input = extract_action_input(response)

if action == "Finish":
return action_input # 最终答案

# 执行工具
observation = execute_tool(action, action_input)

# 追加到历史
history += f"\nThought: {thought}\nAction: {action}\nAction Input: {action_input}\nObservation: {observation}"

四、生产环境的优化技巧

要让 ReAct Agent 稳定、高效地运行,避免常见陷阱,你需要以下优化:

1. 使用少样本示例(Few-Shot Exemplars)

虽然可以构建”零样本”ReAct Agent,但性能会在你加入人工编写的完整 Thought-Action-Observation 轨迹示例后显著提升。提供 3 到 6 个 高质量、任务特定的示例,能教会模型如何格式化想法、分解任务、处理不同工具。

技巧:示例要覆盖成功路径和典型的错误恢复场景,让模型学会"碰壁后怎么绕路"。

2. 与 Chain-of-Thought 和自一致性结合

研究表明,ReAct 高度依赖搜索结果质量;如果工具返回无用数据,模型的推理会跑偏。反过来,标准 CoT 受困于幻觉。

最佳实践是构建混合系统:

  • 如果 ReAct Agent 在给定步数内无法返回答案,回退到内部 CoT 推理(使用 Self-Consistency,即采样多条 CoT 路径并取多数答案)
  • 如果 CoT-SC 置信度低,切换到 ReAct 收集外部事实

这种”双保险”策略在知识密集型任务上效果最好。

3. 设置严格的循环限制

因为框架本质上是反馈循环,ReAct Agent 有时会陷入重复生成相同想法和行动的困境,导致高延迟和 token 成本爆炸。你必须在代码中设置最大迭代次数或特定结束条件(如置信度阈值)来防止无限循环。

1
2
3
4
5
6
7
8
9
10
11
# 示例:多层防护
MAX_ITERATIONS = 10
MAX_COST = 0.5 # 美元
seen_actions = set()

for step in range(MAX_ITERATIONS):
action_signature = (action_name, action_input)
if action_signature in seen_actions:
# 检测到循环,触发终止或切换策略
break
seen_actions.add(action_signature)

4. 微调实现可扩展性

纯粹从上下文提示中学习复杂推理和行动是困难的,尤其是对较小语言模型。然而,在几千条正确的 ReAct 轨迹上微调较小模型(如 8B 参数模型),能让它们大幅超越仅依赖标准提示的更大模型(如 PaLM-540B)。

工程建议:

  • 收集生产环境中的高质量轨迹作为微调数据
  • 使用 LoRA 等高效微调技术降低计算成本
  • 小模型+ReAct 往往比大模型裸跑更省算力、更可控

5. 实现人在回路(Human-in-the-Loop)纠正

因为 ReAct 生成可读的、 verbalized 的推理痕迹,系统具有高度可解释性。你可以设计 Agent 允许人类检查其内心独白。如果模型产生了幻觉想法或走错了路,人类可以直接编辑生成的 Thought 文本。这能纠正模型的后续行为,引导它成功,无需重写代码或手动执行动作。

典型应用场景:

  • 客服 Agent 遇到边界案例时,人工客服介入修正推理方向
  • 代码生成 Agent 逻辑走偏时,程序员编辑 Thought 引导它回到正轨
  • 研究 Agent 检索到无关信息时,研究员删除幻觉并提供正确线索

五、写在最后

ReAct 给我的最大启发,不是技术细节,而是一种设计哲学的转变。

以前我们总想造一个”什么都知道”的 AI——把人类知识全塞进模型参数里。ReAct 走的是另一条路:承认模型不可能全知,给它一套”查资料+推理”的机制,让它像人一样边做边学

当前 AI 的最先进水平并不依赖单一框架,而是协同的切换方法。最有能力的系统将 ReAct 与 CoT-自一致性结合,对逻辑任务利用内部参数知识,当内部置信度低时切换到 ReAct 进行外部锚定。

随着我们从对话式聊天机器人过渡到能够浏览网页、使用软件工具和管理工作流的自主 Agent,Thought-Action-Observation 循环正在成为安全和可靠性的行业标准。我们不再只是构建会说话的模型;我们正在构建为了行动而思考的 Agent。


参考

[1]: ReAct Prompting - Prompting Guide
[2]: What is a ReAct Agent? - IBM
[3]: ReAct Paper (PDF) - arXiv
[4]: ReAct: Synergizing Reasoning and Acting in Language Models