从 Bit 到 AGI第十一章:工程化(Serving)

A/B 测试

从 Bit 到 AGI · 第十一章:工程化(Serving) · LLM 模型与策略的在线实验

作者 David更新于 第 173 篇(共 186 篇)

注册表里的 v7 比 v6 MMLU 高 0.6——但 线上用户满意度 会变吗?LLM 的 A/B 测试把流量按 5%~50% 切到新模型/新 prompt/新温度,对比 业务指标(点击率、解决率)和 系统指标(TTFT、cost/token),统计显著后再全量。Gateway + 注册表 + 可观测性三者在此汇合。

直觉

A/B 像两家相邻奶茶店试卖:同一条街(用户),一半进 A 店(v6),一半进 B 店(v7),比复购率而非只看「B 店员工说更好喝」(offline benchmark)。LLM 额外难点:同一用户多轮对话必须 sticky 到同一 variant,否则前后模型不一致体验崩坏。

图表加载中…

定义

LLM A/B 实验要素:

要素说明
Unit通常 user_id 或 session_id(非 request)
Variant模型版本 / prompt 模板 / temperature
Split90/10、50/50;Canary 常用 5→20→50→100
Metrics主:业务 KPI; guardrail:延迟、错误率、 toxicity
Duration至少 7 天 或 10 K sessions/variant(取大)

统计:两比例 z-test 或 Bayesian;显著性 p < 0.05 且 MDE(最小可检测效应)预先定义。

例子

例 1:Gateway Header 路由(Istio)

# VirtualService:10% v7
route:
  - destination: { host: vllm-v6 }
    weight: 90
  - destination: { host: vllm-v7 }
    weight: 10

配合 consistent hash on x-user-id,保证同用户同 variant。

例 2:实验数据(客服 bot,14 天)

VariantSessions解决率平均 tokensTTFT P95成本/会话
v6 (control)48 20071.2%890620 ms$0.0042
v7 (treatment)5 31074.8%920580 ms$0.0044

解决率 +3.6 pp,95% CI [+1.2, +6.0] → 显著;成本 +4.8% 在预算内 → promote v7。

例 3:Shadow traffic(零用户风险)

模式用户看到用途
A/Bvariant 之一业务指标
Shadow始终 control新模型 mirror 请求,output 丢弃,比 latency/崩溃

Shadow 100% 流量 24 h,v7 OOM 率 0.02%(v6 0%)→ 修 batch 配置再进 A/B。

量化

样本量(比例指标,MDE=2 pp,baseline=70%):

n≈2×(zα/2+zβ)2×p(1−p)MDE2n \approx \frac{2 \times (z_{\alpha/2} + z_{\beta})^2 \times p(1-p)}{\text{MDE}^2}

p=0.7p=0.7,MDE=0.02,power=0.8(zα/2=1.96z_{\alpha/2}=1.96,zβ=0.84z_\beta=0.84)→ n≈n \approx ~8 200 / variant,两组共 ~16 K。只放 10% 流量进实验,就需要 ~165 K total sessions 才攒得够——对多数团队这不是「跑 7 天」,是跑一个月。

注意分母是 MDE 的平方,这是全篇最该记住的一件事:

MDEnn / variant相对
4 pp~2 0601×
2 pp~8 2404×
1 pp~33 00016×

想多测出一半的精度,要付四倍的样本。 所以 MDE 不是「越小越严谨」——它是你愿意为多大的效应买单。如果 1 pp 的提升对业务无所谓,就别把 MDE 定在 1 pp,那只是在烧流量。

实验污染:员工 dogfood、爬虫 bot 应 exclude;占流量 ~5% 时可 skew 结果。

Rollback SLA:promote 后若解决率 24 h 内跌 > 2 pp,自动切回 v6——Feature flag + registry stage 联动,MTTR 低于 5 min。

Prompt A/B(system 模板)比模型 A/B 便宜——无新 pod;但 metrics 需 NLP 评判(LLM-as-judge)或人工标注,噪声更大。

常见误区

  1. 「offline benchmark 够就全量」——MMLU +0.6 可能对应解决率 -1%(过拟合 benchmark)。
  2. 「50/50 永远最优」——高风险模型先用 5% Canary + shadow。
  3. 「按 request 随机」——同用户多轮进不同模型,对话失忆;必须 sticky session。

实验平台集成

与 Gateway + 可观测性 联动的最小实验配置:

# 应用层:每个请求打 label
variant = assign_variant(user_id, "exp-v7-202507")
headers = {"x-experiment-variant": variant}
metrics.labels(variant=variant).observe(ttft)

# 分析:按 variant 聚合 7 日 rolling
# Grafana: histogram_quantile(0.95, ttft{variant="treatment"})

Guardrail metrics(实验必须监控,超阈自动停实验):

Guardrail阈值动作
TTFT P95> control × 1.25停 treatment
5xx rate> 0.3%停 treatment
toxicity score> baseline + 0.05停 treatment
cost/session> control × 1.15告警

Sequential testing 警告:每天偷看结果并提前停止会 inflate false positive——预注册 固定 14 天 或 固定样本量,中途只查 guardrail。

Multi-armed bandit(进阶):高流量场景用 Thompson sampling 动态调流量,比固定 90/10 平均 -12% regret——但工程复杂度显著,建议 QPS >500 再上。

动手试一试

import hashlib

def assign_variant(user_id: str, experiment: str, split: float = 0.1) -> str:
    h = hashlib.sha256(f"{experiment}:{user_id}".encode()).hexdigest()
    bucket = int(h[:8], 16) / 0xFFFFFFFF
    return "treatment" if bucket < split else "control"

for uid in ["u1", "u2", "u1"]:
    print(uid, assign_variant(uid, "v7-rollout"))
# u1 两次结果相同 → sticky

模拟 10 K user_id,统计 treatment 比例是否落在 split ± 0.5%——偏差大说明 hash 或 experiment salt 有问题。

小结

LLM A/B 需 sticky user 分流、7 天 / 10 K sessions 量级样本;v7 解决率 +3.6 pp 显著方可 promote。Shadow 流量先验 稳定性,再开用户-facing 实验。

→ 下一篇:成本治理

本页目录