ReAct 模式(Reasoning + Acting)详解
⚠️ 注意 :这里的 ReAct 不是 前端框架 React.js,而是 LLM Agent 领域的一个经典范式,全称 Reasoning + Acting ,出自 2022 年论文 ReAct: Synergizing Reasoning and Acting in Language Models 。
🔹 核心思想 LLM 在一个循环 中交替进行 思考(Reasoning) 和 行动(Acting) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 循环开始 │ ├─ 🤔 Thought: "用户要提取 CSV 第一列,我先看看文件结构" ← 推理 ├─ 🛠️ Action: read_file(path="questions.csv", n_rows=5) ← 调用工具 ├─ 👁️ Observation: "type,question,options,answer,..." ← 工具返回 │ ├─ 🤔 Thought: "第一列是 type,我用 pandas 提取" ← 推理 ├─ 🛠️ Action: python_runner(code="import pandas...") ← 调用工具 ├─ 👁️ Observation: "执行成功,生成 output.csv" ← 工具返回 │ ├─ 🤔 Thought: "验证一下结果文件" ← 推理 ├─ 🛠️ Action: read_file(path="output.csv", n_rows=3) ← 调用工具 ├─ 👁️ Observation: "type\nmultiple-choice\n..." ← 工具返回 │ ├─ 🤔 Thought: "结果正确,任务完成" ← 推理 └─ ✅ Final Answer: "已成功提取..." ← 结束循环
🔄 循环三要素
阶段
英文
作用
示例
思考
Thought
分析当前状态,决定下一步行动
“文件有 5 列,我需要用 pandas 提取第一列”
行动
Action
调用工具执行具体操作
python_runner(code="...")
观察
Observation
获取工具执行结果,反馈给模型
“执行成功,生成 output.csv”
🔹 在代码中的体现 adk.NewChatModelAgent 本身就实现了 ReAct 循环 ——MaxIterations 控制的就是这个循环的最大轮数:
1 2 3 4 5 adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{ MaxIterations: 1000 , })
🔄 每一轮迭代的流程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ┌─────────────────────────────────────────┐ │ 第 N 轮 ReAct 循环 │ ├─────────────────────────────────────────┤ │ 1️⃣ 模型推理 │ │ • 分析历史对话 + 工具返回结果 │ │ • 决定调用哪个工具、传什么参数 │ │ │ │ 2️⃣ 执行工具 │ │ • 解析 LLM 生成的 Tool Call │ │ • 调用实际函数(如 bash/python_runner)│ │ • 返回结果给模型 │ │ │ │ 3️⃣ 模型再推理 │ │ • 判断:任务完成了吗? │ │ • 是 → 输出 Final Answer,结束循环 │ │ • 否 → 继续下一轮 Thought/Action │ └─────────────────────────────────────────┘
🔹 Instruction 中这句话的目的 1 "You are in a react mode, and you should use the following libraries..."
🎯 这是在提示 LLM:
你现在处于一个可以反复调用工具的循环中 ,不需要一次性给出答案,可以分步骤通过工具 来完成任务。
💡 这样 LLM 就知道自己可以:
能力
说明
✅ 先 read_file 看看数据长什么样
不盲目写代码,先理解输入
✅ 再 python_runner 写代码处理
基于观察结果制定行动方案
✅ 出错了可以再改代码重试
支持迭代调试,提升成功率
✅ 验证结果后再提交
确保输出质量,避免错误传播
❌ 而不是试图一次性在回复中把所有事情说完
避免”幻觉式”回答
🔹 对比:普通模式 vs ReAct 模式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ┌─────────────────────────────────────────────────────────┐ │ 普通模式(一次性回答) │ ├─────────────────────────────────────────────────────────┤ │ 用户提问 → LLM 一次性回答 → 结束 │ │ │ │ 优点:快,适合简单问答 │ │ 缺点:无法调用工具,无法处理复杂/多步任务 │ └─────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────┐ │ ReAct 模式(思考-行动循环) │ ├─────────────────────────────────────────────────────────┤ │ 用户提问 → [思考→调用工具→观察结果] × N轮 → 最终回答 │ │ │ │ 优点:能调用工具、支持多步推理、可迭代调试 │ │ 缺点:耗时更长,需要控制最大迭代次数防止死循环 │ └─────────────────────────────────────────────────────────┘
📊 场景对比
场景
普通模式
ReAct 模式
简单问答:”1+1=?”
✅ 适合
⚠️ 大材小用
文件处理:”提取 CSV 第一列”
❌ 无法执行
✅ 适合
网络搜索:”查一下今天天气”
❌ 无实时数据
✅ 可调用搜索工具
代码调试:”为什么这段代码报错”
❌ 无法执行验证
✅ 可运行→观察→修正
🔹 ReAct 模式的关键配置 1️⃣ 控制迭代次数 1 2 MaxIterations: 1000 MaxIterations: 10
⚠️ 必须设置上限 ,防止模型陷入死循环或无限调用工具。
2️⃣ 工具描述要清晰 1 2 3 4 Desc: `Run commands in a bash shell. Use this for file operations, git commands, or running scripts. Output includes stdout, stderr, and exit code.`
3️⃣ 结果反馈要简洁 1 2 3 4 5 func FilePostProcess (...) string { return fmt.Sprintf("✅ Success\nstdout: %s\nstderr: %s" , result.Stdout, result.Stderr) }
🔹 常见陷阱与最佳实践 ⚠️ 陷阱 1:模型忘记调用工具,直接编答案 1 2 3 4 5 6 7 8 ❌ 错误示例: Thought: "我需要读取文件" Final Answer: "文件第一列是 type..." ← 没调用工具就瞎编 ✅ 解决方案: • Instruction 明确强调 "必须使用工具" • 工具返回结果中携带明确的成功/失败标识 • 后处理函数格式化结果,让模型容易理解
⚠️ 陷阱 2:模型陷入循环,反复调用同一工具 1 2 3 4 5 6 7 8 9 ❌ 错误示例: Round 1: read_file → "文件太大" Round 2: read_file → "文件太大" Round 3: read_file → "文件太大" ... ✅ 解决方案: • 设置 MaxIterations 上限 • 在 Observation 中给出明确错误提示:"文件过大,请指定 start_row 和 n_rows" • Instruction 引导模型:"如果工具报错,先分析原因再重试"
⚠️ 陷阱 3:工具参数格式错误 1 2 3 4 5 6 7 ❌ 错误示例: Action: python_runner(code=import pandas...) ← 缺少引号,不是合法 JSON ✅ 解决方案: • 使用 WrapTool + jsonrepair 自动修复参数 • ToolInfo 中明确参数类型和必填项 • 预处理函数清除模型生成的格式残留
🔑 关键要点速记 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ┌─────────────────┬───────────────────────────────────────────┐ │ 要点 │ 说明 │ ├─────────────────┼───────────────────────────────────────────┤ │ ReAct 全称 │ Reasoning + Acting,思考与行动交替循环 │ ├─────────────────┼───────────────────────────────────────────┤ │ 循环三要素 │ Thought → Action → Observation │ ├─────────────────┼───────────────────────────────────────────┤ │ MaxIterations │ 控制最大循环轮数,防止死循环 │ ├─────────────────┼───────────────────────────────────────────┤ │ Instruction 作用│ 引导模型"分步做",而非"一次性答" │ ├─────────────────┼───────────────────────────────────────────┤ │ 工具描述质量 │ 直接影响 LLM 能否正确选择和使用工具 │ ├─────────────────┼───────────────────────────────────────────┤ │ 结果反馈格式 │ 简洁明确,便于模型理解并决定下一步 │ ├─────────────────┼───────────────────────────────────────────┤ │ 适用场景 │ 复杂任务、多步推理、需要外部工具的场景 │ └─────────────────┴───────────────────────────────────────────┘
🎯 一句话总结
ReAct 模式 = 让 LLM 学会”边想边做” :通过 Thought-Action-Observation 循环,模型可以调用工具、观察结果、迭代修正,从而完成单靠语言生成无法解决的复杂任务。理解这一范式,是构建实用 Agent 系统的核心基础。