【从0开发一个 Agent】第十一章:构建 Planner
在前面的章节中我们赋予了 AI 工具调用、长期记忆、RAG 知识库和工程化 Prompt 等强大能力。但当你向它提出“帮我分析上周的销售数据生成一份包含图表的周报并发送给团队”这样的复杂指令时它依然会陷入混乱。它可能会在还没有获取数据时就尝试生成图表或者在发送失败后直接放弃而不是寻找替代方案。这是因为传统的 ReAct 模式思考-行动-观察在处理长链路、多依赖的复杂任务时存在严重的“上下文稀释”和“意图漂移”问题。本章我们将引入 Planner规划器与多 Agent 协作架构让 AI 从“单步执行者”进化为“项目管理者”。1. 为什么复杂任务不能一次完成在单 Agent 模式下模型需要同时承担“拆解任务”、“执行工具”、“整合结果”三重角色。随着任务步骤增加Prompt 中充斥着大量的中间状态和工具返回结果导致模型对最初目标的注意力被严重稀释。更致命的是ReAct 模式是串行的每一步都依赖上一步的输出一旦中间某个工具调用失败或返回非预期结果整个链路就会崩溃且模型缺乏“回溯重规划”的能力。Planner 的核心价值将“规划”与“执行”解耦。Planner 负责将复杂目标拆解为有向无环图DAG明确任务依赖关系Executor 负责按图执行当执行失败时Planner 能够基于当前状态进行局部重规划而不是推倒重来。2. Planner 架构设计从 ReAct 到 REWOO我们摒弃传统的串行 ReAct采用REWOOReason without Observation架构。它通过“一次性生成完整工具链”来减少 Token 消耗并通过“规划-执行-合并”三阶段实现稳定的复杂任务处理。REWOO 三阶段解析Planner规划器接收用户指令一次性生成包含多个相互关联计划的蓝图。每个计划都分配了变量如#E1供后续任务引用。Executor执行器根据 Planner 的蓝图循环执行任务。它不依赖 LLM 的实时推理而是直接调用工具将结果存入变量。Solver合并器将所有计划和执行结果结合起来形成最终解决方案。为什么选择 REWOO 而非 ReActToken 效率ReAct 每一步都需要 LLM 调用长任务会导致 Token 爆炸REWOO 只在规划和合并阶段调用 LLM中间执行阶段零 LLM 开销。稳定性ReAct 的串行依赖容易因单步失败而崩溃REWOO 的变量引用机制和重规划能力使其具备更强的容错性。可观测性REWOO 生成的任务 DAG 是结构化的便于前端可视化展示任务进度也便于后端进行断点续传和状态追踪。3. 核心代码实现3.1 Planner生成结构化任务 DAG我们使用 Zod 定义严格的任务输出格式确保 Planner 生成的计划是可执行的。// src/lib/planner/schema.tsimport{z}fromzod;exportconstTaskSchemaz.object({id:z.string().describe(任务唯一标识),name:z.string().describe(任务名称),description:z.string().describe(任务详细描述),tool:z.string().describe(需要调用的工具名称),params:z.record(z.any()).describe(工具参数可引用上游变量如 #E1),dependencies:z.array(z.string()).describe(依赖的上游任务ID列表),});exportconstPlanSchemaz.object({title:z.string().describe(计划标题),tasks:z.array(TaskSchema).describe(任务列表),});exporttypePlanz.infertypeofPlanSchema;在src/lib/planner/index.ts中实现 Planner// src/lib/planner/index.tsimport{generateObject}fromai;import{openai}from/lib/ai/config;import{PlanSchema}from./schema;exportasyncfunctioncreatePlan(userQuery:string,availableTools:string[]):PromisePlan{const{object}awaitgenerateObject({model:openai(gpt-4o),schema:PlanSchema,system:你是一个任务规划专家。请将用户指令拆解为可执行的任务DAG。 可用工具:${availableTools.join(, )}规则: 1. 任务必须原子化每个任务只调用一个工具。 2. 明确任务依赖关系确保DAG无环。 3. 参数中引用上游结果时使用 #E{taskId} 格式。 4. 如果任务无法完成不要编造返回空任务列表。,prompt:userQuery,});returnobject;}3.2 Executor按图执行与变量管理Executor 负责解析 Planner 生成的 DAG按依赖顺序执行任务并管理变量池。// src/lib/planner/executor.tsimport{Plan,Task}from./schema;import{getTool}from/lib/ai/tools;exportclassExecutor{privatevariablePool:Mapstring,anynewMap();privatetaskResults:Mapstring,anynewMap();asyncexecute(plan:Plan):PromiseMapstring,any{// 拓扑排序确保依赖任务先执行constsortedTasksthis.topologicalSort(plan.tasks);for(consttaskofsortedTasks){try{// 解析参数中的变量引用constresolvedParamsthis.resolveParams(task.params);// 调用工具consttoolgetTool(task.tool);constresultawaittool.execute(resolvedParams);// 存入变量池和结果集this.variablePool.set(#E${task.id},result);this.taskResults.set(task.id,{status:completed,result});}catch(error){this.taskResults.set(task.id,{status:failed,error:error.message});// 失败时触发重规划见下文constreplannedawaitthis.replan(plan,task.id,error);if(replanned){returnthis.execute(replanned);}thrownewError(Task${task.id}failed and replanning failed:${error.message});}}returnthis.taskResults;}privateresolveParams(params:Recordstring,any):Recordstring,any{constresolved:Recordstring,any{};for(const[key,value]ofObject.entries(params)){if(typeofvaluestringvalue.startsWith(#E)){resolved[key]this.variablePool.get(value);}else{resolved[key]value;}}returnresolved;}privatetopologicalSort(tasks:Task[]):Task[]{// 实现 Kahn 算法进行拓扑排序// ...returntasks;}privateasyncreplan(plan:Plan,failedTaskId:string,error:any):PromisePlan|null{// 调用 Replanner基于当前状态生成新计划// ...returnnull;}}3.3 Solver整合结果与生成最终响应// src/lib/planner/solver.tsimport{generateText}fromai;import{openai}from/lib/ai/config;exportasyncfunctionsolve(plan:Plan,results:Mapstring,any):Promisestring{constresultSummaryArray.from(results.entries()).map(([id,data])任务${id}:${JSON.stringify(data)}).join(\n);const{text}awaitgenerateText({model:openai(gpt-4o),system:你是一个结果整合专家。请基于以下任务执行结果生成最终的用户响应。 如果任务失败请向用户解释原因并提供替代方案。,prompt:计划:${JSON.stringify(plan)}\n执行结果:\n${resultSummary},});returntext;}3.4 在 API Route 中集成 Planner// src/app/api/chat/route.tsimport{createPlan}from/lib/planner;import{Executor}from/lib/planner/executor;import{solve}from/lib/planner/solver;import{getAvailableTools}from/lib/ai/tools;exportasyncfunctionPOST(req:Request){const{messages}awaitreq.json();constuserQuerymessages[messages.length-1].content;// 1. 判断是否需要规划简单问题直接回答constneedPlanningawaitcheckIfPlanningNeeded(userQuery);if(!needPlanning){returnstreamText({model:openai(gpt-4o),messages}).toDataStreamResponse();}// 2. 生成计划constavailableToolsgetAvailableTools();constplanawaitcreatePlan(userQuery,availableTools);// 3. 执行计划constexecutornewExecutor();constresultsawaitexecutor.execute(plan);// 4. 整合结果constfinalResponseawaitsolve(plan,results);returnnewResponse(JSON.stringify({content:finalResponse}),{headers:{Content-Type:application/json},});}4. 测试验证验证清单复杂任务拆解输入“分析上周销售数据并生成周报”验证 Planner 是否生成了包含“查询数据”、“生成图表”、“撰写报告”等步骤的 DAG。依赖关系正确性验证“生成图表”任务是否正确依赖“查询数据”任务的结果。失败重规划故意让“查询数据”工具返回错误验证 Executor 是否触发 Replanner 并生成替代方案如“使用缓存数据”或“询问用户是否重试”。变量引用解析验证下游任务是否正确接收了上游任务的结果如 #E1 被正确替换为实际数据。5. 常见问题与踩坑分析问题 1Planner 生成的任务 DAG 存在循环依赖原因模型对任务依赖关系的理解出现偏差生成了 A→B→A 的环。解决在 Executor 的拓扑排序阶段增加环检测。如果发现环直接返回错误并触发 Replanner而不是尝试执行。问题 2变量引用解析失败导致工具调用参数错误原因Planner 生成的变量名格式不规范或 Executor 的解析逻辑未覆盖所有引用场景。解决在 Planner 的 Prompt 中明确变量命名规范如 #E{taskId}并在 Executor 中使用正则表达式进行严格匹配和解析。问题 3Replanner 陷入无限重规划循环原因Replanner 生成的新计划依然包含失败的任务且没有改变执行策略。解决在 Replanner 中记录历史失败任务强制要求新计划必须避开已失败的任务或工具或引入“最大重规划次数”限制。本章总结我们剖析了 ReAct 模式在处理复杂任务时的局限性并引入了 REWOO 架构。实现了 Planner、Executor、Solver 三阶段协作机制支持任务 DAG 生成、按图执行和结果整合。构建了变量池和拓扑排序机制确保任务依赖关系正确执行。实现了失败重规划能力增强了 Agent 的容错性和鲁棒性。至此我们的 AI Agent 已经具备了拆解复杂任务、按图执行和失败重规划的能力真正实现了从“单步执行者”到“项目管理者”的跨越。但企业级应用不仅是单个 Agent 就能满足的。从下一章开始我们将实现多 Agent让你的 Agent 复杂任务能一次完成。

