从ReAct到Reflexion:Planning Agent架构演进与工程实践
2026/9/4 7:37:02 网站建设 项目流程

1. 从“单步思考”到“规划执行”:为什么我们需要Planning Agent?

如果你在过去一年里尝试过用大语言模型(LLM)来干点“正经事”,比如让它帮你分析一份财报、写一个爬虫脚本,或者处理一个多步骤的客服请求,你大概率经历过这样的挫败:你给了它一个复杂的任务,它一开始说得头头是道,列出了第一步、第二步、第三步……然后,在执行到第二步时,它突然就忘了第一步的结论是什么,或者把第三步的逻辑给搞混了,最后输出的结果要么是错的,要么是虎头蛇尾。这种体验,本质上暴露了当前LLM作为一个“即时反应者”的核心短板——它缺乏持续、连贯的规划与执行能力

这就是Planning Agent(规划智能体)架构要解决的根本问题。我们不再把LLM看作一个“一问一答”的聊天机器人,而是将其视为一个能够自主进行任务分解、策略规划、步骤执行、结果反思与动态调整的“智能工作流引擎”。这听起来有点像我们人类处理复杂项目的过程:先想清楚要做什么(目标),再拆解成几个关键阶段(规划),然后一步步去执行,过程中遇到问题就停下来想想,调整计划后再继续。

网络上关于“React面试题”、“微服务架构”的讨论热度不减,这恰恰反映了工程界对结构化、可管理、可扩展的系统有着永恒的需求。Planning Agent就是将这种工程思想引入AI应用层的一次重要实践。它试图为LLM这匹“能力强大但思维跳跃的野马”,套上“规划与执行”的缰绳,使其能够稳定、可靠地完成更长链条、更复杂的任务。从简单的ReAct模式,到更复杂的Plan-and-Execute(规划与执行)和Reflexion(反思)架构,我们可以清晰地看到一条从“启发式探索”到“系统工程化”的演进路径。这篇文章,我将结合实际的工程踩坑经验,为你深度解析这三种核心架构的设计思想、实现细节以及它们各自最适合的应用场景。

2. ReAct:思维链与工具调用的首次联姻

ReAct(Reasoning + Acting)可以看作是Planning Agent的“启蒙架构”。它的核心思想非常直观:让模型在回答问题时,将内部的“推理”(Reasoning)过程以文本形式“说”出来(这就是著名的Chain-of-Thought,思维链),同时,在推理到某个节点时,如果发现需要调用外部工具(比如计算器、搜索引擎、数据库API)来获取信息,就立刻去“执行”(Acting)这个工具调用,然后将工具返回的结果纳入后续的推理中。如此循环,直到得出最终答案。

2.1 ReAct的核心工作流与Prompt设计

一个典型的ReAct Prompt模板会明确要求模型按照以下格式输出:

Thought: 我需要分析用户的问题。这是一个关于计算的问题,我需要先理解其中的数学表达式。 Action: Calculator Action Input: "3 + 5 * 2" Observation: 13 Thought: 计算器返回的结果是13。用户的问题是“3加5乘以2等于多少?”,根据数学运算法则,先乘除后加减,5*2=10,再加3,结果确实是13。所以答案是13。 Action: Finish Action Input: "13"

这个流程的关键在于,ThoughtActionObservation构成了一个固定的“执行单元”。模型在Thought里进行逻辑推理,决定下一步做什么;在Action里声明要使用的工具(来自一个预定义的列表);在Action Input里提供工具的输入参数;系统执行工具后,将结果以Observation的形式返回给模型;模型再基于新的观察进行下一轮思考。

工程实践中的核心细节:

  1. 工具描述必须精确:你不能只告诉模型有一个“Search”工具。你必须详细描述:“Search(query): 一个搜索引擎工具,输入一个查询字符串,返回相关的网页摘要信息。” 模糊的工具描述会导致模型错误调用。
  2. Observation的格式化至关重要:工具返回的原始数据(可能是JSON、HTML或纯文本)必须被处理成一段简洁、清晰的文本,再作为Observation喂给模型。杂乱的数据会干扰模型的推理。我常用的做法是设计一个“结果提取器”函数,从工具返回结果中抽取出核心信息。
  3. 停止条件的设计:模型如何知道任务完成了?通常需要定义一个特殊的工具,如Finish,或者设定一个最大的循环步数(例如10步),防止陷入死循环。在Prompt中必须清晰说明:“当你认为已经得到最终答案,或无法继续时,请使用Finish动作。”

2.2 ReAct的优势与局限性:为什么它更像“探索”而非“规划”

