09-Agent 设计三阶段:ReAct → Memory → Reflection

Agent 设计三阶段:ReAct → Memory → Reflection

你用过 ChatGPT------一问一答。你还用过 LangGraph 的 Supervisor 模式------多个 Agent 协作完成任务。但你知道怎么从前者升级到后者吗?这篇文章把 Agent 设计拆成三个阶段,每阶段加一个核心能力,最终从零构建一个能自主研究、有记忆、会反思的智能体。


Agent 到底是什么

Agent = LLM + 工具 + 记忆 + 自主决策循环

别被"智能体"这个名字吓到。Chat 和 Agent 的区别,一句话就能说清楚:

复制代码
Chat:  用户 → LLM → 回复 → 结束
Agent: 用户 → LLM → 思考 → 选工具 → 执行 → 观察结果 → 再思考 → ... → 完成任务

Chat 是"一问一答",Agent 是"自主完成一个目标"。你告诉 Agent "帮我调研 LangGraph 和 CrewAI 的差异",它不会一次回答你,而是会自己搜索、自己整理、自己写报告。

Agent 的四个核心要素:

要素 角色 类比
LLM(大脑) 理解任务、推理、决策 大脑皮层
Planning(策略) 拆解任务、规划步骤 前额叶
Tools(工具) 执行具体操作 手脚
Memory(记忆) 记住上下文和经验 海马体

阶段一:ReAct ------ 让 LLM 学会"边想边做"

ReAct 是什么

ReAct = Reasoning(推理)+ Acting(行动)交替进行。

这是 Google DeepMind 2022 年提出的范式,如今是所有 Agent 的基础架构。流程极其简单:

复制代码
┌──────────┐    ┌──────────┐    ┌──────────────┐
│ Thought  │───►│  Action  │───►│ Observation  │
│ (推理)   │    │ (行动)   │    │  (观察)      │
└──────────┘    └──────────┘    └──────────────┘
      ▲                              │
      └──────────────────────────────┘
              循环直到 Final Answer

一个完整的 ReAct 过程

复制代码
任务:LangGraph 最新版本是多少?支持哪些 Python 版本?

Step 1:
  Thought: 我需要搜索 LangGraph 的最新版本信息。
  Action: search("LangGraph latest version 2026")
  Observation: LangGraph 1.2.0 已发布,支持 Python 3.10-3.13

Step 2:
  Thought: 已获取版本号和 Python 支持范围,信息齐全。
  Final Answer: LangGraph 最新版为 1.2.0,支持 Python 3.10 到 3.13。

最简 ReAct Agent 实现

python 复制代码
# 30 行代码的 ReAct Agent
def react_agent(task: str, max_steps: int = 10) -> str:
    history = [{"role": "user", "content": task}]

    for step in range(max_steps):
        response = llm.chat(history)  # LLM 输出 Thought + Action 或 Final Answer

        if "Final Answer:" in response:
            return response.split("Final Answer:")[-1].strip()

        if "Action:" in response:
            action = parse_action(response)  # 解析:Action: search("query")
            result = execute_tool(action)     # 执行工具
            history.append({"role": "user", "content": f"Observation: {result}"})

    return "达到最大步数限制"

三个关键点:

  • 循环:不是调用一次 LLM,而是一直循环直到完成任务
  • 工具调用:LLM 通过特定格式声明要调什么工具、传什么参数
  • 观察反馈:工具结果注入对话历史,LLM 据此调整下一步

ReAct 的 Prompt 模板

这是让 LLM 进入 ReAct 模式的关键------一个精心设计的 Prompt:

复制代码
你是一个研究助手。按以下格式回答:

Question: 用户的问题
Thought: 你当前的思考
Action: 要执行的动作,格式:tool_name(tool_input)
Observation: 工具返回的结果
... (Thought/Action/Observation 可重复)
Thought: 最终思考
Final Answer: 最终答案

可用工具:
- search(query: str): 搜索互联网
- calculator(expression: str): 计算数学表达式

Question: {question}

ReAct 为什么有效? 四个原因:

  1. 思考链可见------每一步推理都可追溯,调试不靠猜
  2. 工具与推理解耦------推理归 LLM,执行归工具,各司其职
  3. 自我纠正------观察到意外结果,LLM 可以调整下一步
  4. 可中断可恢复------任何一步都可以检查、修改后继续

阶段二:Memory ------ 让 Agent 不再"失忆"

为什么需要记忆

