你有没有见过一位经验丰富的主厨同时处理十桌客人的订单?他从来不会站在灶台前发懵,而是先把每桌的菜品拆成“冷盘先上、热菜分锅、甜品最后”的流程,再按顺序一道道安排。遇到复杂的招牌菜,他还会拆出“腌制、焯水、爆炒、收汁”四个步骤,每一步都有明确的标准。这位主厨之所以能游刃有余,靠的正是任务分解的能力——把一个大目标拆成可执行的小步骤,然后按顺序、按优先级一一完成。 AI Agent(智能体)也是一样。当我们让一个 Agent“帮我策划一场完整的公司年会”时,它不可能一步到位。它需要像主厨一样,把这个大任务分解成“确定预算、选定场地、设计流程、安排节目、发出邀请”等多个子任务,再逐个执行。这个能力,就是本文的主角——任务分解(Task Decomposition)。它是 Agent 架构中最核心的能力之一,决定了你的 Agent 是只能应付“帮我查天气”这样的小活儿,还是能真正独当一面、完成复杂目标。

岗位关联

对于 AI 从业者来说,掌握任务分解技术是开发智能助手、自动化 Agent 和复杂任务处理系统的关键技能。它能直接决定你构建的 Agent 是“高级玩具”还是“生产力工具”,也是面试中高频考察的架构设计能力。

目录
  1. 可视化演示
  2. 任务分解概览
  3. CoT思维链分解
  4. ToT树状探索
  5. ReAct行动推理
  6. 分解粒度控制
  7. 工程实现技巧
  8. 探索未来方向
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示任务分解树形结构展开过程、CoT/ToT/ReAct三种范式对比,以及分解粒度对成功率的影响曲线。

本节配有交互动效(进入视口后自动加载,约 3KB)。

任务分解树结构 复杂任务逐层拆解为子任务再拆为叶子步骤 规划拆解详情执行四阶段递进展开 Depth = log_n(total_steps) 分层分解将复杂目标拆为可执行原子操作

任务分解概览

想象一下,主厨接到“准备一场200人的婚宴”这个任务时,他不会直接站在灶台前开始炒菜,而是会先把宴席拆成“冷菜区、热菜区、汤品区、甜点区”,每个区再拆成具体的菜品,每道菜再拆成“备料、切配、烹饪、装盘”的步骤。这个层层拆解的过程,就是任务分解。对Agent来说,任务分解就是把它收到的一个大指令,拆成一系列可执行的子步骤。

从技术角度看,任务分解是Agent规划(Planning)能力的核心。当一个Agent收到“帮我写一份行业分析报告”这样的复杂任务时,它可以先分解为“确定报告主题、收集行业数据、分析市场趋势、撰写报告大纲、填充详细内容、润色排版”这些子任务,然后按顺序执行。没有这个分解能力,Agent面对复杂任务会像没有菜谱的主厨一样手足无措——要么只输出一句话的“报告”,要么生成一堆杂乱无章的内容。

根据论文《Plan-and-Solve》和《HuggingGPT》等研究的总结,当前主流的任务分解范式主要有三种:CoT(Chain-of-Thought)思维链、ToT(Tree-of-Thoughts)思维树和ReAct(Reasoning + Acting)推理行动协同。这三种范式各自对应不同的任务场景和拆解策略。理解这三种范式,是掌握任务分解技术的第一步。

回到主厨的比喻:一个合格的主厨会根据宴席规模决定拆成多少道菜、每道菜分几步做。Agent的任务分解同样需要根据任务复杂度来调整拆解的层级和数量。这既是艺术,也是一门可以训练和控制的工程学。

Task Decomposition: Tcomplex→{T1,T2,T3,…,Tn}\displaystyle \text{Task Decomposition: } T_{\text{complex}} \rightarrow \{T_1, T_2, T_3, \ldots, T_n\}
这个公式表示:一个复杂任务 $T_{\text{complex}}$ 被分解为一个有序的子任务集合,每个子任务 $T_i$ 都可以被Agent独立执行。
  1. 复杂任务 $T_{\text{complex}}$这是Agent收到的最初任务,通常包含多个目标、需要多步操作才能完成。比如“帮我策划旅行”就是一个复杂任务。
    TcomplexT_{\text{complex}}
  2. 分解符号 $\rightarrow$表示“被分解为”。这是一个规划动作,将整体拆成部分,且子任务之间通常存在顺序或依赖关系。
    →\rightarrow
  3. 有序子任务集合 $\{T_1, T_2, T_3, \ldots, T_n\}$分解后的产物是 $n$ 个子任务。$n$ 的大小取决于任务的复杂程度和设定的分解粒度——可能只有3步,也可能有20步。
    {T1,T2,…,Tn}\{T_1, T_2, \ldots, T_n\}

