偏好数据集:`chosen` / `rejected` 与那个必须显式打开的 `ranking`
本文所有事实以
hiyouga/LlamaFactory官方仓库 2026-08-09 的内容为准,来源是data/README.md与src/llamafactory/hparams/下的参数定义。我们没有安装、训练或部署过任何模型。
做偏好数据的人最容易漏的不是 chosen 和 rejected 这两列——列名摆在文档示例里,很难看不见。真正容易漏的是 ranking 这个顶层字段:data/README.md 的字段规格里写着它的默认值是 False,也就是说,你把数据文件准备得再标准,只要 dataset description 里没有显式写上 "ranking": true,这条数据集在配置层面就仍然被声明为”不是偏好数据集”。
这篇只讲数据这一侧:偏好数据长什么样、ranking 待在哪一层、alpaca 和 sharegpt 两条路各自怎么写、写漏了可以怎么比对着查。至于 pref_beta、pref_loss 这些训练侧的偏好对齐参数,我们另有一篇专门讲,这里一律不展开。
先确认这类数据是给哪几步用的
data/README.md 在偏好数据集那一节写得很明确:偏好数据集用于奖励建模、DPO 训练、ORPO 与 SimPO 训练。要求也只有一句——chosen 列放更好的响应,rejected 列放更差的响应。
这个列表值得留意的地方在于,它把四件事放进了同一种数据形态。也就是说,从数据准备的角度看,你不需要为奖励建模和 DPO 各造一份文件;差异被推到了训练侧的参数里。这一点在 src/llamafactory/hparams/finetuning_args.py 里能找到旁证:那里有 pref_loss(默认 "sigmoid")、simpo_gamma(默认 0.5)这类参数,而不是四个各自独立的数据格式。至于这些参数具体怎么组合、各自意味着什么算法细节,我们没有读过实现,不推断,也不给”该设多少”的建议。
顺带说一句仓库里的写法差异:data/README.md 正文里出现的项目名是带连字符的旧写法 LLaMA-Factory,而仓库当前路径是 hiyouga/LlamaFactory、PyPI 包名是 llamafactory。新旧写法在仓库内并存,如实说到这儿就够了,改名的时间和原因我们没有核实过。
Alpaca 格式的偏好数据:四个键
data/README.md 给的示例结构是这样的:
[
{
"instruction": "user instruction (required)",
"input": "user input (optional)",
"chosen": "chosen answer (required)",
"rejected": "rejected answer (required)"
}
]
和监督微调数据集比,差别是把 output 换成了 chosen 与 rejected 一对。instruction 与 input 的关系没有变——文档在监督微调那一节写明用户提示词是 instruction\ninput 的拼接结果,input 本身是可选的。
对应的 dataset description,原文是这一段:
"dataset_name": {
"file_name": "data.json",
"ranking": true,
"columns": {
"prompt": "instruction",
"query": "input",
"chosen": "chosen",
"rejected": "rejected"
}
}
请注意这段 JSON 的形状:ranking 和 file_name 平级,是 dataset description 的顶层键;chosen 与 rejected 则在 columns 这个子字典里。两处分属不同层级,写配置时一起漏掉的概率并不低。
为什么这四个位置都得手写
把字段规格里的默认值排一遍,就能看清哪些能省、哪些不能省。
| 字段 | 所在层级 | 默认值 |
|---|---|---|
ranking | dataset description 顶层 | False |
formatting | dataset description 顶层 | alpaca |
columns.prompt | columns 子字典 | instruction |
columns.query | columns 子字典 | input |
columns.chosen | columns 子字典 | None |
columns.rejected | columns 子字典 | None |
这张表只取了与本篇直接相关的六行,完整的十一个顶层键和两组子字典另有一篇专门讲。
读法是这样的:prompt 默认就是 instruction、query 默认就是 input,所以上面那段官方 description 里的这两行其实是把默认值又写了一遍,属于写出来更清楚、不写也对得上的类型。但 chosen 和 rejected 不一样——它们在字段规格里的默认值是 None,不是”默认与字段名同名”。这意味着即使你的数据文件里的列名就叫 chosen 和 rejected,也仍然要在 columns 里显式映射一次,靠默认值是接不上的。
ranking 同理,而且更硬:默认 False,偏好数据集要显式设 true。它不是从 columns 里出现了 chosen / rejected 就能自动推出来的东西——至少在字段规格的口径上,这是两处独立的声明。
formatting 默认 alpaca,取值只能从 {alpaca, sharegpt} 里选。所以走 alpaca 路线时它可以不写,走 sharegpt 路线时必须写。
ShareGPT 那一侧:同样两列,多一个 formatting
data/README.md 的 sharegpt 小节里,偏好数据集给的示例数据集是 dpo_en_demo.json,规则和 alpaca 侧一致:chosen 列放更好的消息、rejected 列放更差的消息。差别在于对话本体走 conversations 那一套多角色结构,并且 dataset description 里得把 formatting 显式写成 sharegpt。
sharegpt 格式还有一条位置约束——human 与 observation 必须在奇数位、gpt 与 function 必须在偶数位——那条规则对偏好数据同样是要遵守的前提,但它有专门一篇在讲,这里不展开。
顺带提一个能省事的对照:两种格式的小节几乎一一对应,各有 7 个小节;差别是 sharegpt 多了 OpenAI Format 一节,且 sharegpt 的预训练小节原文只有一句 “Not yet supported, please use the alpaca format.”。也就是说,偏好数据在两种格式下都有,预训练数据只有 alpaca 一条路。
配置写漏了怎么查
这类问题的麻烦之处在于,漏写 ranking 的 JSON 仍然是合法 JSON,格式检查器不会拦你。所以只能靠比对。下面这套动作全都停留在配置层面——我们没有跑过训练,也不去猜运行时会报什么错。
第一步,确认这条数据集在不在册。 data/README.md 开头写得很清楚:使用自定义数据集时,必须在 dataset_info.json 里加一段 dataset description,并在训练前用 dataset: dataset_name 指定它。所以先确认你训练配置里 dataset 的那个名字,与 dataset_info.json 里的键名一字不差。
第二步,确认这个文件被找得到。 dataset_info.json 必须放在 dataset_dir 目录下,dataset_dir 的默认值是 ./data(hparams/data_args.py 里 dataset_dir 默认 "data")。允许的文件类型是 json、jsonl、csv、parquet、arrow 五种。
第三步,逐项比对四个位置:顶层有没有 ranking: true;columns 里有没有 chosen;有没有 rejected;这两个键的值是不是你文件里真实的列名。走 sharegpt 时再加一项:formatting 是不是写成了 sharegpt。
第四步,验证。 验证手段也是比对——把你的 description 和 data/README.md 偏好数据集那一节的官方示例逐行对齐;仓库里 data/dataset_info.json 共有 104 个数据集条目,data/README.md 在 sharegpt 偏好数据集那一节点名的示例数据集是 dpo_en_demo.json,官方示例本身就是最省事的写法参照。
第五步,什么情况说明不是这个原因。 如果你的 description 四个位置都对、数据文件列名也对得上,那问题多半不在 ranking 这一层,而在别的层:比如 template 没设(data_args.py 里 template 默认就是 None)、stage 不对(finetuning_args.py 里 stage 默认是 "sft")、又或者你根本没注意到 cutoff_len 这个长度相关的值默认是 2048。这几处各有各的篇幅,ranking 这条线到这儿就该收了——继续在数据声明里翻找是浪费时间。
数据放在别处时的两点差异
如果偏好数据不在本地,字段规格里另有几个来源字段:hf_hub_url 指向 Hugging Face 上的数据集仓库、ms_hub_url 指向 ModelScope 上的、script_url 指向加载脚本目录、cloud_file_name 指向 s3/gcs 上的文件名。这四个和 file_name 之间有一条明确的覆盖链——前面的指定了就忽略后面的,都没指定时 file_name 是必填的。这条链另有一篇专门讲,这里只提醒一句:换成 hub 来源之后,ranking 和 columns 该写还是要写,它们与数据放在哪里无关。
用 ModelScope 那条路时,仓库文档给的开关是环境变量 USE_MODELSCOPE_HUB=1,两个平台的写法不一样,别混用:
# Linux / macOS
export USE_MODELSCOPE_HUB=1
:: Windows
set USE_MODELSCOPE_HUB=1
Windows 上还有一点值得提前避开:dataset_dir 如果要填绝对路径,反斜杠在 JSON 字符串里是转义符,得写成双反斜杠或者干脆用正斜杠。这属于通用的 JSON 与路径常识,不是该项目文档里的内容,但它踩起来和配置写错一样费时间。默认值 ./data 是相对路径,两个平台都不用改。
最后交代一句边界
到这里,数据这一侧的活就干完了:两列、一个顶层布尔、一个可选的 formatting。再往后是训练侧的事——用哪种偏好损失、pref_beta 取多少、要不要走 SimPO,那是另一组参数的地盘。这些值该设成多少,取决于你的数据和硬件,官方没有给通用值,我们也不替你猜。
本文依据 LlamaFactory 官方仓库(github.com/hiyouga/LlamaFactory)的 README、data/README.md、examples/ 下的配置与 src/llamafactory/hparams/ 的参数定义整理,核对日 2026-08-09。本文内容为仓库源码与文档口径,我们没有安装、训练或部署过任何模型,文中显存数字均为官方标注的估算值(README 原文标 * estimated)而非实测占用。参数与默认值随版本变动,请以 llamafactory-cli train -h 的实际输出为准。