A/B 实验:85% 比 78% 好,居然不算赢?(R03)

28 阅读5分钟

系列《AI 应用生产化手册》第 12 篇(共 30 篇)|配套开源项目:github.com/ChenYingbo/…

一、先看问题:感觉 ≠ 结论

R02 灰度保证"新版本别炸",但留下第 3 个问题:

  1. "新提示词更好"只是感觉——10% 用户跑了三天,有人说好有人说差,没有结论。
  2. 单看一个维度会误判——线上成功率没降,但回答质量悄悄变了;或者评测分数高了,但线上延迟爆了。
  3. 结论无法复现——"感觉新版好",换个人评审,结论相反。

解法:A/B 实验——确定性分组、双维度对比(离线评测 + 线上指标)、显著性检验。

核心认知:灰度回答"会不会炸",A/B 回答"哪个更好"。实验不是"跑两组数据",而是"先写假设、定指标、算够样本、下统计结论"的严谨流程。

二、原理

A/B 实验五步法

① 写假设   "canary 提示词的'范围确认'规则能降低幻觉率"
② 定指标   主指标:评测通过率 + 线上成功率;辅助:P95 延迟、token 成本
③ 算样本   样本量不够 = 结论不可信
④ 跑实验   确定性分组(复用 R02 哈希分桶),两组并行
⑤ 下结论   z 检验 → p 值 → 显著才改;不显著就保持现状

先写假设再跑数据——没有假设的实验是数据钓鱼(跑完总能"看出"点什么)。

双维度对比(必须两个都看)

维度工具回答漏看的代价
离线(评测集)评测 + ab_test offline质量变了吗线上没炸但质量悄悄退化
线上(真实流量)监控 + ab_test online有没有变坏评测集覆盖不到的长尾问题

结论标准:两个维度都支持才采纳。

显著性检验(z 检验速成)

H0:两组通过率相同
z = (pA - pB) / 标准误    p 值 < 0.05 → 拒绝 H0(显著)

两个必懂概念:

  • p 值:差异是"真差异"的置信度(p<0.05 是惯例,不是真理)
  • 效应量:就算显著,也要看差距多大("90% vs 89%"显著但没意义)

本系列实测(ab_test.py ztest,各 100 样本):

a-success 85 / b-success 78 → z=1.27, p=0.20 → 差异不显著

85% vs 78% 看起来差 7 个点,但样本量不够支撑结论——这是"样本量不足"最常见的翻车现场。

样本量直觉(不必背公式,但要懂方向)

想检测的差异需要样本量(每臂)直觉
10 个点(85% vs 75%)~200差异大,少样本够
3 个点(85% vs 82%)~2000差异小,要很多样本
1 个点~18000接近噪声

想检测的差异越小,需要的样本越大。 "跑了 100 个用户没看出差别" ≠ 没差别。

A/B vs 灰度

灰度A/B
目的降低风险(别炸)对比效果(谁更好)
决策放量 or 回滚采纳 or 不采纳

实践组合:灰度保护上线 → 稳定后 A/B 找更优版本 → 新版本再走灰度。

三、动手:分组 + 检验 + 双维度

git clone https://github.com/ChenYingbo/ai-prod-demo.git && cd ai-prod-demo
source .venv/bin/activate

# 1. 分组确定性验证(10000 用户 50/50)
python scripts/ab_test.py assign --n 10000 --split 0.5
# 真实输出:A=5006 B=4994 (50.1% / 49.9%)

# 2. 显著性检验(先学会读结果)
python scripts/ab_test.py ztest --a-success 85 --a-total 100 --b-success 78 --b-total 100
# 真实输出:z=1.2747, p=0.2024 → 差异不显著

# 3. 线上维度分析(R02 灰度跑一批请求后)
python scripts/ab_test.py online --log /tmp/app.log
# 输出:stable vs canary 的成功率/P95/token + z 检验结论

反直觉实验(必做)

python scripts/ab_test.py ztest --a-success 85 --a-total 100  --b-success 80 --b-total 100
python scripts/ab_test.py ztest --a-success 850 --a-total 1000 --b-success 800 --b-total 1000

同样的 5 个点差异,样本放大 10 倍后结论翻转——这就是样本量的力量,也是"别急着下结论"的原因。

完整实验(有 API Key 后)

  1. 写假设:canary 提示词的"范围确认"规则能降低幻觉率
  2. 离线:评测集分别跑两个变体 → 通过率 + ztest
  3. 线上:CANARY_ROLLOUT=50 跑一周 → 成功率 + ztest
  4. 下结论:两个维度都显著支持 canary → 全量(rollout=100);否则保留 stable

四、真实踩坑

  1. 没有假设就跑数据:跑完总能"看出"点什么——先写假设再跑
  2. 样本量不足就下结论:100 个样本看不出 3 个点的差异——差异越小样本要越大
  3. 只看 p 值不看效应量:p<0.05 但差距 1 个点——显著 ≠ 有意义
  4. 只跑一个维度:只看线上成功率或只跑评测——必须双维度都支持
  5. 实验期间改配置:跑到一半调阈值/放量——数据污染,实验期冻结一切变更
  6. 多重比较:一个实验看 20 个指标,总有一个 p<0.05——主指标先定,辅助只参考
  7. 分组不随机:新老用户天然不同——确定性 + 随机打散(哈希分桶已保证)

五、小结

  • 五步法:假设 → 指标 → 样本 → 实验 → 结论
  • 双维度:离线质量 + 线上稳定,都支持才采纳
  • 样本量:想检测的差异越小,需要的样本越大
  • 灰度 vs A/B:先灰度保平安,再 A/B 找最优

明天(R04):《回滚与快速恢复》——模型降级链 + 功能开关,出问题 1 分钟止血(含网关全停自动降级 200 的实测)。 收藏 + 关注,每天一篇,30 天把 AI 应用送上生产。