DPO 偏好数据应该采用什么格式?
简化版
DPO 的基本样本是同一上下文 prompt 下的一对回答:chosen 明确优于 rejected。两者必须共享完全相同的系统消息、历史和用户输入,只比较助手回答;还应保存偏好维度、标注者、置信度、策略版本和来源。数据质量关键不在 JSON 长相,而在比较是否有效:差异应对应目标行为,避免长度、格式和模板泄漏成为捷径。
详细版
聊天模型可存成三段消息数组或预渲染文本,但训练前必须使用与部署一致的 chat template,并准确标出只计算回答 token 的 mask。推荐保留原始消息结构,在数据加载阶段统一渲染。
{"prompt":[{"role":"user","content":"..."}],
"chosen":[{"role":"assistant","content":"..."}],
"rejected":[{"role":"assistant","content":"..."}],
"criterion":"factuality","confidence":0.9,"policy_version":"v3"}
校验包括 chosen≠rejected、上下文一致、回答非空、长度分布、重复与泄漏、偏好方向和敏感信息。工具调用数据还要保留结构化 call/result 边界,不能把工具结果误算为模型回答。训练集、验证集按 prompt 或来源簇拆分,避免同题改写跨集合。
完整版教学
一、DPO 学的是同一条件下的相对偏好
DPO 比较的是在同一个 x 下,回答 y_w 比 y_l 更受偏好。如果 chosen 和 rejected 使用了不同历史、系统提示或工具结果,差异不能归因到回答质量,训练目标就被污染。
因此数据主键不是单独两段文本,而是“共享上下文 + 成对候选 + 偏好元数据”。上下文必须字节级或结构级一致。
记忆钩子:DPO 一对样本只能有一个比较变量——回答;上下文变了,就不再是公平比较。
二、保留消息结构而非过早拼字符串
消息数组能区分 system、user、assistant 和 tool,便于换模板、审计与 mask。若采集阶段就拼成字符串,后续很难发现角色边界错误或模板重复。
| 字段 | 必需信息 | 用途 |
|---|---|---|
| prompt | 系统、历史、用户输入 | 条件 x |
| chosen | 优选回答消息 | 正样本 |
| rejected | 劣选回答消息 | 负样本 |
| criterion | 安全、事实、风格等 | 切片与诊断 |
| provenance | 来源与版本 | 血缘和去重 |
训练加载器再用目标模型 tokenizer 和 chat template 渲染,保证离线与部署一致。
三、loss mask 必须只覆盖应该学习的 token
通常 prompt token 不参与 chosen/rejected 的回答损失,否则模型会被要求“偏好”完全相同的上下文,既浪费计算又可能掩盖边界错误。工具消息也要按训练目标决定是否 mask。
[system][user][assistant-prefix] -> mask 0
[chosen assistant answer] -> mask 1
若模板在 assistant 前插入特殊 token,要确认 chosen 与 rejected 的起始位置一致。一个 off-by-one 错误可能让模型学习角色标记而非内容。
四、偏好对要有信息量
chosen 与 rejected 完全相同或只差空格,没有学习信号;差异过大又容易产生长度、格式捷径。理想困难对在大部分内容相似,只在目标维度上有清晰差异。
例如训练事实性时,让 chosen 引用正确证据、rejected 使用错误数字;不要让 chosen 同时更长、更礼貌、有列表,而 rejected 粗短且含事实错,否则无法知道模型学了什么。
可以记录偏好强度或是否接近平局,低置信样本降权、复核或剔除。
五、长度偏差是常见泄漏
若 90% chosen 都比 rejected 长,模型可能学到“越长越好”。反之,安全数据中 chosen 都是短拒答,会把简短与安全绑定。
假设 chosen 平均 420 token,rejected 平均 180 token,长度差已足以预测标签,必须做分桶统计。可通过配对生成、长度匹配、反例和损失校正减少偏差。
还要检查固定免责声明、特定标点或模型签名是否泄漏标签。
六、多轮与工具调用的边界
多轮样本要明确偏好只针对最后一轮,还是整个轨迹。如果前序 assistant 消息不同,就应视为轨迹偏好而非普通单轮 DPO。
工具调用候选包含工具名和参数,工具结果由环境提供,不应让模型学习伪造。可比较“正确 call”与“错误 call”,共享同一工具定义和状态;执行结果另存并做权限脱敏。
高风险动作的 chosen 也不能仅因为标注者喜欢就绕过系统权限,数据生成需先通过策略校验。
七、数据清洗和拆分
做 Schema 校验、角色交替、空值、截断、Unicode、PII、重复和标签冲突检查。同一 prompt 出现相反偏好时,先确认是否政策版本不同或标注分歧。
训练验证按 prompt 语义簇、来源文档或用户会话拆分。若同一个问题的轻微改写分别进入训练和验证,会高估泛化。
测试集保留时间外和私有挑战样本,避免训练管线反复使用造成污染。
八、版本与审计决定可复现性
每条样本记录生成模型、采样参数、标注指南、标注者类型、政策版本和处理脚本版本。数据修订不覆盖旧记录,而是产生新版本。
训练报告按偏好维度、语言、长度与来源统计数量和胜率。模型回归时可以追溯是否某批数据过度代表特定风格。
数据删除请求也要能沿血缘找到派生样本与训练版本,不能只删原始表一行。
九、常见误区与追问
- 误区:只要有 prompt/chosen/rejected 三列就够。 还需角色、模板、mask、来源和偏好维度。
- 误区:chosen 越明显比 rejected 好越有价值。 太容易的对可能只教会长度或格式捷径。
- 误区:多轮对话直接拼字符串最方便。 容易破坏角色边界与训练 mask。
- 误区:验证集随机按行切分即可。 同 prompt 改写会泄漏,需按语义簇或来源拆分。
- 误区:工具结果也算模型回答一起训练。 环境事实与模型生成必须区分。
- 追问:平局样本怎么处理? 可剔除、降权或使用支持 tie 的目标,不能随机指定赢家。
- 追问:如何发现长度偏差? 比较 chosen/rejected 长度分布,并训练简单长度基线预测标签。
- 追问:chat template 为什么重要? 它决定实际 token 和角色边界,训练与部署不一致会产生分布偏移。
十、加强记忆
DPO 数据记住“同上下文、成对答、只训回答、记录偏好、排查捷径”:prompt 必须完全共享,chosen/rejected 在目标维度形成有信息量的对;保留消息结构,用部署一致模板渲染并正确 mask;记录标准、置信、政策版本与数据血缘。交付前重点检查长度、格式、固定模板、重复和标签冲突,再按 prompt 语义簇或来源拆分训练验证集。这样模型学到的才是目标行为差异,而不是“更长、有列表、排在某一侧”之类采集痕迹,验证结果也才反映真正泛化。