模型路由的降级链设计:别让一个超时拖垮整个产品

📅 2026/4/26 ✍️ 小文 📖 约 1 分钟

多模型路由不只是为了省钱,更是为了可用性。给出降级链的四级设计、超时预算分配、熔断参数取值与一个可直接抄用的路由配置模板。

一次真实的故障

某天下午,主模型供应商的一个区域节点限流,P99 延迟从 1.2 秒飙到 40 秒。你的产品没有做降级——因为”我们不希望质量下降”。结果:用户看到的是转圈,客服收到 200 条投诉,运营群里所有人问”是不是崩了”。

质量下降 10% 远好过一个功能完全不可用。 这是降级链的第一原则。

降级链的四级结构

不要设计成”A 模型 → B 模型”这么简单。完整的链应该分四层,每层解决不同问题:

层级触发条件动作用户感知
L0 主模型正常最强模型 + 完整上下文最优
L1 同级备选主模型错误率 >5% 或延迟超标换另一供应商同级模型,提示词适配层介入几乎无感
L2 降档模型L1 也不可用/超时换小模型 + 更短上下文略有质量下降
L3 模板兜底全部不可用或超总预算返回预置模板 / 转人工 / 推迟处理明确告知

第 4 层是最容易被忽略、也最重要的。必须有 L3,否则降级链只是把失败推迟了。

超时预算怎么分

假设产品级 SLA 是 3 秒返回首字:

  • L0:1200ms(超过就放弃)
  • L1:900ms
  • L2:700ms
  • 剩余 200ms 留给网络与渲染

注意两个细节:

  1. 超时要”预算感知”:已经花了 2.5 秒,就不要再试 L1(900ms 预算已不够),直接进 L2 或 L3。实现上用一个全局 deadline 传递,而不是每层各自设 timeout。
  2. 流式请求的判定不同:首 token 超时和总时长超时是两回事。首 token 超时应短(800ms),一旦开始输出,中断的代价很高——宁可让它说完。

熔断参数怎么取

别用默认值。推荐起点:

  • 滑动窗口:10 秒
  • 错误率阈值:50%(不是 5%——5% 会被正常抖动频繁触发)
  • 最小请求数:20(样本太少不触发)
  • 半开探测:熔断后每 30 秒放 3 个请求探活
  • 恢复条件:3 个探测请求全部成功

对延迟敏感的场景,加一条独立规则:窗口内 P95 延迟 > 3× 基线 也触发熔断。供应商的”慢”比”错”更常见也更伤人。

L1 的隐藏成本:提示词适配层

换供应商最容易翻车的不是接口,是输出差异。必须在路由层和模型之间加一个薄适配层,处理:

  • 格式差异:JSON 输出是否被 markdown 代码块包裹、字段名大小写
  • 风格差异:另一个模型可能更啰嗦或更简洁,需按模型注入不同的风格约束片段
  • 能力差异:备选模型可能不支持并行工具调用 → 适配层要把并行调用降级为串行

这意味着提示词不能硬编码在某一个模型上。正确做法是提示词分”通用核心 + 模型特定微调片段”,路由时组合。

一个路由配置模板

routes:
  - name: primary
    model: gpt-5
    provider: openai
    timeout_ms: 1200
    prompt_profile: gpt
  - name: secondary
    model: claude-sonnet-5
    provider: anthropic
    timeout_ms: 900
    prompt_profile: claude
  - name: degraded
    model: llama-4-70b
    provider: self-hosted
    timeout_ms: 700
    prompt_profile: compact
  - name: fallback
    action: template
    template: service_busy

breaker:
  window_s: 10
  error_rate: 0.5
  min_requests: 20
  latency_multiplier: 3

两件必须做的运维事

  1. 降级要打点:每次进入 L2/L3 都要记录事件和原因。每周看一次”降级率”,如果 L2 长期占 15%,说明主模型方案本身不匹配,该换的不是路由是主方案。
  2. 定期演练:每季度人为把主模型错误率调到 100%,看降级链是否按预期工作。不演练的降级链,大概率在真出事时才发现某个环节的提示词早就不兼容了。

别陷入的误区

  • 不要为了省钱做降级:省钱应该用”前置路由”(先判断任务难度再选模型),这和”故障降级”是两套逻辑,混在一起会让代码难以维护。
  • 不要在 L2 静默降质:面向用户的产品,质量降档应该有感知(如”当前为简化回答”),或者控制在用户难以察觉的范围内。
  • 不要没有 L3:没有兜底的降级链,本质上是”更复杂的失败方式”。
📤 分享到