想象你是一名侦探,接手一起离奇的珠宝失窃案。你不会把自己锁在办公室里凭空虚想,而是按一套熟练的节奏推进:先摊开已有线索,在心里形成“很可能有内鬼”的初步判断(思考);然后起身去现场、调监控、询问保安(行动);几小时后,一份指纹报告放到你的桌上,报告可能推翻、也可能佐证你的推断(观察);于是你重新坐下来,带着新证据开始下一轮推理(再思考)。如此循环,直至破案。 这套“推理—行动—观察—再推理”的节奏,正是 ReAct(Reasoning + Acting,推理与行动)模式的灵魂。2022 年,研究者提出让大语言模型模仿这种办案节奏:每一步先输出一段思考(Thought),说明正在分析什么、打算怎么做;接着输出一个行动(Action),调用外部工具;工具返回的结果则作为观察(Observation)反馈给模型,驱动下一轮思考。三者首尾相接,构成一个动态闭环。本文就用侦探办案的比喻,带你从零理解 ReAct 的完整循环、核心环节与工程落地要点。

岗位关联

掌握 ReAct 模式,你就能设计出会“干活”的 AI 应用——让模型调用工具、读取反馈、动态调整决策,从“纸上谈兵”进化为“真刀真枪”。

目录
  1. 可视化演示
  2. 1. ReAct 核心循环
  3. 2. 思考生成环节
  4. 3. 行动调用机制
  5. 4. 观察反馈处理
  6. 5. 动态决策闭环
  7. 6. Prompt 设计要点
  8. 7. 应用与挑战
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

动态演示大模型ReAct推理与行动协的核心机制,通过开始/执行/监控/完成四种模式展示关键概念与交互流程。

本节配有交互动效(进入视口后自动加载,约 3KB)。

大模型ReAct推理与行动协:一ReA 一、ReAct推理与行动协同核 二、思考行动观察循环机制详解 核心机制可视化 大模型ReAct推理与行动协整体架构与关键组件

1. ReAct 核心循环

侦探每次办案都会按一套熟练的节奏推进:先摊开已有线索,在心里形成“很可能有内鬼”的初步判断(思考);然后起身去现场、调监控、询问保安(行动);几小时后,一份指纹报告放到桌上,报告可能推翻、也可能佐证推断(观察);于是带着新证据开始下一轮推理(再思考)。这不是偶然的办案风格,而是优秀侦探的标准工作法。

这套“推理—行动—观察—再推理”的节奏,正是 ReAct 模式的灵魂。2022 年,研究者提出让大语言模型模仿这种办案节奏:每一步先输出一段思考(Thought),说明正在分析什么、打算怎么做;接着输出一个行动(Action),调用外部工具;工具返回的结果则作为观察(Observation)反馈给模型,驱动下一轮思考。三者首尾相接,构成一个动态闭环。

在这个闭环中,模型的角色从“一次性回答问题的解说员”转变为“持续与环境互动的行动者”。以问答为例:纯语言模型只能依据训练时见过的知识作答,遇到“帮我查一下明天的天气”这类时效性问题就束手无策;而 ReAct 模型会先思考“需要天气数据”,再调用天气查询工具,把返回的实况信息纳入推理,最终给出准确答案——哪怕这段知识从未出现在训练数据里。

回到侦探的故事:若指纹报告与嫌疑人完全不符,侦探绝不会视而不见地继续原计划,而是会停下脚步,把这条“意外信息”写进推理,调转调查方向。ReAct 的循环也如此——每一次观察都是对推理的“打磨”,让模型越走越接近正确答案。