ReAct的最大优势是简单、灵活、易于实现。它不需要预先进行复杂的任务分解,模型在“思考-行动”的循环中实时探索解决方案,这对于那些解决方案路径不明确、需要即兴发挥的任务(比如开放式问答、创意写作)非常有效。它完美结合了LLM的内部推理能力和外部工具的事实获取能力。

然而,它的局限性在复杂任务面前暴露无遗:

  • 缺乏全局视野(“走一步看一步”):模型只关注当前步骤,没有对整体任务进行前瞻性规划。这容易导致“局部最优但全局错误”的决策,或者执行一些冗余、无效的步骤。
  • 上下文消耗与遗忘:每一步的ThoughtObservation都会追加到对话历史中。对于长任务,上下文窗口很快会被填满,导致模型“忘记”最早几步的规划和中间结果。虽然可以通过摘要等方式缓解,但本质问题仍在。
  • 脆弱性高:任何一步的推理错误或工具调用失败,都可能导致整个链条崩溃,且没有有效的回滚或重试机制。模型很难从错误中恢复。
  • 不适合流程固定的任务:对于像“数据ETL流程”、“编译部署流水线”这类步骤明确、顺序固定的任务,ReAct的实时探索反而显得低效且不稳定。

一个真实的踩坑案例:我曾用ReAct构建一个自动竞品分析Agent。任务是从给定公司名开始,搜索其产品、财务、市场新闻,最后生成报告。Agent经常陷入这样的循环:搜索公司名 -> 观察结果里提到一个产品 -> 再以这个产品名为关键词搜索 -> 观察结果里又提到另一个相关技术……如此反复,离最初的“财务和市场新闻”目标越来越远,最终耗尽步数也没生成报告。这就是缺乏顶层规划导致的“任务漂移”。

3. Plan-and-Execute:将软件工程思想引入Agent设计

为了解决ReAct“走一步看一步”的问题,Plan-and-Execute架构应运而生。它的思想深受传统软件工程影响:将“规划”(设计)与“执行”(开发)两个阶段分离。先由一个“规划器”(Planner)制定一份详细的、步骤化的计划书,再由一个“执行器”(Executor)严格按计划一步步执行。

3.1 架构拆解:Planner与Executor的职责分离

  1. Planner(规划器)

    • 输入:用户的初始任务描述、可用的工具列表及其详细功能说明。
    • 过程:Planner(通常也是一个LLM)分析任务,将其分解成一个有序的步骤列表(Plan)。每个步骤应包含:步骤ID、步骤描述、预期输出、以及该步骤建议使用的工具。
    • 输出:一份结构化的计划,例如JSON或Markdown列表。
    • 关键设计:Planner的Prompt需要强烈引导其进行“自上而下”的分解。例如:“你是一个资深项目经理。请将以下任务分解为具体的、可执行的步骤。确保步骤间有逻辑依赖关系,前一步的输出可能是后一步的输入。请为每个步骤推荐一个最合适的工具。”
  2. Executor(执行器)

    • 输入:Planner生成的计划。
    • 过程:Executor(可以是另一个LLM,也可以是简单的程序逻辑)遍历计划中的每一个步骤。对于每个步骤,它可能需要:a) 理解步骤要求;b) 准备输入参数(可能需要整合之前步骤的结果);c) 调用指定的工具;d) 处理工具返回的结果,并将其存储为“步骤输出”。
    • 输出:所有步骤执行完毕后的最终结果集合,或由最后一个步骤产出的最终答案。
    • 关键设计:Executor需要具备状态管理能力,能够访问和维护一个“工作区”(Workspace),用来存储每个步骤的输入和输出,以便后续步骤引用。

3.2 工程实现中的关键决策与“坑”

决策一:Planner的粒度把控计划应该多细?步骤太粗(如“1. 进行市场调研”),Executor无法直接执行;步骤太细(如“1.1 打开浏览器,1.2 在地址栏输入www.google.com…”),会浪费Token且增加复杂度。我的经验是,以“一个工具调用能完成的工作”为一个步骤单元。例如,“使用Search工具查找公司A的最新财报”就是一个合适的步骤。

决策二:如何处理步骤间的依赖?这是Plan-and-Execute架构的核心挑战。简单的线性计划(Step1 -> Step2 -> Step3)容易实现,但很多任务有分支或并行需求。

  • 线性流:最简单,Executor顺序执行即可。适用于ETL、文档生成等任务。
  • 有向无环图(DAG):更通用。Planner需要明确声明步骤间的依赖(如“Step3需要Step1和Step2的输出”)。Executor需要一个调度器来解析依赖,决定哪些步骤可并行执行。这引入了显著的工程复杂度。
  • 实践技巧:在初期,可以强制Planner生成线性计划,并在步骤描述中用自然语言声明依赖,如“基于步骤2得到的股价数据,计算年均收益率”。Executor(LLM)在准备该步骤输入时,能理解并去查找“步骤2的输出”。

