跳到主要内容

AI 流水线的复合故障模式:局部成功远远不够

· 阅读需 10 分钟
Tian Pan
Software Engineer

大多数构建 AI 流水线的工程师都会孤立地评估每个组件:检索成功的频率是多少,LLM 做出正确判断的频率是多少,下游工具调用成功的频率是多少。如果每个答案都是"95%",系统看起来相当稳固。

然而事实并非如此。三个各为 95% 的组件组合在一起,只能给你一个 86% 可靠的系统。再加第四个 95% 的组件,降到 81%。加第五个,低于 77%。那些看起来质量很高的独立组件,在你发布任何功能之前,就会组成一条五次请求中就有一次失败的流水线。

这就是复合故障问题——大多数 AI 工程团队在用户开始提交工单之前从未去做的那道数学题。

没有人去做的乘法运算

在顺序流水线中,所有步骤都成功的概率是每个步骤成功率的乘积。对于独立事件来说,这是基本概率论。问题在于大多数团队从单个阶段的角度思考流水线,而非从乘积的角度:

  • 查询改写:97% 成功
  • 检索:95% 成功
  • 重排序:96% 成功
  • LLM 生成:95% 成功
  • 输出解析:98% 成功

听起来像是一个高质量的系统。但乘积是:0.97 × 0.95 × 0.96 × 0.95 × 0.98 = 0.84。即使没有任何阶段低于 95%,每六次请求中也有将近一次在流水线某处失败。

这不是一个理论上的担忧。2024 年对生产 AI 系统的一项调查发现,90% 的 Agentic RAG 项目在生产中失败,复合阶段故障被列为主要原因之一。如果数据清洗质量影响向量索引,向量索引影响检索,检索影响生成——这些故障以乘法方式而非加法方式叠加。

工程直觉是修复最薄弱的阶段。这有帮助,但效果没有你预期的那么大。在五阶段流水线中,将最差阶段从 90% 提升到 95%,只会将整体可靠性从约 77% 推到 84%。真正的可靠性需要减少流水线深度,或者设计独立的故障域。

为什么数学更糟糕:相关性

朴素模型假设每个阶段独立失败。但真实流水线不断违反这一假设。

考虑一个 RAG 流水线,其中检索和生成都依赖于同一个嵌入模型。当嵌入模型提供商性能下降时,两个阶段会同时失败——至少一个阶段失败的概率不是它们各自故障率之和,而是几乎等于其中一个失败的概率。相关组件之间的冗余几乎没有任何好处。

同样的效应还出现在:

  • 共享基础设施依赖:所有阶段调用同一个 LLM 提供商,它们的故障会集中在该提供商的事故期间,而非独立分散。
  • 语义传播:第一步中被误解的查询,会在第二步产生微妙错误的上下文,进而在第三步产生看似合理但实际错误的生成结果。这种失败在任何单独的交接点都不可见——只在最终输出时才显现。这就是"语义不透明"问题:自然语言即使错了也能通过校验。
  • 时间复合:在长时运行的 Agent 中,会话早期产生的幻觉事实会传播到后续推理步骤中。模型建立在错误的中间结论之上,每一步看起来都是有效的,而累积误差持续增长。
  • 工具级相关性:在多 Agent 系统中,Agent 共享内存存储或工具服务器时,一个被污染的工具响应不只会影响一个 Agent——它会影响所有从共享状态读取数据的 Agent。

谷歌委托的一项多 Agent 系统研究发现,独立架构与单 Agent 基线相比,错误放大率可达 17 倍。以 Orchestrator 为基础进行验证的集中式架构将这一放大率降低到 4.4 倍——虽然仍然显著,但要易于管理得多。关键变量是组件之间共享状态的多少。

你的 RAG 流水线可能失败的七个地方

理解复合故障需要了解每个阶段的实际故障模式。对于检索增强生成流水线,故障分类可以分为七个不同类别:

检索前

  1. 内容缺失——相关信息从未被索引,或被错误索引
  2. 遗漏高排名文档——相关文档存在但未能出现在 top-k 检索中

上下文组装期间: 3. 不在上下文中——检索到的文档在因 token 限制进行合并时被丢弃 4. 未被提取——LLM 在上下文中有相关文本但未能正确使用

生成阶段: 5. 格式错误——模型忽略格式指令,尽管内容本身是正确的 6. 特异性不当——响应对实际查询来说过于宽泛或过于狭窄 7. 答案不完整——模型在覆盖上下文中所有相关信息之前就停止了

每种故障类型都有不同的根本原因和不同的解决方案。危险的模式是假设高检索召回率能弥补弱生成能力,或者强生成模型能弥补差检索。乘法是无情的:当检索率为 70% 时,将生成率从 90% 提升到 98% 几乎不会改变系统级数字。

