三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

从“一步一想”到“先全局规划”:ReAct vs Plan-and-Execute,AI Agent的两种“思考方式”

从“一步一想”到“先全局规划”:ReAct vs Plan-and-Execute,AI Agent的两种“思考方式”

让Java开发者像写Spring Boot一样开发AI应用——第四课

写在前面

前三天,我们学会了创建单Agent、理解ReAct循环、构建多Agent协作系统。

但有一个问题始终在困扰着许多开发者:ReAct Agent运行时,为什么经常“原地打转”?

明明已经查过天气了,它又查一遍;明明已经得到答案了,它还在继续思考。

这不是你的代码写错了,而是ReAct模式本身存在结构性缺陷

今天的课,我们不仅要解剖ReAct的三大缺陷,还要引入另一种截然不同的思考方式——Plan-and-Execute,并告诉你什么时候该用哪种模式

一、ReAct的困境:为什么Agent会“原地打转”?

先快速回顾ReAct的核心循环:

Thought(思考)→ Action(行动)→ Observation(观察)→ Thought → …

ReAct将推理(Reasoning)和行动(Acting)相结合,通过持续观察环境反馈动态调整决策路径。它的本质是:CoT(思维链)+ 工具调用 + 环境反馈闭环

就像一个经验丰富的老医生——问一句、查一下、想一想,再决定下一步怎么做。

但问题也恰恰出在这里。

缺陷一:无限循环(Infinite Loop)

ReAct最致命的缺陷:Agent可能陷入Thought→Action→Observation的死循环,反复执行相同的操作而无法推进任务。

Thought: 我需要查天气 Action: 调用 get_weather("上海") Observation: 上海晴,25°C Thought: 我需要查天气 ← 又回到原点! Action: 调用 get_weather("上海") ← 重复调用 Observation: 上海晴,25°C ← 无限循环...

为什么会发生?

  • 模型“忘记”了自己已经做过什么
  • 模型对当前进度缺乏清晰的认知
  • 没有内置的“停止”机制

💡解决方案:设置最大迭代次数(recursion limit),通常25-30次是合理阈值。

缺陷二:上下文爆炸(Context Explosion)

ReAct的每一步Thought→Action→Observation都会追加到上下文中。随着循环次数增加,上下文越来越长,最终导致:

  • Token消耗激增
  • 触发上下文窗口限制
  • “关键信息遗忘”(Lost in the Middle)问题

💡 就像一个人不停地往背包里塞东西——背包越来越重,最后连钥匙都找不到了。

缺陷三:缺乏全局规划视角

ReAct的“规划”仍是单路径、线性的——它不能并行探索多条方案,也不能在推理链死胡同时回溯。每一步只考虑当前信息,缺乏对整体任务的全盘把握。

💡课堂话术:ReAct就像一个没有地图的探险家——边走边看,遇到岔路就随机选一条。运气好能走出来,运气不好就在原地打转。

ReAct缺陷总结

缺陷表现后果
无限循环反复执行相同操作任务永远无法完成,API额度刷光
上下文爆炸每一步都追加到上下文Token消耗激增,关键信息丢失
缺乏全局视角每一步只考虑当前信息容易“走弯路”,路径低效

ReAct仍然适用的场景

尽管有上述缺陷,ReAct在以下场景中仍然是最佳选择:

  • 动态环境:需要实时响应环境变化的任务(如实时故障修复、股票交易)
  • 探索性任务:解决方案路径不明确,需要边试边找
  • 对话式交互:用户与Agent多轮对话的场景
  • 工具数量有限:工具集在3-5个以内

二、Plan-and-Execute:换个思路解决问题

Plan-and-Execute模式的哲学很简单:先把整个任务想明白,拆解成有序的步骤,然后逐步执行

用户输入 → Planner(规划器)生成完整计划 → Executor(执行器)按步骤执行 → 输出结果

两个核心角色

角色职责特点
Planner(规划器)根据用户输入生成详细的任务规划和执行方案“想”,不调用工具
Executor(执行器)依据规划内容执行具体任务“做”,按计划调用工具

完整流程

第一步:规划阶段(Planning)

Planner Agent接收用户目标,生成一个结构化的任务计划:

{"goal":"规划一次杭州三日游","steps":[{"id":1,"action":"查询杭州未来3天天气","tool":"get_weather"},{"id":2,"action":"根据天气推荐景点","tool":"recommend_attractions"},{"id":3,"action":"规划每日行程安排","tool":"plan_itinerary"},{"id":4,"action":"推荐酒店和餐饮","tool":"recommend_hotels"}]}

第二步:执行阶段(Execution)

Executor按计划逐步执行,每一步可调用工具。如果步骤之间相互独立,还可以并行执行

第三步:(可选)重规划阶段(Replanning)

如果某一步执行失败或环境发生变化,可以触发Replanner重新规划后续步骤。

Plan-and-Execute的优缺点

优点:

