卡码笔记-最强八股文
首页
计算机基础
C++
Java
Go
🔥大模型🔥
  • 大模型面经
  • Java面经
  • C++面经
简历专栏
秋招投递表
代码随想录 (opens new window)
首页
计算机基础
C++
Java
Go
🔥大模型🔥
  • 大模型面经
  • Java面经
  • C++面经
简历专栏
秋招投递表
代码随想录 (opens new window)
  • 本栏必读

    • 卡码大模型专栏介绍
  • 大模型面经

  • 大模型动态

  • Claude学习专栏

  • 入门认知

  • Prompt与调用基础

  • RAG检索增强

  • Agent智能体

    • AI Agent学习路线(专攻Agent先看)
    • Agent到底是什么?和普通问答有什么区别
    • ReAct、Reflection、规划执行怎么选
    • Agent vs Workflow:什么时候不需要Agent
    • 工具设计决定Agent上限
    • MCP协议:Agent工具调用的新标准
    • Agent为什么容易翻车
    • Agent的记忆:短期、长期、RAG的关系
    • Agent怎么评估:任务完成率与可靠性度量
    • Plan-and-Execute怎么落地成DAG执行器
      • 面试官会怎么问
      • 简要回答:四层解决三个问题
      • 为什么不能按列表串行执行
      • 结构化计划:让模型输出可解析的DAG
      • 拓扑排序找出并行的层
      • 状态机让失败只影响该影响的节点
      • 局部Replan:改后半段,不推翻前半段
      • 面试怎么讲
      • 知识拓展
      • 写在最后
  • 微调认知

  • 部署与工程化

  • 多模态入门

  • Transformer原理

  • 手撕Transformer

  • 模型家族与Llama架构

# Plan-and-Execute怎么落地成DAG执行器

KamaClaude

上一篇ReAct、Reflection、规划执行三种思路讲了Plan-and-Execute的设计理念:先拆步骤,再按计划推进,适合复杂任务。

但到了真实项目里,还有一个问题绕不开:

模型吐出来的计划是一段文字,怎么变成能跑、能恢复、能改的系统?

# 面试官会怎么问

"你们的Plan-and-Execute是怎么实现的?"

很多录友的回答是:

"模型输出了一个步骤列表,我们用for循环依次执行,每步调一个工具,执行完返回结果。"

这个回答有三个问题:

第一,它默认了所有步骤都必须串行。 实际上很多步骤互相不依赖,完全可以并行,for循环把能30秒跑完的任务拉成2分钟。

第二,它没说失败怎么办。 第3步挂了,前两步的结果丢不丢?整个任务重来还是跳过继续?

第三,它没考虑计划本身可能有问题。 执行到一半发现某步的结果证明后续步骤没意义了,只能整个推翻重来,还是能局部调整?

面试官真正想听的是:你们怎么把文本计划变成可调度的DAG,怎么处理并行、失败、恢复和重规划。

# 简要回答:四层解决三个问题

for循环执行的问题不是浅,是它回避了依赖、失败和纠错三件事。

要做到并行、可恢复、可纠错,Plan-and-Execute落地要过四层:

第一层,结构化计划。 不要纯文本列表,让模型输出JSON格式的nodes和edges,每个节点是一步,每条边是依赖关系,变成有向无环图DAG。

第二层,校验和排序。 执行前做环检测,确保没有死循环;用拓扑排序算出哪些节点可以同时跑,哪些必须等前置完成。

第三层,状态追踪和持久化。 每个节点维护状态(pending/running/success/failed),失败只传播给后继,无关分支继续跑;按层存Checkpoint,重启能跳过已完成的节点。

第四层,局部重规划。 节点失败或结果证伪了后续步骤时,锁定已完成部分,只对受影响的子图做Replan,上限3次,不全盘推翻。

计划不是一次性的步骤清单,是可变的执行图:并行靠依赖,恢复靠状态,纠错靠局部重规划。

Plan-and-Execute执行流程

这张图回答的是:文本计划要经过哪几层处理,才能变成可调度、可恢复的执行图。上层是规划校验(环检测→拓扑排序),下层是调度执行(并行调度→状态机→Checkpoint),两条虚线反馈分别处理成环和节点失败。

# 为什么不能按列表串行执行

先看一个真实场景。

