第 07、08 篇分别剖析了 LangGraph 和 CrewAI 的源码,第 09 篇把博客工具封装成了 MCP。本篇是编排层的收官——把前面所有能力组合成一个生产级多 Agent 流水线。用一个真实案例贯穿:博客的钓鱼日记自动生成流水线(tools/douyin-blog/generate-blog.py)从单次调用升级为多 Agent 编排。
多 Agent 不是”为了 Agent 而 Agent”。它解决的问题是:复杂任务的每一步有不同质量要求、不同成本敏感度、可能失败、需要并行。单 Agent 一条 prompt 全包,面对这些必然顾此失彼。
一、先算账:单 Agent 的代价
generate-blog.py 当前是”一次 DeepSeek 调用生成完整日记”。它的隐性代价:
- 一次 prompt 塞了所有需求(素材、人设、结构、SEO),模型”捡了芝麻丢了西瓜”,输出经常某方面不合格(比如 front matter 格式错了、鱼获数据编错了)。
- 失败就是全盘重来:输出 2000 字之后发现格式错,整篇重生成,浪费 token 和时间。
- 质量不可分步审查:正文写得再烂也得等全文生成完才能发现。
这就是第 08 篇结尾说的”成本翻 4 倍但换来可审查”——多 Agent 的本质是用更多、更小的 LLM 调用,换取每步的可控性和可重试性。
二、流水线设计:把任务拆成有状态的步骤
1 | ┌────────────────────────────────────────────┐ |
每步职责和资源配置:
| 步骤 | 角色 | 模型 | 成本等级 | 失败处理 |
|---|---|---|---|---|
| 素材整理 | 读 videos.json + 相册目录,出结构化清单 | 本地 Qwen 或 deepseek-chat | 低 | 重试 2 次 |
| 策划大纲 | 出分节结构 + 亮点 | deepseek-chat | 低 | 重试 2 次 |
| 正文写作 | 完整日记正文 | deepseek-chat(长输出) | 高 | 重试 1 次 |
| SEO 校对 | 校验 front matter、标签、违禁词 | deepseek-chat(temperature 0.1) | 中 | 校验失败回写 |
关键工程决策:
- 每步一个小调用,而不是一个大调用——单步失败只重跑一步。
- 不同步骤用不同 temperature:写作步骤创造性(0.7~0.8),校验步骤确定性(0.1)。
- “策划”和”写作”分开:大纲是轻量任务(快、便宜),正文是重量任务(慢、贵)。大纲先行,正文才不跑偏——这也是内容生产的常识。
三、失败恢复:三种策略
3.1 步骤级重试(Retry)
第 02 篇的指数退避重试,在 Agent 层同样适用——但每步要有独立的 max_retries。写作步骤 token 大、失败代价高,重试次数应少于素材整理这种便宜步骤:
1 | def run_with_retries(step_fn, step_name, max_retries, budget): |
3.2 降级(Fallback)
写作步骤的模型挂了,降级到另一个模型(云端 → 本地,第 06 篇的链路在此复用)。降级优先级:重试 < 换模型 < 换策略(策略降级如”正文生成失败就输出大纲,人工补齐”)。
3.3 检查点续跑(Resume)
第 07 篇 LangGraph 的检查点是这个场景的杀手锏:thread_id 每篇日记一个,跑完正文后崩溃,续跑时只重跑 SEO 和落盘,正文结果已持久化。
1 | config = {"configurable": {"thread_id": f"diary-{publish_date}"}} |
四、并行调度:什么时候值得并行
多 Agent 的第二个价值是并行。但并行不是免费的——并行同时占用多个模型并发额度,成本不变、延迟降低,但复杂度上升。判断标准:
1 | 任务之间是否有数据依赖? |
ByteFisher 场景里值得并行的例子:多篇日记同时生成(一次钓一周的鱼,生成一周的日记)。LangGraph 超步天然支持并行节点,或用 asyncio.gather:
1 | import asyncio |
注意:并行时每篇独立 thread_id、独立预算、失败互不影响。这又是一个”失败隔离”——一个坏素材拖垮不了整周的生产。
五、成本与延迟的平衡模型
多 Agent 流水线必须回答两个问题:跑一次多少钱?要等多久? 用第 02 篇的成本模型推演:
| 步骤 | 输入 token | 输出 token | 成本占比 |
|---|---|---|---|
| 素材整理 | 600 | 200 | 5% |
| 策划大纲 | 500 | 300 | 6% |
| 正文写作 | 1200 | 3000 | 45% |
| SEO 校对 | 4000 | 500 | 50% |
(示例值,正文和校对是成本大头,因为校对要重读全文)
优化杠杆:
- 校对步骤的输入压缩(第 03 篇上下文工程):不用全文,用正文的关键段 + front matter。
- 模型路由(第 02/06 篇):素材整理这种简单任务下放给本地/小模型。
- 并行摊薄延迟:串行 E2E 延迟 = 4 步延迟之和;并行后 E2E = 最长链路延迟。
- 失败成本 = 已消耗 token:检查点 + 步骤级重试让失败只损失当前步,不损失全文。
工程红线:流水线的”单次成本上限”必须写进代码。用第 02 篇的预算模型给整个流水线设一个硬预算(比如单篇不超过 ¥0.5),预算耗尽直接落”大纲 + 标记人工补齐”,绝不让一次故障任务烧穿月度预算。
六、落地清单与小结
| 优先级 | 改造 | 收益 |
|---|---|---|
| P0 | 把 generate-blog.py 拆成 4 步 + 独立重试 | 单步可控、失败只重试一步 |
| P0 | 每步独立 temperature/模型路由 | 质量与成本双优 |
| P1 | LangGraph 检查点 + thread_id | 崩溃续跑 |
| P1 | 流水线总预算硬上限 | 成本红线 |
| P2 | 多篇日记并行 + 失败隔离 | 批量产能 |
| P2 | 校对输入压缩 | 省 30% 成本 |
核心结论:
- 多 Agent 的本质是用更多更小的 LLM 调用换可控性与可重试性,不是炫技。
- 拆分三原则:每步一个职责、每步独立重试、每步独立温度与模型。
- 失败恢复三级:重试 → 换模型降级 → 检查点续跑;失败隔离让单篇故障不影响批量任务。
- 并行判断:强依赖串行、无依赖并行、弱依赖流水线并行;并行必须配失败隔离。
- 成本与延迟是设计输入而非事后遗憾:模型路由 + 输入压缩 + 总预算硬上限,三管齐下。
下一篇进入可观测性:给 ByteBot 和这条流水线装上 Langfuse 追踪,把第 02~10 篇的所有埋点变成可看的 trace 和指标。
本系列持续更新中,每周一篇。