相关新闻

大学生HTML期末大作业——HTML+CSS+JavaScript音乐网站

大学生HTML期末大作业——HTML+CSS+JavaScript音乐网站

HTMLCSSJS【音乐网站】网页设计期末课程大作业 web前端开发技术 web课程设计 网页规划与设计💥 文章目录一、🏁 网站题目二、🚩 网站描述三、🎌 网站介绍四、🏴 网站效果五、🏳️ 网站代码六、&#x1f3f3…

2026/7/24 20:31:07 阅读更多 →
开源RPA工具OpenRPA终极指南:免费企业级自动化零基础入门

开源RPA工具OpenRPA终极指南:免费企业级自动化零基础入门

开源RPA工具OpenRPA终极指南:免费企业级自动化零基础入门 【免费下载链接】openrpa Free Open Source Enterprise Grade RPA 项目地址: https://gitcode.com/gh_mirrors/op/openrpa 想要实现业务流程自动化却担心高昂的软件费用?OpenRPA作为一款完…

2026/7/24 20:31:07 阅读更多 →
2026 年 GEO 优化服务商怎么选?先看技术路线和国内AI平台的适配度

2026 年 GEO 优化服务商怎么选?先看技术路线和国内AI平台的适配度

一、AI搜索普及,GEO成为企业数字营销刚需中国信通院《2026生成式搜索产业白皮书》数据显示,2026年国内GEO服务市场规模预计突破286亿元,全年增速达125%;企业级GEO服务渗透率达到48.2%,消费、制造、教育培训、B2B服务等…

