想象你是一家大餐厅的总排菜长,后厨有三位主厨:川菜师傅 A、粤菜师傅 B,还有刚挖来的融合菜师傅 C。C 师傅总说自己比 A 师傅强,可你不敢直接换菜单——万一客人不买账,砸的是整家店的招牌。怎么办?你定下规矩:先把客人公平地分成两桌,一桌照旧菜单、一桌偷偷加一道 C 师傅的新菜;试菜三周,回收满意度问卷,算清楚新菜到底赢没赢、赢在哪、代价是什么;确认胜出后,再让新菜先上给 10% 的客人,逐步铺开到全店;同时把 A 师傅留在后厨待命,随时准备回锅救场。 这套“分桌、试菜、打分、放量、复盘”的机制,正是 Harness Engineering 的决策中枢——多模型路由与 A/B 测试。本文带你从零看懂:如何用实验数据决定哪个模型上线、哪部分流量该走哪条路。
对 AI 从业者而言,掌握路由与实验设计意味着从“调参炼丹”升级为“数据驱动决策”,这是做大模型平台运营、模型效果持续优化的核心能力,也是 AI 工程化从单点模型走向系统架构的分水岭。
可视化演示
动态演示多模型路由与A/B测试的核心机制,通过入门/进阶/实战/优化四种模式展示关键概念与交互流程。
本节配有交互动效(进入视口后自动加载,约 3KB)。
多模型路由与A/B测试:多模型路 多模型路由规则与决策策略 A/B测试实验设计与流量分桶 核心机制可视化 多模型路由与A/B测试整体架构与关键组件
流量分桶策略
排菜长要试 C 师傅的新菜,第一步不是炒菜,而是分桌——把当晚的客人按规则切成两拨:一半照旧菜单(对照组 A),一半悄悄加一道新菜(实验组 B)。分桌不能随心情:如果 A 桌全是老顾客、B 桌全是新顾客,满意度差异根本不是菜的区别。于是排菜长立下规矩:用客人的号码做“指纹”,同一位客人每次试菜都进同一桌;指纹相似的客人要均匀散落两桌,保证两桌的老少比例、辣口占比都差不多。
在 Harness 里,这个“分桌”叫流量分桶。系统对每个请求计算一致性哈希,把用户流量稳定地切成 0~99 的桶位;再根据实验配置,把 0~49 号桶划给实验组(新模型)、50~99 号划给对照组(旧模型)。哈希(hash)是一种把任意字符串变成固定范围整数的映射函数,像给每个客人盖一个终身不变的编号。同一位用户永远落在相同桶位,避免同一个人一会儿吃新菜一会儿吃老菜,导致指标被“平均”稀释。
分桌公平,试菜得出的结论才敢信。分桶是 A/B 测试的基石:桶切歪了,后面所有统计都白做。
- 拼接标识把用户 ID 和实验 ID 拼在一起,让不同实验使用互相独立的桶位,避免实验之间串扰。
- 哈希映射hash 把任意字符串映射成空间巨大的均匀整数,保证不同用户散落得足够均匀。
- 取模分桶对 100 取模,把大整数压缩到 0~99 的桶号空间。
- 组别判定桶号小于实验比例(如 50)则进入实验组,否则进入对照组;因哈希稳定,同用户实验期间永远落同一组。
路由规则设计
分好桌后,排菜长还要决定每桌客人吃哪位师傅的菜。他手里有顾客档案:是否吃辣、预算高低、是商务宴请还是家庭聚餐。C 师傅川菜一绝,但让不吃辣的广东客人吃他的菜,客人当场就会投诉。这就是路由要做的事——根据每个请求的“画像”决定交给哪个模型。
在 Harness 中,路由的输入叫路由上下文(routing context):用户画像、query 类型、预算成本、当前系统负载等。规则引擎把这些输入翻译成决策,最简单的形式是 if-else:用户问法律问题 → 走法律微调模型;用户只是闲聊 → 走便宜快速的通用模型。但真实场景里特征经常打架——“爱吃辣但预算很低”,这时硬规则不够用,得用加权打分:每个模型在上下文上算一个得分,再按得分占比分配流量。
排菜长不是随机点将,而是综合档案打分的“加权选人”。但评分再合理,也防不住突发状况——这时就要靠兜底策略:路由超时或模型报错时,自动改走最稳定的默认小模型,保证顾客永远有菜吃。
- 计算得分模型 i 根据上下文得到实数得分 s_i,可正可负,代表它适合这单的程度。
- 放大差异取指数把得分变成正数,同时优秀者与平庸者的差距被放大。
- 归一化分母对所有 e 的指数求和,保证总概率为 1。
- 得出占比两者相除后得到模型 i 被选中的概率 P_i,路由层按此概率分配请求。
实验设计方法
试菜不能试一天就拍板。万一那晚客人心情好、隔壁餐厅打折、天气凉爽,什么因素都可能干扰满意度。排菜长必须定下严谨的试菜方案:试多久、每桌几道菜、要多少样本才算数。这套方案在 A/B 测试里叫实验设计。
第一步是提出假设:“C 师傅的新菜能让满意度提升至少 5%”;第二步是设定对照组:B 桌吃新菜、A 桌吃老菜;第三步是划流量比例:实验组一般取 10%~50%,太小统计效力不足,太大会让多数用户陪跑;第四步是定实验周期:至少覆盖一个完整自然周,把周末和工作日的差异都算进去。要回答“样本要多少”,得先预估基准满意率 p 和最小可检测差异 δ,代入样本量公式。
没有实验设计的试菜就是凭感觉。同样,显著性判断也很关键:实验结束不能只看谁分高,还要用统计检验确认差异不是运气。z 检验就是这样一把“尺子”——差异足够大且样本足够多时,z 值超过 1.96 才能说“新菜真的赢了”。
- 置信临界值z_{α/2} 取 1.96,对应 95% 置信度——意思是“判断错的风险控制在 5% 以内”。
- 基准发生率p 是当前满意度的预估比例(如 0.6),p(1−p) 是自然波动的方差估计。
- 方差与差异比z² · p(1−p) 是噪声总量,除以 δ²(最小可检测差异)得到样本量。
指标归因分析
三周试菜结束,排菜长开始收问卷。C 师傅的新菜满意度确实高,但他上菜更慢、食材更贵。如果只看满意度就换菜单,客人可能为了一道好菜天天等位,成本还吃掉利润。排菜长需要一套综合打分:把满意度(质量)、上菜时长(延迟)、食材成本(成本)放在同一张表里比较。
在 A/B 测试里,这一步叫指标归因与效果对比。首先要定核心指标体系:质量类指标(回答准确率、满意度)、效率类指标(延迟、超时率)、成本类指标(单次调用费用)。其次是归因方法:采用意向性分析(intention-to-treat),即按最初分桶的组别统计,哪怕中途有用户流失也算进原组,防止“中途换桌”污染结论。最后把多维指标加权成一个综合分,对比实验组与对照组。
综合打分避免了“上菜快但难吃”的单指标陷阱。归因分析的意义就在于此:把“效果好”拆成“哪个指标带来的、代价是什么”,让决策者对每一分提升心中有数。
- 标准化指标quality、latency、cost 各自归一化到 0~1 区间,消除量纲差异。
- 加权求和权重 w_1、w_2、w_3 代表业务优先级,质量好的产品给 w_1 高,客服场景给 w_2 高。
- 惩罚项延迟和成本用负号,越慢越贵扣分越多。
- 胜负判定算实验组与对照组的 Q 值差,再结合显著性检验判断差值是否可信。
自动切换上线
新菜综合分胜出了,排菜长会立刻全量换菜单吗?不会。他会先让 10% 的客人吃新菜,确认没有过敏投诉,再扩到 50%,最后才 100% 铺开。这套节奏在模型上线里叫灰度发布:通过渐进放量把风险锁在笼子里。
胜出判定不只要看 ΔQ 为正,还要求连续若干天胜出、关键监控指标没有恶化(如错误率飙升、超时增加)。满足条件后进入灰度发布流程:初始放量 5%~10%,观察一段窗口,指标平稳则按步长扩大流量;任何一步异常,立即触发回滚机制——因为旧模型一直保留在模型池中,路由配置一键切回,用户无感。
新菜写入菜单是流程,不是赌注。灰度放量的每一步都有观测窗口和回滚预案,这就是“自动驾驶式上线”和“拍脑袋换模型”的本质区别。
- 时间累计t 是灰度开始后经过的时间(比如按小时计)。
- 线性放量t/T 表示当前进度占比,开始时接近 0,逐渐增大。
- 封顶到 1min(1, ·) 保证放量比例不超过 100%,防止过冲。
模型运营体系
菜单不是写一次就完事。排菜长每月复盘:哪些菜叫好不叫座,哪位师傅状态下滑,要不要再请新师傅试菜。这就是模型运营体系——它不是一次实验,而是一台永不停转的决策机器。
模型池管理:保持一个候选模型库,包含线上主模型、往期旧模型、新训练的实验模型;旧模型不是垃圾而是“安全气囊”。路由日志分析:每一笔请求都记录“谁接的单、上下文是什么、用户给了几分”,沉淀为路由日志,供后续归因和复盘使用。迭代闭环:新模型提出假设 → 设计实验 → 分桶验证 → 指标归因 → 灰度上线 → 复盘日志 → 提出下一个假设。周而复始,模型池越转越优。
决策中枢的价值不是某一顿菜做得好,而是长期会复盘的排菜长。模型运营体系把“选模型”从一次性项目变成持续进化的能力,这正是 Harness Engineering 作为决策中枢的终极形态。
- 质量分Q_m 是模型 m 在最近窗口内的综合质量分,来自线上路由日志的滚动统计。
- 成本惩罚C_m 是单次调用平均成本,λ 是惩罚系数,成本越高的模型被扣得越多。
- 健康度计算两者相减得到健康度,低于阈值的模型退出主路由、留在池中。
AI 应用场景
智能客服平台的多档模型路由
阶段:模型选择与流量调度
解决的问题:传统做法是“一个模型服务所有提问”,要么贵而准的大模型烧钱,要么便宜快的小模型答非所问。平台团队希望按问题复杂度路由:简单问题走小模型省钱,疑难问题才上大模型。
具体案例:某电商客服平台接入 Harness 路由层,用规则引擎按“问题长度 + 关键词 + 用户等级”打分:简单咨询(退款进度、物流查询)走 5ms 的小模型,纠纷仲裁类走 300ms 的大模型;同时新到的大模型版本先吃 20% 实验流量,与旧大模型做 A/B 对比,连续两周胜出后灰度放量至全量。
内容推荐系统的多模型实验平台
阶段:实验设计与指标归因
解决的问题:推荐算法团队每次迭代都要验证“新模型是否真的更好”,传统做法是离线跑分后直接上线,经常上线后指标反而下滑。需要一套线上实验基础设施让数据说话。
具体案例:某内容社区把用户按下发渠道、活跃度路由到不同推荐模型;新模型通过一致性哈希分桶,只影响 10% 用户;实验期间用意向性分析统计点击率、时长、退出率三个指标,加权成综合分;胜出后按 5% → 30% → 100% 灰度,全程保留旧模型随时回滚。
Python 演示
import hashlibimport mathimport random class Router: def __init__(self, models, split=0.5): self.models = models # {"A": 0.82, "B": 0.78}, 值代表基础满意度 self.split = split def bucket(self, user_id, exp_id): h = int(hashlib.md5((user_id + exp_id).encode("utf-8")).hexdigest(), 16) return h % 100 def route(self, user_id, exp_id): g = self.bucket(user_id, exp_id) if g < self.split * 100: return "B", "实验组" return "A", "对照组" def run_study(self, users, exp_id): stats = {"A": [0, 0], "B": [0, 0]} # [样本数, 满意数] for uid in users: model, group = self.route(uid, exp_id) p = self.models[model] + random.uniform(-0.05, 0.05) satisfied = random.random() < max(0.0, min(1.0, p)) stats[model][0] += 1 stats[model][1] += int(satisfied) return stats def compare(self, stats): out = {} for model in stats: n, ok = stats[model] out[model] = (n, ok / n if n else 0) return out def main(): random.seed(42) router = Router({"A": 0.82, "B": 0.78}) users = [f"user_{i}" for i in range(2000)] raw = router.run_study(users, "exp_20240601") result = router.compare(raw) for model, (n, rate) in result.items(): print(f"模型 {model}: 样本 {n} 个, 满意度 {rate:.2%}") p_a = result["A"][1] p_b = result["B"][1] n = 1000 z = (p_b - p_a) / math.sqrt(p_a * (1 - p_a) / n + p_b * (1 - p_b) / n) print(f"z 分数: {z:.3f}") if z > 1.96: print("结论: B 显著优于 A, 建议切换") elif z < -1.96: print("结论: A 显著优于 B, 保持现状") else: print("结论: 差异不显著, 继续观察") if __name__ == "__main__": main()
h = int(hashlib.md5((user_id + exp_id).encode("utf-8")).hexdigest(), 16)一致性哈希核心:把用户与实验拼成字符串再算出均匀大整数,作为“客人指纹”。return h % 100取模得到 0~99 桶号,同用户永远同桶。if g < self.split * 100桶号小于阈值进实验组(B),否则进对照组(A)。p = self.models[model] + random.uniform(-0.05, 0.05)模拟真实满意度在基础质量附近的随机波动。satisfied = random.random() < max(0.0, min(1.0, p))用概率抽样决定该用户是否满意。ok / n if n else 0计算组内满意率,作为效果指标。z = (p_b - p_a) / math.sqrt(p_a * (1 - p_a) / n + p_b * (1 - p_b) / n)z 检验:判断两个满意率的差异是“真差距”还是“随机噪声”。if z > 1.96:超过临界值说明 B 显著优于 A,触发切换建议。
常见误区
误区新模型在离线测试集上跑了 92 分,旧模型才 85 分,为什么还要分 50% 流量慢慢做实验?直接全量替换不香吗?省时省力。
正解离线评测用的是历史数据,与线上真实用户分布有偏差;且没有对照组,效果提升无法归因——是模型变好了,还是恰好碰上流量旺季?A/B 测试的成本是部分流量,收益是“用数据代替感觉做决策”。宁可慢三周,不可错一次。
为何常见:离线跑分直观快速,容易让人忽略线上环境的动态差异和未知风险。
误区实验嘛,把每个请求随机丢到 A 组或 B 组就行了,反正样本量够大,随机天然公平。
正解如果同一用户在一次会话里的多次请求被随机分到两组,他会感到“时好时坏”,体验不一致;更严重的是,同一用户的多次请求在组内形成自相关,会稀释组间差异,让实验“看不出区别”。一致性哈希就是给用户盖终身指纹,保证实验期间稳定落在同一组。
为何常见:从“请求”角度而非“用户”角度思考问题,忽略了真实业务中一个用户会反复交互。
误区新模型回答质量高出一截,用户满意度明显涨了,直接上线吧!延迟慢一点、成本贵一点有什么关系?
正解模型上线是多目标权衡:质量提升 1% 但延迟翻倍、成本翻三倍,业务上往往不可接受。综合加权分 Q 把质量、延迟、成本统一成标量,实验组 Q 值真正胜出才算赢。单指标冠军经常是“叫好不叫座”的花架子。
为何常见:质量是离业务最近的目标,直观且容易量化,容易被单独放大而忽视资源约束。
误区B 模型已经连续两周胜出,灰度也跑完了,旧模型 A 留着占地方,删掉吧!
正解旧模型必须保留在模型池中作为回滚候选。灰度上线期间一旦监测到异常(错误率飙升、延迟超时),必须能秒级切回旧模型。删掉旧模型等于开车卸掉刹车——上线决策再严谨,也要保留“撤销”的能力。
为何常见:资源紧张时想省存储和运维成本,忽略了运营安全的后备需求。
面试题
Q1. 多模型路由中“一致性哈希分桶”的主要作用是什么?
- A.保证同一用户总进入同一组← 正确答案
- B.让所有用户随机进入实验组
- C.提升模型推理的响应速度
- D.代替人工评估模型的效果
答案:A。一致性哈希把用户 ID 映射到固定桶位,同用户实验期间永远落在同一组,避免体验不一致和样本自相关。B 说反了,随机进入正是要避免的;C、D 与哈希分桶无关。
Q2. A/B 测试中实验组和对照组的核心区别是?
- A.实验组用新模型对照组用旧模型← 正确答案
- B.实验组流量比对照组多一倍
- C.对照组不需要收集任何指标
- D.两组使用完全相同的模型
答案:A。实验组吃“新菜”、对照组吃“老菜”,这是 A/B 测试的基本设定。两组流量通常按比例切分而非一方多一倍;对照组同样要收集指标,否则无法对比。
Q3. 以下哪个属于“兜底策略”的例子?
- A.路由超时后改走默认小模型← 正确答案
- B.把用户按照地域分到不同组
- C.提高实验组所占的流量比例
- D.每个月重新训练一次模型池
答案:A。兜底策略是当主路由异常(超时、报错)时的应急预案,最典型的就是退回默认小模型保证服务可用。B 是分桶维度,C 是流量比例调整,D 是模型池维护,都不是兜底。
Q4. z 检验公式 z = (p₁ − p₂) / √(p(1−p)(1/n₁ + 1/n₂)) 中 p 代表什么?
- A.合并两组的总体事件发生率← 正确答案
- B.实验组占用的样本量大小
- C.检验的显著性水平阈值
- D.模型拥有的参数量多少
答案:A。p 是两组合并后的总体发生率,即把两组样本合在一起算出的满意率,作为零假设下的公共概率估计。它用于估计标准误,不是样本量(n)、显著性水平(α)或参数数量。
Q5. 划分实验流量时需要考虑哪些因素?
- A.保证组间样本特征分布相似← 正确答案
- B.同一用户多次请求进入不同组
- C.避免实验与对照流量互相污染← 正确答案
- D.只保留免费用户参与实验
答案:AC。分桶要保证组间特征均衡、互不污染,这样差异才能归因于模型而非用户结构。B 恰恰是反面做法(同一用户应稳定同组);D 人为筛选用户会破坏样本代表性。
Q6. 实验发现新模型质量更高但延迟明显增加,综合指标 Q = w₁·quality − w₂·latency − w₃·cost 下应如何决策?
- A.权衡三个维度后看综合分正负← 正确答案
- B.只比较质量一个维度的差异
- C.直接全量切换新模型上线
- D.把三个权重全部设为相同值
答案:A。多目标决策必须看加权综合分:质量加分、延迟和成本减分,Q 值为正且显著才算胜出。B 是单指标陷阱;C 忽略风险;D 权重由业务优先级决定,不能一律相等。
Q7. 新模型胜出后上线的“灰度发布”是指什么?
- A.先小流量再逐步扩大到全量← 正确答案
- B.直接一次性替换全部流量
- C.只对内部员工开放测试
- D.训练阶段分批喂入数据
答案:A。灰度发布是渐进放量:5% → 30% → 100%,每步观察监控指标。B 是“全量发布”,风险极高;C 是内测;D 是训练阶段的 batch 概念,与上线无关。
Q8. 灰度发布已放量到 30%,此时监测到错误率超过阈值,正确的做法是?
- A.立即回滚到旧模型并复盘原因← 正确答案
- B.调高新模型权重继续观察
- C.删除失败日志避免影响评估
- D.新旧模型同时服务所有请求
答案:A。灰度期间指标恶化,第一优先级是保障线上稳定:立即切回旧模型,再复盘日志定位原因。B 是逆向操作,继续放大风险;C 销毁证据无法归因;D 让所有请求同时被两模型处理会造成混乱。
Q9. A/B 测试中“样本量估算”的主要作用是什么?
- A.保证实验有足够统计效力← 正确答案
- B.减少模型的响应延迟时间
- C.提高实验组流量所占比例
- D.提升模型离线评测的准确率
答案:A。样本量 n = z²p(1−p)/δ² 是为了保证实验能检测出预设的最小差异,避免“实验做完却说不清输赢”。它与延迟、流量比例、离线准确率无直接关系。
Q10. 模型运营体系的“迭代闭环”包含哪些环节?
- A.提出假设并设计对照实验← 正确答案
- B.对实验数据做归因分析← 正确答案
- C.胜出模型灰度发布上线← 正确答案
- D.永久删除所有失败模型
答案:ABC。迭代闭环是“假设 → 实验 → 归因 → 灰度 → 复盘 → 新假设”的循环。失败模型应保留在模型池中备回滚,而不是永久删除,因此 D 错误。