用户说:"分析昨天支付接口变慢的原因,写个报告。"

模型给出的计划:

1. 查支付接口延迟监控
2. 查依赖服务健康度
3. 查昨天的发布记录
4. 查错误日志
5. 分析延迟和错误的时间相关性
6. 汇总生成报告
1
2
3
4
5
6

看着是6个步骤,实际上是3层:

前4步互相不依赖,可以同时发起。第5步要等前4步的数据都到齐。第6步等第5步。

for循环把这3层压成了6步串行。本来30秒能跑完的事,拖成2分钟。

再看失败。第3步查发布记录时API超时了,for循环只有两条路:整个任务抛异常,前两步的结果丢掉;或者跳过继续,第5步拿着不完整的数据硬分析。

正确的行为是第三种:只暂停依赖第3步的节点,其他分支照跑,第3步单独重试。

要做到这一点,前提是系统知道谁依赖谁。所以第一步是把计划转成DAG——节点是步骤,箭头是依赖。

# 结构化计划:让模型输出可解析的DAG

关键在输出格式。不要纯文本列表,要能直接解析的JSON:

{
  "nodes": [
    {"id": "1", "action": "查延迟监控", "tool": "query_metrics", "params": {...}},
    {"id": "2", "action": "查依赖健康度", "tool": "query_service_health", "params": {...}},
    {"id": "5", "action": "分析相关性", "tool": "analyze_correlation", "params": {...}}
  ],
  "edges": [
    {"from": "1", "to": "5"},
    {"from": "2", "to": "5"}
  ]
}
1
2
3
4
5
6
7
8
9
10
11

节点带上要调的工具和参数,边表示"from完成后to才能执行"。这样模型交付的就不是文字,而是一张执行图。

# 环检测不能省

DAG的硬要求是无环。但模型在任务复杂时,确实会输出"1依赖2、2依赖3、3依赖1"这种死循环。

标准做法是DFS配三色标记:白色未访问,灰色在当前递归路径上,黑色已访问完。遍历中撞到灰色节点,就说明成环。

检测到环,优先让模型重新规划,而不是自动打断某条边。自动断边看着能跑,但破坏了原始意图,事后排查也不知道断的是哪条。

# 拓扑排序找出并行的层

无环之后要算执行顺序,用Kahn算法:

先统计每个节点的入度(多少条边指向它)。入度为0的节点没有前置依赖,进队列。从队列取节点执行,删掉它的出边,邻居入度减1,减到0就入队。

顺带一个好处:如果最后排出来的节点数少于总数,说明有环。 环检测和排序可以合成一步。

Kahn算法一次从队列里取出的一整批节点,就是可以并行的一层。前面的例子第一层是1、2、3、4,第二层是5,第三层是6。

执行器用异步任务池,对同一层的节点一起发起,全部返回后再进下一层。

但并行度必须有上限。 一层里有20个节点就同时打20个工具调用,很容易撞上API限流,或者一口气吃掉Token预算。用信号量把并发压到固定数量(比如5个),ready队列再长,同时在跑的也只有5个。

# 状态机让失败只影响该影响的节点

每个节点维护自己的状态:pending(前置未完成)、ready(可执行)、running、success、failed、skipped(前置失败被跳过)。

有了状态,三件事才成立:实时知道任务进展到哪;某节点失败时,只把它的后继标成skipped,无关分支继续跑;重启后知道哪些节点已经成功,可以跳过。

默认的失败传播是"前置失败,后继全部跳过"。但这条规则不该一刀切。

比如第4步查错误日志挂了(日志服务故障),第5步用1、2、3的数据仍然能分析,只是结论不够全面。这种情况把边标成软依赖:{"from": "4", "to": "5", "optional": true},第4步失败不阻塞第5步,但要在第5步的输入里明确标注"缺少日志数据"。

# Checkpoint解决长任务重启

20个步骤跑到第15步,服务重启,没有Checkpoint就得从头来。

要存的是四样:DAG结构、每个节点的状态、已完成节点的输出、当前的ready队列。恢复时跳过success的节点,重试running的(它可能只做了一半),然后接着跑。

频率是个权衡:每个节点存一次开销大,全跑完再存等于没存。通常按层存一次,或者固定30秒存一次,具体看单个节点的重跑成本有多高。

# 局部Replan:改后半段,不推翻前半段