CoT思维链分解

主厨在教徒弟做红烧肉时,不会只说“做一份红烧肉”,而是会一步一步示范:“先切肉焯水,再炒糖色,然后加料焖煮40分钟,最后大火收汁。”这种把过程拆成一步步可见操作的教导方式,就是思维链(Chain-of-Thought,CoT)的精髓:让模型像主厨示范一样,把思考过程一步步写出来,而不是直接跳到答案。

CoT的核心思想是:通过让大语言模型在给出最终答案之前,先产生一系列中间推理步骤,从而提升模型处理复杂推理任务的能力。这个思想最早由Google在2022年的论文《Chain-of-Thought Prompting Elicits Reasoning in Large Language Models》中提出。实现CoT最常用的方法是Few-shot示例引导——在Prompt中给出一个包含完整推理步骤的示例,让模型模仿这个模式。

使用CoT时,最经典的方式是在提示词中加上一句"Let's think step by step"(让我们一步步思考),或者提供一个包含完整推理链的示例。实际操作中,工程上通常这样构造Prompt:

CoT是最基础、最容易实现的任务分解方法,但它有一个明显弱点:它只生成一条直线式的推理路径,一旦中间某一步错了,后面就会跟着错,而且无法回头修正。就像主厨做菜做到一半发现糖色炒糊了,如果不回头重做,整道菜就废了。为了解决这个问题,人们发明了更强大的ToT方法。

CoT Prompting: (x1,r1)⏟示例1+(x2,r2)⏟示例2+xquery→rreasoning→Answer\displaystyle \text{CoT Prompting: } \underbrace{(x_1, r_1)}_{\text{示例1}} + \underbrace{(x_2, r_2)}_{\text{示例2}} + x_{\text{query}} \rightarrow r_{\text{reasoning}} \rightarrow \text{Answer}
CoT的本质是给模型提供“推理示范”,让模型按照示范的格式生成中间推理步骤 $r_{\text{reasoning}}$,最后再给出答案。
  1. Few-shot示例 $(x_1, r_1)$输入示例任务 $x_1$ 和它的推理步骤 $r_1$。这就像主厨先给徒弟示范一道菜,让徒弟知道“原来做菜要这样一步步来”。
    (x1,r1)(x_1, r_1)
  2. 第二个示例 $(x_2, r_2)$再多给一个不同场景的示例,强化模式。比如主厨再示范一道清蒸鱼,徒弟就能总结出“做菜 = 备料+烹饪+装盘”的通用模式。
    (x2,r2)(x_2, r_2)
  3. 新查询 $x_{\text{query}}$这是用户真正想要Agent解决的任务。模型会模仿示例中展示的推理路径,先生成推理过程 $r_{\text{reasoning}}$,再输出最终答案。
    xquery→rreasoning→Answerx_{\text{query}} \rightarrow r_{\text{reasoning}} \rightarrow \text{Answer}
text8 行
你是一个任务规划助手。请将用户的目标分解为有序的执行步骤。示例:目标"做一顿晚餐" → 步骤:1. 查看冰箱里有什么食材2. 设计菜单(一荤一素一汤)3. 备料(洗菜、切菜、腌肉)4. 烹饪(先汤后菜)5. 装盘上桌请按上述格式分解以下目标:{{用户输入}}

ToT树状探索

如果CoT是主厨示范徒弟做一道菜,那么ToT(Tree-of-Thoughts,思维树)就像是让主厨在开新店前,先在纸上画出好几套菜单方案,让团队评估每套方案的成本、口味和出餐速度,然后选择最优的一套,如果某套方案在试菜环节被否掉,就换下一套。这就是ToT的核心思路:不是只沿着一条路走到底,而是同时考虑多条分解路径,评估后选择最优路径。

ToT由普林斯顿大学的研究者在2023年提出,它的核心思想是:将任务分解过程视为在一棵“思路树”上的搜索。树的每个节点代表一个中间步骤或子任务,每个节点可以延伸出多个候选分支(即不同的分解方式)。Agent需要做两件事:一是从一个节点生成多个候选子步骤(分支),二是评估每个候选分支的价值,决定继续探索哪个分支、剪掉哪个分支。

