路由并行与汇聚

本节目标

你将掌握提示词链、门控、路由、并行扇出和汇聚五个基础结构,能为每个中间产物定义 schema,并能判断哪些步骤不能并行。

先把流程写成数据依赖

工作流不是“按顺序调用几个函数”这么简单。每个节点都应有输入契约、输出契约和失败语义;边表示依赖或条件。常见结构如下:

输入 -> 解析 -> 门控 -> 路由 ─┬─ 分支 A ─┐
                              ├─ 分支 B ─┼─ 汇聚 -> 验收
                              └─ 分支 C ─┘
  • 链(chain):前一步输出是后一步输入。
  • 门控(gate):用规则判断中间结果是否合格,不合格就停止或修复。
  • 路由(routing):从多个后续路径中选择一个或多个。
  • 扇出(fan-out):把互不依赖的工作分派出去。
  • 汇聚(join / reduce):确认分支完整性、处理冲突并决定整体状态。

Anthropic 官方文章把 prompt chaining、routing、parallelization、orchestrator-workers、evaluator-optimizer 作为可组合模式介绍。它们是设计词汇,不是必须绑定某个供应商的 API。

路由:规则优先,未知值失败关闭

优先用可解释规则处理文件类型、金额阈值、权限级别、字段是否齐全等确定性特征。语义边界模糊时才让模型分类,并要求返回受约束标签:

{
  "label": "billing",
  "evidence_ids": ["message-17"],
  "needs_clarification": false
}

字段阅读:

  • label 必须先与应用定义的路由 allowlist 比对,再决定后续分支。
  • evidence_ids 把分类结论连接到可核对的原始消息或片段。
  • needs_clarification 显式表示信息不足;为 true 时不应默认进入高权限路径。

不要直接把自由文本拼成函数名。解析后先验证:标签是否在允许集合、证据是否存在、是否达到业务门槛。unknown 应进入澄清或人工分支,而不是默认使用权限最高的工具。

路由测试至少覆盖:

  • 每个合法分支;
  • 空输入与缺字段;
  • 未知标签;
  • 模型返回多余字段、非法 JSON 或互相矛盾的结果;
  • 临界值两侧;
  • 恶意内容试图改变路由规则。

并行:只有无依赖任务才能同时运行

两个任务可以并行,需要同时满足:

  1. 不读取对方尚未产生的结果;
  2. 不竞争修改同一可变状态;
  3. 失败与重试不会重复不可逆副作用;
  4. 汇聚层知道预期返回哪些分支。

“实体抽取”和“敏感信息扫描”可在同一不可变文档副本上并行;“检索证据”和“依据证据写结论”不能并行。线程或异步只能改善等待型工作,不会自动提升 CPU 密集任务,也不会修复错误的数据依赖。

并行 worker 应返回自己的结果,不直接写共享字典。主线程在 join 后一次性更新状态。这样可以让重放顺序和测试结果更稳定。

汇聚:不是简单拼接

一个健壮的汇聚器至少回答:

  • 预期分支是否全部返回?
  • 每个结果来自哪个输入版本和执行版本?
  • 超时、取消、部分成功如何表示?
  • 冲突由规则、模型还是人工解决?
  • 是否允许降级结果继续?

适合的中间结构:

{
  "branch": "risk_scan",
  "status": "ok",
  "input_digest": "sha256:...",
  "claims": [{"text": "...", "evidence_id": "chunk-03"}],
  "latency_ms": 128
}

字段阅读:

  • branch 标识结果来自哪条预期 worker 分支,供汇聚器检查完整性。
  • status 是稳定结果类别,不能只根据自由文本判断成功或可重试性。
  • input_digest 绑定该分支处理的输入版本,避免把旧结果混入新任务。
  • claims 保留带证据 ID 的断言,让汇聚后仍可追溯来源。
  • latency_ms 是观测数据,可用于定位慢分支和制定超时预算。

不适合的中间结构是“看起来没问题”这样的自由文本,因为汇聚器无法判断缺失、来源或是否可重试。

Map–Reduce 与 orchestrator–workers

长文档处理可把片段映射到多个 worker(map),每个 worker 产出 {chunk_id, claims, citations},最后去重、检查引文并汇总(reduce)。关键不在“用了多少 Agent”,而在输入切分、结果 schema 和汇聚规则。

当子任务数量无法预先确定时,可以由 orchestrator 动态拆分 worker 任务;这比固定并行更灵活,也多了拆分错误、重复任务、预算失控和汇聚遗漏。先用固定样本证明动态拆分能提升结果,再引入它。

完整例子:客服入口

需求:账号问题允许自动只读查询;退款请求只生成建议并等待审批;无法分类时请用户澄清。

  1. validate_input 检查工单结构。
  2. route_intent 只返回 account | refund | unknown。
  3. 账号分支并行执行身份状态查询与服务健康检查。
  4. refund 分支并行执行政策核对与订单只读查询。
  5. join 要求两项检查都返回;任何权限拒绝都不能重试为更高权限。
  6. unknown 分支不调用业务工具,只输出澄清问题。

验收不能只看回复文本,还要检查调用的工具、参数范围和是否产生了禁止的写操作。

常见错误与排查

  • 路由标签漂移:集中定义枚举和 schema,不在各节点复制字符串。
  • 并行分支写共享状态:改为 worker 返回值,由 join 统一合并。
  • 只等待最先返回结果:若业务要求完整证据,必须验证全部预期分支。
  • 超时等同失败:超时属于未知结果;先查动作回执,再决定重试。
  • reduce 丢失来源:让来源 ID 随中间结果传递,最终输出也保留映射。
  • 模型置信度被当成概率保证:置信字段只是信号,必须用校准数据证明其可用性。

练习

设计“上传合同后生成风险摘要”的流程:

  1. 画出解析、格式门控、条款分类、并行风险扫描和汇聚。
  2. 为每个节点写输入/输出 schema。
  3. 设计一个分支超时、一个分支返回非法字段、两个分支结论冲突的处理。
  4. 写 8 个路由测试,至少包含两个未知或恶意样本。

掌握检查

  • 能区分链、门控、路由、扇出和汇聚。
  • 能证明两个步骤没有数据依赖后再并行。
  • 能为未知路由值给出安全默认行为。
  • 能让汇聚层检查完整性、来源、冲突和部分失败。
  • 能解释为何 worker 不应直接修改共享可变状态。

下一步

进入 反思、规划与停止条件,把动态迭代限制在可测试边界内。

参考资料