Plan-and-Execute的优势是有全局规划,但模型不是神,计划照样会错。

两种情况需要重规划:节点失败且重试无用(权限不足、接口不存在);或者节点的返回结果说明后面的计划没意义了——比如查发布记录返回空,昨天根本没发布,那"分析发布影响"这一步就是空转。

这时候不该放弃整个计划,也不该硬跑完交一份不完整的报告。正确做法是只重规划受影响的那部分:

已成功的节点锁定,不许改。把失败节点连同它的所有后继摘出来,带上原始目标、已完成节点的结果、失败原因,让模型重新规划这一段,然后把新的子图合并回原DAG继续执行。

前面例子里,1、2、4已成功保留,第5步从"分析发布与延迟的相关性"改成"分析依赖服务与延迟的相关性",第6步不动。

Replan必须有次数上限,一般3次。模型每次都规划错就会陷入死循环,超限就终止,返回已完成的部分结果和失败原因。

# 面试怎么讲

别停在"让模型输出计划再执行"。可以这样讲:

我们把它落地成了DAG执行器。

模型输出的是结构化的nodes和edges,不是文本列表。执行前做环检测,用Kahn算法拓扑排序,同一层的节点并行,信号量控制并发数。

每个节点有状态机,失败只传播给后继,无关分支照跑。长任务按层存Checkpoint,重启能跳过已完成的节点。

节点失败或结果证伪了后续计划时,锁定已完成部分,只对受影响的子图做Replan,上限3次。

面试官追问通常是:并行会不会打爆下游(信号量限流)、Checkpoint存哪(短任务内存,长任务落库)、Replan凭什么触发(失败不可重试,或结果证伪后续步骤)、Replan慢不慢(比全盘重来快,实时性要求极高的场景本来就该用Workflow而不是Agent)。

# 知识拓展

# DAG和Workflow是一回事吗?

调度机制几乎一样,区别在图谁定的。Workflow的图是开发者提前画好的,运行时不变;Agent的DAG是模型每次现场生成的。所以Airflow、Argo这类Workflow引擎的调度内核可以直接复用。

# 结构化输出保证了格式,参数错了怎么办?

JSON Schema管得住形状,管不住语义。模型把时间范围写成"yesterday"而不是具体日期,格式完全合法。要么在工具调用前加一层参数校验,要么让工具自己容错解析。前者边界清楚,后者对模型更宽容,选一个在团队内统一。

# 节点粒度怎么定?

默认一个节点对应一次工具调用,或一个逻辑完整的子任务。太粗则失败后无法细粒度恢复,重跑代价高;太细则依赖关系爆炸,Checkpoint和Replan的开销反过来盖过收益。

# 有的节点要跑几小时怎么办?

同步等待会把执行器堵死。让这类节点启动异步任务后立即返回task_id,状态机加一个polling状态定期查进度,完成后再切success触发后继。

# Replan时怎么把已完成的结果给模型?

全塞进Prompt会撑爆上下文。存到外部,Prompt里只放摘要或引用ID,模型需要细节时自己用工具去读。多Agent协作里的Artifact引用也是同一个思路。

# 写在最后

DAG、状态机、Checkpoint、Replan这四层,每一层都对着一个具体的坑:DAG解决依赖和并行,状态机解决失败隔离,Checkpoint解决重启,Replan解决计划本身出错。

少了这些,Plan-and-Execute就只是"先规划再执行"六个字。

面试时能把这四层的因果讲出来,面试官才知道你真跑过这套东西。

Last Updated: 9/2/2026, 11:14:53 AM

← Agent怎么评估:任务完成率与可靠性度量 SFT、RLHF、DPO:微调方法全景认知 →

评论

验证登录状态...

侧边栏 侧边栏
夜间模式 夜间
卡码简历 卡码简历
代码随想录 代码随想录
卡码投递表 卡码投递表🔥
2026实习校招群 2026群
添加客服微信 2026实习校招客服微信 PS:通过微信后,请发送姓名-学校-年级-2026实习/校招
支持卡码笔记 支持卡码笔记
鼓励/支持/赞赏Carl 卡码笔记赞赏码
1. 如果感觉本站对你很有帮助,也可以请Carl喝杯奶茶,金额大小不重要,心意已经收下
2. 希望大家都能梦想成真,有好的前程,加油💪