在ToT中,有两个关键组件:生成器(Generator) 和 评估器(Evaluator)。生成器负责产生候选的分解步骤示例:“给定当前状态,列出下一步可能的3种做法”;评估器负责给每个候选打分,例如使用LLM对候选步骤进行“确定/可能/不可能”的三档评价。生成器产生分支、评估器打分、搜索策略决定前进还是回溯——三者协作构成了完整的树状搜索。

ToT适合需要“尝试多种方案并对比”的任务,比如解题、创意写作、复杂规划。但它也有成本:每一步都要调用多次LLM来生成和评估候选分支,Token消耗较大。因此,在实际工程中,ToT通常用在任务确实有多个可能方向、且错误代价较高的场景,而不是所有任务都值得用ToT。

ToT Search: V(st)=max⁡a∈Candidates(st)[Eval(st,a)+V(st+1)]\displaystyle \text{ToT Search: } V(s_t) = \max_{a \in \text{Candidates}(s_t)} \left[ \text{Eval}(s_t, a) + V(s_{t+1}) \right]
这个公式表示:在状态 $s_t$ 下,Agent会评估所有候选分解动作 $a$ 的价值(即当前动作的评估值加上未来状态的递归价值),选择价值最大的分支继续。
  1. 状态 $s_t$当前已经完成的部分任务。比如任务做到第3步,已经完成了“确定主题”和“收集数据”,这就是当前状态。
    sts_t
  2. 候选集合 $\text{Candidates}(s_t)$从当前状态出发,所有可能的下一步分解选项。比如“分析数据”可以拆成“做数据可视化”、“写统计摘要”或“直接找结论”三条路。
    Candidates(st)\text{Candidates}(s_t)
  3. 评估函数 $\text{Eval}(s_t, a)$评估在状态 $s_t$ 下选择动作 $a$ 这一步的即时价值,判断这一步是否合理。
    Eval(st,a)\text{Eval}(s_t, a)
  4. 递归价值 $V(s_{t+1})$选择动作 $a$ 之后到达新状态,从新状态继续搜索能获得的价值。这一步让Agent能“看得更远”,而不只是做眼前一步。
    V(st+1)V(s_{t+1})

ReAct行动推理

现在让我们的主厨从“设计菜单”进入到“实际操作”阶段。在做菜时,主厨不是闭着眼睛按照预定步骤一步步做,而是每做完一步就观察结果:炒糖色时看到颜色变成琥珀色了就进行下一步,如果变成黑色了就赶紧调整。这就是ReAct(Reasoning + Acting)的思路:推理和行动交替进行,每一步行动之后都观察外部反馈,再根据反馈调整下一步的推理和行动。

ReAct由Shunyu Yao等人在2022年提出,它的核心循环是 Thought(思考)→ Action(行动)→ Observation(观察)。在任务分解的语境下,ReAct不是一次性把任务全部拆完,而是“拆一步、走一步、看一步”——先生成一个思考(这一步我应该做什么),然后执行一个动作(调用工具、查询数据库、执行代码),再根据工具返回的结果(观察)决定下一步怎么做。

ReAct特别适合需要与环境交互的任务,比如“查询实时天气并规划行程”——Agent需要先思考“我需要天气数据”,然后调用天气API(行动),看到返回数据(观察),再思考下一步“根据天气决定穿什么”。ReAct让Agent从“闭眼规划”变成“睁眼行动”,大大提升了在动态环境中的任务成功率。

ReAct、CoT和ToT并不是互相排斥的,而是可以组合使用。在实际的Agent架构中,你可以用CoT风格的Prompt让模型“列出计划”,用ReAct风格的循环去执行计划中的每一步,遇到有多个可能方向时再用ToT做分支探索。它们就像主厨的“菜谱设计、试菜调整、现场应变”三个层次——先规划,再尝试,最终灵活应对。

ReAct Loop: Thoughtt→Actiont→Observationt→Thoughtt+1\displaystyle \text{ReAct Loop: } \text{Thought}_t \rightarrow \text{Action}_t \rightarrow \text{Observation}_t \rightarrow \text{Thought}_{t+1}
ReAct循环是“思考-行动-观察”的不断迭代:每一次观察都会成为下一次思考的依据,直到任务完成。
  1. 思考 $\text{Thought}_t$第 $t$ 步时,Agent根据当前状态判断“接下来应该做什么”。比如“要写报告,我需要先拿到行业数据”。
    Thoughtt\text{Thought}_t
  2. 行动 $\text{Action}_t$将思考变成实际动作,比如调用一个数据API、执行一段Python代码或搜索网页。
    Actiont\text{Action}_t
  3. 观察 $\text{Observation}_t$获得行动的结果反馈。比如API返回了2024年的行业报告数据,Agent看到“数据是2024年的,对于2025年的报告来说有点旧”。
    Observationt\text{Observation}_t
  4. 下一次思考 $\text{Thought}_{t+1}$基于观察结果进行下一轮思考。比如“数据太旧了,我应该再找一个更新的数据源”。
    Thoughtt+1\text{Thought}_{t+1}

