首页 实战 N° F5

我调了一周 prompt 把团队用崩了——过拟合到 5 个测试 case,prod 全军覆没

Trainer 模式的承诺是「调好一次、复用一年」。我调了一周,A/B 测试 5 个 case 全过——然后 prod 80% 的请求都翻车。我调的是测试,不是模型。

一句话总结:Trainer 的核心是「eval set 必须代表 prod 的真实分布」。我用 5 个自己写的测试 case 调 prompt,过拟合到这 5 个 case 全过——但 prod 跟我那 5 个 case 完全不是同一个分布。

任务源头

2026 年 2 月,我加入一家 AI 公司做 prompt 工程师,负责公司主产品的客服 prompt——一个 GPT-4 驱动的客服机器人,回答用户的售前售后问题。

我入职时 prompt 是这样的:

你是 {公司} 的客服助手。
- 回答用户问题
- 不能承诺退款
- 不能推荐竞品
- 不能谈论价格

当时效果:40% 用户问题答得对,60% 会答非所问或编内容。

我的 KPI 是 3 个月内把”答对率”提到 70%。我打算用 Trainer 模式——改 system prompt + 加 few-shot + A/B 测试

时间线:7 天调优 + 上线翻车

Day 1-2:收集测试 case。

我从客服历史对话里挑了 5 个 case——都是我觉得”典型的”用户问题:

  1. “你们支持哪些支付方式?”
  2. “我的订单什么时候发货?”
  3. “可以开发票吗?”
  4. “这个产品适合初学者吗?”
  5. “能不能便宜点?”

这是我犯的第一个错:我挑 case 时已经偏向了我能答的 case**。

Day 3:写 v2 prompt + 5 个 case 全过。

我在原 prompt 上加了:

你是 {公司} 的客服助手。
- 回答用户问题,**语气友好但专业**
- 不能承诺退款
- 不能推荐竞品
- 不能谈论价格
- **回复长度控制在 50-150 字**
- **结尾必须问"还有什么可以帮您"**
- **不能使用"我们很抱歉"超过 1 次**
- **不能使用 emoji**

跑 5 个 case:

[case 1] "我们支持微信、支付宝、信用卡、银联。" (87字, 结尾"还有什么可以帮您", 无 emoji, 无抱歉)
[case 2] "您的订单将在 24 小时内发货。" (52字, ...)
[case 3] "可以开发票。下单时备注即可。" (45字, ...)
[case 4] "适合。我们的产品有详细教程。" (50字, ...)
[case 5] "抱歉,价格由系统决定,不便议价。" (42字, ...)

5/5 全过。 我以为这就搞定了。

Day 4:内部 A/B 测试。

我把 v2 prompt 给客服组长试用 1 天。反馈:“比 v1 好多了。”

Day 5:上线到 10% 流量。

上线后 24 小时,用户问题答对率从 40% 掉到 32%——比 v1 还差。

我慌了。看日志,发现 prod 的真实用户问题跟我那 5 个 case 完全不是一回事

  • 60% 用户问题带情绪:“你们骗人""垃圾产品""我投诉 12315”
  • 20% 用户问题很具体:“iPhone 15 的充电器接口是 USB-C 吗”(我们的产品跟 iPhone 没关系)
  • 10% 用户问题要求超出客服范围:“能帮我写代码吗""能帮我做 plan 吗”
  • 5% 用户问题是真正的售后:“我的快递丢了”
  • 5% 是其他

而我那 5 个 case,全是”礼貌的标准问题”——连 5% 都不到。

我调了 5 个 case,让 prompt 在那 5 个 case 上变好,但让 prompt 在剩下 95% 的 case 上变差——因为我加了”严格控制”约束(字数、结尾、不能抱歉、不能 emoji),这些约束在情绪化场景里完全失效

  • 用户骂人 → prompt 让 agent 用”友好专业”语气 → agent 答”感谢您的反馈” → 用户更怒
  • 用户要求写代码 → prompt 让 agent “回答问题” → agent 答”抱歉我无法帮您” → 用户:“那你有什么用”
  • 用户快递丢 → prompt 让 agent 不能承诺退款 → agent 完全不知道怎么处理 → 转人工率 80%