数据在这里很能说明问题:2025 年的分析表明,80% 的 RAG 故障可以追溯到分块决策,而非检索策略或模型质量。那些优化嵌入模型、添加重排序器,却不动分块流水线的团队,是在优化错误的阶段。

打破乘法效应的架构模式

一旦你接受了级联故障是顺序流水线的数学属性,三种架构对策就变得显而易见。

1. 通过并行执行路径缩短链路

不要设计一条每一步都必须成功的单一顺序流水线,而是设计在投票或置信度评分阶段汇合的独立路径。并行运行稠密检索和 BM25 关键词检索。如果一个失败或返回低置信度的结果,另一个可以补位。系统的整体可靠性趋近于表现更好的那条路径的可靠性,而非两者之积。

这并不能消除故障——它重新定义了什么构成故障。单条路径失败是降级结果,不是流水线中断。从 BM25 回退路径获得部分完整答案的用户,比收到错误的用户得到了更好的服务。

2. 将熔断器作用于正确的粒度

熔断器可以防止故障依赖项被反复冲击,但大多数团队的作用粒度有误。作用于整个流水线的熔断器没有帮助——它只是用更快的中断取代了级联故障。

正确的粒度是单个外部依赖:向量数据库、重排序 API、工具执行服务。当向量数据库触发熔断器时,流水线应该降级到某种模式——也许只用关键词搜索——而不是完全失败。当工具执行服务不可用时,Agent 应该跳过非关键工具或将工作排队,而不是让整个任务失败。

AI 熔断器的关键设计决策是失败模式:故障关闭(重新排队等待)还是故障开放(继续输出降级结果,并相应标注)。故障关闭保护准确性,但会牺牲可用性。故障开放保留可用性,但需要明确标注,以便下游系统和用户了解他们获得的是降级结果。正确选择取决于你的具体用例中不正确输出比无输出更糟糕,还是更好。

3. 建立独立故障域

最持久的可靠性改进是架构隔离:确保一个组件的故障不能直接导致另一个组件的故障。这意味着:

  • 当检索和生成阶段之间的高相关性令人担忧时,为两者使用不同的提供商。
  • 避免执行独立子任务的 Agent 之间共享内存存储。
  • 给每个组件自己独立的速率限制配额,而不是共享一个可能被一个行为不当的组件耗尽的池子。
  • 为每个阶段分配独立测量的单独 SLO,这样你就能精确地看到哪个阶段在拖累整体可靠性。

谷歌的一项多 Agent 架构研究发现,与具有共享状态的完全独立架构相比,带验证的集中式编排将错误放大降低了大约 4 倍。关键机制是:中央编排器在将中间结果传递到下一阶段之前对其进行验证,从而打断语义传播链。

衡量乘法效应的代价

大多数团队测量端到端成功率,并将失败归因于"模型"或"流水线"。这个聚合指标掩盖了乘法效应发生的位置。

真正有帮助的监测方式:

  • 明确记录乘积的各阶段成功率:从各阶段指标计算理论上的端到端可靠性,并与观测到的端到端可靠性进行比较。差距意味着存在相关故障。
  • 故障共现矩阵:对于每对阶段,测量它们在同一请求上同时失败的频率。高共现表示相关性;这些阶段共享一个共同原因或存在因果关联。
  • 降级路径,而非仅是错误路径:追踪哪些请求触发了回退行为,哪些完全失败了。健康的系统应该表现出比完全失败更多的降级(回退激活)。
  • 级联深度:对于多 Agent 系统,记录当单个工具或数据源失败时有多少个 Agent 受到影响。如果单个向量数据库故障影响了 15 个 Agent 中的 15 个,你的故障域隔离就需要改进。

最早发现复合故障的团队,是那些停止将可靠性视为模型属性,开始将其视为架构属性的团队。

更深层的观点:可靠性是系统属性

AI 工程中有一种诱人的思维模型,认为模型就是系统。如果模型足够好,其他一切都会随之而来。这种模型催生了痴迷于基准分数而忽视流水线架构的团队。

概率数学驳斥了它。由卓越组件组成的流水线,如果这些组件顺序排列、共享故障模式或依赖公共基础设施,仍然可能 20% 的时间都在失败。反之,由个别表现平庸的组件组成、但通过并行回退、有作用范围的熔断器和隔离故障域进行组织的流水线,可以提供远超其组件分数的可靠性。

实际后果是:当你的 AI 功能表现不佳时,答案很少是"换一个更好的模型"。更多时候,是需要数清楚你的流水线阶段数,把各阶段故障率相乘,看看乘积落在哪里。这个数字通常解释了用户的抱怨。修复方案通常是结构性的。

构建短链路。打破相关性。为你的熔断器界定作用范围。从第一天起就将可靠性作为架构约束,而不是上线后冲刺阶段的事后补救。

References:Let's stay in touch and Follow me for more thoughts and updates