优点说明
结构清晰计划一目了然,便于人类理解和调试
避免死循环执行路径由计划决定,不会无限循环
执行效率高大模型只在规划和重规划时被调用
支持并行独立步骤可并行执行,显著缩短总耗时
资源可控可预先评估计算成本

缺点:

缺点说明
计划可能失真前期信息不足时,计划可能与真实环境脱节
动态调整弱执行过程中的动态调整和容错能力较弱
灵活性不足偏向静态工作流,难以应对突发变化
单轮对话限制部分实现不支持基于历史上下文的多轮对话

Plan-and-Execute的适用场景

  • 步骤繁多、逻辑依赖明确的长期复杂任务
  • 任务可以预先分解为清晰的子任务
  • 对实时性要求较低但对内容丰富度要求较高的任务(如深度分析报告、长篇网页生成)
  • 批量数据处理等静态环境任务

三、ReAct vs Plan-and-Execute:全面对比

核心差异对比表

对比维度ReAct模式Plan-and-Execute模式
规划方式动态生成,每轮迭代更新一次性生成,执行前固定
执行方式边想边做,循环迭代先想后做,按计划执行
工具调用按需调用,可能重复调用按计划调用,顺序明确
状态管理实时更新环境状态仅在计划失败时更新状态
失败处理通过循环自动修正需显式设计重试/回滚机制
环境适应性优秀(动态环境)一般(静态环境更高效)
死循环风险
上下文增长线性累积,易爆炸可控

性能数据参考

在某自动化测试场景中,Plan-and-Execute模式相比ReAct:

  • 任务完成率提升27%
  • 工具调用次数减少42%
  • 平均执行时间缩短35%

选型决策树

开始:我有一个任务要交给Agent │ ├─ 任务解决方案路径是否明确? │ ├─ 不明确,需要边探索边决策 → 【ReAct】 │ └─ 明确,可以预先拆解为子任务 → 继续 │ ├─ 任务是否需要实时响应环境变化? │ ├─ 是(如实时监控、故障修复)→ 【ReAct】 │ └─ 否 → 继续 │ ├─ 任务步骤是否繁多(>5步)且依赖关系明确? │ ├─ 是 → 【Plan-and-Execute】 │ └─ 否 → 继续 │ └─ 最安全的混合策略:Plan-and-Execute做全局规划 + ReAct做每步内的灵活执行

💡核心观点:ReAct和Plan-and-Execute不是二选一的关系,而是两个不同粒度的策略。实战中最好的做法是混合使用——Plan-and-Execute做全局规划,ReAct做每步内的灵活执行。

四、Spring AI Alibaba Graph:底层工作流引擎

在深入代码之前,需要了解一个关键事实:Spring AI Alibaba的Agent Framework底层运行在Graph Runtime之上

Graph是什么?

Graph是一个低级别的工作流和多智能体编排框架,能够帮助开发者实现复杂的应用程序编排。在底层,Spring AI Alibaba框架会将Agent编排为Graph,组成一个由节点串联而成的DAG(有向无环图)

Graph的三大核心概念

概念说明
状态(State)在Node与Edge之间传递的数据结构,是一个Map<String, Object>
节点(Node)执行逻辑单元,接受State作为输入,执行操作后返回更新的State
边(Edge)定义Node间的控制流,可为固定连接或条件分支

💡一句话总结:Node完成工作,Edge告诉下一步该做什么。

Graph的核心能力

  • 流式输出(Streaming):将每个节点的运行情况实时发送到客户端
  • 人机协同(Human In The Loop):允许对Agent运行过程中的工具调用进行评估、修改、批准
  • 记忆管理(Memory & Context):处理短期记忆(会话内)和长期记忆(跨会话)

Agentic API vs Graph API

Agentic APIGraph API
抽象层次高层声明式API底层原子化API
使用方式使用预置的Agent模式独立定义每个Node和Edge的逻辑
控制粒度粗粒度细粒度,完全控制
适用场景大多数Agent应用开发需要超高可靠性、大量自定义逻辑的场景
上手难度中高

💡推荐策略:优先使用Agent Framework内置的Agent抽象(ReactAgent、SequentialAgent、ParallelAgent等)。只有当需要更灵活的编排、更直接的状态控制时,才考虑直接使用Graph API。

五、代码实战:对比两种方案

实战一:用ReAct模式实现“旅行规划Agent”

@Service@Slf4jpublicclassTravelReActAgentService{privatefinalChatModelchatModel;@Tool(description="查询指定城市的天气")publicStringgetWeather(Stringcity){returncity+"未来3天晴到多云,气温22-28°C";}@Tool(description="根据城市和天气推荐景点")publicStringrecommendAttractions(Stringcity,Stringweather){return"推荐景点:西湖、灵隐寺、宋城、西溪湿地";}publicvoidrunReActTravelAgent(){ReactAgentagent=ReactAgent.builder().name("react_travel_agent").model(chatModel).instruction(""" 你是一个旅行规划助手。用户会告诉你目的地和天数, 请按以下步骤完成任务: 1. 先查询天气 2. 根据天气推荐景点 3. 推荐酒店 4. 生成完整的行程计划 """).methodTools(this).build();Stringquestion="帮我规划杭州3日游";log.info("========== ReAct模式执行 ==========");longstart=System.currentTimeMillis();AssistantMessageresponse=agent.call(question);longend=System.currentTimeMillis();log.info("耗时:{}ms",end-start);log.info("回复:\n{}",response.getText());}}

