Agent 核心架构:思考-行动-观察循环(ReAct)
2026/7/5 12:54:18 网站建设 项目流程

Agent 核心架构:思考-行动-观察循环(ReAct)

ReAct 是 Agent 最经典的工作模式:思考要做什么 → 执行动作 → 观察结果 → 再思考下一步。这篇深入讲 ReAct 的原理、Prompt 模板设计、循环控制、停止条件,以及实际开发中的常见问题。

大家好,我是黒漂技术佬。

上一篇讲了 Agent 是什么,这篇深入核心架构:ReAct 循环。

Reason + Act = 推理 + 行动。Agent 不是一次性输出答案,而是像人解决问题一样,先想想要干嘛,动手做,看看结果,再决定下一步,循环往复直到搞定。

这篇讲 ReAct 的原理、Prompt 怎么写、循环怎么控制、怎么判断任务完成。


一、ReAct 是什么?

来源

ReAct 是 2022 年普林斯顿和 Google 提出的方法,论文《ReAct: Synergizing Reasoning and Acting in Language Models》。

核心思想:让大模型把「推理过程」和「行动」交替输出,边想边做。

循环结构

┌─────────────────────────────────────┐ │ Thought(思考):我现在要做什么? │ │ ↓ │ │ Action(行动):调用某个工具 │ │ ↓ │ │ Observation(观察):工具返回结果 │ │ ↓ │ │ 再 Thought:根据结果想下一步 │ └─────────── 循环直到完成 ────────────┘

每一轮输出一个 Thought + Action,拿到 Observation 后进入下一轮。

最终输出

当模型判断信息足够了,就输出 Final Answer,结束循环。


二、完整的 ReAct 示例

问题

张三出生于哪一年?他创办的公司上市了吗?

ReAct 过程

问题:张三出生于哪一年?他创办的公司上市了吗? Thought: 我需要先知道张三是谁、创办了什么公司,然后查他的出生年份和公司上市情况。 先搜索张三的基本信息。 Action: 搜索「张三 创始人 公司」 Observation: 张三,1980年出生,某科技公司创始人兼CEO,公司名为"未来科技", 2015年成立,主要做人工智能。 Thought: 知道了,张三1980年出生,创办了未来科技。接下来要查这家公司有没有上市。 Action: 搜索「未来科技 是否上市」 Observation: 未来科技于2021年在科创板上市,股票代码688XXX。 Thought: 信息都齐了:张三1980年出生,他的公司未来科技2021年科创板上市。 可以给出最终答案了。 Final Answer: 张三出生于1980年。他创办的未来科技公司已于2021年在科创板上市。

两轮思考+行动,就把问题解决了。


三、ReAct Prompt 模板

系统提示词(System Prompt)

告诉模型怎么按 ReAct 格式输出。核心要素:

  1. 说明有哪些工具可用
  2. 规定输出格式(Thought / Action / Action Input)
  3. 说明循环规则
  4. 什么时候输出 Final Answer

一个标准模板

你是一个智能助手,可以使用以下工具来回答问题: 工具列表: - 搜索:输入关键词,搜索互联网信息 - 计算器:输入数学表达式,计算结果 - 天气查询:输入城市名,获取实时天气 回答问题时严格按照以下格式输出: Thought: 你对当前问题的思考,说明接下来要做什么 Action: 工具名称 Action Input: 工具的输入参数 Observation: 工具返回的结果(这部分由系统填入,不用你写) (然后继续下一轮 Thought/Action,直到信息足够) 当你认为已经有足够信息回答问题时,输出: Final Answer: 最终的答案 注意: 1. 每次只输出一个 Action 2. 必须有 Observation 才能继续思考 3. 不确定的时候就搜索,不要瞎猜 4. 信息足够就立刻给出 Final Answer,不要多余步骤

为什么格式要严格?

因为程序要解析模型的输出,提取 Action 和 Action Input,然后去调用工具。格式乱了解析失败,整个循环就断了。

实际开发中,Function Calling 原生支持的模型更方便,不用手写解析。但理解 ReAct 的原理很重要。


四、循环控制流程

程序侧的执行流程

# 伪代码defagent_run(question,max_steps=10):history=""step=0whilestep<max_steps:# 1. 把历史拼到 prompt 里,调用大模型prompt=system_prompt+history+f"\n问题:{question}"response=llm(prompt)# 2. 解析模型输出if"Final Answer:"inresponse:returnextract_answer(response)action,action_input=parse_action(response)history+=response+"\n"# 3. 调用工具observation=call_tool(action,action_input)history+=f"Observation:{observation}\n"step+=1return"达到最大步数,未能完成任务"

关键要素

  1. 历史记录:每轮的 Thought/Action/Observation 都要传给模型,它要看着前面的过程继续想
  2. 解析输出:从模型回复里提取 Action 和参数
  3. 工具调用:执行实际的工具函数
  4. 停止条件:输出 Final Answer 或者达到最大步数

五、停止条件

正常停止:Final Answer

模型自己判断信息足够了,输出 Final Answer,循环结束。

异常停止

1. 最大步数限制

防止模型死循环,设一个最大轮数(比如 10 步),到了就强制停止。

ifstep>=max_steps:return"执行步数超限,任务未完成"
2. 重复 Action 检测

连续调用同一个工具同样的参数,说明卡住了,强制停止。