Thoughtt→Actiont→Observationt→Thoughtt+1\text{Thought}_t \rightarrow \text{Action}_t \rightarrow \text{Observation}_t \rightarrow \text{Thought}_{t+1}
这个公式描述 ReAct 的一轮标准循环:思考驱动行动,行动产生观察,观察又触发新的思考,循环往复直到得出答案。
  1. Thought_t(第 t 步思考)模型在当前时刻的推理内容,显式写出“我在分析什么、下一步打算做什么”。
    Thoughtt:"根据线索,我推测…下一步应…"\text{Thought}_t : \text{"根据线索,我推测…下一步应…"}
  2. Action_t(第 t 步行动)从可用工具集中选中一个并填入参数,例如“搜索[嫌疑人出入记录]”。
    Actiont=SelectTool(⋅)+FillArgs(⋅)\text{Action}_t = \text{SelectTool}(\cdot) + \text{FillArgs}(\cdot)
  3. Observation_t(第 t 步观察)工具执行后返回的环境反馈,如搜索结果、日志或数值结果。
    Observationt=Env(Actiont)\text{Observation}_t = \text{Env}(\text{Action}_t)
  4. Thought_{t+1}(下一步思考)模型把观察纳入上下文,修正推理方向,开启新一轮循环。
    Thoughtt+1←Thoughtt⊕Observationt\text{Thought}_{t+1} \leftarrow \text{Thought}_t \oplus \text{Observation}_t

2. 思考生成环节

侦探每次行动前,都会翻开笔记本写下两行字:“已知……”“我推测……所以我去……”。这段文字也许不会直接出现在最终报告里,但它把决策过程外化,让侦探自己看得清下一步的来由,也让旁人能够审查他的思路。

对应到 ReAct,思考(Thought)就是模型“写下来的内心独白”。它不是一个黑盒里的隐式计算,而是以自然语言显式输出的推理轨迹。研究发现,强制模型先说清楚“为什么”,再决定“做什么”,比直接让它输出动作准确得多——因为语言本身参与了推理过程,迫使模型在行动前整理思路,而不是凭概率“跳”到某个动作。

技术上,思考内容的生成依赖完整的上下文:初始的系统指令、此前各轮的行动调用与观察结果,全部拼接成输入序列,交给大模型按自回归方式生成。思考的质量取决于两部分:一是上下文是否完整,二是模型是否被训练成善于把“分析”与“执行”分离的推理者。

侦探笔记本的价值在于“可审阅、可纠偏”。若行动失败,侦探能翻回笔记本找出是哪条假设引错了路;ReAct 同样把推理外化,让开发者在每一步都能看到模型“在想什么”,定位错误更轻松,也让模型的推理路径具备可解释性。

Thoughtt=LLM(Prompt+History1:t−1)\text{Thought}_t = \text{LLM}(\text{Prompt} + \text{History}_{1:t-1})
该式说明:每一步思考都是大模型基于完整历史(此前所有思考、行动、观察)重新生成的文本。
  1. Prompt(系统提示)系统的“委托书”,包含角色设定、任务目标、工具清单和格式示例。
    Prompt=Instruction+Format+Tools\text{Prompt} = \text{Instruction} + \text{Format} + \text{Tools}
  2. History(历史轨迹)第 1 步到第 t-1 步的全部轨迹,即此前的思考、行动与观察记录。
    History1:t−1={(T1,A1,O1),…,(Tt−1,At−1,Ot−1)}\text{History}_{1:t-1} = \{(T_1,A_1,O_1), \ldots, (T_{t-1},A_{t-1},O_{t-1})\}
  3. LLM(大语言模型)在给定上下文下生成下一步思考文本的推理引擎,通过最大化条件概率实现。
    Thoughtt=arg⁡max⁡P(text∣Prompt+History1:t−1)\text{Thought}_t = \arg\max P(\text{text} \mid \text{Prompt} + \text{History}_{1:t-1})

3. 行动调用机制

侦探决定去档案馆调取一份十年旧案卷宗,就得填写一张申请单:申请人、档案编号、调阅目的……每一项都必须准确无误。填错编号,管理员会驳回;漏填项目,档案馆不给办。行动调用也一样,模型不能只“想要”结果,而要精确指明“调用哪个工具、传什么参数”。

在 ReAct 中,模型的文本输出不会自动触发任何外部动作。系统需要一套“解析器”:从模型的输出文本中提取结构化的工具调用指令。常见的格式有两种:一是带标记的文本,如 Action: Search[北京人口];二是 JSON 函数调用,如 {"name": "search", "args": {"query": "北京人口"}}。解析后的调用交给对应的工具执行,所得返回值再封装成 Observation 拼回上下文中。

