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

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 的原理很重要。


四、循环控制流程

程序侧的执行流程

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

关键要素

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

五、停止条件

正常停止:Final Answer

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

异常停止

1. 最大步数限制

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

python 复制代码
if step >= 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 描述,模型直接输出要调用哪个函数、参数是什么,结构化输出,不用自己解析。

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

模型返回:

json 复制代码
{
    "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(伪代码)

python 复制代码
tools = {
    "search": lambda query: search_web(query),
    "calc": lambda expr: str(eval(expr)),
}

system_prompt = """
你可以使用以下工具:
- search: 搜索,输入关键词
- calc: 计算器,输入数学表达式

格式:
Thought: 思考
Action: 工具名
Action Input: 参数
Observation: 结果

信息足够就输出 Final Answer: 答案
"""

def run(query):
    history = ""
    for _ in range(10):  # 最多10步
        prompt = system_prompt + history + f"\n问题:{query}\nThought:"
        resp = llm(prompt)
        
        if "Final Answer:" in resp:
            return resp.split("Final Answer:")[-1].strip()
        
        # 解析 action
        action = 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 的具体用法、工具怎么定义、多工具怎么选、常见的工具类型。

我是黒漂技术佬。

相关推荐
HyperAI超神经1 小时前
活动预告|智源/TileRT/腾讯/华为/智元创新同台,共探 AI 编译的多层级协同优化
人工智能·ai 编译器·腾讯·具身智能·矩阵乘法·算子优化·华为昇腾
在水一缸1 小时前
GLM 5.2 发布:当长上下文与智能体走向深度融合
人工智能·大模型·智能体·智谱ai·长上下文·glm-5.2
小妖同学学AI2 小时前
AI编程 AI Ping+Cline搭建自己的编程助手!
人工智能·ai编程
菩提小狗2 小时前
每日极客日报 · 2026年07月04日
ai·开源·极客日报·it热点·技术资讯
星马梦缘2 小时前
机器学习与模式识别 第十四章 神经网络中的反向传播 考点压缩
人工智能·机器学习·微分·反向传播
love530love2 小时前
WorkBuddy + 本地 ComfyUI MCP:免订阅费的自建方案
人工智能·windows·mcp·comfy cloud
oscar9992 小时前
Codex 编程智能体入门指南
ai·chatgpt·codex