想象你站在除夕的厨房门口,家人催你“快去准备年夜饭”。这句话听起来简单,但要真正落地,你得先想清楚请谁来、吃什么、预算多少,再列出一张菜单,拿着菜单去采购,回来后按冷热次序一道道做出来。这中间每一次“再想想下一步该做什么”的动作,就是子目标生成。AI Agent 面对抽象大任务时同样如此——用户丢来一句“帮我写一份市场分析报告”,它不能凭空生成报告,而要先拆出“确定分析框架、收集数据、梳理竞品、撰写报告、校对格式”这些中介目标,再逐个完成。这篇文章就用“年夜饭思维”带你拆解子目标生成:它是什么、模型怎么想、输出长什么样、怎样拆得好、如何评估、会遇到什么坑,以及真实工作中怎么用。

岗位关联

一句话价值:子目标生成是 Agent 从“看懂任务”到“动手执行”的桥梁,掌握它,你才能设计出真正可靠的自主规划系统。

目录
  1. 可视化演示
  2. 概念定位
  3. 工作原理
  4. 结构化输出
  5. 分解策略
  6. 评估体系
  7. 挑战应对
  8. 实践应用
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示系统处理流水线、实时性能指标曲线及多方案对比分析,包含数据流转、吞吐延迟监控与方案评估。

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

系统可视化 处理流程:输入→处理→模型→输出 性能监控:实时指标 P=L×T

概念定位

年夜饭不会凭空出现在餐桌上。你得先回答“请谁来、吃什么、预算多少”,然后把它变成一份菜单和一张采购清单。这个从“一桌年夜饭”的模糊念头,到“菜单+采购单”的清晰方案的过程,就是人类版的子目标生成——它把不可执行的愿望,翻译成了一串可以动手做的事情。

在 Agentic AI 中,子目标生成(Subgoal Generation)是自主规划的第一步。它接收一个抽象大任务——比如“帮我规划一篇技术博客”——借助 LLM 的推理能力,输出一串中介目标:确定主题、收集资料、搭建大纲、逐节写作、校对发布。这些目标不是最终动作,而是中间站:每个子目标都足够具体,让后续的规划器或执行器知道“下一步该做什么”。

公式化地看,给定任务描述 $T$ 和上下文 $C$(工具清单、历史记忆、环境约束),模型生成子目标序列 $G_1, G_2, \dots, G_n$ 的联合概率,可以按链式法则展开:

所以,子目标生成在 Agent 中的位置,就像年夜饭的“备菜环节”:它是整个下厨流程的起点。如果这一步拆错了——菜单列了一堆不存在的菜、采购单漏了关键调料——后面所有执行环节都会被带偏。这也是为什么它是自主规划中“第一公里”的原因:起点歪了,走得再快也到不了目的地。

P(G1,G2,…,Gn∣T,C)=∏i=1nP(Gi∣T,C,G1,…,Gi−1)\displaystyle P(G_1, G_2, \dots, G_n \mid T, C) = \prod_{i=1}^{n} P(G_i \mid T, C, G_1, \dots, G_{i-1})
这个公式说:拆解不是一口气完成的,而是一步一步“边看前面已拆好的目标,边决定下一个目标”。
  1. 任务与上下文(T 与 C)$T$ 是用户给出的抽象指令,$C$ 是工具、记忆、预算等约束信息。年夜饭场景中 $T$=“办年夜饭”,$C$=“6 人、800 元、4 小时”。
    T,  C\displaystyle T, \; C
  2. 子目标序列(G₁……Gₙ)分解出的有序中介目标集合,对应“定菜单→采购→预处理→烹饪→上菜”这条链路。
    G1,G2,…,Gn\displaystyle G_1, G_2, \dots, G_n
  3. 连乘符号(∏)与链式法则把“一次性生成所有子目标”的联合概率,拆成每步只生成一个子目标的条件概率相乘,让生成过程可逐步落地。
    ∏i=1n\displaystyle \prod_{i=1}^{n}
  4. 条件部分(G₁……Gᵢ₋₁)生成第 $i$ 个子目标时,要参考之前所有已生成的目标——这正是“先定菜单才能采购”的数学表达。
    P(Gi∣T,C,G1,…,Gi−1)\displaystyle P(G_i \mid T, C, G_1, \dots, G_{i-1})