选择合适的工具并生成合法的参数,是行动环节的两个关键点。选择错误往往源于工具描述不清晰或语义相近的工具难以区分;参数错误则可能表现为字段缺失、类型不对或格式不符。因此在 Prompt 设计阶段,为每个工具写清楚“功能是什么、参数有哪些、返回什么”,能大幅降低这类错误。

正如填写查档单需要按规矩办事,工具调用也要靠“格式之弦”绷紧。如果解析器无法识别模型输出的工具格式,行动就会落空——这也是为什么要在 Prompt 中用示例把格式“钉死”,让模型照着写。

Actiont=Parse(LLMout,t, T)\text{Action}_t = \text{Parse}\big(\text{LLM}_{\text{out},t},\ \mathcal{T}\big)
模型输出经过结构化解析,才能在预注册的工具集合中触发一次真实的调用。
  1. LLM_out,t(模型原始输出)第 t 步模型生成的原始文本,其中包含“思考”与“行动”两部分内容。
    LLMout,t=Thoughtt+ActionTextt\text{LLM}_{\text{out},t} = \text{Thought}_t + \text{ActionText}_t
  2. T(工具集合)预先注册的所有可用工具,如搜索引擎、计算器、数据库查询器等。
    T={Search, Calculator, SQLQuery,…}\mathcal{T} = \{ \text{Search}, \ \text{Calculator}, \ \text{SQLQuery}, \ldots \}
  3. Parse(解析器)从 ActionText 中提取工具名与参数的函数,输出标准化动作。
    Parse("Search[北京人口]")→(Search,"北京人口")\text{Parse}( \text{"Search[北京人口]"}) \rightarrow (\text{Search}, \text{"北京人口"})

4. 观察反馈处理

侦探拿到一份指纹比对报告,直接归档并不能破案。他需要逐行读那串数据,判断哪几枚指纹属于嫌疑人、哪里出现第三方痕迹、哪组数据有异常——真正有信息量的不是“报告本身”,而是侦探从中提炼出的判断。

ReAct 中的观察(Observation)同样是“原始素材”。工具返回的可能是上百条网页结果、一段系统日志、一串 JSON 数据,信息密度不一、噪声繁多。模型若不加甄别地把全部内容当作推理依据,很容易被无关信息带偏。因此观察反馈处理的核心是:在下一步思考中,对原始反馈做信息提取和价值判断——“这段输出里,哪些与我当前目标相关?哪些可以忽略?哪些提示我需要更换工具?”

一个现实的困难是:观察结果并不总是成功的。工具可能超时、返回空、或给出错误格式。模型需要具备“识别异常”的敏感性:是重试一次?换关键词?还是换一个工具?这类判断无法提前写成规则,而需要模型结合上下文灵活决定,这正是 ReAct 相比预设脚本的优势所在。

侦探不会让化验师替自己断案,而会把报告变成自己推理的一部分。同样,ReAct 中的观察必须“流回思考”才有价值;把工具结果直接拼进最终答案,而不经过思考消化,就退化为一次普通的 API 拼装,失去了推理与行动协同的意义。

Observationt=Env(Actiont),Infot=Extract(Observationt)\textbf{Observation}_t = \text{Env}(\text{Action}_t), \quad \text{Info}_t = \text{Extract}(\textbf{Observation}_t)
观察是环境的原始回音,信息提取则把回音转化为可用于决策的“线索”。
  1. Env(环境执行器)接收行动指令并执行,返回原始结果。
    Env:Actiont↦Result\text{Env}: \text{Action}_t \mapsto \text{Result}
  2. Observation_t(原始观察)第 t 步的原始反馈,可能是文本、数值或结构化数据。
    Observationt=(status, content, meta)\textbf{Observation}_t = ( \text{status}, \ \text{content}, \ \text{meta} )
  3. Extract(信息提取)在下一步思考中完成的信息浓缩,把原始反馈转变为对决策有用的线索。
    Infot={k∈Observationt∣relevance(k)≥τ}\text{Info}_t = \{ k \in \textbf{Observation}_t \mid \text{relevance}(k) \geq \tau \}

5. 动态决策闭环