分解粒度控制

如果让十位主厨分别设计“做一顿晚餐”的菜谱,你会得到完全不同的答案:有人只写“备料、烹饪、上桌”三步,有人会写出“洗菜→切菜→热锅→倒油→下菜→翻炒→调味→装盘”八步。谁的做法对?答案取决于情境。这就是分解粒度(Granularity)问题——任务应该拆到什么细致程度才最合适。

分解粒度是任务分解中最需要平衡的艺术。如果粒度过粗,子任务仍然太复杂,Agent一步做不完,就像“烹饪”这个步骤还是包含了太多操作;如果粒度过细,子任务过于琐碎,每次调用LLM都有延迟和Token成本,就像切菜还要拆成“拿刀-握菜-下刀-抬起”四个动作,浪费时间。最优的粒度应该满足两个条件:每个子任务恰好能被Agent一步完成,且子任务的总数不过多(通常控制在5-15个之间)。

实践中,控制粒度有几个可操作的原则:一是以工具调用为粒度——如果你的Agent能调用“搜索、写代码、发送邮件”这些工具,那么每个子任务应该恰好对应一次工具调用;二是以验证节点为粒度——每个子任务的产物应该可以被验证(比如“写一段代码”可以验证是否运行成功);三是设置最大深度——限制递归分解的层数,防止无限拆分下去。

回到主厨的比喻:判断粒度是否合适,就看两个问题——“这一步我能直接上手吗?”和“做完这一步,我能判断自己做得好不好吗?”如果答案都是“是”,那么分解粒度就是合适的。如果想了半天不知道怎么做,说明粒度太粗;如果觉得“这一步根本没有必要单独拆出来”,说明粒度太细。

Optimal Granularity: ∀Ti,Executable(Ti)=true∧Verifiable(Ti)=true\displaystyle \text{Optimal Granularity: } \forall T_i, \quad \text{Executable}(T_i) = \text{true} \quad \wedge \quad \text{Verifiable}(T_i) = \text{true}
最优粒度的判断标准是:每个子任务都可执行(Agent能独立完成)且可验证(完成质量可以被检查)。
  1. 任意子任务 $\forall T_i$对所有分解出来的子任务都适用,不因任务不同而例外。
    ∀Ti\forall T_i
  2. 可执行性 $\text{Executable}(T_i)$Agent面对这个子任务时,不需要再额外思考“这到底要做什么”,而是可以直接动手完成。
    Executable(Ti)\text{Executable}(T_i)
  3. 可验证性 $\text{Verifiable}(T_i)$子任务完成后有一个检查标准。比如“生成代码”的验证标准是“代码能编译通过”。
    Verifiable(Ti)\text{Verifiable}(T_i)

工程实现技巧

现在我们已经理解了几种分解范式和粒度控制原则,接下来进入实际操作:如何在自己的Agent系统中稳定实现任务分解。这就像主厨把菜谱变成餐厅的标准作业流程——需要工具、标准和容错机制。

在工程实践中,实现可靠的任务分解通常需要以下几个关键技巧。第一是设计结构化的Prompt模板。不要把“请帮我完成任务”这样模糊的Prompt丢给模型,而是用清晰的格式约束它的输出,例如要求“输出一个JSON数组,每项包含任务描述、优先级和依赖关系”。第二是设置递归深度限制。当Agent在“分解→执行→发现子任务还是太大→再分解”的过程中,必须设置最大分解层数(比如3层),防止无限递归。第三是设计失败重试机制。如果某个子任务执行失败,Agent应该有能力重新尝试或重新分解该子任务,而不是直接放弃整个任务。

一个典型的任务分解引擎实现流程如下:先用一个“规划器(Planner)”调用LLM生成任务分解方案,然后用“执行器(Executor)”逐个执行子任务,执行过程中用“监控器(Monitor)”检查每个子任务的结果是否成功。如果成功,继续下一个;如果失败,将失败信息反馈给规划器,让规划器重新调整分解方案。这个“规划-执行-反馈”循环是任务分解工程化的核心。

