推理降级链路:大模型不可用时自动切小模型 — 方向4

发布时间:2026/7/16 17:53:29
推理降级链路:大模型不可用时自动切小模型 — 方向4 推理降级链路大模型不可用时自动切小模型 — 方向4一、大模型挂了返回 503 不是降级方案在高可用架构的讨论中推理服务有一个特别容易被忽略的场景当 70B 模型因为 GPU OOM 或节点故障而不可用时系统应该返回什么一个直接的回答是返回 503 Service Unavailable让上游做重试。但这是故障传递不是降级。故障传递意味着用户的请求彻底失败不仅当前 token 什么都没生成还要触发上游熔断把本该服务于其他能力的资源也拖下水。真正的降级是降质不断流——大模型不可用时自动切换到一个小模型继续提供服务。虽然回答质量可能会降低但至少请求不会失败。对于某些场景这个降质甚至是可以接受的。例如在 RAG 知识库问答中小模型的准确率下降约 5-10%但用户感知到的差异远小于一个空白响应。构建降级链路的挑战在于降级的决策时机和流量切换的无缝性。二、降级决策的多级触发与质量控制降级不仅是大模型挂了切小模型这么简单。实际生产中需要多个维度的触发条件触发的条件不是单一的不可用而是分层的绝对不可用GPU OOM、节点 NotReady、推理超时——立即降级。性能退化P99 延迟超过 SLO 的 1.5 倍——基于排队深度和 KV Cache 命中率做加权判断。资源预警GPU 显存使用率超过 85% 且持续上升——提前降级防止雪崩。降级目标的选择同样有优先级先尝试同架构的中等尺寸模型如从 70B 降到同系列的 13B再尝试小模型7B 或更低。这一优先级基于模型输出格式的兼容性。三、降级引擎的实现// DegradationRouter 推理降级路由 type DegradationRouter struct { tiers []DegradationTier // 降级梯队按优先级排序 healthCheck HealthChecker } type DegradationTier struct { Name string Priority int // 优先级0最高 Client InferenceClient // 推理客户端 MaxTokens int // 该梯队模型的最大token数 Quality float64 // 相对质量评分(0-1) } type DegradeDecision struct { ShouldDegrade bool Target *DegradationTier Reason string Metadata map[string]float64 // 降级时的上下文指标 } func (r *DegradationRouter) Route(ctx context.Context, req InferenceRequest) (*InferenceResponse, error) { // 遍历降级梯队找到第一个可用的 for i, tier : range r.tiers { // 健康检查 state : r.healthCheck.Check(ctx, tier.Name) if state ! StateReady { continue } // 对于非首选梯队检查是否需要降级触发 if i 0 { decision : r.shouldDegrade(ctx, i) if !decision.ShouldDegrade { continue } // 注入降级上下文到 metadata if req.Metadata nil { req.Metadata make(map[string]string) } req.Metadata[degraded_from] r.tiers[i-1].Name req.Metadata[degrade_reason] decision.Reason } // 执行推理 resp, err : tier.Client.Infer(ctx, req) if err ! nil { continue // 继续尝试下一个梯队 } // 标记降级信息 if i 0 { resp.Degraded true resp.DegradedFrom r.tiers[i-1].Name } return resp, nil } return nil, fmt.Errorf(all degradation tiers exhausted) } func (r *DegradationRouter) shouldDegrade(ctx context.Context, currentTier int) DegradeDecision { decision : DegradeDecision{ShouldDegrade: false} // 获取上一梯队的健康指标 upperTier : r.tiers[currentTier-1] metrics : r.healthCheck.Metrics(ctx, upperTier.Name) // 条件1上一梯队不可用 if metrics.State StateDead || metrics.State StateDegraded { decision.ShouldDegrade true decision.Reason upper tier unhealthy decision.Metadata map[string]float64{error_rate: metrics.ErrorRate} decision.Target r.tiers[currentTier] return decision } // 条件2P99延迟超过SLO的1.5倍 if metrics.P99Latency upperTier.Client.SLO()*1.5 { // 二次确认排队深度是否也超标 if metrics.QueueDepth 10 { decision.ShouldDegrade true decision.Reason latency spike with queue buildup decision.Metadata map[string]float64{ p99_latency_ms: float64(metrics.P99Latency.Milliseconds()), queue_depth: float64(metrics.QueueDepth), } decision.Target r.tiers[currentTier] return decision } } return decision }降级引擎的设计不强依赖外部服务。健康检查、指标采集、降级决策三者内聚在一个组件中避免降级链路本身成为新的单点故障。四、降级不是免费午餐降级链路在提供可用性的同时引入了一些不可忽视的成本模型输出一致性不同尺寸的模型对同一 prompt 的输出格式可能不同。如果下游消费方依赖特定的输出结构如 JSON Schema切换到小模型后可能解析失败。需要在降级规则中声明各梯队的输出格式兼容性。KV Cache 无法继承降级意味着切换到完全不同的模型实例上一个模型已生成的 KV Cache 无法复用。降级后的请求需要从头开始推理这意味着用户已经拿到的前几个 token 实际上浪费了。滥用降级导致质量漂移如果降级阈值设得太低大多数请求都被路由到小模型用户体验会持续下降。需要设置降级请求占总请求的比例上限建议不超过 20%超过上限时触发告警而非继续降级。适用边界适合大模型部署资源受限、有明确 SLO 要求的在线推理服务。适合对回答质量有一定容忍度的场景如搜索摘要、自动补全。不适合对回答质量零容忍的金融、医疗等合规场景。不适合只部署了一款模型的推理平台——没有可降级的目标。五、总结推理降级链路的本质是在质量与可用性之间做可控的折中。设计原则多级触发而非单一不可用判断降级目标按同架构兼容性排序每次降级都打标记录以便事后分析。落地步骤第一步部署至少两个尺寸的模型形成降级梯队。第二步实现多维度健康检测触发降级。第三步给降级请求打标上报持续监控降级比例防止质量漂移。基础设施不需要漂亮话需要的是大模型挂了之后用户看到的不是空白页面而是一个打了降级标记但仍然有效的回答。