真实破案很少走直线。侦探会在每个岔路口停下来,拿出当前所有证据权衡:继续追查这条线还是转去另一条?现有证据够不够申请搜查令?再查下去有没有危险?如果发现自己在一条死胡同里,就果断折返。最终,当证据链闭合、疑点消解,他才会收网结案。

ReAct 的决策机制同样不是“固定流程”,而是每步动态判断的闭环。模型每一步都要回答三个问题:当前目标是否已经达成?如果没达成,下一步用什么行动最有可能推进?如果已有信息足以支撑答案,就直接输出最终回答(通常以 Finish 动作标示)并终止循环。

这个闭环还内置了安全阀:最大步数限制(T_max)。无论任务是否完成,循环最多执行 T_max 轮,避免模型在复杂任务中无限循环、白白消耗资源。另外,当模型发现某条路径连续多步没有带来新信息时,也应具备“回溯或换路”的能力——这正是动态决策优于静态脚本的地方。

侦探收网凭的是“证据链闭合”的底气;ReAct 停止循环凭的是模型对答案的“信心”。一个好的系统设计,既要让模型有足够的探索空间(T_max 足够大),也要在它足够确定时及时叫停(信心阈值合理),两者共同决定了一次任务的质量与成本。

Stop  ⟺  Confidence(Answer∣History1:t)>θ ∨ t=Tmax⁡\text{Stop} \iff \text{Confidence}(\text{Answer} \mid \text{History}_{1:t}) > \theta \ \lor \ t = T_{\max}
循环在两种情况下停止:模型对已有答案有足够信心,或达到步数上限。
  1. Confidence(信心评估)模型基于全部历史判断是否已能给出可靠答案。
    Confidence(⋅)∈[0,1]\text{Confidence}(\cdot) \in [0,1]
  2. theta(信心阈值)人为设定的回答信心门槛,高于它则输出答案并停止。
    θ≈0.9 (经验值,可调)\theta \approx 0.9 \ (\text{经验值,可调})
  3. History(累计轨迹)到第 t 步为止的全部思考、行动与观察,用于支撑最终答案。
    History1:t=(T1,A1,O1,…,Tt,At,Ot)\text{History}_{1:t} = (T_1, A_1, O_1, \ldots, T_t, A_t, O_t)
  4. T_max(最大步数)系统设定的循环上限,防止死循环与失控开销。
    t=Tmax⁡⇒强制终止t = T_{\max} \Rightarrow \text{强制终止}

6. Prompt 设计要点

一位雇主若想把案子办利索,委托书写得越清楚越好:委托人身份与目标、可调配的资源清单、报告格式要求,甚至附上一份“别人是怎么做的”范本。侦探拿到这样一份委托书,才不会乱查一气。

ReAct 的 Prompt 承担同样职责。一组合格的 Prompt 通常包含四层内容:角色与任务设定、工具描述、约束边界、以及 Few-shot 示例。其中,示例的价值尤为显著——给模型展示一两条“思考→行动→观察→再思考”的完整轨迹,相当于给侦探一份标准卷宗范本,它照着格式步步推进的准确率会大幅提升。

工具描述也极具讲究。好的工具描述应包含:工具的用途、参数的类型与含义、返回结果的格式、以及适合使用它的场景;反之,含糊的描述会让模型在“搜索”和“查询”之间反复横跳,甚至生成工具集中根本不存在的名字,导致解析失败。

一份好的“委托书”让侦探少走弯路,一份糟糕的 Prompt 会让模型在第一步就格式混乱、工具乱选。实践中的一个高效技巧是:先在 3-5 个典型 case 上反复调试示例格式,直到模型稳定输出可解析的动作,再去扩展更多场景——正如先让侦探吃透一本范本,再派他接手复杂案件。

