ReAct 模式是什么?和 Function Calling 有什么关系?

进阶高频原理约 6 分钟读完

一句话回答

ReAct(Reasoning + Acting)让模型交替进行推理和行动:先想清楚下一步做什么(Thought),再调用工具(Action),拿到结果(Observation)后接着推理,循环到能给出答案为止。ReAct 是一种组织 Agent 推理和行动的模式;Function Calling 是一种接口能力,让模型以结构化的方式表达"调用哪个工具、传什么参数"。早期 ReAct 靠 Prompt 约定文本格式、再用正则解析来实现;现在通常基于原生工具调用实现,推理体现在模型调用工具前写的说明里,或者推理模型内部的思考过程里。

详细解析

为什么要让推理和行动交替进行

方式 做法 问题
只推理(思维链) 模型一步步推理后直接回答 缺少外部信息,容易编造事实
只行动 模型直接连续调用工具 缺少推理,难以规划多步任务,遇到意外结果也不善于调整
ReAct 用推理决定下一步行动,用行动得到的信息修正推理 步骤多,耗时和成本更高

ReAct 出自 Yao 等人 2022 年的论文。核心思想是两者互补:推理让行动有计划、能随结果调整,行动给推理提供真实依据,减少凭空编造。什么是 Agent 里有一个最简单的例子,下面看一个结果会改变后续决策的轨迹。

一段轨迹

文本
问题:我上周买的耳机怎么还没到?

Thought: 先找到用户最近购买耳机的订单
Action: search_orders({"keyword": "耳机"})
Observation: 订单 O123,已发货,快递单号 SF1001
Thought: 已经发货,接下来查物流
Action: track_shipment({"trackingNo": "SF1001"})
Observation: 3 天前到达转运中心,之后没有更新
Thought: 物流停滞超过 3 天,属于异常,按规则可以帮用户催件
Action: create_ticket({"type": "催件", "orderId": "O123"})
Observation: 工单 T88 已创建
Final Answer: 订单已经发货,但物流 3 天没有更新,已为你创建催件工单 T88……

第二步和第三步做什么,都取决于上一步的观察结果,这是 ReAct 和"一次性规划好再执行"的区别。

早期实现:Prompt 约定格式,再解析文本

TypeScript
const prompt = `你可以使用以下工具:${toolDescriptions}
按下面的格式交替输出,直到得出答案:
Thought: 你的思考
Action: 工具名[输入]
Observation: 工具结果(由系统填写,你不要写)
Final Answer: 最终答案

问题:${question}
${history}`

// llm.complete 是文本补全的伪接口。遇到 Observation 就停止,防止模型自己编造工具结果
const text = await llm.complete({ prompt, stop: ['\nObservation:'] })
const final = text.match(/Final Answer:\s*([\s\S]*)/)
const action = text.match(/Action:\s*(\w+)\[([\s\S]*?)\]/)
// 两者都匹配不到说明格式不对,要把错误提示追加到 history 里让模型重来

这种写法的问题:格式经常出错,解析容易失败;参数只能是一段字符串,很难表达结构化的参数;工具结果和指令混在同一段文本里。

现在的实现:基于原生工具调用

  • 工具定义通过接口参数传入,模型用专门的结构返回工具名和 JSON 参数,不用再解析文本
  • 工具结果作为单独的消息回传,和普通对话内容分开,模型也没法"替系统"编造结果
  • Thought 的位置:可以是模型调用工具前输出的一段说明文字;推理模型则在内部的思考过程中完成。不少接口只返回思考的摘要或加密数据,不返回完整原文。多步工具调用时,有的接口要求把返回的思考块原样回传(如 Anthropic 的 thinking 块,同一轮工具调用中必须完整、不加修改地传回),有的建议回传(如 OpenAI Responses API 的 reasoning 项),让模型接着之前的推理继续
  • 循环的完整代码见 手写一个最小的 Agent 循环
ReAct Function Calling
是什么 组织推理和行动的 Agent 模式 模型以结构化方式提出工具调用的能力
解决的问题 什么时候想、什么时候做、怎么根据结果调整 怎么表达"调用哪个工具、参数是什么"
关系 可以用文本解析实现,也可以用 Function Calling 实现 也可以脱离 ReAct 单独用,比如一次调用完成信息抽取

ReAct 的问题

  • 步骤多:每一步都是一次模型调用,延迟和成本随步数增加,上下文越来越长
  • 容易跑偏:只看眼前一步,缺少全局计划;前面一步出错会一路传下去;可能在两个动作之间来回打转
  • 被观察结果带偏:工具返回的内容很长或带有误导信息时,模型可能偏离最初的目标

改进方向:先做计划再执行,见 Agent 的规划能力是怎么实现的;设置步数上限和重复检测,见 怎么防止 Agent 失控。

面试官可能追问

用推理模型时,还需要在 Prompt 里要求模型先写 Thought 吗?

一般不需要。推理模型会在内部先思考,再要求它把推理过程写出来,往往是重复劳动,还多花 token。对非推理模型,在复杂任务里让它调用工具前用一两句话说明意图,有助于提升效果,也方便排查问题。见 思维链和推理模型是什么。

ReAct 和思维链(CoT)有什么区别?

思维链只在模型内部推理,不获取新信息,事实性的错误它自己发现不了。ReAct 在推理过程中穿插行动,用外部信息校正推理。信息已经齐全的推理题用思维链就够了;需要查询或操作外部系统的任务,才需要 ReAct。

为什么早期实现要设置 stop 序列?

模型是按格式续写文本的,写完 Action 后很可能顺手写出一段 Observation,相当于自己编造了工具结果。在 Observation 处停止生成,由应用执行真正的工具,再把结果填进去。原生工具调用把工具结果放在单独的消息里,从结构上避免了这个问题。

易错点

  • 把 ReAct 当成某个框架或 API。它是一种模式,任何能调用工具的循环都可以实现
  • 把 ReAct 和 Function Calling 混为一谈:一个是组织方式,一个是接口能力
  • 认为思考写得越长越好。推理会增加延迟和成本,简单任务直接行动反而更好

AI 模拟面试官

用自己的话回答,AI 对照参考答案打分、指出遗漏,再追问,最多 3 轮

登录后就可以和 AI 面试官对练,面试记录也会保存下来。登录

这道题你掌握了吗?

选一个最接近的状态,没掌握的题会出现在"我的进度 · 待复习"里。

学习记录暂存在本机浏览器。登录后自动同步到账号,换设备也能看到。