除了上面三个核心组件,工程上还有一些实用技巧:为每个子任务设置优先级和依赖关系(比如“收集数据”必须排在“分析数据”之前);限制单次任务的Token预算;给每个子任务设置超时时间;在关键节点设置人工审核入口。这些技巧让任务分解从“理论可行”变成“生产可用”。

Engine Flow: Planner⏟分解→Executor⏟执行→Monitor⏟检查→Success / Feedback\displaystyle \text{Engine Flow: } \underbrace{\text{Planner}}_{\text{分解}} \rightarrow \underbrace{\text{Executor}}_{\text{执行}} \rightarrow \underbrace{\text{Monitor}}_{\text{检查}} \rightarrow \text{Success / Feedback}
任务分解引擎的三个核心组件:规划器负责分解、执行器负责干活、监控器负责检查结果并决定继续还是返工。
  1. 规划器 Planner接收用户的目标,调用LLM生成子任务列表。它决定“拆成什么步骤、分成什么顺序”。
    Planner\text{Planner}
  2. 执行器 Executor逐个执行子任务。每个子任务可能调用一个工具、生成一段文本或查询一个数据库。
    Executor\text{Executor}
  3. 监控器 Monitor验证执行结果。可以用程序化验证(比如检查代码是否运行成功),也可以用LLM评估(比如检查报告是否覆盖了所有要点)。
    Monitor\text{Monitor}
  4. 反馈循环 Feedback当执行失败时,监控器将错误信息返回给规划器,规划器重新调整分解方案——比如把失败的任务进一步拆细,或者更换一种执行方式。
    Feedback\text{Feedback}

探索未来方向

任务分解技术发展很快,当前最前沿的方向是自适应分解(Adaptive Decomposition)——让Agent根据任务的实际情况动态调整分解策略,而不是死板地套用固定模板。这就像经验丰富的主厨,遇到难处理的食材时会临时增加处理步骤,遇到简单的菜品则会精简流程,而不是无论什么都按同一个菜谱执行。

自适应分解的核心挑战是“什么时候该拆得更细、什么时候该合并步骤”。目前有几种探索思路:一是基于成本反馈的自适应——如果当前子任务执行失败,说明粒度太粗,自动细分;如果子任务执行时间过长或Token消耗过高,说明粒度太细,自动合并。二是基于模型置信度的自适应——让模型在分解时给出每个子任务的置信度,置信度低的子任务自动进一步分解。三是元认知规划(Meta-planning)——不直接分解任务,而是先让Agent思考“这个任务应该用什么策略来分解”,再做具体分解。

另一个重要方向是分解结果的可解释性。在金融、医疗等高风险场景中,Agent不仅需要完成任务,还需要向用户解释“为什么这样拆解”。为此,研究者们在任务分解过程中引入“里程碑”机制——每个子任务关联一个可读的目标说明和验收标准,让用户随时追踪进度。这就像是主厨的“中央厨房显示屏”,让顾客看到每道菜进行到哪个环节了。

未来,任务分解会从“人工设计Prompt”走向“Agent自主学习分解策略”。这个方向虽然还在早期,但它代表了Agent从“聪明的工具”走向“真正的自主智能体”的关键一步。掌握任务分解,就是掌握打开这扇门的钥匙。

AI 应用场景

智能客服Agent:处理复杂的用户售后请求

阶段:任务规划与执行

解决的问题:传统客服机器人只能处理“查订单、改地址”这类单一意图的请求,面对“我想退货但找不到订单号而且有优惠券没使用”这种复合问题时往往束手无策。通过任务分解,Agent可以将这个复杂请求拆解为:确认用户身份→查找订单→检查退货政策→核算优惠券→生成退货方案,逐一执行。

具体案例:某电商平台的客服Agent收到用户消息“我要退货,但我不确定以前的优惠券是不是还能用”。Agent先调用用户身份识别工具确认账号,再查询订单列表找到目标订单,然后检查该商品的退货窗口期,接着计算优惠券的返还规则,最后生成一条完整的退货方案说明。整个过程用户只需说一句话,Agent完成了所有拆解和执行。

自动化研究报告生成:从关键词到完整报告的流水线

阶段:多步骤任务编排

解决的问题:传统的自动化报告工具只能做“模板替换”,用户需要自己提供所有素材。而Agent可以自主将“生成一份行业研究报告”这个目标分解为:搜索行业数据→整理关键趋势→分析竞品格局→撰写报告大纲→填充各章节→生成摘要和图表,每个步骤调用不同的工具完成。