Prompt=Role+Task+Tools′+DemoTAO+Constraints\text{Prompt} = \text{Role} + \text{Task} + \text{Tools}' + \text{Demo}_{TAO} + \text{Constraints}
ReAct Prompt 是多个模块的组合,每个模块都服务于“让模型稳定地走完推理-行动循环”这个目标。
  1. Role + Task(角色与任务)交代模型扮演的角色与要完成的目标,划定总方向。
    Role+Task:"你是一个智能助手,请回答用户问题"\text{Role} + \text{Task}: \text{"你是一个智能助手,请回答用户问题"}
  2. Tools'(工具描述)枚举可用工具,并逐一说明功能、参数与返回格式。
    Search(query): 返回与 query 相关的网页摘要\text{Search(query): 返回与 query 相关的网页摘要}
  3. Demo(Few-shot 示例)展示 1-2 条完整的思考-行动-观察轨迹,作为格式范本。
    DemoTAO:Thought→Action→Observation→Answer\text{Demo}_{TAO}: \text{Thought} \to \text{Action} \to \text{Observation} \to \text{Answer}
  4. Constraints(约束边界)规定回答语言、最大步数、禁止事项等硬性限制。
    Constraints:不超过 5 步,最终用中文给出答案\text{Constraints}: \text{不超过 5 步,最终用中文给出答案}

7. 应用与挑战

侦探所接的案子越多,越能体会到现实约束:联合勘查成本不菲、分析师连续熬夜会出错、查一个月案子的开销可能抵得上三个简单案子。好侦探不仅要会破案,还要会估算“这个案子的投入值不值”。

ReAct 已经在许多实际场景中展现出价值:需要时效性的问答(天气、股票查询)、需要多步查询的分析任务(“对比三个城市的房价并分析趋势”)、需要与环境交互的决策任务(自动订票、代码执行)等。相比纯文本推理,ReAct 的准确率和可解释性都更强——每一步决策都有迹可循。但它的代价同样明显:每轮循环都涉及一次 LLM 调用与一次工具调用,延迟与 token 成本随步数线性增长;一旦某一步观察被错误解读,错误会沿轨迹累积,形成“一步错、步步错”的雪崩效应。

工程上通常采用三类对策:一是给循环设置合理的最大步数与终止阈值,剪掉低价值探索;二是引入自我反思(Reflexion)机制,让模型复盘失败轨迹并改正错误;三是为高频子任务固化流程,能用一次工具调用解决的就不绕圈子。这些手段的本质,都是在“探索深度”与“资源开销”之间寻找平衡点。

侦探所的精明之处,在于知道何时派资深侦探、何时交给实习生、何时干脆拒绝委托。ReAct 的工程调度也一样:简单问题走单次生成,复杂任务才启动多步循环,并在循环中动态决定何时收手。理解了这套成本模型,你才算真正掌握了把 ReAct 用好的分寸。

Costtotal=∑t=1Tmax⁡(cLLM,t+ctool,t)\text{Cost}_{\text{total}} = \sum_{t=1}^{T_{\max}} \big( c_{\text{LLM},t} + c_{\text{tool},t} \big)
一个 ReAct 任务的总成本,近似等于每一步模型推理成本与工具调用成本的累加。
  1. T_max(总步数)任务实际执行的循环轮数,通常不超出系统设定的上限。
    Tmax⁡=min⁡(Tlimit, 实际需要步数)T_{\max} = \min(T_{\text{limit}},\ \text{实际需要步数})
  2. c_LLM,t(模型成本)第 t 步 LLM 推理花费的 token 费用与 GPU 资源。
    cLLM,t=pricetoken×tokenstc_{\text{LLM},t} = \text{price}_{\text{token}} \times \text{tokens}_t
  3. c_tool,t(工具成本)第 t 步外部工具的调用费用与网络延迟折算。
    ctool,t∈{0, API费用, 计算资源}c_{\text{tool},t} \in \{ 0,\ \text{API费用},\ \text{计算资源} \}

AI 应用场景

智能客服:自助解决多环节问题

阶段:推理增强 Prompt 的应用落地阶段

解决的问题:传统客服机器人只能将用户问题匹配到预设话术,一旦问题需要查订单、算差价、看物流等跨系统操作就无能为力;人工客服成本高、响应慢。ReAct 让客服机器人先思考用户意图,再依次调用订单查询、价格计算等工具,根据返回信息逐步组织回答,实现端到端自助解决。

具体案例:某电商平台的售后助手接到“我上周买的东西降价了,能退差价吗”。机器人先思考需要查询订单与当前价格,调用订单检索工具定位订单,再调用价格计算工具算出差价,确认退款规则后生成回复,全程无需人工介入。

