Agent 怎么"想"和"做"?ReAct 决策引擎代码级拆解
Agent 会”思考”、会”行动”、会”观察”——但高质量的思考从哪来?怎么让 Agent 稳定输出 Thought 和 Action?
ReAct(Reasoning + Acting)是当前最主流的决策范式:让模型交替进行推理和工具调用,用 Observation 反馈驱动下一轮思考。本篇代码级拆解 ReAct 的 Prompt 模板、工具调用和错误处理,对比 Self-Ask、Tree of Thoughts 等策略。
ReAct 依赖四个概念:思维链(一步步想)、工具调用(能执行操作)、Agent 循环(思考→行动→观察→再思考)、结构化输出(输出 Thought/Action 等固定格式,方便程序解析)。前几篇已讲 CoT 和 Prompt,这里重点看如何让模型稳定输出 Thought + Action。新手可先看概念(第 1 节),代码部分(第 2 节)可跳过。
🔄 一、ReAct 范式:Agent 决策的基石
Agent 的组成(LLM + Tools + Memory + Loop)与核心概念详见第 6 篇。本篇聚焦 ReAct 决策引擎。
1.1 为什么需要 ReAct?
你让 LLM”查数据库并生成报告”——它只会输出 SQL 和报告模板,不会真的去查、去生成。查错了,它也不会根据结果重试。
ReAct 解决三件事:能调用工具(真查、真执行)、能根据结果自我修正(错了就换策略)、能拆多步任务(一步步完成)。
1.2 什么是 ReAct?
ReAct (Reasoning + Acting) = CoT + 工具调用 + 循环。思考 → 行动 → 观察 → 再思考 → 再行动,直到任务完成。
工作流程:
1. 思考(Reasoning) |
像做菜:查菜谱 → 准备食材 → 观察缺什么 → 再准备 → 再观察… ReAct 让 AI 也这样迭代执行。
1.3 ReAct Prompt 模板拆解
ReAct 的核心:让 LLM 输出固定格式,而不是自由发挥。程序要能解析出”调用哪个工具、传什么参数”,才能真去执行。
- ❌ 自由文本:”我需要查询数据库,然后生成报告”——程序没法解析
- ✅ 结构化:
Thought: ...Action: query_database(sql="...")——程序能解析并调用
核心组件:三个关键标签
ReAct 要求 AI 输出三个标签:
| 输出标签 | 简单理解 | 作用 | 例子 |
|---|---|---|---|
| Thought | AI 的思考过程 | 分析当前状态,决定下一步做什么 | Thought: 我需要先查询数据库获取用户数据 |
| Action | AI 要执行的操作 | 调用哪个工具,传入什么参数 | Action: query_database(sql="SELECT * FROM users") |
| Observation | 工具执行的结果 | 工具返回了什么结果 | Observation: 查询成功,返回 1000 条记录 |
为什么需要这三个标签?
- Thought(思考):让 AI 的决策过程可解释,我们能看到 AI 为什么这样做
- Action(行动):让程序能够解析和执行,调用对应的工具
- Observation(观察):让 AI 能够根据结果调整策略,如果出错了可以修正
完整 Prompt 模板
模板结构(你可以直接复制使用):
System Prompt: |
💡 模板说明:
{tool_descriptions}:可用工具的列表和说明{user_task}:用户的任务{history}:之前的思考-行动-观察历史
实际示例:一步步看 ReAct 如何工作
场景:让 AI 完成”查询用户数据并生成报告”
Step 1:准备 Prompt
System Prompt: |
Step 2:AI 的第一轮输出
Thought: 我需要先查询数据库获取用户数据。 |
Step 3:程序执行工具,返回结果
Observation: 查询成功,返回 1000 条用户记录 |
Step 4:AI 的第二轮输出(基于观察结果)
Thought: 数据已获取,现在需要生成报告。 |
Step 5:程序执行工具,返回结果
Observation: 报告生成成功,文件路径:/reports/users_2025-12.pdf |
Step 6:AI 判断任务完成,输出最终答案
Thought: 报告已生成,任务完成。 |
💡 关键理解:
- AI 不是一次性完成所有任务,而是一步步来
- 每一步都会思考、行动、观察
- 根据观察结果,决定下一步做什么
1.4 ReAct 的优势与局限
优势:
| 优势 | 说明 | 实际价值 |
|---|---|---|
| 高可控性 | 结构化输出易解析和执行 | 可以稳定地解析和执行工具调用 |
| 迭代修正 | 工具执行失败可在下一 Thought 中自我修正 | 能够处理错误,自动调整策略 |
| 通用性 | 适用于大多数多步任务 | 可以处理各种复杂任务 |
| 可解释性 | 每一步都有明确的思考过程 | 便于调试和审计 |
局限:
| 局限 | 说明 | 影响 |
|---|---|---|
| 局部最优 | 每步基于当前状态做最优选择,可能错过更优长期路径 | 可能无法找到全局最优解 |
| 单分支探索 | 无法自然处理多分支思考或高度不确定任务 | 对于需要探索多种方案的任务效果有限 |
💡 关键理解:ReAct 是 Agent 决策的稳定基础,适合大多数多步任务。对于需要探索多种方案的任务,可以考虑 Tree of Thoughts(见第3节)。
🔧 二、代码级实现:ReAct 的完整实现
⚠️ 新手提示:如果你不写代码,或者只是想理解概念,可以跳过这一节,直接看第3节”其他决策策略对比”。等你需要实际开发时,再回来学习代码实现。
理解了 ReAct 的原理后,我们来看看如何从代码层面实现一个完整的 ReAct Agent。
实现 ReAct 需要做什么?
- 构建 Prompt:把任务、工具、历史记录组合成完整的 Prompt
- 调用 LLM:让 LLM 生成 Thought 和 Action
- 解析 Action:从 LLM 输出中提取工具名和参数
- 执行工具:调用对应的工具
- 循环:重复上述过程,直到任务完成
2.1 Prompt 构建
核心任务:将任务、历史记录、可用工具组合成完整的 Prompt。
简单理解:
就像做菜需要准备食材一样,构建 Prompt 就是把所有”食材”(任务、工具、历史)组合在一起。
# Prompt 构建(伪代码) |
使用示例:
# 假设我们有这些工具 |
2.2 Action 解析
从 LLM 输出中解析出工具名和参数。例如 Action: query_database(sql="SELECT * FROM users") → 工具名 query_database,参数 {"sql": "..."},才能调用。
# Action 解析(伪代码) |
2.3 工具调用与错误处理
解析出工具名和参数后:找工具 → 调用 → 处理错误(工具不存在、参数错误、执行失败)。
# 工具调用与错误处理(伪代码) |
2.4 完整 ReAct Loop 实现
完整流程:构建 Prompt → 调 LLM 得 Thought/Action → 解析 Action → 执行工具 → 结果加入历史 → 下一轮,直到完成或达最大步数。
# 完整 ReAct Loop(伪代码) |
💡 关键理解:
- ReAct Loop 就是一个循环:思考 → 行动 → 观察 → 再思考…
- 每一步都会记录到
history中,让 AI 知道之前做了什么- 如果达到最大步数还没完成,就停止(防止无限循环)
2.5 错误处理与自我修正
核心任务:当工具调用失败时,让 Agent 在下一轮 Thought 中自我修正。
简单理解:
如果工具调用失败了(比如数据库连接失败),Agent 不应该直接放弃,而是应该:
- 分析错误原因
- 调整策略
- 尝试其他方法
就像人遇到问题时会想办法解决一样。
# 错误处理与自我修正(伪代码) |
实际例子:
Step 1: |
💡 关键理解:
- Agent 遇到错误时,不是直接放弃,而是分析原因并修正
- 错误信息会被加入到历史记录中,帮助 AI 做出更好的决策
🔍 三、其他决策策略对比
ReAct 是 Agent 决策的基石,但在某些场景下,其他策略可能更合适。
💡 为什么需要其他策略?
ReAct 适合执行性任务(调用工具、操作),但对于信息检索任务(搜索、查询),可能有更合适的策略。
3.1 Self-Ask:解决信息依赖问题
简单理解:
Self-Ask 专门解决”需要先查资料才能回答问题”的场景。
生活例子:
- 问题:”谁是《三体》的作者?这本书获得了什么奖项?”
- 你无法直接回答,需要:
- 先搜索”《三体》的作者”
- 再搜索”《三体》获得的奖项”
- 最后组合答案
Self-Ask 就是让 AI 也这样做。
Self-Ask 是 CoT 的变体,专门解决 多步信息检索问题。
机制详解
原理:当问题无法直接回答,Agent 会将问题分解为多个 子问题,逐步检索答案。
Prompt 模板:
Question: [原始问题] |
实际示例:
Question: 谁是《三体》的作者?这本书获得了什么奖项? |
对比 ReAct:什么时候用哪个?
| 维度 | ReAct | Self-Ask |
|---|---|---|
| 主要用途 | 执行性工具调用(API、脚本、操作) | 信息检索(搜索引擎、RAG、查询) |
| 输出格式 | Thought → Action → Observation | Question → Follow up → Intermediate Answer |
| 适用场景 | 需要执行操作的任务(如”查询数据库并生成报告”) | 需要检索信息的任务(如”查资料回答问题”) |
| 生活例子 | 做菜:思考 → 行动(拿食材) → 观察(食材准备好了) | 查资料:问题 → 搜索 → 答案 → 新问题 → 再搜索 |
选择指南:
- ✅ 用 ReAct:需要调用工具、执行操作(查询数据库、生成报告、发送邮件)
- ✅ 用 Self-Ask:需要检索信息、查资料(搜索、RAG、知识库查询)
融合策略
在复杂 Agent 框架中,常结合两者:
- 信息检索阶段:使用 Self-Ask,确保问题所需信息完备
- 执行阶段:切换到 ReAct,调用工具或操作系统 / API
示例:
# 融合策略(伪代码) |
3.2 Tree of Thoughts (ToT):深度探索与多路径决策
简单理解:
ToT 就像做决策时,同时考虑多种方案,然后选择最好的。
生活例子:
- 你要设计一个测试方案
- 不是只考虑一种方案,而是:
- 方案A:单元测试 + 集成测试
- 方案B:端到端测试 + 性能测试
- 方案C:自动化测试 + 手工测试
- 评估每个方案,选择最好的
ToT 让 AI 也这样做:同时探索多种方案,选择最优的。
ToT(思维树)模仿人类深度思考与多路径探索,适合处理复杂、不确定性高的任务。
ToT 核心原理
简单理解:
- 状态空间搜索:每步生成多个候选 Thought (3-5 个),形成分支
- 树形结构:分支构成思维树,探索多种可能方案
- 评估与剪枝:评估每个方案的质量,去掉差的,保留好的
工作流程:
任务:设计一个测试方案 |
策略对比:三种方法怎么选?
| 策略 | 搜索深度 | 搜索广度 | 适用场景 | 计算成本 | 简单理解 |
|---|---|---|---|---|---|
| CoT | 1 (单链) | 1 (贪婪) | 简单推理、问答 | 低 | 一步步思考,只考虑一种方案 |
| ReAct | N (迭代) | 1 (贪婪) | 多步任务、工具调用 | 中 | 一步步思考+行动,只考虑一种方案 |
| ToT | N (迭代) | M (多分支) | 复杂规划、创意生成、代码调试 | 高 | 一步步思考,同时考虑多种方案 |
选择指南(用生活例子理解):
简单任务:使用 CoT
例如:回答”1+1等于几?”(不需要工具,不需要多方案)
多步执行任务:使用 ReAct
例如:”查询数据库并生成报告”(需要调用工具,但不需要探索多种方案)
需要探索多种方案:使用 ToT
例如:”设计一个测试方案”(需要同时考虑多种方案,选择最好的)
ToT 实现挑战
为什么 ToT 用得少?
高计算成本:多分支生成与评估需大量 Token / LLM 调用
简单理解:需要调用很多次 LLM,成本高
Evaluator 设计难度:需要准确评估分支质量与潜力
简单理解:需要判断哪个方案更好,这个判断本身很难
内存与上下文管理:需跟踪树形结构中每个分支的状态与上下文
简单理解:需要记住很多分支的状态,管理复杂
💡 建议:大多数情况下,ReAct 就够用了。只有在需要探索多种方案的特殊场景下,才考虑 ToT。
名词卡片
- Greedy Search(贪婪搜索):每步选择当前最优路径
- State Space Search(状态空间搜索):在所有 Thought-Action 组合中寻找最优解
- Pruning(剪枝):移除低质量分支,节省资源
🔍 总结:决策引擎是 Agent 的核心灵魂
决策引擎决定了 Agent 如何思考和如何行动,是 Agent 系统的核心。
💡 快速回顾:你学到了什么?
- ReAct 是什么:让 AI 通过”思考 → 行动 → 观察”的循环完成任务
- ReAct 如何工作:结构化输出 Thought 和 Action,解析后调用工具
- 代码实现:Prompt 构建 → Action 解析 → 工具调用 → 循环
- 其他策略:Self-Ask(信息检索)、ToT(多方案探索)
三大策略对比总结
| 策略 | 核心特点 | 适用场景 | 计算成本 | 推荐度 | 一句话总结 |
|---|---|---|---|---|---|
| ReAct | 迭代式思考+行动 | 多步工具调用任务 | 中 | ⭐⭐⭐⭐⭐ 最常用 | 思考→行动→观察,一步步完成任务 |
| Self-Ask | 多步信息检索 | 需要检索信息的任务 | 中 | ⭐⭐⭐⭐ 信息检索场景 | 把问题拆成子问题,逐个检索答案 |
| ToT | 多路径探索 | 复杂规划、创意生成 | 高 | ⭐⭐⭐ 特殊场景 | 同时考虑多种方案,选择最优的 |
选择指南
何时使用 ReAct:
- ✅ 需要调用工具、API、执行操作
- ✅ 多步骤任务,需要迭代执行
- ✅ 需要错误处理和自我修正
- ✅ 大多数 Agent 应用场景
何时使用 Self-Ask:
- ✅ 需要多步信息检索
- ✅ 问题依赖多个子问题的答案
- ✅ 需要结合 RAG 或搜索引擎
何时使用 ToT:
- ✅ 需要探索多种解决方案
- ✅ 任务不确定性高
- ✅ 有充足的计算预算
- ✅ 创意生成、代码调试等场景
实战建议
- 从 ReAct 开始:ReAct 是最通用、最稳定的策略,适合大多数场景
- 根据任务调整:如果任务主要是信息检索,考虑 Self-Ask
- 特殊场景用 ToT:只有在需要探索多种方案时才使用 ToT
- 混合使用:可以在不同阶段使用不同策略(如信息检索用 Self-Ask,执行用 ReAct)
💡 核心理解:决策引擎是 Agent 的”大脑”,选择合适的决策策略,能让 Agent 更高效、更准确地完成任务。
📚 延伸阅读(含可直接访问链接)
以下资源按主题分类,每个资源都附有简要说明,帮助你选择合适的学习材料。
🔄 ReAct 范式
ReAct: Synergizing Reasoning and Acting in Language Models(ReAct 原始论文):ReAct 范式的开创性论文,展示了如何结合推理和行动。必读论文,适合所有读者。
ReAct 项目主页:ReAct 的官方项目主页,包含示例 Prompt 模板和代码。强烈推荐,适合想实践 ReAct 的开发者。
LangChain ReAct Examples(LangChain ReAct 示例):LangChain 的 ReAct 实现示例。强烈推荐,适合使用 LangChain 的开发者。
LlamaIndex Agent Examples(LlamaIndex Agent 示例):LlamaIndex 的 Agent 实现示例。适合使用 LlamaIndex 的开发者。
🔍 Self-Ask
Self-Ask: Empowering LLMs to Ask Clarification Questions(Self-Ask 论文):Self-Ask 的原始论文。适合想了解 Self-Ask 的读者。
Self-Ask with Search(Self-Ask 实现):Self-Ask 的开源实现。适合想实践 Self-Ask 的开发者。
🌳 Tree of Thoughts
Tree of Thoughts: Deliberate Problem Solving with LLMs(ToT 原始论文):ToT 的开创性论文,展示了如何通过树形结构探索多种推理路径。必读论文,适合想了解 ToT 的读者。
Tree of Thoughts 实现:ToT 的开源实现。适合想实践 ToT 的开发者。
🛠️ 工具调用与 Function Calling
OpenAI Function Calling(OpenAI 工具调用):OpenAI 的 Function Calling 官方文档。必读,适合使用 OpenAI API 的开发者。
Anthropic Tool Use(Claude 工具使用):Anthropic 的工具使用文档。适合使用 Claude 的开发者。
LLM Tool Calling Best Practices(工具调用最佳实践):工具调用的最佳实践指南。适合想优化工具调用的开发者。
📊 评估与评分
- LLM Heuristic Evaluation for Planning(规划评估):LLM 规划评估的综述论文。适合想了解如何评估 Agent 决策质量的读者。
🔔 系列说明
本文是《🧠 LLM/Agent 从入门到精通:告别浅尝辄止》系列第 7 篇。上一篇:只会聊天不够用?Agent 如何让 LLM 能做事、会思考、能修正。下一篇:复杂任务 Agent 怎么拆?任务规划与 Self-Correction。