决策三:Executor的“智能”程度Executor必须完全“傻”地执行计划吗?不一定。可以赋予它一定的“临机决断”能力。例如,当调用工具失败(如API超时)时,Executor可以尝试重试、更换参数,或者将错误信息反馈给Planner请求调整计划。但这需要在稳定性和灵活性之间权衡。

我踩过的一个大坑:动态参数解析。计划中一个步骤是:“使用QueryDatabase工具,查询用户{{user_id}}的订单历史。”这里的{{user_id}}是一个变量,应该在实际执行时,从用户输入或上下文里替换。最初我的Executor只是简单地将整个步骤描述传给LLM,让它去调用工具,结果LLM经常无法正确解析出{{user_id}}这个变量占位符。解决方案是,在Executor内部实现一个简单的模板渲染引擎。在执行前,先提取步骤描述中的变量名(如user_id),然后从共享的工作区或用户输入中查找对应的值,进行替换,再将替换后的、具体的指令发给LLM去执行工具调用。这大大提高了执行的可靠性。

4. Reflexion:为Agent赋予“复盘”与“迭代”能力

无论是ReAct还是基础的Plan-and-Execute,它们本质上都是一次性的、“开环”的执行过程。执行失败了,或者结果不理想,Agent就停在那里了。这显然不符合人类解决问题的方式——我们会复盘,会从错误中学习,然后调整策略再试一次。Reflexion架构就是为了给Agent注入这种“反思-迭代”的能力。

4.1 Reflexion的核心循环:行动、评估、反思、重规划

Reflexion在Plan-and-Execute的基础上,增加了一个“评估器”(Evaluator)和“反思”(Reflection)环节,形成一个闭环:

  1. 行动(Act):基于当前计划(或初始计划)执行任务,产生一个轨迹(Trajectory),包含一系列行动和观察。
  2. 评估(Evaluate):使用一个评估标准,对执行轨迹和最终结果进行打分或定性判断。评估器可以是:
    • 规则型:检查最终输出是否包含某些关键词、格式是否正确。
    • 模型型:用另一个LLM(或同一个LLM的不同提示)作为裁判,判断结果是否满足要求(例如:“从准确性、完整性和相关性三个方面,给这个答案打分1-10分,并说明理由”)。
    • 工具型:调用一个验证工具(如代码执行器看是否报错,单元测试是否通过)。
  3. 反思(Reflect):如果评估结果不达标(如分数低于阈值,或验证失败),则启动反思环节。将整个任务描述、执行轨迹、以及评估反馈一起喂给LLM,要求它分析失败原因,并给出一个具体的、高层次的“反思总结”(Reflection)。例如:“失败的原因是在步骤2查询数据库时,使用了错误的日期格式,导致没有返回数据。此外,整个计划缺少对异常数据的处理步骤。”
  4. 重规划(Re-plan):将最初的“任务描述”和刚刚生成的“反思总结”一起,再次提交给Planner,要求它生成一个新的、改进了的计划。这个新计划会充分考虑上一次失败的经验教训。
  5. 迭代:用新的计划回到第1步“行动”,开始下一次尝试。通常可以设置一个最大迭代次数(如3次)。

4.2 工程化挑战:如何设计有效的“反思”与“评估”?

Reflexion听起来很美好,但把它工程化落地,难度比前两种架构高出一个数量级。

挑战一:评估标准(Evaluator)的客观性与成本

  • 主观任务:对于“写一篇吸引人的营销文案”这类任务,评估标准极其主观。让LLM自己评估自己(或另一个LLM)的产出,容易陷入自洽循环或产生模糊的反馈(如“不够生动”),这种反馈对后续反思的帮助有限。
  • 解决方案:尽量将评估指标客观化、具体化。例如,对于文案任务,可以评估:“是否包含了产品三大卖点?”“是否使用了至少一个疑问句和感叹句来引导用户?”“长度是否在200-300字之间?”同时,可以考虑引入人工评估环节作为黄金标准,或者在多次迭代后由人工选择最优解。

挑战二:反思提示(Reflection Prompt)的设计反思提示的质量直接决定了迭代改进的效果。一个差的反思提示可能只会让模型说“上次做得不好,这次要做好点”这样的废话。

  • 优秀反思提示要素
    • 要求聚焦根本原因:不要只说“步骤2错了”,要分析“为什么步骤2会错?是输入数据问题、工具使用问题还是逻辑假设问题?”
    • 要求提供具体改进建议:例如,“建议在查询前增加一个数据格式校验步骤”,“建议将模糊搜索改为精确匹配”。
    • 结构化输出:要求模型以“根本原因:...;具体改进:...”的格式输出,方便后续程序化处理。
  • 示例:“你是一名技术负责人, reviewing 上次任务执行失败的报告。请基于任务目标、执行步骤和失败结果,分析导致失败的最核心、最根本的原因(不超过2个)。然后,针对每个原因,提出一个在下次计划中必须实施的具体、可操作的改进建议。”