具体案例:某咨询公司使用Agent自动生成每周行业周报。Agent收到指令后,先在数据库中检索本周政策动态,然后用爬虫抓取行业新闻,再用LLM分析趋势并撰写报告初稿,最后通过排版工具输出PDF。如果某个数据源抓取失败,Agent会自动尝试备用数据源,并在报告中标注数据来源和更新时间。

自动化测试Agent:自主规划测试策略并执行

阶段:规划-执行-反馈循环

解决的问题:传统自动化测试需要测试工程师手动编写每条测试用例,工作量大且覆盖不全。Agent通过任务分解,可以将“测试这个Web应用”分解为:分析应用页面结构→生成核心功能测试用例→执行测试→分析失败原因→补充边缘用例→输出测试报告,并在测试失败时自动重试或调整测试策略。

具体案例:某SaaS公司使用Agent自动执行每次代码提交后的回归测试。Agent首先阅读代码变更日志,判断受影响的功能模块,然后针对这些模块生成重点测试用例,执行过程中发现表单校验功能出现异常,Agent自动抓取错误日志,分析根因是前端脚本冲突,随后生成包含截图和日志的缺陷报告提交给开发团队。

Python 演示

python68 行
import jsonimport time  class TaskDecompositionEngine:    """任务分解引擎:规划->执行->监控->反馈循环"""     def __init__(self, max_depth=3):        self._count = 0        self.max_depth = max_depth     def planner(self, task, depth):        """模拟LLM规划器:将任务分解为子任务列表"""        self._count += 1        if depth > self.max_depth:            return [task]        results = []        keywords = ["report", "data", "email"]        for kw in keywords:            if kw in task.lower():                results.append({"task": f"收集{kw}信息", "status": "pending"})        if not results:            results.append({"task": str(task), "status": "pending"})        return results     @staticmethod    def executor(sub_task):        """模拟执行器:执行单个子任务,返回是否成功"""        if "收集" in sub_task["task"]:            time.sleep(0.05)            return True, "已收集到相关信息"        return False, "未知任务类型,执行失败"     def monitor(self, sub_task, success, message):        """模拟监控器:检查执行结果,返回是否合格"""        if success and len(message) > 0:            sub_task["status"] = "completed"            return True        sub_task["status"] = "failed"        return False     def run(self, goal):        """运行完整流程:规划->执行->监控->反馈"""        all_results = []        tasks = self.planner(goal, depth=1)        while tasks:            current = tasks.pop(0)            print(f"[执行] {current['task']}")            ok, msg = self.executor(current)            passed = self.monitor(current, ok, msg)            if not passed:                print(f"[反馈] 子任务失败,重新分解: {current['task']}")                sub_tasks = self.planner(current["task"], depth=2)                if len(sub_tasks) == 1 and sub_tasks[0]["task"] == current["task"]:                    print("[警告] 无法继续分解,放弃该子任务")                    continue                tasks = sub_tasks + tasks            else:                all_results.append(current)                print(f"[完成] {current['task']}")        return all_results  if __name__ == "__main__":    engine = TaskDecompositionEngine(max_depth=3)    output = engine.run("生成一份市场分析报告")    print("\n=== 最终结果 ===")    print(json.dumps(output, ensure_ascii=False, indent=2))
目的:演示Agent任务分解的完整循环——规划器把“生成市场分析报告”分解为若干子任务,执行器逐个执行,监控器校验结果,失败则重新分解。
  1. self._count += 1记录规划器调用次数,防止无限循环(每调用一次规划器就计数一次)。
  2. keywords = ["report", "data", "email"]模拟LLM的关键词识别逻辑,现实中这里会调用大模型生成分解结果。
  3. sub_task["status"] = "pending"子任务的初始状态,后续由监控器更新为completed或failed。
  4. if "收集" in sub_task["task"]:执行器只处理“收集”类任务,模拟实际Agent执行工具调用的过程。
  5. ok, msg = self.executor(current)执行器返回两个值:是否成功,以及执行消息。
  6. passed = self.monitor(current, ok, msg)监控器根据成功标志和消息内容判断子任务是否合格。
  7. sub_tasks = self.planner(current["task"], depth=2)失败时调用规划器重新分解,这是“反馈循环”的核心。
  8. tasks = sub_tasks + tasks把重新分解的子任务放到队列最前面,优先执行。
  9. if len(sub_tasks) == 1 and sub_tasks[0]["task"] == current["task"]:防止无法再分解时陷入死循环。

常见误区

