系列《AI 应用生产化手册》第 12 篇(共 30 篇)|配套开源项目:github.com/ChenYingbo/…
一、先看问题:感觉 ≠ 结论
R02 灰度保证"新版本别炸",但留下第 3 个问题:
- "新提示词更好"只是感觉——10% 用户跑了三天,有人说好有人说差,没有结论。
- 单看一个维度会误判——线上成功率没降,但回答质量悄悄变了;或者评测分数高了,但线上延迟爆了。
- 结论无法复现——"感觉新版好",换个人评审,结论相反。
解法: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 后)
- 写假设:canary 提示词的"范围确认"规则能降低幻觉率
- 离线:评测集分别跑两个变体 → 通过率 + ztest
- 线上:CANARY_ROLLOUT=50 跑一周 → 成功率 + ztest
- 下结论:两个维度都显著支持 canary → 全量(rollout=100);否则保留 stable
四、真实踩坑
- 没有假设就跑数据:跑完总能"看出"点什么——先写假设再跑
- 样本量不足就下结论:100 个样本看不出 3 个点的差异——差异越小样本要越大
- 只看 p 值不看效应量:p<0.05 但差距 1 个点——显著 ≠ 有意义
- 只跑一个维度:只看线上成功率或只跑评测——必须双维度都支持
- 实验期间改配置:跑到一半调阈值/放量——数据污染,实验期冻结一切变更
- 多重比较:一个实验看 20 个指标,总有一个 p<0.05——主指标先定,辅助只参考
- 分组不随机:新老用户天然不同——确定性 + 随机打散(哈希分桶已保证)
五、小结
- 五步法:假设 → 指标 → 样本 → 实验 → 结论
- 双维度:离线质量 + 线上稳定,都支持才采纳
- 样本量:想检测的差异越小,需要的样本越大
- 灰度 vs A/B:先灰度保平安,再 A/B 找最优
明天(R04):《回滚与快速恢复》——模型降级链 + 功能开关,出问题 1 分钟止血(含网关全停自动降级 200 的实测)。 收藏 + 关注,每天一篇,30 天把 AI 应用送上生产。