`train/` 下没有 orpo 和 simpo 目录:它们是怎么被表达的
本文所有事实以
hiyouga/LlamaFactory官方仓库 2026-08-09 的内容为准。我们没有安装、训练或部署过任何模型,也没有读过train/下任何一个训练器的实现代码,文中数字均为仓库目录与源码里写着的值。
这是一个典型的「文档粒度和代码粒度对不上」的场景:README 的训练方法矩阵有 8 行,其中两行明明白白写着 ORPO Training 和 SimPO Training;但你打开 src/llamafactory/train/,只能数出六个阶段目录,没有 orpo/,也没有 simpo/。
第一次遇到的人通常会怀疑三件事:是不是版本太老、是不是我看漏了、是不是这两个方法其实没实现。这篇不猜,只把两侧的可核实事实摆在一起,然后说清楚从中能读出什么。
先把目录实况摆出来
实读 src/llamafactory/train/,当前的内容是这样:
src/llamafactory/train/
pt/ 预训练
sft/ 监督微调
rm/ 奖励建模
ppo/ PPO
dpo/ DPO
kto/ KTO
mca/ Megatron-core adapter 相关
megatron_bridge/ Megatron bridge 相关
hyper_parallel/ 并行相关
callbacks.py fp8_utils.py test_utils.py trainer_utils.py tuner.py
九个子目录里,能对上「训练阶段」这个概念的是前六个:pt、sft、rm、ppo、dpo、kto。后面三个 mca、megatron_bridge、hyper_parallel 是 Megatron 桥接与并行相关的,不是阶段。再往下是五个平铺的 Python 文件。
对面那张训练方法矩阵是 8 行 × 6 列的完整表,我们另有一篇专门讲怎么读它,这里只取跟本篇直接相关的两行——ORPO Training 与 SimPO Training。这两行在矩阵里的形态跟 DPO 那行没有任何区别,六种微调方式(Full-tuning、Freeze-tuning、LoRA、QLoRA、OFT、QOFT)全都打了勾。8 × 6 = 48 格全是 ✅,这张矩阵是满的。
于是差异就很清楚了:矩阵列了 8 个阶段,train/ 下只有 6 个阶段目录,差的正好是 ORPO 和 SimPO 这两个。
「阶段」在这套体系里首先是一个参数
理解这件事的关键,是别把 train/ 的目录名当成阶段的唯一定义处。
在 src/llamafactory/hparams/finetuning_args.py 里,stage 这个参数的默认值是 "sft",finetuning_type 的默认值是 "lora"。也就是说,你跑一次训练时选的「阶段」和「微调方式」,是两个独立的参数取值;目录只是这些取值在代码里的落点之一,不是一一对应的映射表。
一旦接受这个视角,再去参数文件里翻,答案就露出来了。
那组以 pref_ 开头的参数
finetuning_args.py 的偏好对齐部分,有这么几个字段的默认值(逐字取自源码的 field(default=...)):
| 参数 | 默认值 |
|---|---|
pref_beta | 0.1 |
pref_ftx | 0.0 |
pref_bco_weight | 0.0 |
pref_loss | "sigmoid" |
dpo_label_smoothing | 0.0 |
simpo_gamma | 0.5 |
注意最后一行:存在一个以 simpo_ 开头的参数 simpo_gamma(默认 0.5),却不存在一个 simpo/ 目录。 同时,pref_loss 是一个有默认值 "sigmoid" 的字段,名字直译就是「偏好损失」。
把目录结构和参数命名这两侧对照起来,可以如实描述出这样一个结构性结论:ORPO 和 SimPO 是通过偏好损失参数在 DPO 训练器里表达的,而不是独立的训练阶段目录。
这句话的依据边界必须说清楚:它来自「train/ 下没有这两个目录」加「参数表里有 pref_loss 和 simpo_gamma」这两个可核实的事实的交叉对照,不是我们读了 dpo/ 下的实现代码得出的。我们没读。所以再往下的一切——pref_loss 的各个取值分别对应什么损失公式、ORPO 和 SimPO 在数学上差在哪里、哪个效果更好——本文一律不写。
同理,pref_beta 该设成多少、simpo_gamma 的 0.5 要不要动,取决于你的数据和硬件,官方没有给出通用值,我们也不编。你能拿走的确定信息只有一条:这些字段的出厂默认值就是上表里的数字。
一个有意思的对照:KTO 两样都有
kto/ 是有独立目录的,同时参数表里也有 kto_chosen_weight(默认 1.0)和 kto_rejected_weight(默认 1.0)这两个专属字段。
也就是说,在这个仓库里,「有独立阶段目录」和「有专属参数字段」不是互斥的两种表达方式,KTO 是两样都占。ORPO 和 SimPO 落在「只有参数、没有目录」那一侧。
这是仓库当前状态下可以核实到的差异,说到这儿就够了——为什么这么分、是不是有计划调整、会不会以后加目录,我们都没有依据,不做推断,也不用它去评价这个项目的工程质量。
顺着这条线还能看出一件对翻源码很实用的事:这一片参数的前缀是混着来的。pref_beta、pref_ftx、pref_bco_weight、pref_loss 用的是通用的 pref_ 前缀,而 dpo_label_smoothing 挂在 dpo_ 下,kto_chosen_weight 与 kto_rejected_weight 挂在 kto_ 下,simpo_gamma 挂在 simpo_ 下。
这里要提醒一句,别把它当成一条可靠的规律去用:pref_bco_weight 这个字段名里带着 BCO 这个方法名,前缀却是通用的 pref_ 而不是 bco_。所以「一个方法的旋钮一定以自己的名字开头」这个推论是不成立的,仓库里两种挂法都存在。对翻源码的人来说,实际可操作的做法是两边都搜一遍:先按方法名当前缀搜(simpo_、kto_、dpo_),搜不到再按 pref_ 这个通用前缀把这一片字段整体拉出来看。无论如何,这都比按目录名去猜路径靠谱——毕竟目录压根就没有。
落到实际操作:你该去哪儿找
如果你的目的是读代码或翻 issue,上面这个结构差异直接决定了你的搜索路径。
别按目录名找。 在仓库里搜 orpo/ 或 simpo/ 这样的路径是搜不到的,这不是你的环境有问题。
按参数名找。 起点是 src/llamafactory/hparams/finetuning_args.py 里的 pref_* 系列字段,以及 simpo_gamma;实现侧的落点在 src/llamafactory/train/dpo/。
顺手要一起看的还有参考模型与奖励模型那一组。 这几个字段跟偏好对齐是同一片区域,源码默认值分别是:ref_model、ref_model_adapters、ref_model_quantization_bit 都是 None;reward_model、reward_model_adapters、reward_model_quantization_bit 也都是 None;只有 reward_model_type 有一个非空默认值 "lora"。这里只能说到「这六个字段的出厂值就是 None」为止——代码在拿到 None 时具体怎么处理(是完全不加载,还是另有一套回退逻辑),我们没有读过那段实现,不做推断。
以命令行的实际输出为准。 参数与默认值会随版本变动,本文抄的是核对日那一刻的源码。真要动手前,跑一次 llamafactory-cli train -h,以它打印出来的为准。
自己核一遍目录:Windows 和 Linux/macOS 写法不同
这个结论很容易自己验证一遍,就是列一次目录。两边的命令不一样,别混用。
Linux / macOS:
ls src/llamafactory/train/
Windows(cmd):
dir src\llamafactory\train\
Windows(PowerShell):
Get-ChildItem src\llamafactory\train\
以上三条是通用的 shell 命令,不是该项目文档里的内容,写在这里只是为了让你能在自己机器上把目录清单对一遍。
还有一个搜资料时的小坑值得一并提醒:这个仓库内部的项目名新旧写法并存——src/llamafactory/launcher.py 的欢迎语里写的项目主页仍是带连字符的旧名 https://github.com/hiyouga/LLaMA-Factory,README 正文里 LLaMA-Factory 和 LlamaFactory 两种写法也都出现过。所以你去搜 issue 或历史讨论时,两种拼法都试一遍,别因为拼法不同就以为搜到的是另一个项目。至于改名的时间、原因、有没有重定向,我们没有核实过,不做推断。
这个现象能读出什么、不能读出什么
能读出的:文档层的枚举粒度(8 个阶段名)和代码层的目录粒度(6 个阶段目录)不一致,差额部分由参数字段承载;simpo_gamma 这个字段名就是这条线索的实物证据。
不能读出的:那张 8 × 6 的满格矩阵,说明的是 README 声明了这些组合都可用,不能由此推断任意组合都同样好用、同样稳定、或者都被同等测试过。同样地,ORPO 和 SimPO 没有独立目录,也不能反过来推断它们「实现得更简陋」或者「是顺手加的」——目录结构不承载这类信息,我们也没有任何依据。
说白了,这篇能给你的就是一张地图:知道名字在文档的哪一行、参数在源码的哪个文件、代码在哪个目录,剩下的判断留给你自己去读那份实现。
本文依据 LlamaFactory 官方仓库(github.com/hiyouga/LlamaFactory)的 README、data/README.md、examples/ 下的配置与 src/llamafactory/hparams/ 的参数定义整理,核对日 2026-08-09。本文内容为仓库源码与文档口径,我们没有安装、训练或部署过任何模型,文中显存数字均为官方标注的估算值(README 原文标 * estimated)而非实测占用。参数与默认值随版本变动,请以 llamafactory-cli train -h 的实际输出为准。