误区我总是把任务分解到最细,比如“打开电脑→打开编辑器→新建文件→输入代码→保存文件”,这样每一步都很明确,Agent执行起来一定更准确吧?但实际运行下来Agent反而变慢了,还经常出错。

正解分解粒度并非越细越好。就像主厨不会把“拿刀”拆成“伸手→握住刀柄→抬起刀”一样,过细的分解会让Agent把认知资源浪费在琐碎的子任务切换上,每次切换都有Token消耗和延迟。合适的粒度是“每个子任务恰好能对应一次工具调用或一个完整产出”。如果“打开电脑”这种动作都需要单独一步,Agent会被淹没在细节里,反而看不到全局目标。

为何常见:因为初学者容易把“详细”和“清晰”混为一谈。看到CoT论文中“逐步思考”的效果很好,就误以为所有场景都是步骤越多越好,忽略了步骤间的切换是有成本的。

误区我在Prompt里加了“Let's think step by step“,为什么Agent输出的步骤还是很空泛?比如让它”策划市场活动“,它只列了”确定目标→制定方案→执行”三步就没下文了,根本没法直接执行。是不是这个提示词是骗人的?

正解CoT确实能提升模型的推理质量,但它不是万能魔法。"Let's think step by step"只是引导模型把推理过程写出来,如果模型本身缺少任务领域的知识,它依然无法做出有效的分解。正确的做法是:结合Few-shot示例,提供2-3个高质量的分解范例;在Prompt中给出可用的工具列表、约束条件和输出格式;对分解结果进行后校验,而不是直接信任输出。

为何常见:因为网上很多教程把CoT宣传成“零样本就能显著提升”的银弹,初学者照搬句式后发现效果不理想,产生了误解。实际上CoT的效果高度依赖任务类型和示例质量。

误区我读了一些博客,说ToT在数独、创意写作等任务上超过了CoT,那我是不是应该把所有Agent的任务分解都换成ToT?这样效果一定更好吧?但是运行成本太高了,每个问题都要调几十次API。

正解ToT的强大来自于“多次生成候选+评估+搜索”,这意味着Token消耗大约是CoT的10-50倍。就像你点一份蛋炒饭,不需要让厨师先做三种不同版本再选最好吃的。ToT只适用于:任务有多个合理方向需要探索、错误代价高(如医疗诊断)、且用户愿意为质量接受更高成本。对于大多数日常任务,CoT的线性分解足够好,ReAct的交互式执行性价比更高。

为何常见:因为搞AI的人容易“技术先进崇拜”——总想用最新最复杂的技术,而忽略了一个基本问题:这个技术解决的关键问题,我的场景里真的存在吗?

误区我在Agent里实现了ReAct循环,让模型观察工具返回结果并决定下一步。但有时候模型看到工具的返回数据后会“脑补”出不存在的信息,比如工具返回了空列表,模型却在下一步假设“已经拿到了数据”。这不应该是工具返回什么,模型就看到什么吗?

正解ReAct中的“观察”环节需要工程化的校验,不能完全依赖模型的自我报告。大语言模型在处理外部信息时,可能会产生幻觉,尤其是当工具返回内容较长或格式复杂时。正确的做法是:在观察环节加入程序化的解析和校验,例如检查API返回码是否为200、JSON解析是否成功、关键字段是否存在,只有通过校验的结果才交给模型作为下一步推理的依据。

为何常见:因为ReAct论文中的例子看起来很流畅(Thought→Action→Observation),初学者容易把这个理想化的循环当成天然可靠的机制,忽略了工程实现中需要加的一层层防护。

面试题

Q1. 任务分解在Agent架构中的核心作用是什么?

单选题 · easy

  • A.减少模型的参数量
  • B.将复杂任务拆为可执行子步骤← 正确答案
  • C.加速模型训练速度
  • D.提高文本生成的流畅度

答案:B。任务分解的核心作用就是把复杂目标转化为有序的子任务集合,让Agent能够逐步执行(像主厨拆解宴席订单)。参数量、训练速度、文本流畅度都与任务分解无关。

Q2. CoT(思维链)提示词的核心思想是什么?

单选题 · easy

  • A.让模型一次性输出最终答案
  • B.让模型先生成中间推理步骤再给答案← 正确答案
  • C.让模型训练更多数据
  • D.让模型同时处理多个任务

答案:B。CoT的核心是让模型在给出最终答案前,先产生一步步的推理过程,就像主厨示范做菜时逐步讲解每一道工序。这样能显著提升复杂推理任务的效果。选项A是CoT想要避免的做法,C和D与思维链无关。