2026/7/24 20:31:07 阅读更多 →

最新新闻

Agent工作流的可观测性设计:Trace追踪、断点重试与异常熔断机制

Agent工作流的可观测性设计:Trace追踪、断点重试与异常熔断机制

Agent工作流的可观测性设计:Trace追踪、断点重试与异常熔断机制 一、Agent的黑盒困境:为什么它卡住了?在哪一步? 多Agent工作流在生产环境面临的核心困境是可观测性缺失:执行失败时不知道在哪个Agent卡住、哪个工具的调…

2026/7/24 20:37:08 阅读更多 →
FreeBSD Podman 安装与 GPT4Free 容器部署指南 by Trae

FreeBSD Podman 安装与 GPT4Free 容器部署指南 by Trae

FreeBSD Podman 安装与 GPT4Free 容器部署指南 服务器容器化环境搭建与 AI 对话平台部署完整手册 服务器: 192.168.0.88 系统: FreeBSD 15.1-RELEASE-p1 日期: 2026-07-21 一、项目概述 本文档记录了在 FreeBSD 15.1 服务器上安装 Podman 容器引擎,并通过容器部…

2026/7/24 20:37:08 阅读更多 →
融云分享基于 Rust 的鸿蒙 SDK 开发实践

融云分享基于 Rust 的鸿蒙 SDK 开发实践

