ReAct 与 Plan-Execute:两种 Agent 范式的实战对比

前言

在前面写了第一个 Agent Loop(think → act → observe),但它有个局限:只能做"一次工具调用 + 一次回复" 。这次我把 Agent 升级成两种真正的"范式"------ReAct 和 Plan-Execute,并且接入了 MCP(Model Context Protocol)让工具调用走标准协议。

这篇文章讲三个东西:两种范式怎么选、MCP 怎么接入、以及模型选型踩的一个大坑。


一、ReAct:边想边做

ReAct 让 LLM 交替输出「思考」和「行动」:

yaml 复制代码
Thought: 用户需要电子摇滚,BPM 130-150 → 调用 search_catalog
Action: search_catalog({style: 电子摇滚, bpm_min: 130, bpm_max: 150, budget: 3000})
Observation: 返回甜蜜蜜 (BPM 140) 和 Neon Pulse (BPM 135)
Thought: 两首都符合 → 回答用户
Action: Final Answer

和 Agent Loop 的区别 :Agent Loop 是"调用一次工具就回答",ReAct 是"可能连续调多个工具直到攒够信息"。所以 MAX_STEPS=6,比 Agent Loop 的 MAX_TURNS=3 大------给模型探索空间,但 6 轮封顶防死循环。

前端类比:ReAct ≈ 事件循环里每个 tick 决策------边跑边改,遇到新信息现场调整。

实测发现 :7b 模型会重复调用同一个工具(拿到数据后又调了一次同样的参数)。MAX_STEPS 正好兜住这种行为------浪费一轮但不死循环。这是 ReAct 在小模型上的常见失败模式。


二、Plan-Execute:先计划再执行

Plan-Execute 分两步:第一步让 LLM 生成完整计划,第二步逐步执行

bash 复制代码
Step 1: {"plan": ["确定 BPM 范围", "检索曲库", "筛选适合健身房的", "查询授权价"]}
Step 2-5: 逐条执行,记录每步的 done/result

和 ReAct 的区别

  • ReAct:路径不确定,边走边看------适合探索型任务("帮我查一下...")
  • Plan-Execute:步骤明确,先拆解再执行------适合复杂规划("写一个 RAG 架构文档")

前端类比:ReAct ≈ 每个 tick 决策的事件循环;Plan-Execute ≈ 先写 TODO list 再执行------任务拆解 + 逐个完成。

踩的坑(这个必须记录) :qwen2.5:7b 生成计划时输出了非法 JSON ------数组元素写成 ["步骤1": "内容"](带键值对),json.loads 直接抛错。根因是模型对 prompt 示例 ["步骤1", "步骤2"] 过度模仿,把序号当成了对象键。解法是解析层加修复:正则剥掉 "步骤N": 前缀。

教训:永远别指望小模型输出严格 JSON,解析层必须容错。这是 W3 JSON mode 的实战补充------schema 校验是"事后检查",修复层是"事前补救"。


三、MCP 接入:让工具调用走标准协议

项目要求接入至少一个 MCP server。我把 W4 的 search_catalog 注册成了 MCP 工具,然后写了适配器让 ReActAgent 通过 MCP 调用它。

MCP server@tool() 装饰器注册):

python 复制代码
server = MCPServer("music-catalog-server")

@server.tool(name="search_catalog", description="根据风格/BPM/预算检索曲库")
async def search_catalog(style: str, bpm_min: int, bpm_max: int, budget: int):
    ...

接入 Agent 的关键设计------适配器 :ReActAgent 只认 execute(name, arguments) → {"success", "result"/"error"} 这个接口。我写了个 MCPToolAdapter 实现同样的接口,内部走 MCP 协议:

ini 复制代码
# W4 手写:executor.execute(name, args) → 直接调本地函数
# MCP:adapter.execute(name, args) → JSON-RPC 到 server → 返回

# Agent 一行不改,只要注入不同的 executor:
agent = ReActAgent(executor=ToolExecutor(registry))   # W4 方式
agent = ReActAgent(executor=MCPToolAdapter(client))   # MCP 方式

