我在把一批会议转写做成 SFT 数据,目标是让一个小模型照固定模板写会议纪要。
管线搭完、过滤规则也写好之后,我顺手验了一件本该早点验的事:同一份纪要,同一个裁判模型,同样的参数,连判两次。第一次判出零处事实错误,第二次判出十几处。
下面是整个过程里值得记下来的几件事。
人工纪要不能当标准答案
一开始我想的是拿”转写 + 人工纪要”直接配对。不行。
人工纪要是某个人开完会凭印象写的。它会漏掉决定,会把两件事记串,还会包含转写里根本没有的内容——因为那部分是会前私下聊的。拿它当 gold,模型学到的是另一个人的记忆偏差。
要的是另一种配对:转写,配一份每句话都能在转写里指出处的纪要。
基座模型的问题不在格式,在填空
基座模型写出来的第一版,格式基本能看。逐条对转写才发现问题:转写没说谁主持,它填了个人名;待办没提截止时间,它写”本周内”;两个人讨论完没有结论的事,它写成”会议决定”。
这些都能通过格式校验。它们是幻觉,而且读起来跟上下文完全自洽。
三个角色,各干一件事
- 学生:待微调的基座模型,产出初稿。
- 裁判:一个大模型,只拿到转写原文和一份不署名的候选纪要。它看不到人工纪要。它把纪要拆成一条条陈述逐条判:有出处、部分有、还是没有。再反向查一遍转写里有什么重要的东西纪要漏了。
- 教师:另一个大模型,拿转写、初稿和裁判结论去改写。
flowchart TD
A["会议转写"] --> B["学生模型
写出初稿"]
A --> C
B --> C["裁判
逐条核对证据"]
C --> D["教师
输出结构化字段"]
A --> D
D --> E["渲染器
确定性排版"]
E --> F["裁判复核
三票独立判定"]
F --> G{"三道门槛"}
G -->|"格式通过
零事实错误
保留率达标"| H["进入训练集"]
G -->|"任意一项不过"| I["拒绝
记录原因"]
教师不写 Markdown
这是整套设计里最有用的一条:教师只输出字段——主题是什么、这条待办归谁、这栏是”已知”还是”未提及”,每个字段附一个指向转写具体位置的证据指针。排版由代码做。
模型说”主持人未提及”,渲染器在那格填规定的占位符;模型说”没有待办”,渲染器生成一张只有一行”无”的表。
格式合规率因此是 100%。不是模型变听话了,是格式根本没经过模型。
附带的好处:同一套字段能渲染成任何格式。模板改版就改渲染器,已经攒的数据不用重跑。
切数据集要在生成任何目标之前
会议数据是成系列的:同一个周会每周开,人和项目都不变,上周的待办这周接着跟。
按单场会随机切分,训练集和测试集里会出现同一系列的不同期。模型在测试集上的好成绩有一部分来自它见过上周那场,而且看指标看不出来。
所以按系列整组切,并且在生成任何训练目标之前冻结。测试集身份定下来、哈希记下来之后,管线怎么改都漏不进去。
配套一条规矩:被选作评测基准的样本,它的所有衍生物都不进训练集——裁判对它的判定、教师对它的改写、渲染出的纪要,全部标成仅供评估。这个标记只能往严了改。
保留率:教师改太多也是问题
过滤卡三道:格式、零事实错误、保留率。第三道是我一开始没当回事的。
保留率量的是学生初稿里本来就没错的表述,教师留下了多少。
教师改得越彻底并不越好。微调是在基座已有能力上做局部修正,不是换掉它的语言风格。教师要是把每句话都按自己的措辞重写,数据教的就不止”别编事实”,还捎带”改成我这个腔调”——后半截白占训练预算,也稀释了真正想教的信号:有证据的照写,没证据的标未知。
有一条长会议事实判定全过、格式也没问题,保留率只有三成,教师基本是推倒重写。这条被拒了,不是因为它错,是因为它教的东西超出了范围。
裁判本身不可复现
温度零、贪心解码,我以为两次调用会给一样的结果。实测不是:
- 第一次零处事实错误,第二次十几处
- 也有反过来的,第一次十几处,第二次两三处
原因不止一个。服务端批处理让同样的请求落进不同批次,数值就不一致;前缀缓存改变前向计算的分块方式;后面要是挂着多副本,两次请求可能根本不是同一个进程处理的。更根本的是”逐条核对一篇长文”本来就在模型能力边缘,输出又长,前面差一点后面就放大了。
所以用单次判定卡”事实错误必须为零”,是在抽签。我之前那批”通过”的样本里确实有靠运气过的:一次判定说零错误,复判全是窟窿。
可复现和可信不是一回事
想让管线重跑出一样的结果,有两条路,代价差很多。
真确定性:让推理服务保证同样请求给同样输出。需要框架支持批次无关算子,关掉前缀缓存,而且只能用特定的注意力实现。我这两个模型里,教师能做到逐字节一致,裁判做不到——它依赖的稀疏注意力实现不在框架的确定性支持列表里。
回放:每次模型调用按请求内容做哈希,连回复一起存下来,重跑直接放缓存。
回放便宜得多,也不依赖服务端。但它保的是”这次用的是上次的结论”,不是”这个结论靠谱”。调阈值时区别很明显:改完过滤规则重跑,回放零成本给你新结果;但要问结论稳不稳,只能真的再判一次。
两个都要。回放管可审计,多票管可信。
记下来的几条
一个天天在用、从来没被评估过的判定模型,就是管线里的暗物质。最省事的验法是让它判两次,对一下。
模型出语义,代码出格式。有固定输出结构的任务都适用。
过滤时把”编了转写里没有的东西”和”转写里有但没写”分开算。前者是幻觉必须毙,后者是不完整,混成一道门槛会误杀一大片能用的数据。
这套管线最后留下来的数据比我预期的少很多。但有用的产出不是数据,是知道了哪几个环节不可靠。管线刚跑通那天我盯着通过率,第一反应是调阈值——那时候我还在拿一个有噪声的测量当真值。