12 月 5 日,以“同心聚力,共建共享鸿蒙新生态”为主题的“鸿蒙生态伙伴 SDK 开发者论坛”在京举行。 融云凭借对鸿蒙生态的率先适配和创新贡献,荣获华为鸿蒙生态“HarmonyOS NEXT SDK 星河奖”。本次论坛邀请了多位行业领导者参与&#xff0c…

2026/7/24 20:37:08 阅读更多 →
存储管理与LVM逻辑卷管理:从入门到实战

存储管理与LVM逻辑卷管理:从入门到实战

硬盘类型与选择机械硬盘(HDD)和固态硬盘(SSD)在特性上存在显著差异。HDD采用磁头读写旋转盘片的方式,具有容量大、价格低的优势,但速度较慢且抗震性差。SSD基于闪存芯片,读写速度快、抗震性好&a…

2026/7/24 20:37:08 阅读更多 →
MMPedestron环境安装

MMPedestron环境安装

1、安装python3.7环境并激活 conda create -n mmpedestron python3.7 conda activate mmpedestron2 、安装pytorch、cuda conda install pytorch1.10.1 torchvision0.11.2 torchaudio0.10.1 cudatoolkit11.3 -c pytorch3 、安装openmim和mmcv pip install openmim -i https://m…

2026/7/24 20:37:08 阅读更多 →
C# Winform 使用SunnyUI包 不同分辨率、百分比缩放解决方案

C# Winform 使用SunnyUI包 不同分辨率、百分比缩放解决方案

1、窗体属性更改 2、设置app.manifest文件的dpiAware 右键项目-》新建文件 更改清单文件如下 <application xmlns"urn:schemas-microsoft-com:asm.v3"><windowsSettings><dpiAware xmlns"http://schemas.microsoft.com/SMI/2005/WindowsSettin…

2026/7/24 20:36:07 阅读更多 →

日新闻

用Highcharts 创建可拖拽三维散点立方体3D图表

用Highcharts 创建可拖拽三维散点立方体3D图表

该案例基于Highcharts scatter3d 三维散点图实现空间立方体散点可视化&#xff0c;核心特色&#xff1a;三维 X/Y/Z 三轴空间&#xff0c;所有散点分布在 0~10 立方体空间内&#xff1b;散点使用径向渐变实现立体 3D 圆球质感&#xff1b;支持鼠标 / 触屏拖拽画布&#xff0c;…

2026/7/24 0:00:29 阅读更多 →
AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls&#xff1a;进程创建路径上的 DLL 入口 AppCertDlls 位于 HKLM\System\CurrentControlSet\Control\Session Manager\AppCertDlls。本文的程序功能是只读列出这个键在 64 位和 32 位注册表视图中的全部值&#xff0c;并显示每条值的来源、名称、类型和可安全显示的数…

2026/7/24 0:00:29 阅读更多 →
我的编程之路:第一篇博客

我的编程之路:第一篇博客

大家好&#xff0c;我是一名编程初学者&#xff0c;同时这也是我编程学习之路上的第一篇博客。在这里&#xff0c;我想要向大家介绍我的一些想法和规划。a.自我介绍我是一个刚刚接触编程的新手&#xff0c;目前在学习c语言&#xff0c;我对编程世界充满了强烈的好奇。当然&…

2026/7/24 0:00:29 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中&#xff0c;我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源&#xff0c;还是配置文件、证书等&#xff0c;都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下&#xff0c;但这…

2026/7/24 3:59:20 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP&#xff08;轻量级目录访问协议&#xff09;作为企业级身份认证的黄金标准&#xff0c;已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时&#xff0c;发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/24 1:23:39 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”&#xff0c;而是以可解释、可审计、可迭代的方式&#xff0c;赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/24 18:52:18 阅读更多 →

月新闻