前端类比 :手写 executor ≈ 直接 import 函数调用;MCP 适配器 ≈ 换成 HTTP API 调用------协议变了,接口不变。这就是适配器模式:依赖接口而非实现。

踩的坑(这个最有价值) :一开始适配器的 list_tools() 只返回了工具名和描述,没返回参数 schema 。结果模型完全不知道工具要什么参数,瞎猜了 4 次(genre/bpm_range/budget_per_song)全部失败。把 input_schema 加进返回后,模型一次就猜对了style/bpm_min/bpm_max/budget)。

教训:schema 必须传给 LLM------这和 W4 的"JSON Schema 给模型的菜单"是同一个设计:不给菜单,模型只能瞎点菜。

MCP SDK 新版 API 的坑 :旧版 fastmcp / Client(read, write) 全变了。新版是 MCPServer + Client(in-memory/URL 高层封装)+ ClientSession(stdio 流)。ClientSession 必须显式 await client.initialize() ,否则 tools/list 报 Invalid request parameters------这是我精读时没覆盖到的细节,实测才发现。


四、模型选型:任务形态决定模型

默认模型换了几次,踩了个大坑:

模型 耗时 结果
qwen2.5:7b 5.8s ✅ 快,但 JSON 不稳、ReAct 重复调工具
deepseek-r1:8b >113s ❌ 慢到不可接受
qwen2.5:14b 16.6s ✅ JSON 稳定,定为默认

为什么 r1:8b 不可用 :ReAct 的"思考"已经写死在 prompt 里 (让模型输出 thought 字段),它不需要 R1 那样的隐式思维链。R1 把大量 token 花在 CoT 上,拖慢速度还干扰 JSON 输出------推理模型的强项在这里用不上,短板(慢 + JSON 不稳)却正中要害

选型原则:模型选型要匹配任务形态。推理模型(R1)适合深度分析场景;执行模型(qwen)适合"结构化输出 + 工具调用"场景。ReAct 是执行型任务,不是推理型任务。


五、多轮记忆

之前每次 run() 都从零开始,用户说"对,就是那首"时"那首"没有上下文。前面补全两个记忆:

  • 短期记忆(ShortTermMemory):会话内的消息历史,放 messages 里------≈ React 组件内 state
  • 长期记忆(LongTermMemory):跨会话的用户事实,存 JSON 文件,启动时加载------≈ localStorage

长期记忆的持久化有个细节:__init__ 必须先读文件再初始化 ,否则重开实例数据全丢。测试 test_persistence 专门验证这个。


结论

ReAct 是"边想边做"的探索者,Plan-Execute 是"先计划再执行"的规划师------任务形态决定范式选择。

这周最大的三个收获:schema 必须传给 LLM (不然它只能瞎猜)、小模型 JSON 必须容错 (修复层不是可选项)、模型选型匹配任务形态(推理模型不是万能的)。

从 手写 Agent Loop,到 ReAct + Plan-Execute + MCP------ Agent 终于有了"范式"和"协议",不再是单次调用。

相关推荐
用户61595868000221 小时前
从零原生搭建一个微前端简易框架
前端
小月土星1 小时前
React + TypeScript 企业级开发实战:从类型约束到组件设计
前端
玉鸯1 小时前
多 Agent 并行时如何保证状态一致性?
分布式·python·agent
沙洲1 小时前
Vite 环境变量终极指南:从原理到企业级实战
前端
刘婉晴1 小时前
【Web漏洞】SQL 注入实战技巧
前端·数据库·sql
di24k24k2 小时前
多个 el-form 共用同一 ref 导致表单校验部分失效
前端·javascript·vue.js·elementui
NutShell Wang2 小时前
每帧重建整条路径、每秒倾倒 48MB 给 GC:实时折线图渲染架构的实测复盘
前端·性能优化·架构·图形渲染·数据可视化·vibe coding
小彤花园2 小时前
和 AI 结对写网站:从 JSON 到一整个工具集
前端·人工智能·程序员
CoovallyAIHub2 小时前
Coco 在病房:一个企业级 AI Agent,如何帮住院医师省下每天三小时的文书时间
操作系统·agent·产品