ReAct 原理简介

Reasoning + Acting:让大模型会思考、会行动

  • 前置知识:了解大语言模型(LLM)的基本概念即可

目录

  • [第一章 ReAct 是什么](#第一章 ReAct 是什么)
  • [第二章 为什么需要 ReAct](#第二章 为什么需要 ReAct)
  • [第三章 ReAct 的核心原理](#第三章 ReAct 的核心原理)
  • [第四章 ReAct 的工作流程详解](#第四章 ReAct 的工作流程详解)
  • [第五章 Prompt 设计:如何让模型按 ReAct 模式工作](#第五章 Prompt 设计:如何让模型按 ReAct 模式工作)
  • [第六章 一个完整的 ReAct 示例](#第六章 一个完整的 ReAct 示例)
  • [第七章 动手实现一个最小 ReAct Agent](#第七章 动手实现一个最小 ReAct Agent)
  • [第八章 ReAct 的优缺点与常见坑](#第八章 ReAct 的优缺点与常见坑)
  • [第九章 ReAct 与其他范式的对比](#第九章 ReAct 与其他范式的对比)
  • [第十章 进阶话题与延伸阅读](#第十章 进阶话题与延伸阅读)
  • [附录 常用参考 Prompt 模板](#附录 常用参考 Prompt 模板)

第一章 ReAct 是什么

ReAct = Reasoning(推理) + Acting(行动)

ReAct 是 2022 年由 Google Research 和普林斯顿大学在论文

《ReAct: Synergizing Reasoning and Acting in Language Models》

中提出的一种大语言模型 Agent 工作范式。

一句话概括:

让 LLM 在解决问题的过程中,交替地进行"思考(Thought)"和"行动(Action)",

并根据行动返回的"观察结果(Observation)"不断修正自己的思路,直到得出最终答案。

传统的大模型只有两种用法:

  1. 纯推理:Chain-of-Thought(思维链),只动脑不动手,容易产生"一本正经地胡说八道"(幻觉)。
  2. 纯行动:直接输出动作序列,不动脑,缺乏规划,出错后无法自我纠正。

ReAct 把两者结合起来:边想边做,做完再看,看完再想。这非常接近人类解决问题的方式。

一个生活化的类比

你要在陌生的城市找一家好吃的面馆:

  • 纯推理派:坐在家里凭空想象------"城东应该有一家不错的",结果到了地方发现根本没有。(幻觉)
  • 纯行动派:出门乱走,看到第一家就进去,不管好不好吃。(缺乏规划)
  • ReAct 派
text 复制代码
思考:我先打开地图搜一下附近的面馆。
行动:搜索"附近 面馆 评分"。
观察:搜到 3 家,A 店 4.8 分最近。
思考:A 店评分高且近,先走过去看看排队情况。
行动:走到 A 店门口。
观察:排队 40 分钟,太久了。
思考:换 B 店,评分 4.6 但不用排队。
行动:前往 B 店就餐。
结论:吃上了面,问题解决。

第二章 为什么需要 ReAct

1. 对抗幻觉(Hallucination)

纯思维链推理时,模型只能依赖训练时记住的知识。一旦记错或知识过时,就会错到底。

ReAct 让模型通过 Action 去外部世界(搜索引擎、数据库、API)获取真实、最新的信息,

用 Observation 来"grounding(接地)",大幅减少编造。

2. 突破知识边界

LLM 的知识有截止日期,也不会算复杂数学、查不了实时天气。

ReAct 通过工具调用(搜索、计算器、代码解释器等)扩展能力边界。

3. 可解释、可干预

ReAct 的思考轨迹(Thought 序列)是显式的文本,人类可以读懂 Agent 每一步为什么这么决策,

出错时也容易定位是哪一步出了问题。

4. 自我纠错

行动失败时(比如搜索没有结果、API 报错),错误信息会作为 Observation 反馈给模型,

模型可以在下一步 Thought 中分析原因并换一条路走,而不是一条道走到黑。


第三章 ReAct 的核心原理

3.1 三个基本元素

ReAct 的每一步循环由三个部分组成:

text 复制代码
+-------------+
|  Thought    |  思考:模型对当前状态的分析、推理、计划
|  (思考)    |  例如:"我需要先查到苹果的股价。"
+-------------+
       |
       v
+-------------+
|  Action     |  行动:模型决定调用的工具及参数
|  (行动)    |  例如:search["苹果公司 当前股价"]
+-------------+
       |
       v
+-------------+
| Observation |  观察:外部环境执行 Action 后返回的结果
|  (观察)    |  例如:"苹果公司股价为 228.52 美元"
+-------------+
       |
       v
(带着新信息回到 Thought,进入下一轮循环)

如此循环,直到模型认为信息足够,输出:

text 复制代码
+-------------+
| Final Answer|  最终答案:任务完成,循环结束
| (最终答案) |
+-------------+

3.2 本质:把推理轨迹写进上下文

ReAct 并没有改变模型的权重,也没有任何训练魔法。

它的本质是 上下文学习(In-context Learning)

  • 通过 Prompt 中的少量示例(few-shot),教模型学会 Thought/Action/Observation 的输出格式;
  • 每轮循环把历史轨迹拼接回上下文,让模型基于完整的思考-行动历史做下一步决策;
  • 模型的自由文本生成能力负责"思考",外部工具负责"行动",两者通过文本协议衔接。

3.3 形式化描述

可以把 ReAct 看成一个循环:

text 复制代码
状态 S0 = (问题 Q, 空历史)
重复:
    Thought_t     = LLM(Q, 历史轨迹)
    Action_t      = LLM(Q, 历史轨迹, Thought_t)
    Observation_t = 环境执行(Action_t)
    历史轨迹 += (Thought_t, Action_t, Observation_t)
直到 LLM 输出 Final Answer

第四章 ReAct 的工作流程详解

以一个多跳问答(multi-hop QA)问题为例:

问题:《流浪地球》导演的首部长片是哪一年上映的?

第 1 轮

text 复制代码
Thought 1:     我需要先知道《流浪地球》的导演是谁。
Action 1:      search["流浪地球 导演"]
Observation 1: 《流浪地球》由郭帆执导,2019 年上映。

第 2 轮

text 复制代码
Thought 2:     导演是郭帆。接下来我要查郭帆的首部长片是哪一部。
Action 2:      search["郭帆 首部长片 处女作"]
Observation 2: 郭帆的长片处女作是《李献计历险记》。

第 3 轮

text 复制代码
Thought 3:     首部长片是《李献计历险记》,我还需要它的上映年份。
Action 3:      search["李献计历险记 上映年份"]
Observation 3: 《李献计历险记》于 2011 年上映。

第 4 轮

text 复制代码
Thought 4:     我已经得到全部信息:《流浪地球》导演郭帆的首部长片
               《李献计历险记》于 2011 年上映。
Final Answer:  2011 年

流程要点:

  • 每一步只解决一个小问题(分解);
  • 每步的 Action 都基于之前的 Observation(依赖传递);
  • 思考过程全程可见(可审计)。

第五章 Prompt 设计:如何让模型按 ReAct 模式工作

一个典型的 ReAct Prompt 由四部分组成:

  1. 任务说明:告诉模型它要解决什么问题、可以使用哪些工具。
  2. 工具说明 :列出每个 Action 的名称、参数格式和功能。例如:
    • search[query]:在搜索引擎中查询 query
    • calculator[expr]:计算数学表达式
    • finish[answer]:输出最终答案并结束
  3. Few-shot 示例:给 1~3 个完整的 Thought/Action/Observation 轨迹示范,让模型模仿格式。这是 ReAct 原版论文的做法。
  4. 真实问题 :以 Question: ... 开头,留出让模型续写的位置。

简化版 Prompt 骨架

text 复制代码
你需要回答一个问题。你可以交替使用 Thought、Action、
Observation 来逐步推理。Thought 是你的思考过程,
Action 是调用工具,可用工具如下:
  search[关键词]:搜索互联网
  calculator[表达式]:计算数学表达式
Observation 是工具返回的结果。
当你有足够信息时,输出 "Final Answer: 答案"。

示例:
Question: 中国人口是美国的几倍?(示例略......)

Question: {用户真正的问题}
Thought:

运行时的拼接逻辑(伪代码)

python 复制代码
prompt = 系统说明 + 工具说明 + 示例 + "Question: " + 问题
loop:
    output = LLM(prompt)          # 生成 Thought 和 Action
    if output 包含 "Final Answer":
        返回答案,结束
    action = 解析 output 中的 Action
    observation = 执行 action      # 调用真实工具
    prompt += output + "Observation: " + observation

注意 :现代支持 Function Calling 的模型(如 GPT 系列)通常不再需要手写这种纯文本格式,

而是用结构化的 tool_calls 字段表达 Action,但背后的"思考 → 行动 → 观察 → 再思考"

循环思想完全一样。


第六章 一个完整的 ReAct 示例(带计算工具)

问题 :2024 年北京到上海的高铁二等座票价约 553 元,如果一个 4 人家庭往返一次,

总花费是多少?再算一下这笔钱大约能买多少杯 30 元的咖啡。

第 1 轮

text 复制代码
Thought 1:     4 人往返一次,每人 2 张票,共 4×2=8 张票,
               每张 553 元。我用计算器算总价。
Action 1:      calculator[553 * 4 * 2]
Observation 1: 4424

第 2 轮

text 复制代码
Thought 2:     总花费 4424 元。接下来算能买多少杯 30 元的咖啡。
Action 2:      calculator[4424 / 30]
Observation 2: 147.46666666666667

第 3 轮

text 复制代码
Thought 3:     4424 元 ÷ 30 元/杯 ≈ 147 杯。信息已经足够,可以给出最终答案。
Final Answer:  4 人家庭往返一次总花费 4424 元,
               这笔钱大约能买 147 杯 30 元的咖啡。

第七章 动手实现一个最小 ReAct Agent

下面是一个不到 60 行的 Python 最小实现,演示 ReAct 循环的骨架(LLM 调用部分用伪代码表示):

python 复制代码
import re

# ---------- 1. 定义工具 ----------
def search(query):
    # 实际项目中替换为真实搜索 API
    fake_db = {
        "流浪地球 导演": "《流浪地球》由郭帆执导",
        "郭帆 首部长片": "《李献计历险记》,2011年上映",
    }
    return fake_db.get(query, "没有找到相关信息")

def calculator(expr):
    return str(eval(expr))   # 演示用,生产环境勿用 eval

TOOLS = {"search": search, "calculator": calculator}

# ---------- 2. 构造 Prompt ----------
PROMPT = """
你可以使用 Thought/Action/Observation 来解决问题。
可用工具:
  search[关键词]:搜索信息
  calculator[表达式]:计算数学表达式
格式:
  Thought: 你的思考
  Action: 工具名[参数]
得到答案后输出:
  Final Answer: 答案

Question: {question}
"""

# ---------- 3. ReAct 主循环 ----------
def react_agent(question, max_steps=8):
    history = PROMPT.format(question=question)
    for step in range(max_steps):
        # 调用 LLM,生成 Thought 和 Action
        output = call_llm(history)          # 伪代码
        history += output

        # 检查是否得到最终答案
        match = re.search(r"Final Answer: (.+)", output)
        if match:
            return match.group(1)

        # 解析并执行 Action
        match = re.search(r"Action: (\w+)\[(.+)\]", output)
        if not match:
            history += "\nObservation: 格式错误,请重试\n"
            continue
        tool_name, tool_arg = match.group(1), match.group(2)
        result = TOOLS[tool_name](tool_arg)
        history += f"\nObservation: {result}\n"

    return "达到最大步数,任务失败"

# ---------- 4. 运行 ----------
answer = react_agent("流浪地球导演的首部长片是哪一年上映的?")
print(answer)

代码说明:

  • call_llm():调用任意大模型 API(OpenAI、Claude、本地模型均可),输入是累积的完整轨迹;
  • 每次循环只做三件事:让模型想 → 解析动作 → 执行工具并把结果拼回上下文;
  • max_steps 防止模型陷入死循环,是必备的安全阀。

工程实践中推荐直接使用现成框架:

  • LangChain:AgentExecutor + create_react_agent
  • LlamaIndex:ReActAgent
  • 以及各家模型的原生 Function Calling 能力

第八章 ReAct 的优缺点与常见坑

优点:

  • 显著减少幻觉,答案有真实信息来源支撑;
  • 推理轨迹透明,可解释、可调试;
  • 实现简单,无需训练,纯 Prompt 即可工作;
  • 通用性强,问答、网页操作、代码调试、游戏等场景都适用
    (论文中在 HotpotQA、Fever、ALFWorld、WebShop 等任务上验证了效果)。

缺点与常见坑:

  1. 上下文膨胀 :每轮循环都把历史拼回 Prompt,轨迹长了之后 token 消耗大、成本高,
    还可能超出上下文窗口。
    对策:压缩历史、摘要旧步骤、限制 max_steps。
  2. 死循环与原地踏步 :模型可能反复执行同一个失败的 Action。
    对策:检测重复动作、强制最大步数、在 Observation 中提示"该方法已失败,请换思路"。
  3. 格式漂移 :模型偶尔不按约定格式输出,导致解析失败。
    对策:解析失败时把错误信息反馈为 Observation 让模型自我修正;或使用 Function Calling。
  4. 错误传播 :早期的错误 Observation(比如搜索返回错误结果)会误导后续所有推理。
    对策:允许模型反思验证、多路搜索交叉验证。
  5. 一步错、步步错的长程依赖 :复杂任务需要几十步时,模型容易"忘记"最初目标。
    对策:在 Prompt 中始终保留原始问题;复杂任务先用 Plan-and-Execute 做高层规划,
    每一步再用 ReAct 执行。
  6. 工具设计很关键 :工具的粒度、命名、返回格式直接影响 Agent 表现。
    经验法则:工具要"少而精",返回结果要简洁、结构清晰,避免把大段无关文本塞给模型。

第九章 ReAct 与其他范式的对比

范式 特点 局限
直接回答 一步到位 易错、易幻觉
CoT 思维链 推理能力强 无法获取外部信息,仍幻觉
ReAct 推理 + 行动,事实可接地 上下文长、步骤多成本高
Plan-Execute 先整体规划再逐步执行 规划错了难局部修正
Reflexion ReAct + 自我反思与记忆 更耗 token

实际工程中的常见组合:

  • ReAct + Function Calling:现代 Agent 的标配形态;
  • Plan-Execute + ReAct:先规划大步骤,每个步骤内部用 ReAct 灵活执行;
  • ReAct + Reflexion:任务失败后让模型写"反思报告",存入记忆,下次尝试时参考。

第十章 进阶话题与延伸阅读

进阶话题:

  1. Reflexion:在 ReAct 基础上加入自我反思与长期记忆,让 Agent 从失败中学习;
  2. Toolformer / Function Calling:让模型通过微调原生学会调用工具,而不是靠 Prompt 模仿;
  3. Multi-Agent:多个 ReAct Agent 分工协作(如一个负责搜索、一个负责写代码、一个负责审查);
  4. CodeAct:让 Agent 直接输出可执行代码作为 Action,比文本格式的 Action 表达力更强;
  5. 评估方法:如何衡量 Agent 的轨迹质量(成功率、步数、成本、轨迹合理性)。

必读论文与资料:


附录 常用参考 Prompt 模板

模板 A:通用问答 ReAct

text 复制代码
Answer the following questions as best you can. You have
access to the following tools:

{tools}

Use the following format:

Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can
repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original question

Begin!

Question: {input}
Thought:

这是 LangChain 经典 ReAct 模板,英文撰写,对多数模型效果更好。

模板 B:中文简洁版

text 复制代码
你是一个会思考、会使用工具的智能助手。
解决任何问题时,请严格按以下格式交替输出:

思考:<分析当前情况,规划下一步>
行动:<工具名>[<参数>]
观察:<工具返回的结果,由系统提供>

可用工具:
{工具列表}

当你确定已经得到答案时,输出:
最终答案:<答案>

问题:{用户问题}
思考:

核心要点回顾

  1. ReAct = 思考(Thought)+ 行动(Action)+ 观察(Observation) 的交替循环;
  2. 它用外部工具给模型"接地",是对抗幻觉的关键手段;
  3. 纯 Prompt 即可实现,但工程上推荐 Function Calling;
  4. 注意上下文膨胀、死循环、错误传播三大坑;
  5. ReAct 是现代 LLM Agent(搜索助手、编程助手、自动化操作)最基础、最重要的设计模式。

祝学习愉快!

相关推荐
COOLMO研究AI1 小时前
Python 如何在 AI 接口中实现请求幂等性:防止重复提交与重复扣费
人工智能·python·php
x861 小时前
Agent 的搜索引擎:Agentic Resource Discovery 规范,以及它解决不了的信任问题
搜索引擎·agent
微三云-张梅1 小时前
东莞企业做GEO:AI信任体系的三个建设层级
大数据·人工智能·微三云geo·东莞系统开发·东莞geo
CTA量化套保1 小时前
新手学量化,先做能复查的小流程
人工智能·python
狂奔蜗牛(bradley)1 小时前
RKNN Toolkit2开发环境搭建实操
人工智能
weixin_446260852 小时前
AutoDesign:面向长时序智能体设计的元调度优化框架
人工智能
ZJU_统一阿萨姆2 小时前
【DSH】如何将 DeepSeek Harness 嵌入生产环境?万字解构 DeepSeek Agent Harness 的运行机制与安全边界
前端·javascript·安全
用户921080262862 小时前
4. 前端地图大量点位实时更新优化:后端推增量,前端做 diff
前端
Rocktech_ruixun2 小时前
机器人端侧大模型部署对主板有哪些要求?瑞迅主控板分级方案对比
人工智能·嵌入式硬件·机器人