阶段一的问题:Agent 只能在一次调用内保持连贯。跨调用?完全不记得。

复制代码
用户第 1 次:「帮我研究一下 ReAct 范式」
Agent 搜了一堆资料 → 生成报告 → 结束(所有中间结果丢失)

用户第 2 次:「再研究一下 Reflection」
Agent 从头开始,不知道你刚研究过 ReAct → 重复搜索

记忆系统解决的就是这个问题------让 Agent 记住"之前干了什么"和"之前学了什么"。

两层记忆

复制代码
┌──────────────────────────────────────────────┐
│ 短期记忆(Short-term Memory)                  │
│   当前对话的完整历史                            │
│   作用:理解上下文、追踪多轮对话                 │
│   实现:对话历史列表(memory.short_term)       │
│   类比:会议中的白板                            │
├──────────────────────────────────────────────┤
│ 长期记忆(Long-term Memory)                   │
│   跨会话保留的知识和总结                        │
│   作用:积累经验、避免重复搜索                   │
│   实现:向量数据库或简单 dict 存储               │
│   类比:会议纪要存档                            │
└──────────────────────────────────────────────┘

记忆系统实现

python 复制代码
class MemorySystem:
    def __init__(self):
        self.short_term: list[dict] = []       # 短期:对话历史
        self.long_term: dict[str, str] = {}    # 长期:topic → summary
        self.index: dict[str, list[str]] = {}  # 索引:topic → keywords

    def remember(self, topic: str, summary: str):
        """存入长期记忆"""
        self.long_term[topic] = summary
        self.index[topic] = [w for w in topic.lower().split() if len(w) > 1]

    def recall(self, query: str) -> list[dict]:
        """从长期记忆中检索相关知识"""
        query_words = set(query.lower().split())
        matches = []
        for topic, summary in self.long_term.items():
            index_words = set(self.index.get(topic, []))
            if query_words & index_words:  # 有交集 → 相关
                matches.append({"topic": topic, "summary": summary})
        return sorted(matches, key=lambda m: len(query_words & set(m["topic"].split())), reverse=True)

    def summarize_context(self, max_tokens: int = 500) -> str:
        """压缩短期记忆,避免 token 爆炸"""
        if len(self.short_term) <= 3:
            return "\n".join(str(m) for m in self.short_term)
        # 保留最近 2 条完整,更早的做摘要
        recent = self.short_term[-2:]
        older_summary = f"[前{len(self.short_term)-2}步] " + " → ".join(
            m["thought"][:50] for m in self.short_term[-5:-2]
        )
        return older_summary + "\n" + "\n".join(str(m) for m in recent)

Token 预算管理

ReAct 循环中,每一步的 Thought/Action/Observation 都会加入对话历史。10 步之后,历史可能膨胀到 5000+ tokens。解决方案:上下文压缩------超过阈值时,将早期步骤压缩为摘要,只保留最近几轮的完整信息。


阶段三:Reflection ------ 让 Agent 学会"自我纠错"

反思是什么

阶段二的 Agent 能搜索、能记忆、能生成报告------但它从不检查自己的输出质量。

Reflection(反思)= Agent 审视自己的输出,发现不足并自我改进。

复制代码
┌──────────┐    ┌──────────┐    ┌──────────┐
│ Generate │───►│  Review  │───►│  Revise  │
│ (生成)   │    │ (审视)   │    │ (修改)   │
└──────────┘    └──────────┘    └──────────┘
                      │               │
                 检查通过?         不通过
                      │               │
                      ▼               │
                  ┌──────────┐        │
                  │  Output  │◄───────┘
                  └──────────┘

两阶段架构:生成 + 反思

第一阶段(生成 Agent)------用 ReAct 循环生成初始报告。

第二阶段(反思 Agent)------用另一个视角审视报告。注意,反思可以用同一个 LLM(内省式),也可以用另一个 LLM(对抗式,效果更好)。

python 复制代码
REFLECTION_PROMPT = """请审视以下报告,按以下维度检查:

1. 事实准确性:所有数据是否有来源支撑?
2. 完整性:是否覆盖了问题的所有方面?
3. 逻辑性:论证链条是否有漏洞?
4. 清晰度:表述是否容易理解?

给出:
- 评分(1-10)
- 具体问题清单
- 改进建议

如果评分 >= 8,输出 "PASS"。

报告内容:
{report}
"""

防止无限反思

反思机制一个必须处理的问题:Agent 可能反复修改,没完没了。