3. 错误累积

工具连续报错,说明方向不对,停止并提示。

4. 超时

整体执行时间设上限,防止某个步骤卡住太久。


六、ReAct 的变种

1. CoT(Chain of Thought)

只有思考,没有行动。就是让模型一步步想,但不调用外部工具。适合纯推理问题。

问题:一个苹果3块,买5个多少钱? 思考:一个3块,5个就是3×5。 计算:3×5=15 答案:15块

ReAct = CoT + 工具调用。

2. Plan-and-Execute

先做完整规划,再按计划执行。

Plan: 1. 查A 2. 查B 3. 对比总结 执行步骤1... 执行步骤2... 执行步骤3...

适合任务比较明确、步骤可以预先规划的场景。ReAct 是走一步看一步,Plan-and-Execute 是先想好全部再做。

3. Reflexion(反思型)

执行完之后反思效果好不好,不好就重来。

执行 → 评估结果 → 反思问题 → 重新执行

多了一个反思的步骤,质量更高但也更慢更贵。


七、Function Calling vs 手写 ReAct

原生 Function Calling

现在主流大模型(GPT、Claude、Qwen、DeepSeek)都原生支持 Function Calling / Tool Use。

你给模型一份工具的 JSON Schema 描述,模型直接输出要调用哪个函数、参数是什么,结构化输出,不用自己解析。

// 工具描述{"name":"search","description":"搜索互联网信息","parameters":{"type":"object","properties":{"query":{"type":"string","description":"搜索关键词"}},"required":["query"]}}

模型返回:

{"tool_calls":[{"name":"search","arguments":{"query":"张三 出生日期"}}]}

对比

手写 ReAct Prompt原生 Function Calling
格式稳定性容易乱,解析容易失败结构化输出,稳定
工具数量少了还行,多了容易乱支持多工具
兼容性所有模型都能用需要模型支持
开发成本高,要写解析逻辑低,直接用API

实际开发优先用原生 Function Calling。但理解 ReAct 的原理有助于调试和设计 Agent。


八、常见问题和优化

问题 1:模型不按格式输出

原因:Prompt 约束不够强,或者模型能力不够。

解决

  • 系统提示词写得更详细、更严格
  • 给 1-2 个示例(Few-shot)
  • 用支持 Function Calling 的模型
  • 输出解析加容错,匹配不到就重试

问题 2:死循环,反复调用同一个工具

原因:模型判断不了信息够不够,或者工具返回的结果它理解不了。

解决

  • 最大步数限制
  • 重复检测,连续 2-3 次同样的调用就强制停止
  • Prompt 里强调「信息足够就给 Final Answer」
  • 工具返回结果做摘要,别把太长的原文直接塞进去

问题 3:跳过工具,直接瞎答

原因:模型偷懒,或者没意识到需要用工具。

解决

  • Prompt 里强调「不知道的就搜索,不要编造」
  • 系统提示词里加「禁止直接回答需要实时信息的问题」
  • 用更听话的模型(比如 GPT-4)

问题 4:上下文太长爆了

原因:轮次多了,历史记录越来越长,token 超了。

解决

  • 工具结果做摘要,只保留关键信息
  • 历史记录截断,只保留最近几轮
  • 用总结代替完整历史

问题 5:工具调用参数错

原因:模型没理解工具参数的含义,或者格式不对。

解决

  • 工具描述写清楚每个参数的含义和格式
  • 加参数校验,不对就让模型重试
  • 给调用示例

九、一个最小可运行的 ReAct Agent(伪代码)

tools={"search":lambdaquery:search_web(query),"calc":lambdaexpr:str(eval(expr)),}system_prompt=""" 你可以使用以下工具: - search: 搜索,输入关键词 - calc: 计算器,输入数学表达式 格式: Thought: 思考 Action: 工具名 Action Input: 参数 Observation: 结果 信息足够就输出 Final Answer: 答案 """defrun(query):history=""for_inrange(10):# 最多10步prompt=system_prompt+history+f"\n问题:{query}\nThought:"resp=llm(prompt)if"Final Answer:"inresp:returnresp.split("Final Answer:")[-1].strip()# 解析 actionaction=extract(resp,"Action:")action_input=extract(resp,"Action Input:")# 调用工具obs=tools[action](action_input)history+=f"Thought:{resp}\nObservation:{obs}\n"return"超出步数限制"

实际开发不用自己写这么底层,LangChain 之类的框架都封装好了。但原理就是这么回事。


十、本篇小结

  • ReAct = Reason(推理)+ Act(行动),思考-行动-观察循环
  • 标准格式:Thought → Action → Observation,循环直到 Final Answer
  • 程序侧控制循环:拼历史 → 调模型 → 解析动作 → 调工具 → 拼结果 → 下一轮
  • 停止条件:输出 Final Answer、达到最大步数、重复检测、超时
  • 变种:CoT(纯思考)、Plan-and-Execute(先规划再执行)、Reflexion(带反思)
  • 实际开发优先用原生 Function Calling,比手写 ReAct 稳定很多
  • 常见问题:格式乱、死循环、跳过工具瞎答、上下文太长、参数错

下一篇讲工具调用:Function Calling 的具体用法、工具怎么定义、多工具怎么选、常见的工具类型。

我是黒漂技术佬。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询