Q3. ToT(思维树)与CoT最主要的区别是什么?

单选题 · mid

  • A.ToT不需要调用大模型
  • B.ToT探索多条候选路径并评估选择← 正确答案
  • C.ToT只能用于数学计算
  • D.ToT比CoT使用更少的Token

答案:B。ToT的核心是从树的每个节点生成多个候选分支,用评估器打分后进行选择、回溯或剪枝(像主厨试做多套方案再选择)。CoT只沿着一条路径走到底。ToT需要更多Token而不是更少,也不只限于数学任务。

Q4. ReAct循环的正确顺序是什么?

单选题 · mid

  • A.行动→观察→思考→行动
  • B.观察→行动→思考→观察
  • C.思考→行动→观察→思考← 正确答案
  • D.思考→观察→行动→思考

答案:C。ReAct循环是“Thought(思考)→ Action(行动)→ Observation(观察)→ Thought(思考)”的不断迭代。Agent先想,再做,再看结果,根据结果再想。就像主厨先想“该炒糖色了”,然后行动,观察颜色,再决定下一个动作。

Q5. 关于任务分解粒度,以下哪种说法是正确的?

单选题 · mid

  • A.分解越细越好,永远不会出现错误
  • B.分解越粗越好,节省Token最重要
  • C.每个子任务应可执行且可验证← 正确答案
  • D.所有任务的分解粒度应该完全一致

答案:C。最优粒度是“恰好能被一步完成且结果可以被验证”。太粗一步做不完,太细浪费Token和延迟。不同复杂度的任务应有不同的粒度,不存在万能标准。选项A和B走向两个极端,D忽略了任务差异。

Q6. 在ReAct范式中,Agent执行一个工具调用后获得的API返回数据属于哪个环节?

单选题 · mid

  • A.Thought(思考)
  • B.Action(行动)
  • C.Observation(观察)← 正确答案
  • D.Planning(规划)

答案:C。工具调用本身是Action(行动),而API返回的数据就是Observation(观察)。Agent基于这个观察结果进行下一轮思考,决定下一步行动。就像主厨炒糖色后看到锅里的颜色变化,这个视觉反馈就是“观察”。

Q7. 在任务分解的工程实现中,以下哪些做法是合理有效的?

多选题 · mid

  • A.设置递归分解的最大深度← 正确答案
  • B.子任务失败时重新分解← 正确答案
  • C.让Agent无限循环直到成功
  • D.用结构化格式约束分解结果← 正确答案

答案:ABD。设置最大深度防止无限递归是必要的;失败时重新分解是反馈循环的核心;用JSON等结构化格式约束分解结果有利于程序化校验。选项C“无限循环”会导致死循环和Token耗尽,必须用最大重试次数来限制。

Q8. 关于三种任务分解范式的适用场景,以下说法正确的是哪些?

多选题 · hard

  • A.CoT适合简单直接的线性推理任务← 正确答案
  • B.ToT适合需要多方案对比的复杂任务← 正确答案
  • C.ReAct适合需要与环境实时交互的任务← 正确答案
  • D.CoT在所有场景下都优于ReAct,不需要工具调用

答案:ABC。CoT适合线性推理,ToT适合多分支探索,ReAct适合与环境交互(需要调用工具并观察结果)。三种范式各有适用场景,D选项说“CoT在所有场景下都优于ReAct”是错误的——需要工具信息的任务必须用ReAct。

Q9. “子任务粒度合适”的标志是什么?

单选题 · hard

  • A.每个子任务在10秒内完成
  • B.每个子任务可直接执行且完成后可验证← 正确答案
  • C.每个子任务恰好消耗1次API调用
  • D.每个子任务包含至少5个细节要点

答案:B。合适的粒度标准是“可直接执行”和“可验证”两个条件,类似于“这一步我能直接上手”和“做完我能判断好坏”。耗时和API调用次数不是判断粒度的标准,因为不同任务单步执行的复杂度本身就有差异。

Q10. 下面哪些是任务分解中常见的失败模式?

多选题 · easy

  • A.分解步骤过于空泛导致无法执行← 正确答案
  • B.分解过于琐碎导致效率低下← 正确答案
  • C.子任务之间缺少依赖关系控制← 正确答案
  • D.所有子任务同时执行不需要顺序

答案:ABC。分解过于空泛=粒度太粗,过于琐碎=粒度太细,缺少依赖关系会导致“分析数据”先于“收集数据”执行,都是常见失败模式。选项D恰恰是错误做法的描述——很多任务有严格的先后依赖关系,不能同时执行。