课堂观察点

  • 观察Agent的Thought→Action→Observation循环日志
  • 记录工具调用次数和总耗时
  • 注意Agent是否出现“重复查询”或“循环”现象

实战二:用SequentialAgent模拟Plan-and-Execute

@ConfigurationpublicclassPlanExecuteTravelConfig{// 1. Planner Agent - 只负责规划,不调用工具@BeanpublicReactAgentplannerAgent(ChatModelchatModel){returnReactAgent.builder().name("planner").model(chatModel).instruction(""" 你是一个旅行规划专家。请根据用户需求,生成一个详细的旅行计划。 计划必须包含以下部分: 1. 行程总览(天数、目的地) 2. 每日详细安排(上午、下午、晚上) 3. 住宿推荐 4. 餐饮推荐 注意:只生成计划文本,不要执行任何实际操作。 用户需求:{input} """).outputKey("travel_plan").build();}// 2. Executor Agent - 负责执行计划中的具体操作@BeanpublicReactAgentexecutorAgent(ChatModelchatModel){returnReactAgent.builder().name("executor").model(chatModel).instruction(""" 你是一个旅行执行助手。根据以下计划,执行具体的查询操作: {travel_plan} 请调用工具查询天气、景点等具体信息。 """).methodTools(newTravelTools()).outputKey("execution_result").build();}// 3. 组合为顺序Agent@BeanpublicSequentialAgentplanExecuteTravelAgent(ReactAgentplannerAgent,ReactAgentexecutorAgent){returnSequentialAgent.builder().name("plan_execute_travel_agent").subAgents(List.of(plannerAgent,executorAgent)).build();}}

对比结果

对比维度ReAct模式Plan-and-Execute模式
执行路径动态循环,路径不确定固定顺序,路径清晰
工具调用次数可能重复调用按计划调用,无重复
总耗时较长(多次模型调用)较短(2次模型调用+工具执行)
回复质量灵活但可能遗漏信息结构完整,覆盖全面
可调试性较难(路径不确定)容易(计划即文档)

六、Spring AI Alibaba中的混合实践

如前所述,实战中最好的做法是混合使用

用户需求 → Planner(全局规划)→ 步骤1(ReAct执行)→ 步骤2(ReAct执行)→ ... → 最终结果

混合模式的优势

  • Planner提供全局视角,避免ReAct“走弯路”
  • 每个步骤内的ReAct提供灵活性,应对局部变化
  • 既有结构又有弹性

Spring AI Alibaba中的实现方式

  1. 使用SequentialAgent串联多个Agent
  2. 每个子Agent可以是ReActAgent(带工具)
  3. 第一个Agent作为Planner(不带工具,只生成计划)
  4. 后续Agent作为Executor(带工具,执行计划中的各步骤)

这种模式在Spring AI Alibaba的OpenManus实现中已有体现——Planning Agent负责任务分解,多个Manus Agent组成链式可顺序执行的子工作流。

七、读后挑战

任务:分析你的业务场景,判断更适合哪种Agent架构模式

分析框架

分析维度你的答案
任务目标是什么?
任务步骤是否可以预先明确?
是否需要实时响应环境变化?
任务步骤是否繁多(>5步)?
子任务之间是否可以并行?
推荐使用哪种模式?为什么?

验收标准

  • 完成了6个维度的场景分析
  • 给出了明确的模式选择建议及理由
  • 针对所选模式的缺陷提出了应对方案
  • 如果能画出架构图(可选加分)

八、本日核心收获

  1. ReAct有三大缺陷:无限循环、上下文爆炸、缺乏全局视角
  2. Plan-and-Execute是另一种思路:先全局规划,再逐步执行
  3. 两者不是二选一,而是可以混合使用的策略
  4. Spring AI Alibaba Graph是底层工作流引擎,提供State、Node、Edge三大核心概念
  5. 选型决策:动态环境→ReAct;静态复杂任务→Plan-and-Execute;最稳妥→混合模式

📌本文要点回顾:ReAct是“一步一想”,Plan-and-Execute是“先全局规划,再逐步执行”。前者适合探索性任务,后者适合确定性任务。而实战中最好的做法是混合使用——Plan-and-Execute做全局规划,ReAct做每步内的灵活执行。理解这两种模式的区别和各自的适用场景,是Agent架构设计的关键一步。

有任何问题,欢迎在评论区留言交流!


作者:Java老兵搞AI,专注Java生态下的AI应用开发

如果觉得有用,「点赞」+「关注」支持一下吧 公众号搜索“#Java老兵搞AI”查看详细教程

← 返回列表