SFT 不是万能药:一份来自 60 条轨迹的微调可预测性账,幻觉率反而涨了 6.3%

把预训练模型的成功套到自己业务上,最顺手的动作就是微调。但我们团队过去三个月的一份记录显示:微调能修好的,远比想象中少;而微调悄悄弄坏的,远比想象中多。

这不是一篇反对微调的文章。微调在我们的客服路由、意图识别上确实拿到了 +14.2% 的成功率和 -31% 的越界率。但同一份账单上还写着一条刺眼的数据:针对事实性问答的 200 题抽样,幻觉率从 5.4% 涨到了 11.7%,增加 6.3 个百分点。更麻烦的是,抽样中超过六成的幻觉回答”看起来更专业了”——引用格式更规整、语气更笃定,人工抽取时漏检率比微调前高了一倍。

这篇文章把这份账摊开:微调到底改了什么、为什么会让它在该说”不知道”的时候选择编造、以及什么场景才值得动微调这个手术刀。

一、先看账单:60 条真实轨迹的两面

评测对象是我们内部一个 7B 模型,任务是企业内部知识问答+工具调用路由。评测集 60 条,来自生产日志脱敏,全部经过两人交叉标注,分成三组指标:

指标 微调前 微调后 变化
任务成功率(主流程端到端跑通) 71.5% 85.7% +14.2 个百分点
越界率(请求权限外工具/泄露无关字段) 18.3% 12.5% -5.8 个百分点(相对下降 31.7%)
事实幻觉率(200 题外挂抽样) 5.4% 11.7% +6.3 个百分点
拒答率(合理拒答,非幻觉) 22.1% 9.4% -12.7 个百分点

四条曲线,两个方向。前两条是微调想要的,后两条是微调不想要的,而且它们来自同一批参数更新——没有”只学好不学坏”这种选项。

为什么成功率涨了,幻觉也跟着涨

原因要回到 SFT 的本质:它是在教模型把某种输出分布变成”默认动作”。我们的微调集里 89% 的样本都有一个完整、漂亮的答案形态:先复述问题、再给出结论、最后附上引用。模型把这套”形态优先”的规则学得很牢。

于是,当检索器给它 3 条相关度不高但看着很正经的文档片段时,它不再倾向停一下说”资料不足”,而是优先完成”一个像答案的东西”。拒答率从 22.1% 掉到 9.4%,这 12.7 个百分点里,一部分确实是该答的现在答上了(好事),另一部分是不该硬答的现在也硬答了(坏事)。幻觉率那 6.3 个点主要就从这里来。

还有一个更细微但影响很大的变化:微调后的回答平均变长了 34%,里面”术语密度”上升。抽样人工核查时,标注员对”微调后产生的错误答案”的漏检率是 41%,对”微调前的错误答案”只有 18%。这不是模型变准了,是错误变得更贵了——更难被发现。

二、什么该微调,什么不该

三个月里我们也试过其他手段作为对照,把结论压缩成一张表:

问题类型 首选方案 理由 我们实测差异
输出格式/结构固定(如 JSON 字段、JSON Schema) 少样本提示 + 结构化约束 不需要动参数,格式遵守率已 90%+ 提示工程 91.2% vs SFT 93.4%,差 2.2 点,不值得动刀
分类/路由(意图识别、工单分级) SFT 明确优于提示 决策边界清晰,标签固定,幻觉泄漏风险低 准确率 78.6% → 91.3%,且越界率降
事实性问答、摘要、需引用来源 优先 RAG + 提示,慎用 SFT 知识是流动的,SFT 会把过时答案焊死在参数里 SFT 组幻觉 +6.3 点,RAG 组无显著上升
领域术语但其实有检索支撑 提示工程(术语表入 system prompt) 知识外置、可更新、可解释 提示工程 87.9% vs SFT 89.1%
长尾、罕见 edge case SFT(少量高质量样本) 提示难以穷举,SFT 泛化更好 长尾集 61.0% → 74.8%

