ReAct 这个名字本身点明了一切:Reasoning + Acting,推理加行动。它不是新发明一个算法,而是把两件原本分开的事——「想」和「做」——拧成一股绳,让它们在每一步里交替进行。这个交替的循环,就是 LLM Agent 的运转内核。
在 ReAct 之前,LLM 有两种典型的使用方式,各有明显短板:
LLM 只在内部推理(如 CoT),不调用任何工具。
用户: 美国第 47 任总统是谁? LLM (CoT): 让我想想...美国总统一任一任数...第 47 任应该是... (但训练截止后的事它不知道,只能猜) 最终: (可能是错的或编造的)
短板:信息受限——LLM 只能用训练时的知识,不知道当下、查不到外部数据。这就是第 1.1 节讲的「知识截止」。
LLM 直接调用工具,不展开推理。
用户: 我应该买哪只股票? LLM: 直接调用 stock_recommend() (但该买哪只本身需要推理,工具不会替你想)
短板:失去推理——把决策丢给工具,但工具只提供数据,不提供判断。LLM 的推理能力被浪费。
ReAct(Yao et al. 2022)的核心洞察:推理与行动应当交替进行,相互增强。
这就是 ReAct 的三元组:Thought-Action-Observation。
下面是一个经典的 ReAct 轨迹,任务是「苹果公司 2024 年营收是多少,比 2023 年增长多少?」
任务: 苹果公司 2024 年营收是多少,比 2023 年增长多少? [Thought 1] 我需要先查苹果 2024 年营收。 [Action 1] search("Apple revenue 2024 fiscal year") [Observation 1] Apple FY2024 total revenue: $391.0B [Thought 2] 拿到 2024 年了 ($391B)。现在需要 2023 年的对比。 [Action 2] search("Apple revenue 2023 fiscal year") [Observation 2] Apple FY2023 total revenue: $383.3B [Thought 3] 两年都有了。计算增长率: (391.0 - 383.3) / 383.3 = 7.7 / 383.3 ≈ 2.0% [Action 3] calculate("(391.0 - 383.3) / 383.3 * 100") [Observation 3] Result: 2.009% [Thought 4] 计算完成,信息齐全,可以回答了。 [Final Answer] 苹果 2024 财年营收约 3910 亿美元, 较 2023 年的 3833 亿美元增长约 2.0%。
注意这条轨迹的几个关键点:
| 观察 | 含义 |
|---|---|
| 每个 Thought 都明确「我接下来要干什么、为什么」 | 推理过程外显,可调试 |
| Action 是具体的工具调用(search/calculate) | 真实行动,获取外部信息 |
| Observation 把工具结果反馈回来 | 形成闭环 |
| 最后 Thought 判断「信息齐全」才给 Final Answer | 自主判断停止时机 |
💡 ReAct 的精妙:它把第 3 章的「思维链」与第 6 章的「工具调用」无缝融合。Thought 是 CoT 的展开,Action 是 Function Calling 的执行,Observation 是把行动结果接回推理。ReAct 不是新发明,而是把已有的两块积木拼成了完整系统。
逐个看 Thought、Action、Observation 各自的作用:
Thought 让 LLM 把内部推理写成显式文本。它的价值:
| 价值 | 说明 |
|---|---|
| 决定下一步 | 明确「接下来做什么、为什么」 |
| 错误可追溯 | 出错时能定位是哪步推理错了 |
| 人类可审核 | 推理过程可见,便于调试与监督 |
| 引导模型分配算力 | 与 CoT 同理,外显推理提升准确率 |
Action 是 ReAct 与纯 CoT 的根本区别——它真的去调用工具。
| Action 类型 | 例子 |
|---|---|
| 信息查询 | search(query)、get_stock(ticker) |
| 计算 | calculate(expression) |
| 数据操作 | sql_query(sql)、read_file(path) |
| 通信 | send_email(to, subj, body) |
| 求助 | request_human_help(reason) |
Observation 把工具执行结果反馈给 LLM。它的质量直接决定 ReAct 能否收敛。
| Observation 形态 | 例子 |
|---|---|
| 工具返回值 | Result: 391.0B |
| 错误信息 | Error: ticker not found |
| 执行状态 | Success / Failed |
| 环境状态 | 当前时间、用户身份等 |
⚠️ Observation 是 ReAct 的命脉。一个粗糙的 Observation(如把整个 JSON 原样塞回)会让 LLM 抓不住重点;一个精炼的 Observation(如
[search] 苹果 2024 营收: $391B)能让 LLM 高效决策。ReAct 的工程水平,很大程度上体现在 Observation 的格式化质量上——这一点第 2.4 节已讨论过。
ReAct 不是「想一次、做一次」就结束,而是一个循环——直到 LLM 自己判断「信息齐全」或触发停止条件。
| 判读 | 含义 |
|---|---|
| 何时停 | LLM 自主判断「信息齐全」+ 工程兜底(步数上限等) |
| 何时转 | Observation 后必然回到 Thought |
| 何时答 | Thought 判断「无需再调工具」时输出 Final Answer |
注意 ReAct 的「Final Answer」不是一个独立的 Action——它是 Thought 判断「信息已足够、无需再调工具」后的直接输出。LLM 必须学会「什么时候不调工具、直接回答」,否则会陷入「为调工具而调工具」的怪圈。
| 维度 | 纯推理 | 纯行动 | ReAct |
|---|---|---|---|
| 调工具 | 不调 | 调 | 调 |
| 推理展开 | 是(CoT) | 否 | 是 |
| 外部信息 | 无 | 有 | 有 |
| 错误恢复 | 弱 | 弱 | 强(观察反馈) |
| 可解释性 | 高 | 低 | 高 |
| 适用 | 闭卷推理 | 简单查询 | 复杂多步任务 |
💡 ReAct 的本质贡献:它让 LLM 的「推理能力」与「行动能力」形成正反馈——推理指导行动,行动反馈观察,观察又触发新的推理。这种「想-做-看-再想」的循环,正是人类解决问题的核心模式。ReAct 之所以成为 Agent 的灵魂范式,是因为它最贴近人类思维。
回到第 1.2 节的「感知-规划-行动-观察」核心循环,ReAct 与它一一对应:
| 核心循环 | ReAct 三元组 |
|---|---|
| 感知 | Observation(观察上一步结果) |
| 规划 | Thought(推理下一步) |
| 行动 | Action(调用工具) |
| 观察 | Observation(接收结果) |
可以说,ReAct 就是第 1 章核心循环的最小可运行实现。理解了 ReAct,就理解了 Agent 的运转本质。
ReAct 原理虽简,工程实现却有几个硬问题,留待后续小节:
| 问题 | 详见 |
|---|---|
| Prompt 怎么写,LLM 才会按 Thought/Action/Observation 格式输出? | 4.2 节 |
| 上下文越来越长怎么办(每轮都在累积轨迹)? | 4.2 节 |
| 出错了怎么学习(不只是当轮纠错,还跨任务积累)? | 4.3 节 Reflexion |
| 什么时候不该用 ReAct(延迟、成本)? | 4.4 节 |
下一节《4.2 ReAct 的工程实现》将讨论 Prompt 模板设计、轨迹生成与上下文管理——这是把 ReAct 从原理变成生产系统的关键。