工作原理

年夜饭的掌勺人走进厨房时,脑子里在高速运转:家里几口人吃?冰箱里冻着什么?谁对什么过敏?预算还剩多少?这些信息汇聚成一份菜单。在 Agent 系统中,LLM 就是这位掌勺人,而提示词是递给它的“任务单”——任务单上写着角色、目标、约束和输出要求。

LLM 生成子目标主要靠三个引擎:提示词驱动,告诉模型“你是一位任务规划专家,请把以下任务拆成可执行的子目标列表”;连锁推理,模型先生成第一个子目标,把它当作已知信息,再推理第二个,一环扣一环;上下文感知,把工具列表、历史交互、环境状态全部拼进提示词,让模型知道“自己手里有什么资源”。

每个子目标的生成,本质上是模型在候选空间上做一次条件概率采样。LLM 对每个候选子目标计算一个分数,再用 softmax 归一化成概率分布:

主厨从不是凭空乱想——他“看着已做好的菜,决定下一道做什么”。冰箱里有什么决定了采购单,菜单上写了什么决定了下一步动作。LLM 的连锁推理同样如此:已生成的子目标像多米诺骨牌一样,一张搭着一张,把抽象任务一步一步推到可执行的岸边。

P(Gi∣T,C,G<i)=exp⁡(score(Gi))∑G′∈Gexp⁡(score(G′))\displaystyle P(G_i \mid T, C, G_{<i}) = \frac{\exp(\text{score}(G_i))}{\sum_{G' \in \mathcal{G}} \exp(\text{score}(G'))}
模型不是随机挑一个子目标,而是给所有候选打“合理分”,再按分数高低抽签——分数越高的越容易被选中。
  1. 历史子目标(G<ᵢ)前 $i-1$ 个子目标的缩写。它告诉模型:“你已经决定了菜单和采购单,现在该决定什么?”
    G<i=G1,…,Gi−1\displaystyle G_{<i} = G_1, \dots, G_{i-1}
  2. 打分函数 score(Gᵢ)LLM 内部对候选子目标与当前情境匹配程度的评分,匹配度越高分越高。
    score(Gi)\displaystyle \text{score}(G_i)
  3. 候选空间(G' ∈ 𝒢)所有可能成为下一个子目标的候选项集合。年夜饭场景中,“采购食材”和“先睡一觉”都在候选里,但后者分数极低。
    ∑G′∈G\displaystyle \sum_{G' \in \mathcal{G}}
  4. softmax 归一化把一组任意分数压成总和为 1 的概率分布,分数最高的候选获得最大的生成概率。
    exp⁡(x)∑jexp⁡(xj)\displaystyle \frac{\exp(x)}{\sum_{j} \exp(x_j)}

结构化输出

菜单不能只存在于主厨脑子里——得写在一张纸上:凉菜三道、热菜五道、汤一道,每道标注主料和用时。否则,采购员不知道买什么,帮厨不知道从哪下手。Agent 世界里,这张“纸”就是结构化输出。

如果 LLM 用一句自然语言“我觉得可以先去买菜”回答,下游程序没法解析“买菜”是什么字段。所以工程上要求模型输出 JSON,或直接走 函数调用(Function Calling),让每个子目标都能被程序识别、存储和调度。一个典型的子目标对象长这样:包含标题、描述、依赖列表。子目标集合加上依赖关系,天然形成一张有向无环图(DAG)。

这张“电子菜单”不是给人看的随笔,而是后厨执行的总纲。每道菜标注了“需要什么、谁先谁后”;厨师们(执行器)照着单子各就各位,采购员拿到采购项,备菜组拿到切配任务,炒锅组拿到烹饪序列——没有结构化输出,这一切都会变成一团糨糊。

G={gi=(idi,titlei,depsi)}i=1n,depsi⊆{g1,…,gi−1}\displaystyle G = \{ g_i = (\text{id}_i, \text{title}_i, \text{deps}_i) \}_{i=1}^{n}, \quad \text{deps}_i \subseteq \{ g_1, \dots, g_{i-1} \}
每个子目标是一个带“身份证”的对象,deps 字段指着它前面必须完成的目标——这就是“烹饪 A 之前必须先备好菜 B”的形式化表达。
  1. 子目标对象 gᵢ一个三元组,对应 JSON 里的一个对象。比如 $g_2=(\text{"G2"}, \text{"采购食材"}, \{\text{"确定菜单"}\})$。
    gi=(idi,titlei,depsi)\displaystyle g_i = (\text{id}_i, \text{title}_i, \text{deps}_i)
  2. 依赖集合 depsᵢ执行 $g_i$ 之前必须完成的前置子目标集合,可能为空(表示没有前置,可以并行执行)。
    depsi\displaystyle \text{deps}_i
  3. 前序约束(⊆)依赖只能指向更早生成的子目标,禁止反向或循环依赖——这保证了子目标图是一张无环的 DAG,调度器可以放心地按拓扑序执行。
    depsi⊆{g1,…,gi−1}\displaystyle \text{deps}_i \subseteq \{ g_1, \dots, g_{i-1} \}

分解策略

年夜饭的上菜是有讲究的:凉菜提前备好、热菜现炒现上、汤在最后压轴。这不是随机安排,而是根据每道菜的特点(能不能等、要不要现做、有没有先后依赖)设计的时间线。这就是子目标生成中的“分解策略”。

三种典型策略:层次拆解,把大目标逐层细化——“办年夜饭”先拆成“备菜、烹饪、上菜”,再把“备菜”拆成“采购、清洗、切配”;并行协作,无依赖的子目标交给不同执行器同时推进——凉菜组和甜点组互不打扰;动态调整,执行中发现缺了某味调料,就临时插入一个“采购替代品”的子目标。所有子目标加上依赖关系构成一张 DAG:

年夜饭的后厨就是一台并行机器:凉菜组和甜点组同时开工,互不打扰;热菜组眼巴巴等着食材预处理完成才点火。子目标分解策略的意义,正在于把一团乱麻的“办一桌饭”理顺成一张清晰的工序图——谁先谁后、谁等谁、谁可以插队,一目了然。

G=(V,E),(Gi,Gj)∈E  ⟺  Gi⪯Gj\displaystyle \mathcal{G} = (V, E), \quad (G_i, G_j) \in E \iff G_i \preceq G_j
顶点是子目标,边是“必须先做”的偏序关系。有了这张图,调度器就知道谁可以并行、谁必须等待。
  1. 顶点集 V所有子目标的集合。比如 $V=\{\text{定菜单},\text{采购},\text{烹饪},\text{上菜}\}$。
    V={G1,G2,…,Gn}\displaystyle V = \{G_1, G_2, \dots, G_n\}
  2. 有向边集 E依赖边的集合,从前置目标指向后续目标。有边相连的两个目标必须分先后。
    E⊆V×V\displaystyle E \subseteq V \times V
  3. 偏序关系(⪯)$G_i \preceq G_j$ 读作“$G_i$ 先于 $G_j$”,表示 $G_j$ 必须等 $G_i$ 完成后才能开始。若两个目标互不指向对方,则它们可以并行。
    Gi⪯Gj\displaystyle G_i \preceq G_j

评估体系

年夜饭吃完,家人总会评价两句:菜齐不齐、口味如何、花了多久、厨房有没有被炸掉。子目标生成也一样,不能只看“拆没拆出来”,而要建立一套多维评分卡。

一套工业级的评估体系至少包含四个维度:准确性(子目标集合是否覆盖了任务的全部关键环节、有没有遗漏或多余);鲁棒性(把任务换个说法或加点噪声,拆出来的结果还稳不稳定);效率(分解消耗了多少 token、多少轮次、多少延迟);安全性(有没有产生越权、危险或违反约束的子目标)。实际系统中,通常用加权求和把这四个维度压成一个可比较的值:

这就像给年夜饭综合打分:好吃(准确)、换一批客人也不翻车(鲁棒)、两小时就出锅(效率)、厨房没起火(安全)。哪一味权重更高,取决于你请的客人是谁——请了丈母娘,安全和准确都得拉满;请了老同学,效率可以往后放放。

Score=α×A+β×R+γ×E+δ×S,α+β+γ+δ=1\displaystyle \text{Score} = \alpha \times A + \beta \times R + \gamma \times E + \delta \times S, \quad \alpha+\beta+\gamma+\delta = 1
四个维度的重要性由业务场景决定:支付系统安全权重高,论文写作效率权重高,客服机器人准确权重高。
  1. 准确性 A(Accuracy)评估“子目标集合是否真实覆盖用户需求”,用覆盖率、精确率等指标衡量。
    A=正确子目标数总子目标数\displaystyle A = \frac{\text{正确子目标数}}{\text{总子目标数}}
  2. 鲁棒性 R(Robustness)对任务表述加入扰动后重新拆解,得分波动越小,鲁棒性越好。
    R=1−扰动前后得分差异原始得分\displaystyle R = 1 - \frac{\text{扰动前后得分差异}}{\text{原始得分}}
  3. 效率 E(Efficiency)分解的成本指标,包括 token 数、调用轮次、端到端延迟。
    E=11+cost(T,C)\displaystyle E = \frac{1}{1 + \text{cost}(T, C)}
  4. 安全性 S(Safety)违反安全约束(越权访问、危险操作)时该项直接归零甚至倒扣。
    S={0,违规1,合规\displaystyle S = \begin{cases} 0, & \text{违规} \\ 1, & \text{合规} \end{cases}
  5. 权重归一(α+β+γ+δ=1)四个权重之和为 1,保证最终分数在可比较的范围内,不同系统之间能横向对比。
    α+β+γ+δ=1\displaystyle \alpha + \beta + \gamma + \delta = 1

挑战应对

年夜饭年年有翻车时刻:炖汤忘了开火、切到一半发现刀钝了、菜单写了“买新鲜鲈鱼”结果市场没有——这些全是子目标生成在真实环境中的困境。理解这些坑,比知道理论更重要。

三大经典挑战:目标漂移,Agent 执行着执行着忘了原始需求——原计划是“做年夜饭”,中途却开始研究厨房改造;粒度失衡,拆得太粗,“做菜”这种目标没法执行,拆得太细,“把葱切成 3 厘米段”这种原子动作又碎片化到让人抓狂;幻觉控制,LLM 编造出根本不存在的步骤——“采购独角兽肉”这种离谱子目标。应对之道可以用一个优化问题概括:

聪明的掌勺人会做三件事:把“年夜饭总目标”贴在灶台前(防漂移);能买半成品就不从种菜开始(控粒度);菜单先给采购员核对一遍再动身(防幻觉)。对应到 Agent 工程上,就是把原始任务作为不可变约束写进每一步上下文、用“最小可执行粒度”准则约束分解深度、用结构化输出和外部工具交叉验证来拦截编造的子目标。

min⁡G  Cost(G)s.t.  Coverage(G)≥τ\displaystyle \min_{G} \; \text{Cost}(G) \quad \text{s.t.} \; \text{Coverage}(G) \ge \tau
在保证覆盖率不低于阈值 τ 的前提下,让子目标树的执行成本最小——这就是“够用就好,不铺张”的数学版本。
  1. 执行成本 Cost(G)子目标树的深度、宽度、总 token 数、调度开销之和。拆得越细,成本越高。
    Cost(G)=∑g∈Gcost(g)\displaystyle \text{Cost}(G) = \sum_{g \in G} \text{cost}(g)
  2. 覆盖率 Coverage(G)子目标集合对原始任务关键环节的覆盖比例,用来衡量“拆得全不全”。
    Coverage(G)=被覆盖的需求环节数总需求环节数\displaystyle \text{Coverage}(G) = \frac{\text{被覆盖的需求环节数}}{\text{总需求环节数}}
  3. 约束条件(s.t.)覆盖率必须不低于阈值 $\tau$。低于阈值的分解再省也不合格——菜单再简洁,漏了主菜就是失败。
    Coverage(G)≥τ\displaystyle \text{Coverage}(G) \ge \tau
  4. 最小化目标(min)在所有满足覆盖率约束的分解方案里,挑成本最低的那个作为最终计划。
    min⁡G\displaystyle \min_{G}

实践应用

同样是用厨房,日常晚餐和年夜饭的拆法完全不同——一个人的晚饭可能只需要“煮个面”,年夜饭却要拆出五六个环节。这就是“场景决定拆法”。子目标生成的价值,也正体现在不同场景下灵活拆解的能力上。

三个最典型的落地场景:任务规划 Agent,比如智能客服收到“我上周买的耳机有问题想退”,先生成“验证身份→查询订单→核对退款政策→执行退款→通知用户”的子目标链,再逐环执行;AI 编程助手,收到“帮内部系统加一个重置密码功能”,拆成“设计用户表→写后端接口→写前端表单→联调测试”;研究辅助工具,把“总结 Transformer 近三年的改进”拆成“检索论文→筛选文献→阅读摘要→整理时间线→生成综述”。这些场景共享同一个成功模型:

年夜饭能不能顺利端上桌,取决于每一道菜:凉菜没准备、热菜炒糊了、汤忘炖了——任何一环掉链子,这桌饭就算砸了。所以拆菜单时,每一道菜都要“够小、够清楚、够靠谱”。这正是子目标生成在真实系统中的终极使命:让模糊意图,变成一串每一步都能被可靠执行的阶梯。

P(task success)=∏g∈GP(complete(g)∣deps done)\displaystyle P(\text{task success}) = \prod_{g \in G} P(\text{complete}(g) \mid \text{deps done})
整个任务的成功率,等于每个子目标在“前置依赖全部完成”条件下成功执行的概率相乘——链条上任何一环掉链子,全局都会打折。
  1. 完成子目标 complete(g)执行器把子目标 $g$ 从“计划”变成“事实”的过程。比如“采购食材”完成后,购物车变成了冰箱里的菜。
    complete(g)\displaystyle \text{complete}(g)
  2. 依赖就绪 deps done子目标 $g$ 的所有前置目标已完成。烹饪前必须确认食材已预处理完毕。
    deps done=⋀d∈deps(g)complete(d)\displaystyle \text{deps done} = \bigwedge_{d \in \text{deps}(g)} \text{complete}(d)
  3. 连乘(全局成功率)每个子目标都是任务链上的一环。$n$ 个子目标,每个成功率 90%,全局只有 $0.9^n$,子目标越多,全局风险越大。
    ∏g∈G\displaystyle \prod_{g \in G}
  4. 条件概率的启示单个子目标越可靠、粒度越适中,全局成功率越高——宁可少而稳,不要多而脆。
    P(complete(g)∣deps done)\displaystyle P(\text{complete}(g) \mid \text{deps done})

AI 应用场景

智能客服退款 Agent

阶段:自主规划(子目标生成)

解决的问题:传统客服机器人只能按预设脚本逐条问答,遇到“我要退款”这种模糊诉求无法灵活应对。有了子目标生成,Agent 先把诉求拆成“验证身份→查询订单→核对退款政策→执行退款→通知用户”的子目标链,再逐环执行。年夜饭思维在这里的体现是:先拆菜单,再动刀铲。

具体案例:某电商客服机器人收到“我上周买的耳机有问题想退”,子目标生成器产出五步计划并标注依赖关系。执行到“核对退款政策”时发现订单已超退换期,Agent 自动在该节点分流到人工处理,而不是机械地拒绝用户。

AI 编程助手需求拆解

阶段:代码生成的前置规划

解决的问题:直接让 LLM“写一个登录功能”,往往产出一大段结构混乱的代码。子目标生成先把需求拆成“设计用户表→实现认证接口→编写前端表单→联调测试”,每个子目标对应一段独立可验证的代码。就像年夜饭先把“采购”和“烹饪”分开,不会把买菜和炒菜混成一锅。

具体案例:开发者在 IDE 中输入“为内部系统添加重置密码功能”,Copilot 类工具先生成六个带依赖关系的子目标,按拓扑序逐项生成代码片段,每完成一项自动跑一次单元测试,失败则动态重拆分目标。

科研文献调研 Agent

阶段:信息检索与综述规划

解决的问题:复杂调研涉及大量检索与阅读,直接问 LLM“总结一下 transformer 的进展”只会得到泛泛而谈。子目标生成拆出“明确调研问题→检索论文→筛选高相关文献→阅读摘要→整理时间线→生成综述”,实现全流程自动化。这就像年夜饭把“采购→预处理→烹饪”严格分岗,每道工序都有专人负责。

具体案例:研究者让 Agent“总结 Transformer 近三年的架构改进”,Agent 拆出 5 个子目标并行推进——两路检索、一路筛选、一路阅读、一路汇总,最后生成一份带引用来源的结构化报告。

Python 演示

python72 行
"""子目标生成演示:借助 LLM 把抽象任务拆解为可执行子目标"""import jsonfrom dataclasses import dataclass, fieldfrom typing import List  @dataclassclass Subgoal:    id: str    title: str    description: str    deps: List[str] = field(default_factory=list)  def build_prompt(task: str, context: str) -> str:    schema = '{"subgoals": [{"title": "...", "description": "...", "deps": []}]}'    return (        "你是任务分解专家。请将用户任务拆解为 3-6 个可执行子目标。\n"        f"任务:{task}\n"        f"上下文:{context}\n"        f"只输出 JSON,格式:{schema}"    )  def parse_response(text: str) -> List[Subgoal]:    data = json.loads(text)    subgoals = []    for idx, item in enumerate(data["subgoals"], start=1):        subgoals.append(Subgoal(            id=f"G{idx}",            title=item["title"],            description=item["description"],            deps=item.get("deps", []),        ))    return subgoals  def generate_subgoals(task: str, context: str, llm) -> List[Subgoal]:    """核心流水线:构造提示词 -> 调用 LLM -> 解析 JSON -> 返回子目标列表"""    prompt = build_prompt(task, context)    response = llm(prompt)    return parse_response(response)  def mock_llm(prompt: str) -> str:    """模拟 LLM 的结构化输出(真实场景换成 OpenAI/Claude/本地模型调用)"""    return json.dumps({        "subgoals": [            {"title": "确定菜单", "description": "根据家人口味与预算列出菜品清单", "deps": []},            {"title": "采购食材", "description": "按菜单清单购买所需食材与调料", "deps": ["确定菜单"]},            {"title": "预处理食材", "description": "清洗切配腌制,做好备菜", "deps": ["采购食材"]},            {"title": "烹饪菜品", "description": "冷热菜分序烹饪,注意火候", "deps": ["预处理食材"]},            {"title": "摆盘上菜", "description": "装盘装饰并按时端上餐桌", "deps": ["烹饪菜品"]},        ]    })  def print_plan(subgoals: List[Subgoal]) -> None:    print("生成的子目标计划:")    for g in subgoals:        deps = "、".join(g.deps) if g.deps else "无"        print(f"  {g.id} [{g.title}] 依赖: {deps}")        print(f"      {g.description}")  if __name__ == "__main__":    plan = generate_subgoals(        task="办一桌丰盛的年夜饭",        context="6 人用餐,预算 800 元,时间 4 小时",        llm=mock_llm,    )    print_plan(plan)
目的:演示子目标生成的标准流水线——构造提示词、调用 LLM、解析 JSON、输出带依赖关系的子目标计划。
  1. from dataclasses import dataclass, field定义 Subgoal 数据结构,用 dataclass 让子目标对象更简洁可读。
  2. schema = '{"subgoals": [{"title": "...", "description": "...", "deps": []}]}'在提示词里给定 JSON 模式约束,这就是“结构化输出”最直接的工程实现。
  3. f"任务:{task}\n上下文:{context}"把任务的上下文(人数、预算、时间)拼进提示词,对应“上下文感知”要素。
  4. data = json.loads(text)将 LLM 返回的文本解析成 Python 字典,验证格式合法性的第一道关卡。
  5. deps=item.get("deps", [])读取依赖字段,缺失时默认为空列表,保证解析的鲁棒性。
  6. def generate_subgoals(task, context, llm)核心流水线:把提示词构造、模型调用、响应解析封装成一个函数。
  7. def mock_llm(prompt)模拟 LLM 的结构化返回,真实场景替换为 OpenAI/Claude 的 API 调用即可。
  8. deps = "、".join(g.deps) if g.deps else "无"打印依赖时把列表拼成可读字符串,空依赖显示“无”。

常见误区

误区我让 LLM 把任务列出几条,就算完成子目标生成了。反正都是拆分任务,写几条要点不就行了?

正解清单背后有三样硬功夫:结构化(字段可解析)、依赖表达(先后关系明确)、上下文约束(不偏离原始意图)。年夜饭菜单要标注食材、用量和先后顺序,后厨才能照着执行。一份没有 deps 字段的“清单”就像一张没写做法的菜单——采购员不知道买多少,厨师不知道先做哪道。

为何常见:从用户视角看,输出形式确实都像“列表”,于是忽略了列表内部的结构、依赖与约束才是子目标生成的核心价值。

误区为了确保执行可靠,把每个子目标都拆到原子动作,拆得越多越安全,反正 LLM 又不要钱。

正解粒度越细,token 开销、调度延迟、组合爆炸越严重,反而拖垮整个系统。实践准则是“最小可执行粒度”——拆到执行器不需要再思考就能做的程度即可。这与评估体系中的成本公式一致:在覆盖率达标的前提下,Cost(G) 越小越好。把“切葱”拆成“拿刀、握葱、下刀、收刀”,就是典型过度拆分。

为何常见:直觉上“细=精确”,却忽视了工程成本和收益的边际递减——拆到一定程度后,更细的粒度带来的收益趋近于零,成本却线性上升。

误区只要第一步拆得好,后面按计划走就行了。计划就是拿来执行的,改来改去说明拆得不好。

正解真实环境充满变数——工具调用失败、中间结果异常、用户中途改需求。成熟的 Agent 会周期性“回看”子目标树,对失败节点做局部重拆分。年夜饭做一半发现没料酒,就得临时插入“买料酒”或“用黄酒替代”的新子目标。动态调整不是“拆得不好”,而是对不确定世界的正常响应。

为何常见:把复杂系统想成线性流水线,低估了环境动态性和工具调用的不确定性。

误区GPT-4 推理那么强,直接让它用自然语言输出子目标就行,JSON 约束反而限制模型的发挥。

正解自然语言输出没法可靠解析——字段缺失、格式漂移、多一个逗号都可能让下游程序直接报错。结构化输出(JSON Schema / 函数调用)相当于给 LLM 一张“菜单模板”,约束它把思路填进固定的格子。模板看起来限制了自由,却换来了批量运行时的解析率与稳定性,收益远大于损失。

为何常见:只看到单次演示的惊艳效果,没看到生产环境中成百上千次调用的格式脆弱性。

面试题

Q1. 子目标生成在 Agent 自主规划中的核心作用是?

单选题 · easy

  • A.替代大模型做核心推理
  • B.拆分抽象任务为小步执行← 正确答案
  • C.压缩模型参数节省显存
  • D.提高文本生成的推理速度

答案:B。子目标生成把“写市场分析报告”这类抽象任务,拆成“定框架→收数据→写报告”等可执行的小步骤,是连接意图与执行的桥梁。A 错在“替代推理”——它只是规划的一环;C、D 与模型压缩和推理加速无关。

Q2. 子目标生成中最常见的结构化输出格式是?

单选题 · easy

  • A.CSV 表格格式
  • B.Markdown 文档格式
  • C.JSON 对象格式← 正确答案
  • D.HTML 网页格式

答案:C。JSON 是 LLM 结构化输出的事实标准,字段清晰、可嵌套、易解析,天然匹配子目标对象的 id/title/deps 结构。CSV 适合表格但表达不了嵌套依赖;Markdown 和 HTML 更适合渲染展示,不适合机器解析。就像菜单写成清单而不是散文,才能让后厨照单执行。

Q3. “办年夜饭”拆出的第一个子目标“确定菜单”属于?

单选题 · easy

  • A.顶层抽象需求
  • B.可直接执行的动作
  • C.中介子目标← 正确答案
  • D.最终输出结果

答案:C。“确定菜单”既不是抽象需求(那是“办年夜饭”),也不是最终结果,而是一个承上启下的中介目标——它比原任务具体,但还需要进一步拆成“列候选菜、核对预算、定菜单”等更小的动作。这正是子任务树中的中间层节点。

Q4. 子目标 gᵢ 的 deps 字段通常指向?

单选题 · mid

  • A.任意其他子目标
  • B.前序已生成的目标← 正确答案
  • C.后序待生成的目标
  • D.所有叶子节点

答案:B。deps 只能指向已经在它之前生成的子目标,保证依赖图是无环 DAG。这样调度器才能按拓扑序安全执行。指向后序目标会造成循环依赖,指向任意目标或叶子节点会造成调度混乱。就像做菜必须先备好食材才能下锅,依赖永远是向前的。

Q5. 提示词中“你是一位任务规划专家”主要作用?

单选题 · mid

  • A.设定角色约束分解方向← 正确答案
  • B.追加额外训练数据
  • C.调整模型学习速率
  • D.启用梯度裁剪操作

答案:A。这句话是角色设定(System Prompt),通过给 LLM 一个“专家”身份来约束它的分解逻辑——让输出更像规划专家的思考产物。它不影响模型权重(B 错),也不涉及学习率或梯度(C、D 错)。和给主厨一个“总厨任命书”效果类似,让他在这个角色下思考问题。

Q6. 评估子目标生成质量应考虑哪些维度?

多选题 · mid

  • A.准确性覆盖真实性← 正确答案
  • B.鲁棒性抗噪声扰动← 正确答案
  • C.效率控制成本延迟← 正确答案
  • D.安全性避免越权操作← 正确答案

答案:ABCD。四个维度缺一不可:准确性保证子目标真实覆盖任务需求;鲁棒性保证任务换个说法也能稳定拆解;效率控制 token 与延迟成本;安全性防止产生越权或危险操作。就像年夜饭评价要综合“菜齐不齐、换客人翻不翻车、花多久、厨房安不安全”四个角度。

Q7. 以下哪些是子目标生成面临的典型挑战?

多选题 · mid

  • A.目标漂移偏离初衷← 正确答案
  • B.分解粒度难以平衡← 正确答案
  • C.模型幻觉虚构步骤← 正确答案
  • D.模型参数越来越大

答案:ABC。目标漂移(执行中忘记原始需求)、粒度失衡(拆太粗没法执行或拆太细浪费资源)、幻觉(编造不存在的子目标)是三大经典挑战。模型参数规模是模型选型问题,不是子目标生成特有的挑战,D 错。

Q8. 链式概率 P(Gᵢ|T,C,G<ᵢ) 建模子目标生成的好处是?

单选题 · hard

  • A.数学形式上最为简单
  • B.利用已有目标约束下一步生成← 正确答案
  • C.完全消除模型的幻觉
  • D.避免调用任何外部工具

答案:B。链式分解的核心价值在于把“一次性生成全部子目标”变成“逐环决策”,每一步都能参考已生成的目标,让子目标之间保持逻辑连贯。数学形式简单不是关键(A 错),它也不能消除幻觉或免掉工具调用(C、D 错)。就像主厨一道一道决定做什么菜,而不是闭眼一次报出整桌菜。

Q9. 以下哪些可以有效缓解子目标生成中的幻觉问题?

多选题 · hard

  • A.强制 JSON 结构化输出← 正确答案
  • B.外部工具交叉核对← 正确答案
  • C.拆分到无限细粒度
  • D.提示词限定候选动作← 正确答案

答案:ABD。结构化输出约束了格式与字段让编造更困难,但更有效的是与外部工具交叉验证(比如查数据库确认“订单存在”再生成“退款”子目标),以及在提示词中限定候选动作集从源头压缩幻觉空间。拆到无限细粒度不能解决问题,反而放大幻觉与成本,C 错。

Q10. 当子目标树的 Coverage(G) 低于阈值 τ 时,最合理的做法是?

单选题 · extreme

  • A.忽略阈值继续执行
  • B.增大分解深度重新拆分← 正确答案
  • C.减少子目标数量降成本
  • D.直接跳到最后一个目标

答案:B。覆盖率不达标说明关键需求环节没被覆盖,此时应该增大分解深度(拆得更细一点)或补充遗漏的子目标,直到满足 Coverage(G) ≥ τ 再执行。忽略阈值会导致任务做偏,减少数量会让覆盖更差,跳到最后更是不顾中间环节。这就像发现菜单里漏了主菜,加菜而不是删菜。