Day 6:紧急回滚。

把 v2 prompt 撤回 v1。当晚数据回到 38% 答对率(接近基线)。

Day 7-10:重新收集 case + 重写。

我这次随机抽样 200 个真实用户对话作为测试集,每个 case 标”答对 / 答错”。

按这个新测试集重写 prompt 3 轮,最后到 65% 答对率——3 周后到 71%,达到 KPI

但 Day 3 那个 5/5 的 v2 prompt 教训,我一直记着。

决策点反推

错误 1:测试 case 是我”挑的”,不是”抽的”。

我挑 case 的过程已经带了我的偏见——我挑”我能答的 case”。这种 case 集合不代表真实用户

正确做法

  • 随机抽 200 个真实对话(不挑)
  • 覆盖所有场景:礼貌 / 情绪化 / 超出范围 / 真实售后 / 边缘 case
  • 按真实分布权重采样(不是平均采样)

错误 2:5 个 case 太少,无法衡量 overfit。

5 个 case 的 prompt 优化几乎肯定过拟合——5 个 case 是”金鱼缸”,prompt 可以完美适配,但 prod 是”大海”。

经验法则

  • < 30 个 case:纯过拟合风险
  • 30-100 个 case:勉强
  • 100+ case + 真实分布:可信赖

错误 3:我的 prompt 加了”约束”但没加”决策树”。

我加的全是形式约束(字数、结尾、不能抱歉、不能 emoji)。形式约束会让 agent 在异常情况下僵掉——它不知道什么时候该”破例”。

更好的做法

  • 形式约束少一点(不要锁死 agent 的灵活度)
  • 决策树:遇到情绪化用户怎么答、遇到超出范围怎么答、遇到边缘 case 怎么答
  • 让 agent 在决策点多个选项,根据场景选

token 账单

项目数值
Day 1-5 调优轮数23 轮
Claude 调用次数156 次(含 5 case × 4 轮 × 7 版本)
Input tokens0.8 M
Output tokens0.2 M
调优成本$24
上线翻车期间客户投诉+47 条
紧急回滚 + 重写成本+$340(含重新 A/B + 重新上线)
KPI 延期3 周

$24 调优成本听起来不高,但翻车带来的客服投诉 + 客户流失 + 团队信任损失,是 $340 也补不回来的。

给也想用 Trainer 的朋友的 3 条避坑

避坑 1:测试集必须”随机抽样”而不是”挑 case”。

挑 case = 你的偏见 = 过拟合的种子。你写的 case 永远会偏向你能答的——这不是故意的,是人的本能。

做法:从 prod 日志随机抽 200 条对话,按真实场景比例采样。情绪化的、超出范围的、边缘的,全部要有

避坑 2:每版 prompt 必须在 hold-out 测试集上验证。

不要在 train set 上验证——那是过拟合的证据。

做法:把测试集分 70% train + 30% hold-out。**只调 train,**最后在 hold-out 上验证。如果 hold-out 表现差,说明过拟合。

避坑 3:少加形式约束,多加决策树。

形式约束(字数、句式、不能用 X)会让 agent 僵化——它无法处理约束之外的场景。

决策树(“如果用户情绪化 → 先共情再解决”)让 agent 有判断能力——它可以根据场景选不同的应对。

反思

Trainer 模式的核心是”评估驱动”——你调什么取决于你怎么评估。

如果你的评估集合是错的(太小、太挑、太干净),你调出来的 prompt 就只会在错的集合上变好

我这次的失败本质是 eval set 没代表 prod——5 个我自己挑的 case 完全不代表真实用户。

Trainer 的元教训

不要调你测的东西。测你调的东西。

我之前反过来——测的是我挑的 5 个 case,调的也是这 5 个 case,结果在 prod 完全失效

现在我团队的新规矩是:任何 prompt 改动必须有 200+ 真实对话测试集 + hold-out 验证 + 3 周灰度

失败成本:$24 + 47 条投诉 + 3 周延期 + 团队信任 -1。 真正贵的是「我用 5 个 case 调 prompt,然后以为这能代表 prod」。