数据分析助手:多步查询与归因分析

阶段:动态决策闭环的设计与调优

解决的问题:数据分析通常需要多轮 SQL 查询和对比判断。传统模板只能执行固定查询,无法根据中间结果调整方向。ReAct 让模型每一步根据查询结果思考下一步:先查总体趋势,发现异常区域后再深入查询该区域明细,最后汇总归因。

具体案例:一家连锁零售公司的分析助手收到问题“上季度华东区销售额为什么下滑”。模型先查询华东区季度销售额,发现某品类骤降;再查询该品类的库存与竞品数据,定位到缺货问题;最后输出带数据引用的分析报告。

代码辅助工具:执行-报错-修复循环

阶段:工具调用与观察反馈处理

解决的问题:让 AI 写出的代码必须可运行。单次生成的代码常有语法错误或逻辑错误。ReAct 让模型生成代码后自动提交执行,捕获报错信息作为观察,再进入“读报错→改代码→重新执行”的循环,直到测试通过。

具体案例:自动化编码代理在接到“写一个计算斐波那契数列的函数”任务后,先编写初版代码并执行,观察输出与预期不符,分析是递归边界问题,修改后再次执行验证,最终返回通过测试的代码。

Python 演示

python73 行
"""ReAct 推理+行动循环的极简模拟器(无需外部 LLM API) 用规则式 agent 演示 Thought -> Action -> Observation -> Thought 的闭环。"""KNOWLEDGE = {    "北京市人口": "2186万人",    "上海市人口": "2487万人",    "北京市面积": "1.64万平方公里",    "上海市面积": "0.63万平方公里",} def search(keyword):    """模拟搜索引擎:返回知识库中匹配的条目"""    for key_w, value in KNOWLEDGE.items():        if key_w in keyword:            return value    return "未找到相关信息" def calculator(expression):    """模拟计算器工具:计算简单数学表达式"""    try:        return str(eval(expression, {"__builtins__": {}}, {}))    except Exception:        return "表达式出错" class ReActDemo:    def __init__(self):        self.trajectory = []   # 保存完整推理轨迹        self.step_count = 0    # 记录当前步数        self.max_steps = 5     # 最大循环次数     def decide(self, prev_obs):        """思考+行动选择:根据上一步观察生成下一步指令"""        if not prev_obs:            return "需要先查两地人口数据", "搜索", "北京市人口"        if "2186万" in prev_obs:            return "北京人口已知,接下来查上海", "搜索", "上海市人口"        if "2487万" in prev_obs:            return "两地人口已齐,计算人口差值", "计算", "2487-2186"        return "差值已求出,给出最终答案", "完成", "301万人"     def execute(self, action, param):        """执行行动并返回观察结果"""        if action == "搜索":            return search(param)        if action == "计算":            return calculator(param)        return param     def run(self):        obs = ""        while self.step_count < self.max_steps:            thought, action, param = self.decide(obs)            if action == "完成":                self.trajectory.append((thought, "Finish", param))                print(f"[思考] {thought}")                print(f"[行动] Finish(最终答案)")                return param            obs = self.execute(action, param)            self.step_count += 1            self.trajectory.append((thought, action, param, obs))            print(f"[思考] {thought}")            print(f"[行动] {action}('{param}') -> [观察] {obs}")        return "达到最大步数,终止" def main():    agent = ReActDemo()    answer = agent.run()    print(f"\n最终答案:{answer}")    print(f"执行轮数:{len(agent.trajectory)}") if __name__ == "__main__":    main()
目的:用规则 agent 模拟 ReAct 的“思考→行动→观察→再思考”闭环,演示搜索与计算两个工具如何协作完成多步问答任务。
  1. KNOWLEDGE = {模拟外部知识库,相当于 ReAct 中工具背后的真实数据源
  2. def search(keyword):定义搜索引擎工具,对应 Prompt 中注册的一个工具
  3. def calculator(expression):定义计算器工具,用 eval 求值数学表达式
  4. self.trajectory = []保存完整推理轨迹,相当于 ReAct 中的上下文 History,供每一步思考参考
  5. def decide(self, prev_obs):核心方法,模拟模型的“思考+行动”:给定上一步观察,返回想法、行动名与参数
  6. obs = self.execute(action, param)执行行动并获得观察,对应循环中的 Action → Observation
  7. if action == "完成":终止判定的简化版:模型自信地输出最终答案并跳出循环
  8. print(f"[思考] {thought}")把思考过程打印出来,体现 ReAct“推理轨迹可见”的特性
  9. while self.step_count < self.max_steps:最大步数限制,对应正文中的 T_max 安全阀
  10. if __name__ == "__main__":程序入口,让脚本可被直接执行

常见误区

误区ReAct 不就是给大模型加个工具接口嘛,和普通 API 调用没本质区别,工具返回啥我直接复制给用户就行。

正解两者本质不同。普通 API 调用是“一次性交互”——调用工具、拿结果、结束;ReAct 的核心是“循环闭环”——每次工具结果都要作为观察流回思考,驱动下一步行动。没有“观察→再思考”这一步,就没有 ReAct。用侦探比喻:让助手去档案馆查一份档案并把结果贴在报告里,不等于让侦探“根据档案推理出下一步查什么”。

为何常见:因为工具调用(Function Calling)是当前主流大模型的标配能力,很容易把“能调工具”误当成 ReAct 的全部。

误区反正在保证质量的前提下多一步思考就能多核对一次信息,那我把最大步数设大点,让模型多绕几圈,准确率应该更高吧?

正解推理步数增加会带来三重风险:token 成本与延迟线性上升;错误观察被反复引用,形成误差累积;模型还可能陷入“工具调用死循环”——反复搜索同一个词条,毫无信息增益。终止条件(信心阈值 + T_max)的目的是在“足够好”时及时收手,而不是无限探索。办案不是查得越多越好,而是证据闭合就收网。

为何常见:直觉上“多查一步等于多一层保险”,忽略了 ReAct 每一步都有成本与出错概率。

误区模型那么聪明,我把工具名字告诉它就行了,参数格式它自己会猜吧?

正解大模型对工具的理解几乎完全来自 Prompt 中的工具描述和示例。描述含糊会导致:工具名被幻觉成不存在的名字、参数残缺、格式不当被解析器拒绝。好的工具描述要写清“功能、参数类型与含义、返回格式、适用场景”,并配合 1-2 条使用示例,模型才能稳定输出可解析的动作。

为何常见:因为人类天然觉得“这么简单的工具怎么可能会用错”,忽略了模型只能依赖文本描述来推测用法。

误区工具返回的内容肯定是对的,模型直接把这些数据当作推理依据就行了,不用怀疑。

正解工具返回可能超时、为空、包含噪声或直接报错;即便内容正确,也未必与当前问题相关。ReAct 要求模型在下一步思考中做信息甄别:这条观察可信吗?它与目标相关吗?要不要重试或换工具?照单全收等于放弃思考,把动态决策闭环降级为盲目的流水线。

为何常见:人类对“系统输出”有天然的权威信任,忽略了一个事实:外部环境的返回本身就充满不确定性。

面试题

Q1. ReAct 中三个核心环节的正确顺序是?

单选题 · easy

  • A.行动→思考→观察
  • B.思考→行动→观察← 正确答案
  • C.观察→行动→思考
  • D.思考→观察→行动

答案:B。ReAct 的标准循环是“思考→行动→观察→再思考”,即先推理确定下一步,再执行行动,最后接收反馈。选项 B 符合。这就像侦探先判断“要查监控”,再去调监控,最后看录像回放。

Q2. ReAct 中“Acting(行动)”指的是?

单选题 · easy

  • A.模型输出更长的回答
  • B.调用外部工具或环境的动作← 正确答案
  • C.模型在私有数据库中训练
  • D.模型自动复制并增强自己

答案:B。Acting 的核心是模型调用外部工具(如搜索引擎、计算器、数据库)或与环境交互,从而获取新信息。A 只是输出文本,C 和 D 是训练/演化层面的概念,均不属于 ReAct 的行动环节。

Q3. 在 ReAct 中,Observation(观察)信息的主要作用是?

单选题 · mid

  • A.省略思考直接输出答案
  • B.作为环境反馈供模型修正推理← 正确答案
  • C.提高模型自身的训练速度
  • D.完全替代所有外部工具

答案:B。观察是工具执行后返回的环境反馈,模型的下一轮思考会基于观察调整推理方向,形成闭环。A 跳过了思考环节,C 与推理无关,D 描述不成立,观察恰恰来自外部工具的执行结果。

Q4. 以下哪项是 ReAct Prompt 的典型组成?

单选题 · mid

  • A.仅包含角色与任务设定
  • B.角色任务工具描述加示例← 正确答案
  • C.仅包含工具的详细清单
  • D.仅包含历史对话记录

答案:B。ReAct Prompt 需要角色任务、工具描述、Few-shot 示例、约束边界等多模块组合,其中示例示范完整的“思考→行动→观察”轨迹尤其关键。A、C、D 都只覆盖了单一部分,不足以引导模型稳定地走完循环。

Q5. ReAct 相比纯 Chain-of-Thought(思维链)的最大区别是?

单选题 · mid

  • A.使用了更深层的神经网络
  • B.引入外部交互并动态修正推理← 正确答案
  • C.完全不需要编写 Prompt
  • D.只能处理数学计算问题

答案:B。纯思维链只在模型内部做文本推理,无法获取新信息;ReAct 则引入工具与环境的交互,让外部反馈参与推理修正。这正是 ReAct 的核心突破,B 正确。A 与网络结构无关,C、D 均与事实不符。

Q6. ReAct 循环通常何时终止?

单选题 · mid

  • A.模型无法支付 API 费用时
  • B.已给出答案或达到最大步数← 正确答案
  • C.生成第一个 token 时
  • D.工具调用返回空结果时

答案:B。终止条件有两个:模型对答案有足够信心(输出 Finish)或达到最大步数 T_max 被强制停止。工具返回空结果可以触发“换工具”或“重试”,但不一定终止循环。A、C 与循环逻辑无关。

Q7. ReAct 中常见的工具调用参数错误有哪些?

多选题 · mid

  • A.工具名称拼写不准确← 正确答案
  • B.参数格式不符合工具要求← 正确答案
  • C.同时调用多个不同工具
  • D.缺少任务必要的参数← 正确答案

答案:ABD。工具名拼错、参数格式不符、参数缺失都会导致解析失败或执行出错,是典型的动作层错误。C 并不是错误——虽然 ReAct 每步通常只调一个工具,但“同时调用多个”并不属于参数错误。

Q8. ReAct 在工程落地中的典型挑战包括?

多选题 · hard

  • A.多次调用的延迟与 token 成本← 正确答案
  • B.错误观察导致的偏差轨迹累积← 正确答案
  • C.模型完全不需要外部工具支持
  • D.步数上限设置不当导致任务失败← 正确答案

答案:ABD。每次循环都要消耗 LLM 调用与工具调用的成本,错误观察会被后续推理放大,步数上限设太小会截断有效探索,这些都是工程化时的主要难点。C 恰好与 ReAct 的前提相反。

Q9. 假设一次 LLM 调用成本 0.01 元、一次工具调用成本 0.02 元,一个 ReAct 任务平均执行 4 轮循环(每轮各一次),10 万次此类任务的总成本是多少?

单选题 · extreme

  • A.1.2 万元← 正确答案
  • B.12 万元
  • C.1200 元
  • D.120 万元

答案:A。每轮成本 = LLM 0.01 + 工具 0.02 = 0.03 元;4 轮 = 0.12 元;10 万次 = 12000 元 = 1.2 万元。这正是正文成本公式 Cost = Σ(c_LLM + c_tool) 的应用。

Q10. 下列哪些方向能提升 ReAct 系统的稳定性与效率?

多选题 · hard

  • A.引入自我反思机制复盘失败← 正确答案
  • B.实现长期记忆跨任务复用← 正确答案
  • C.忽略所有来自工具的反馈
  • D.设计更聪明的终止判断策略← 正确答案

答案:ABD。自我反思(Reflexion)能让模型从失败轨迹中学习,记忆持久化可避免重复查询,更聪明的终止判断(如信息增益不足时提前收手)能降低成本。C 直接违背 ReAct 的核心闭环,属于错误方向。