换了一版 prompt,上线一周后"人工满意度"从 3.6 涨到 3.9,团队准备把结论写成"新 prompt 效果更好"并全面推广。复盘时有人提了一个问题:这一周的用户是不是同一批?查下去发现,这一周刚好是大促后的低峰期,投诉类问题少了 30 %——满意度上涨里,有多少来自 prompt,有多少来自"这周的问题更好答",没人算过。
AI 功能的实验比普通功能的实验更难做,原因有三个:输出非确定(同一输入不同结果)、指标是主观的(人工评分有抖动)、环境在漂移(知识库、模型版本、用户构成都在变)。所以"A/B 之后涨了"这个句式,在 AI 功能上几乎总是信息量不足。
1. 四个会让结论失效的偏差
| 偏差 | 表现 | 后果 |
|---|---|---|
| 时间混杂 | A 组在前、B 组在后 | 环境变化被算进效果 |
| 用户构成 | 两组用户类型不同 | 难度差异被算进效果 |
| 指标漂移 | 评分标准、抽样方式变了 | 前后不可比 |
| 模型/知识变更 | 中途升级了模型或知识库 | 变量不止一个 |
第一行是最常见的:因为"新 prompt 需要时间上线",A、B 天然不是同期。跨期对比在 AI 功能上几乎必然带入混杂——除非你能证明"这两周的问题分布相同"。
// 一个真实的数字拆解
整体满意度:3.6 → 3.9(+0.3)
按问题类型分层后:
简单问答 3.8 → 3.9(+0.1)
复杂多跳 3.2 → 3.5(+0.3)
投诉类 2.9 → 3.4(+0.5) ← 而这类问题本期占比从 30% 降到 20%
// 结论:+0.3 里约 0.2 来自"难题变少",prompt 的真实贡献约 0.1
2. 正确的分流单位是"会话"而不是"用户"
| 分流单位 | 优点 | 问题 |
|---|---|---|
| 用户 | 体验一致 | 老用户占比差异会污染结果 |
| 会话 | 每组独立可比 | 同一用户会同时体验两版 |
| 请求 | 样本最多 | 同一会话内自相矛盾(风格突变) |
| 租户/团队 | 适合 B 端 | 样本数少 |
第二行是多数 AI 对话场景的正确选择:一次会话内保持一致(不出现"上一句 A 版、下一句 B 版"),而不同会话独立分流。这样既避免体验割裂,又保证两组可比。
// 一个可用的实验配置
experiment:
unit: conversation # 不是 user,也不是 request
split: 50/50
guardrails:
- same_model_version # 实验期内模型锁定
- same_kb_snapshot # 知识库快照锁定
- min_samples: 800 # 每组的会话数下限
stop_rules:
- 失败率上升 > 2x 立即停止
- 人工抽检连续 3 天负向 → 停止
3. 指标要分层,"总体分"几乎总是误导
| 指标层 | 用途 | 抖动 |
|---|---|---|
| 总满意度 | 汇报用 | 大(混了难度) |
| 分类型满意度 | 判断效果 | 中 |
| 事实准确率(可核对) | 客观 | 小 |
| 人工抽检命中率 | 质量底线 | 小但样本少 |
// 分层之后最容易犯的第二个错误:拿小样本下结论
复杂多跳:3.2 → 3.5(+0.3),但这一层只有 60 个会话
// 60 个样本上的 ±0.3,噪声区间往往就是 ±0.4 —— 看不出来
第二行是关键:必须按"问题难度/类型"分层看。总分的变动往往来自难度构成变化,而不是质量变化——这也是"分层后每组都要够样本"的原因(分层会把样本切得很碎)。
第四行提醒:人工抽检样本小,它适合"发现灾难"而不是"证明改善"。用 50 条抽检去证明 +0.2 的差异,统计上站不住。
4. 样本量:先算,再跑
| 想证明的差异 | 每组最小会话数(粗估) |
|---|---|
| +0.5 分(5 分制) | 约 100 |
| +0.2 分 | 约 600–800 |
| +0.1 分 | 约 2,500+ |
| 分类型内部 +0.2 | 再乘类型数 |
这张表的含义很实际:想证明"小幅改善"要跑很久。所以很多"实验"实际上只能证明"没有变差"——这本身也是有价值的结论,但必须如实表述。
// 一个诚实的结论写法(三段)
【观察】B 组总分 +0.3,但分层后简单问答仅 +0.1(在噪声范围内)
【归因】难度构成变化解释了约 0.2 的差异;prompt 的可归因部分约 0.1
【判断】无法确认显著改善;建议延长实验或只保留"未变差"的结论
// 关键:把"无法确认"写出来,而不是四舍五入成"有效果"
5. 什么情况下根本不该做 A/B
| 场景 | 为什么 | 替代 |
|---|---|---|
| 调用量太小 | 样本不足,结论不可信 | 离线评测 + 抽检 |
| 合规/资金类功能 | 不能让一半用户体验差版本 | 灰度 + 回滚 |
| 改动是修复明确 bug | 无需证明"更好" | 直接上,监控指标 |
| 指标无法在窗口内观测 | 长尾效果观测不到 | 长期观测 + 分阶段 |
| 只有一个大客户 | 分流等于得罪人 | 单独环境验证 |
// 实验前的三行自检,缺一行就别开实验
$ grep -rn "model_version" config/ | head -1 // 1 模型版本锁住了吗
$ grep -rn "kb_snapshot" config/ | head -1 // 2 知识库快照锁住了吗
$ python3 -c "print('样本', 1200*0.5*7)" // 3 一周能攒够 800 组会话吗
// 三行都能过,才轮到讨论分流比例与指标口径
第一行最常被忽略:每天几十次调用的功能做 A/B,跑三个月也攒不够样本。此时正确做法是"离线评测集 + 人工抽检",而不是硬做在线实验。
6. 排错:五种"实验结论站不住"
| 现象 | 八成原因 | 处理方向 |
|---|---|---|
| 两组差异巨大但抽检看不出来 | 分流不均(用户构成) | 改按会话分流 |
| 中途指标突然跳变 | 模型/知识库变了 | 锁版本重跑 |
| 分层后每层都没差异 | 总分差异来自构成 | 如实写"无显著" |
| 同样实验两次结论相反 | 样本不足 | 延长或合并 |
| 上线后效果消失 | 实验期环境特殊(低峰) | 覆盖完整周期 |
第五行是"实验通过、上线无效"的标准成因:实验期恰好是低峰》。所以实验窗口至少要覆盖一个完整业务周期(含周内波动与月末/大促)。
7. 边界:什么时候"前后对比"就够了
| 场景 | 可以做前后对比 | 前提 |
|---|---|---|
| 修复了一个明确错误 | 是 | 错误类型可定位 |
| 指标是客观可核对的 | 是 | 如解析失败率 |
| 改动幅度很大(>1 分) | 是 | 噪声淹没不了信号 |
| 环境稳定(无版本变更) | 是 | 模型/知识库锁定 |
| 有长期基线 | 是 | 至少 4 周可比数据 |
判断口径一句话:AI 功能的实验,难点不在"跑 A/B",而在"证明两组可比"——所以判据是"能不能列出所有同时变化的变量并逐个锁住"。锁不住,就该退化成"离线评测 + 分层抽检 + 如实表述",而不是硬凑一个显著差异。
8. 自测
- 四个让结论失效的偏差分别是什么?为什么"跨期对比"在 AI 功能上几乎必然带入混杂?
- 为什么分流单位应该选"会话"而不是"用户"或"请求"?
- "总满意度"为什么几乎总是误导?分层之后要注意什么新问题?
- 想证明 +0.2 分的改善大约需要多少样本?这对实验设计意味着什么?
- 什么情况下根本不该做在线 A/B?替代方案是什么?
- "实验通过、上线无效"的典型成因是什么?实验窗口该怎么选?
9. 一句话总结
AI 功能的实验难点不在跑 A/B,而在证明两组可比:输出非确定、指标主观、环境漂移,三者共同要求锁定模型版本与知识库快照、按会话分流、按类型分层看指标。而"总体分涨了"几乎总是难度构成变化的产物——分层后常发现真实贡献只有 0.1。判据:先算样本量(证明 +0.2 要 600–800 组会话),算不出就别做在线实验,退化成"离线评测 + 分层抽检 + 如实写无显著"。