一句话总结:微调擅长”改行为”,不擅长”教知识”。凡是知识会更新、需要引用来源、需要说”我不知道”的场景,都应该把知识放在模型外面。参数化进去的那一刻,你就失去了随时改它的能力,而且你还给它加了一层”自信”。

三、一套能提前拦住幻觉的评测基线

我们复盘后补上的三件事,第二件最关键:

1. 评测集必须分”行为”和”知识”两类,不能混在一个总分里。我们以前只报一个总成功率,微调后总分涨了,问题就被藏在均值里。现在拆开:行为类(格式遵守、路由正确、权限遵守)单独看,知识类(事实正确、引用可核、合理拒答)单独看。两组分开报,任何一组退化都直接红灯。

2. 显式加入”应拒答”样本,这是最大缺口。60 条评测集里,我们原来只有 4 条”资料不足”场景,微调后这 4 条里 3 条都从”拒答”变成了”硬答”。补到 20 条后,这类样本单独成为一个指标。不会拒答的模型,在知识场景里比不用更危险。

3. 幻觉检出不能只靠人眼。这里给一个可复用的做法:构造一个”事实探针集”——50 个问题,答案完全在提供的上下文之外,其中 25 个的正确答案是”资料不足,无法回答”。看模型在”有 3 条高相关上下文”和”有 3 条无关上下文”两种条件下,给出笃定编造的比例。我们的微调后版本在无关上下文条件下编造率 27%,微调前是 9%。这个探针不需要人工标注新数据,跑一次十分钟,上线前必跑。

# 事实探针(简化版)
probes = [
  {"q": "2027 年公司季度营收是多少?",
   "ctx_relevant": [],        # 故意不给上下文
   "ctx_distractor": [...],   # 放 3 条无关但格式正经的文档
   "expect": "abstain"}
]
for p in probes:
    a = model.answer(p["q"], p["ctx_distractor"])
    if "cannot" not in a.lower() and "no information" not in a.lower():
        fabricated += 1   # 该拒答时给了答案 → 记一次编造
print(f"编造率: {fabricated}/{len(probes)}")

四、我们最后定型的一套判断流程

现在团队里做微调决策,走五步:

  1. 先用提示工程打底两周。加少样本、术语表、输出约束,把该拿的分先拿到。两周内提示工程能到 85% 以上的目标,就不动参数。
  2. 失败样本归类。把提示工程搞不定的 case 分成”格式/结构”、”路由决策”、”长尾行为”三类——这三类是 SFT 的主场。如果是”知识不足”,走 RAG,别走 SFT。
  3. 微调集里混入 15–20% 的拒答样本,形态和”资料不足”场景一致。这是抑制幻觉最直接的手段,也是我们现在唯一在用的护栏。
  4. 上线前的事实探针是硬门槛,编造率超过 15% 直接打回。
  5. 灰度期盯两个反向指标:拒答率不能低于基线的 60%,幻觉人工抽检漏检率不能高于 25%。任何一个破线,回滚。

补一句经验:我们第二次微调时把拒答样本混进去,幻觉率从 11.7% 回落到 7.9%,代价是任务成功率掉了 1.8 个点。这次我们用脚投票选了降幻觉——因为在知识场景里,一个自信的错答案比一个拒答贵得多。

总结

微调是一把很好的手术刀,但它切的是”行为”,切不动”知识”。60 条轨迹的账很清楚:你能买到 +14.2% 的成功率和 -31% 的越界率,也可能同时买到 +6.3% 的幻觉率和 -12.7% 的该拒答。工具没有对错,只有匹配不匹配。

可落地的三件事:评测集必须把行为和知识拆开报;必须显式包含”应拒答”样本;上线前跑一次事实探针,别只靠人眼。

互动提问:你的团队现在做微调前,会先跑两周提示工程做基线吗?还是直接上 SFT?

互动提问:如果拒答率掉下去能换来 2 个点的成功率,你会怎么选?评论区聊聊你的取舍。

分享到:

微博
Twitter
LinkedIn

— IMAI 编辑部 | 2026-10-26

发表评论