跳到主要内容

你在调试时无意中构建的微调数据集

· 阅读需 10 分钟
Tian Pan
Software Engineer

预发布环境界面(staging UI)里的点踩(thumbs-down)按钮原本只有一个作用:告诉值班工程师哪个回复看起来很糟,以便他们去排查。六个月后,模型团队的某个人把“所有带有修正建议的生产反馈”拉取到一个 Parquet 文件中,并针对它运行了一个微调(SFT)任务。评估集在三个指标上有所提升,却在五个指标上悄悄退步。没人能解释原因,直到有人翻看标签并发现修正列中有一行写着:“这没问题,但我讨厌它的措辞方式。”模型习得了这种观点。然后,它又习得了另外四万个观点。

这种失效模式源于调试界面和标注界面是同一个界面。工程师点击“点踩”可能是因为某个环节坏了,或者看起来很奇怪,或者他们正准备提交一个工单,或者排版让他们不爽,甚至只是为了测试按钮是否好用。从那次点击中流出的信号混合了“这个输出是错误的”、“这个输出是对的但很难看”、“我不喜欢这个”以及“我当时很无聊”。作为单一标签,它什么也证明不了。以此进行训练,它教会模型的是所有这些情绪的并集。

界面即契约

产品工程中有一个不成文的约定:按钮的功能应与其标签一致。点踩意味着用户不满意,修正意味着“这才是应该返回的内容”。工程师比任何人都更容易内化这种约定,因为按钮就是他们写的。因此,当工程师在内部工具上点击点踩时,这一点击代表了工程师那一刻的任何想法——调试意图、审美反应、“咦,真怪”——而不是模型团队后来解读出的规范产品含义。

模型团队将点踩视为高精度信号。他们必须这么做:它有标签,有修正文本,且来自了解产品的人。他们构建了一个流水线,通过选择修正内容非空且长于五个 token 的数据行来过滤“高置信度负样本”,将修正内容的长度视为认真程度的代理指标。该流水线成功过滤掉了随手点击。但它无法过滤掉那些写下长篇、仔细修正,解释回复在技术上正确但使用了两次“leverage”一词的工程师。

界面是一个调试输入,流水线却将其视为精选数据集。中间没有任何环节捕获到这种类型不匹配,因为两边的列名是一致的。

工业规模的个人品味

一个有用的练习:选取一千行内部“点踩 + 修正”数据并手动分类。总是会出现的类别:事实错误、实体幻觉、遗漏指令、格式损坏、工具调用失败。这些是模型团队想要的类别。而与它们并列出现的类别还有:语气不对、太罗嗦、太简短、使用了我不喜欢的词组、回复没问题但我想要不同的表述框架、回复没问题但我只是在测试按钮。

这两类数据在生产中界限模糊,因为同一个人在同一会话中往往会产生这两种标签。处理线上事故的工程师处于“错误输出”类别中。十分钟后,同一个工程师刷新页面并随处点点以确认修复,这时他处于“个人品味”类别中。他们的会话 ID 无法标记这种区别,时间戳也做不到。

当你针对混合数据集进行训练时,模型学到的是两者的加权平均值。有时这种平均值是无害的:模型变得稍微不那么罗嗦,因为罗嗦的回复得到了更多点踩。有时它是有害的:模型会偏向某位工程师偏好的句式结构,因为那位工程师点击最频繁。偏好模型研究对后一种模式有一个称呼——特异性偏差(idiosyncratic bias)——共识是,偏好数据中即使是微小的偏差,在经过足够的梯度步骤后也会被放大为系统性偏移。六个月的内部吐槽,经过微调后,看起来就像是那种偏差。

你并未签署授权的数据集

在同一条流水线中还隐藏着另一个更隐蔽的问题。当预发布环境的流量包含真实的客户数据时——可能是因为有人为了调试回归问题而重放了生产环境的追踪数据,或者是团队的“预发布”环境其实只是翻转了一个查询参数的生产环境,或者是客户成功工程师将真实的工单粘贴进聊天框以确认修复——工程师在该界面输入的修正内容就包含了客户的文本。有时是逐字记录,有时是转述,有时还附带工程师自己的注释(“客户说了 X,这是错的,因为政策是 Y”)。

这些数据现在成了训练数据。没有人决定将它作为训练数据。这个决策之所以发生,是因为仓库中存在该列,而 SFT 脚本的输入匹配规则(input glob)捕获了它。没有授权流程,没有数据处理协议(DPA)条款,也没有针对此类用途的特定留存政策,因为该界面是被作为调试工具配置的。合规部门审查数据采集点,但默认情况下,合规部门不会审查名为 feedback_v2_with_corrections 的数据库表,因为没人告诉合规部门它已成为微调来源。

加载中…
References:Let's stay in touch and Follow me for more thoughts and updates