级联路由的可靠性陷阱:当成本优化悄然摧毁你的 p95 延迟
成本仪表盘一片绿意。自从级联路由(cascade router)上线以来,单次请求的支出下降了 62%。CFO 很开心。平台团队正在庆祝。而与此同时,你的 p95 延迟悄然上升了 40%,你最重要的客户刚刚流失,理由是“机器人在处理关键查询时变笨了”,而实验团队已经连续两周在追踪一个根本不存在的幻影回归(phantom regression)了。
这就是级联路由的可靠性陷阱。它是每一个“先尝试廉价模型,如果不成功再升级”架构的隐蔽失败模式,也是生产环境 LLM 系统中最少被讨论的二阶效应之一。成本上的收益是真实的、可衡量的,且易于归因。而可靠性上的损失则是弥散的、统计性的,几乎无法追溯到导致它们的路由。因此,成本上的胜利受到赞彰,可靠性上的损失被归咎于“模型变差了”,团队就这样把自己优化进了一个坑里。
级联路由——先将请求发送给廉价模型,仅在置信度较低时才升级到更强大的模型——确实是现代 LLM 基础设施中杠杆率最高的成本杠杆之一。生产系统通常能降低 45–85% 的支出,同时保留大 部分始终运行前沿模型(frontier model)的质量。数学逻辑说得通。论文也证实了这一点。供应商们都在推销它。但供应商没有强调的是,一旦你引入级联,你就改变了所有依赖响应行为的其他系统的统计特性——延迟 SLO、训练数据飞轮、A/B 实验、值班手册——而大多数团队只有在损害累积后才会发现这一点。
吞噬 p95 的双峰延迟分布
当你始终运行同一个模型时,你的延迟分布是单峰的。它可能是一个长尾单峰分布,但它是单峰的。p50 和 p95 会随着负载和提示词长度的变化而同步缓慢移动,这些变化是可以理顺逻辑的。
级联路由则做了本质上不同的事情。一个未升级的请求从廉价层返回(假设)需要 400ms。一个升级后的请求需要支付 400ms 的廉价层拒绝成本,再加上 2,400ms 的强力层补全时间,总计 2,800ms。你现在拥有了缝合在一起的两个群体:覆盖 70% 流量的 400ms 快速模式,以及覆盖 30% 流量的 2,800ms 慢速模式。均值相比“始终强力”模式有所下降。中位数显著下降。而 p95 则稳稳地落在慢速模式中,那里的每一个点都是两次模型调用的串行求和。
这种算术是无情的。如果你以前“始终强力”的 p95 是 3,000ms,你新的级联 p95 大约就是强力层的延迟 加上 廉价层的拒绝成本——通常比以前高出 400ms,而不是更低。成本下降了。尾部延迟上升了。对于那最难处理的 5% 查询,用户感知到的体验现在明显变差了,而这些查询恰恰是用户已经感到沮丧并盯着加载图标看的时候。
在这一考验中 生存下来的团队,会强迫自己 分别为“保留”和“升级”决策追踪 p95。他们发布一个“保留-p95 SLO”和一个“升级-p95 SLO”,将它们视为两个产品,并拒绝为混合中位数而欢呼。他们还将升级率视为一等公民的可靠性指标——升级率增加 5 个百分点就是尾部延迟退化 5 个百分点,即使没有任何单个请求变慢。
你刚刚切断的硬核案例反馈循环
生产流量是你所能获得的成本最低、最具代表性的训练和评估信号。如果你记录输入、输出和人工评分,你就拥有了一个飞轮:硬核案例进入数据集,模型针对它们进行改进,硬核案例变得更容易,廉价层能处理更多案例,成本进一步下降。这是每个人都想要的飞轮。
级联路由悄悄地打破了它。复杂的查询总是会升级。简单的查询则永远不会。因此,你从廉价层收集的数据,在构建之初就是你流量中 容易 的那一部分。无论你根据廉价层的追踪轨迹进行什么微调、蒸馏或提示词迭代,你都在针对廉价层已经能够处理的案例进行优化。你是在教你的弱模型处理它不需要帮助的查询,而真正能让它变得更强的查询却被默默地永远路由走了。
更糟糕的是,强力层的追踪轨迹现在正朝着相反的方向被污染。强力层只看到廉价层拒绝的查询——这是一个幸存者偏差样本,其中完全缺失了简单和中等的案例。如果你在强力层自身的生产轨迹上对其进行微调,你最终会得到一个对边界情况过度偏执的模型,它会过度思考那些在 廉价层的下一次必然版本更新中就能处理的查询。
修复方法令人不适:保留一部分“影子”流量——哪怕只有 1%——强迫廉价层无论置信度如何都尝试处理每一个查询,并将结果与强力层的真值(ground truth)一起记录。这是防止廉价层过时的唯一方法。这需要花钱,而这恰恰是级联路由本应节省的,大多数团队都会找理由跳过这一步。他们错了。如果没有影子流量,随着周围世界的变化,廉价层的性能会针对其自身的生产分布而默默退化。直到有一天有人注意到,升级率在没有明显原因的情况下从 30% 爬升到了 55%。
为什么你的 A/B 测试在欺骗你
大多数实验框架都假设模型暴露是统一的。你发布了一个新的提示词或新的系统消息,在相同的下游指标上对比实验组与对照组,计算出差值和 p 值。当每个请求都发往同一个模型时,这没问题。但如果前面有一个路由,这种方法就失效了。
想想实际发生了什么。比如,对照组产生的输出稍微短一些。级联路由将基于输出长度生成的特征作为其升级信号的一部分。变体组稍微改变了升级率。现在,你的“实验组”所服务的模型混合比例(mixture of models)与你的“对照组”不同,你测量的指标一部分源于提示词的更改,另一部分则源于你从未考虑过的、具有干扰性的模型组合偏移。这两个效应的方向可能相反。你的 A/B 测试报告的性能退化,实际上可能只是路由造成的伪像(artifact)。或者更糟,它报告了一个在你 100% 全量上线后就会消 失的“胜利”。
在发布新模型或同一模型的新版本时,也存在同样的风险。如果新模型在 token 风格上与旧模型有显著差异,廉价层级的置信度校准就会发生偏移,升级率随之改变,而你归因于“新模型”的成本或质量差异,实际上部分是“新的升级混合比例”导致的。在级联环境下发布的团队要么必须在实验期间冻结路由——这会损失测试期间的一些成本收益——要么必须在层级粒度上进行实验监测,并将模型暴露记录为协变量(covariate)。
正确的做法是实验文献中所说的“分层分析”(stratified analysis)。按层级(仅廉价层、已升级层、强制统一层)切分每个 A/B 测试结果,并要求所有三个切片都朝着正确的方向移动,然后才能宣布获胜。如果变体在仅廉价层获胜但在已升级层失败,你可能只是改变了路由边界,而不是改进了系统。
保持经济性真实可靠的按层级可观测性
默认的可观测性技术栈假设只有单个模型。Token 支出、请求数、延迟直方图、错误率、满意度评分。这些都有用,但当底层模型的身份根据你无法直接看到的分类器随请求发生变化时,这些指标都变得毫无意义。
级联路由的最小可行可观测性大致如下:针对每个层级,跟踪成功率、p50/p95/p99 延迟、token 成本和下游质量信号——所有这些都要细分为“层级终结”(tier-terminal)请求(该层产出了最终答案)和“层级透传”(tier-passthrough)请求(该层拒绝了请求并 进行了升级)。升级率本身需要随时间进行跟踪,按查询类别进行细分,并在偏离基线超过 2–3 个百分点时发出警报。
然后增加合成探测(synthetic probe)覆盖。一组固定的、经过挑选以跨越路由边界的小型金丝雀查询,应按计划针对生产路由运行,并记录分配的层级和最终答案。当廉价层突然开始升级它以前能够处理的查询时,你会在金丝雀探测中发现它,而不是等用户投诉。这是级联环境下的“心跳检查”,而且在实际应用中少见得令人惊讶。
最后,监测“按层级的失败模式”。廉价层的失败方式(截断、拒绝、幻觉化的工具调用)通常与强模型层的失败方式(话术模棱两可、过度冗长、格式漂移)不同。将两者汇总为一个错误率会掩盖到底是哪个层级在退化。报告单一“系统质量评分”的团队失去了调试能力,因为底层组成是不透明的。而报告按层级质量评分加路由混合直方图的团队,可以在一小时内判断出退化是模型问题、提示词问题还是路由问题。
将路由视为产品,而非管道细节
这里更深层次的失败是组织架构上的。大多数团队将级联路由视为平台管道(plumbing)——由基础设施团队负责、配置一次、以成本为中心进行优化。模型团队负责模型质量。产品团队负责用户体验。没有人负责路由决策与其他两者之间的“交互”,而这正是可靠性受损的地方。
那些能处理好级联路由的团队会给路由分配专门的负责人、独立的 SLO、自己的路线图和值班页面 。路由就是一个产品。它有用户——模型团队、实验团队、产品团队——而这些用户中的每一个都有路由可以满足或破坏的需求。按层级的 SLO 满足平台团队。受控实验下的稳定升级率满足实验团队。强制阴影追踪(shadow traces)满足模型团队。当凌晨 3 点发生事故,有人需要知道为什么答案变得诡异时,记录在案的路由决策追踪能满足值班人员。
当负责优化成本的团队不是承担可靠性成本的团队时,成本优化器就会变成可靠性负担。解决办法是结构性的:将成本收益和可靠性成本放在同一个计分板上,由同一个人负责,陷阱自然就会消失。在那之前,你将不断发布那些悄悄增加了尾部延迟、悄悄导致训练数据偏差、并悄悄使每一个触及路由边界的 A/B 测试失效的廉价层改进——而你也会一直纳闷,为什么明明仪表盘上的每一项指标都在变好,模型“感觉起来却变差了”。
- https://openreview.net/forum?id=AAl89VNNy1
- https://arxiv.org/abs/2410.10347
- https://optyxstack.com/performance/latency-distributions-in-practice-reading-p50-p95-p99-without-fooling-yourself
- https://llm-d.ai/blog/predicted-latency-based-scheduling-for-llms
- https://arxiv.org/html/2604.19781
- https://arxiv.org/html/2501.01818v1
- https://www.braintrust.dev/articles/ab-testing-llm-prompts
- https://www.truefoundry.com/blog/observability-in-ai-gateway
- https://www.montecarlodata.com/blog-ai-telemetry/
- https://dev.to/ntctech/cost-aware-model-routing-in-production-why-every-request-shouldnt-hit-your-best-model-1pg9
- https://www.rack2cloud.com/ai-inference-cost-model-routing/
- https://www.getmaxim.ai/articles/top-5-llm-routing-techniques/