挑战三:避免无限循环与成本控制Reflexion可能陷入“失败-反思-再失败”的死循环,尤其是当任务本身不可能完成,或者评估标准有误时。

  • 设置硬性停止条件:最大迭代次数(如3-5次)、总Token消耗上限、总执行时间上限。
  • 反思摘要:随着迭代进行,每次的反思和新的计划都会追加到上下文中。必须对历史反思进行摘要,只保留最关键的经验教训,防止上下文爆炸。
  • “放弃”也是一种策略:在反思环节,可以允许模型得出结论:“基于当前可用工具和信息,此任务无法完成。”然后优雅地终止流程,并向用户报告障碍所在,这比无限循环更有价值。

5. 架构选型与融合:在实战中如何抉择?

了解了三种核心架构后,面对一个具体的AI应用需求,我们该如何选择?没有银弹,只有最适合场景的权衡。

5.1 决策矩阵:根据任务特性选择架构

我通常使用以下几个维度来评估:

任务特性推荐架构理由与注意事项
任务路径不明确,需要探索
(如:研究性问答、创意发散)
ReAct灵活性强,允许模型在思考中动态发现路径。需警惕任务漂移和循环。
任务流程固定,步骤清晰
(如:数据报表生成、CI/CD流水线、客服工单处理)
Plan-and-Execute稳定性高,可预测性强。前期规划好,后期执行稳。重点设计Planner的提示词和步骤依赖。
任务复杂,容错率低,且有机会从错误中学习
(如:代码调试、复杂策略游戏、学术问题求解)
Reflexion通过迭代改进能显著提升最终结果质量。必须设计好客观的评估器和有效的反思机制。成本较高。
任务简单,工具调用少
(如:简单计算、单次信息查询)
直接工具调用无需复杂架构,过度设计反而增加延迟和成本。

5.2 混合架构实践:取长补短

在实际工程中,纯粹的架构很少,更多的是混合模式:

  • Plan-React-Execute:先由Planner制定一个高层计划(如:阶段一:市场分析;阶段二:竞品对比;阶段三:报告撰写)。然后,在每个阶段内部,使用一个ReAct风格的子Agent去完成该阶段具体的、探索性的任务。这结合了规划的全局性和执行的灵活性。
  • 分层Reflexion:不在每一步进行反思(成本太高),而是在每个关键里程碑(Milestone)或阶段结束后进行反思和计划调整。例如,在“数据收集”阶段完成后,反思收集的数据是否足够、质量如何,并据此调整后续的“数据分析”阶段计划。

5.3 基础设施与工具链的考量

无论选择哪种架构,一些共性的基础设施决定了Agent的稳定性和可维护性:

  1. 工具抽象层:所有架构都需要调用工具。设计一个统一的工具注册、描述和调用接口至关重要。工具应尽可能做到无状态幂等,方便重试和并行调用。
  2. 状态管理与工作区:Agent需要记忆自己的计划、执行中间结果、反思历史。需要一个可靠的“工作区”(可以是内存字典、Redis或数据库)来存储和检索这些状态。这对于Plan-and-Execute和Reflexion尤其关键。
  3. 编排与调度引擎:对于复杂的DAG计划或混合架构,需要一个轻量级的调度器来管理步骤间的依赖和执行顺序。可以考虑使用像LangGraph(LangChain生态)或微软Autogen中的群聊调度这样的专门框架,它们内置了状态机和流程控制能力。
  4. 日志与可观测性:Agent的决策过程是个黑盒吗?绝不能是。必须详细记录每一步的Thought、Action、Observation、Plan、Reflection。这不仅是调试和优化Agent所必需,也是建立用户信任、满足审计要求的关键。构建一个清晰的Agent运行日志面板是大型项目中的标配。

从ReAct的灵光一现,到Plan-and-Execute的工程化严谨,再到Reflexion的闭环进化,Planning Agent的架构演进清晰地指向一个目标:让AI智能体更像一个可靠的、有方法的“工作者”,而不仅仅是一个灵光乍现的“提议者”。这个过程充满了工程上的挑战,从提示词设计、工具封装到状态管理、循环控制,每一个环节都需要精心打磨。但回报也是巨大的——当你看到一个Agent能够自动完成从数据抓取、清洗、分析到报告生成的全流程,并且能在出错时自己找到问题并重试时,你会感到这一切的复杂性都是值得的。这不仅仅是构建一个应用,而是在定义一种全新的人机协作范式。

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

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

立即咨询