日期:2026-07-16
我们采用的 AI 网关技术平台上挂的模型不是一成不变的。几乎每个季度都有新模型要上:要么是底座新训出来的业务微调版,要么是某头部云厂商新放的更强版本,要么是某开源社区刚出的一个新尺寸。问题来了——这些新模型我们不敢直接全量切过去。一个新版本在某个评测集上分数高,不代表它在我们真实业务流量上不出 bad case;全量替换一旦翻车,客服话术错乱、商品标题生成跑偏,影响的是真实用户。
所以我们在网关路由层搭了一套灰度与版本路由机制:新模型先按小比例流量放进去,和老模型做 A/B,盯住关键指标,确认稳了再逐步加权重,出问题一键回滚。这件事的核心诉求是:新模型上线不敢全量,需按流量比例灰度、出问题秒级回滚。
路由层天然支持按权重把同一类请求分发到不同模型版本。我们把它用成了三种模式:一是版本灰度,新模型 version=2 从 5% 权重起步,逐步爬到 100%;二是 A/B 实验,两个模型各 50% 对一个新功能做效果对比;三是按用户群分流,比如把内部测试账号、白名单客户、普通用户分别路由到不同模型组合。
管控台里每条路由策略都是一份可热更新的 YAML,运维改完权重,网关秒级生效,不需要重启底座。路由命中情况实时回流到看板,业务和算法能同屏看到两个版本的延迟、错误率、以及业务侧埋点指标(如问答满意度、生成采纳率)。
我们还把灰度状态和底座版本管理打通:一个模型版本在网关里下线,底座对应的推理实例也就不再接流量,避免"网关不叫它但底座还在空跑"的浪费。这里有个组织上的收益——过去算法团队要上新模型,得拉着 SRE 改底座配置、发版、盯监控,一天起步;现在算法自己在管控台改一份 YAML 就能放量,SRE 只需要在容量告警时介入,双方的协作摩擦明显降低。
需要特别说明的是,灰度不是只服务于"新模型替代老模型"。我们也用同一套机制做能力回退:当某开源社区模型在某个版本出现已知缺陷,我们会把权重临时切回稳定版,等上游修复后再灰度切回,全程业务无感。
第一个挑战是权重灰度与流量切分。最简单的做法是无状态哈希分流,但模型调用有上下文连续性要求(同一会话要打到同一版本,否则回答会跳)。我们给请求注入一个 sticky_key(会话 ID 或用户 ID),网关按 sticky_key 做一致性哈希,保证同一用户在一次会话内始终落在同一模型版本;同时按全局权重控制各版本流量占比。配置如下:
案例片段(已脱敏):灰度路由权重配置片段
yaml route: name: intent-classify-route match: { app: "cs-knowledge-qa", intent: "order_query" } strategy: weighted sticky_key: session_id targets: - model: self-72b-v1 weight: 80 - model: self-72b-v2 weight: 20 user_group_override: - group: "internal-tester" route_to: self-72b-v2 # 内部测试号全量走新模型
第二个挑战是灰度指标对比。不能只看 P99 延迟,真正要盯的是业务指标。我们在编排层把每个请求的模型版本写进 trace,下游埋点把"采纳率/投诉率"feedback 回来,看板按 version 聚合做双侧检验。只有新版本在关键业务指标上不劣于老版本、且错误率无显著上升,才允许加权。一次真实灰度里,新版本在订单查询意图上采纳率高出 3 个百分点,但在退换货意图上投诉率翻了一倍——这种结构性的此消彼长,靠总量平均是看不出来的,必须按意图维度拆开对比,否则会误判成"整体更优"而放行。
第三个挑战是秒级回滚。灰度最怕"发现不对但切不回来"。我们把路由权重和开关都做成内存热配置,管控台点一下回滚,网关所有节点在 1 秒内拉到新配置,新流量不再进问题版本,已进入的请求由编排层做 graceful 收尾。回滚动作本身也写入审计日志,谁在什么时候回滚了哪条路由,可追溯。
第四个挑战是多版本共存。新模型上线期间,v1 和 v2 同时在底座跑,GPU 显存和副本数要够。我们用网关的实时调用量反推底座需要的副本数,限流信号和路由权重一起驱动弹性扩缩容,灰度期临时多开的副本在灰度结束后自动回收,避免资源长期占用。实践中我们发现,权重爬坡的节奏要和副本扩容对齐:如果权重从 20% 直接拉到 80%,而底座副本还按 20% 流量配的,新版本会瞬间被打满。所以灰度编排里我们加了一步"扩容确认"——新版本副本就绪且预热完成后,才允许权重继续往上爬。
以下为脱敏示意值,统计自最近一次大模型版本灰度上线。
| 指标 | 改造前(硬切换) | 改造后(灰度路由) | 说明 |
|---|---|---|---|
| 灰度切换耗时 | 约 40 分钟(改代码发版) | 降至约 8 秒 | 热配置秒级生效 |
| bad case 捕获率 | 约 35% | 提升至约 86% | 小流量先暴露问题 |
| 回滚耗时 | 约 25 分钟 | 降至约 3 秒 | 一键热回滚 |
| 实验转化率(A/B 胜出率可信度) | 不可量化 | 提升至约 92% | 双侧检验达标才加权 |
| 灰度期额外 GPU 成本 | — | 约 +6% | 多版本共存临时开销 |
第一,灰度优于全量。任何模型版本变更都不该直接全量,5% 的小流量足以在真实分布下暴露大多数 bad case,代价却只是全量的零头。
第二,回滚预案要先备好。我们规定每条灰度路由上线前必须先在沙箱验证回滚路径,确认"一键能回"才放流量,绝不允许"先上了再看能不能回"。
第三,指标对比要落到业务侧。模型侧的延迟、错误率只是及格线,真正的判据是采纳率、投诉率这类业务埋点,否则灰度会变成"看起来都挺快"的伪安全。
第四,多版本共存要算清资源账。灰度期多开副本是合理的,但必须用网关流量信号自动回收,别让临时资源长期占着不释放。
第五,灰度节奏要和容量扩张对齐。权重爬坡不是调个数字就完事,必须等底座副本预热就绪再继续加量,否则新版本会在瞬间被老流量淹没,反而制造一次人为的"上线事故"。我们把"扩容确认"作为权重爬坡的前置闸门,是这次落地里踩过坑才补上的关键一环。