python 复制代码
MAX_REFLECTION_ROUNDS = 3
PASS_THRESHOLD = 7  # 评分 >= 7 就通过

for round in range(MAX_REFLECTION_ROUNDS):
    review = reflector.review(report, task)

    if review["score"] >= PASS_THRESHOLD:
        break  # 达标,结束

    report = reflector.revise(report, review)  # 修改后继续

    if round == MAX_REFLECTION_ROUNDS - 1:
        print(f"达到最大修改轮次,停止反思")

两条硬规则:最大轮次 + 质量阈值。 少一条都可能出问题。


三种设计模式全景对比

ReAct 不是唯一的 Agent 模式。这里是一张完整的对比表:

模式 核心循环 优点 缺点 适用场景
ReAct Think→Act→Observe 简单可靠,可追溯 复杂任务容易迷路 搜索、问答
Plan-Execute Plan→Execute 路线清晰 计划可能过时 多步工作流
ReWOO Plan→Tool use→Solve 减少 LLM 调用 缺少中间纠正 Token 敏感任务
LLMCompiler 并行执行 DAG 速度快 依赖需明确 可并行的多工具
Reflexion ReAct + 反思 质量高 延迟和成本翻倍 需要高质量输出
Multi-Agent 多角色协作 专业化 协调开销大 复杂项目

选择决策树:

复制代码
任务复杂度?
│
├── 简单(1-2步)→ 直接 ReAct
│
├── 中等(3-5步)→ ReAct + Reflection
│
└── 复杂(>5步或含子任务)
    │
    ├── 子任务独立 → Multi-Agent(Supervisor 模式)
    └── 子任务有依赖 → Plan-Execute + Reflection

生产环境避坑指南

1. Token 成本

ReAct 每步都要调 LLM。一个 10 步的 Agent 任务可能消耗 10 次 × 2000 tokens = 20000 tokens。缓解方案:上下文压缩、中间结果摘要、选择更便宜的模型做简单推理。

2. 死循环

Agent 可能在同一个工具上反复调用。必须设置 max_steps 和循环检测------如果连续 3 步都在调同一个工具且结果相同,强制终止。

3. 幻觉

LLM 可能编造工具调用结果。反思阶段的"事实检查"就是针对这个------强制要求每个结论标注来源。

4. 工具失败

搜索超时、API 限流、参数错误......每个工具都需要异常处理和降级策略。

5. 可观测性

你不知道 Agent 中间干了什么?打印每一步的 Thought/Action/Observation,或接入 LangSmith 做全链路追踪。


总结

Agent 设计的过程,本质上是把"人类完成任务的流程"逐步赋给 LLM:

  1. ReAct(阶段一)------让 LLM 进入"边想边做"的循环,不再是单次问答
  2. Memory(阶段二)------加上短期和长期记忆,让 Agent 记住经验、跨对话关联
  3. Reflection(阶段三)------加上自我审视机制,让 Agent 从"做完"升级到"做好"

三个阶段的代码都在 github.com/barryness/cc-ai-learning009-agent-learning/agent_demo.py,按 --phase 1/2/3 分别运行,每个阶段都是独立的可跑 Demo。

相关推荐
程序员契奇1 小时前
12_Agent的Hook补充+控制Agent+流式输出+总结
人工智能·agent
linge_sun1 小时前
SpringAI 功能体验之SQL智能助手:用自然语言查询数据库
java·人工智能·ai编程
qcx232 小时前
【AI Daily 2026-06-05】「持续迭代」已成为 2026 年 Agent 研究的核心命题
人工智能·python·agent
沉默王二2 小时前
刚上线就斩获 2.3K 星标!AnySearch 搜索能力拉满!
agent·ai编程·claude
腾视科技AI2 小时前
安全驾驶 智在掌控|腾视科技ES06车载智能终端,为车辆运营赋能
大数据·人工智能·科技·安全·ai·边缘计算·车载智能终端
weixin_428005302 小时前
C#调用 AI学习从0开始-第2阶段(Function Calling+工具调用智能体)-第9天实战
人工智能·学习·ai·c#·functioncalling
咖啡星人k2 小时前
开源AI编程的安全性:MonkeyCode 容器沙箱隔离方案深度解析
ai编程
姚青&3 小时前
编写基于 AST 的自定义 Linter
ai
ofoxcoding3 小时前
MiniMax M3 实测手记:踩完坑之后,我总结了报错处理和省 token 的几个办法
java·前端·人工智能·ai