LLaMA Factory:对齐训练、分布式与进阶能力

LLaMA Factory:对齐训练、分布式与进阶能力

本系列第 11/17 章,也是 LLaMA Factory 四章中的收束章。基线仍是 0.9.6.dev0。前三章已经能在单机上跑通 SFT、看懂推理出口。本章把三件容易缠在一起的事情拆开:对齐算法属于哪个 stage、多卡到底打开了哪一层、v1 与那些环境变量开关各自住在哪里。读完应能解释为什么 ORPO 不能写成独立阶段,以及为什么只写 ray_num_workers 并不会启动 Ray。

1. 对齐:四个入口,六种损失

训练 stage 的合法值仍然只有 pt|sft|rm|ppo|dpo|kto。与对齐直接相关的是后四个。它们共用第 9 章那条骨架——tokenizer、模板、数据集、模型、collator、Trainer——但数据形态和模型角色不同。

奖励模型 rm 使用成对的 chosen/rejected,加载带 value head 的因果语言模型,损失是 Bradley–Terry 风格的配对比较。保存时必须把 v_head 拆到独立文件,直接把包装器的 state dict 当普通模型导出会得到错误键名。PPO 同时需要三类模型:待优化的策略、用于 KL 约束的参考模型,以及给出标量奖励的奖励模型。奖励来源可以是独立完整模型、挂到同一底座上的 LoRA,或 HTTP API。PPO 必须提供 reward_model;它走自定义的 ppo_train() 循环,先生成再打分再更新,而不是普通 Trainer.train()

DPO 在训练参数里写 stage: dpo,但数据层调用的是 get_dataset(..., stage="rm")。这是复用 pairwise processor,不是“DPO 其实在训 RM”。KTO 不要求同一 prompt 下成对出现,只要独立的好/坏标签;processor 会额外构造用于估计 KL 的错位样本,并带上 kto_tags

ORPO 与 SimPO 不是独立 stage。它们和 sigmoidhingeipokto_pair 一起,构成 pref_loss 的六种取值,全部挂在 stage: dpo 下面。sigmoid/hinge/ipo/kto_pair 进入 TRL 的 dpo_loss()orpo/simpoCustomDPOTrainer 本地实现,并且不创建参考模型。pref_loss=kto_pair 仍是成对 DPO 损失,不等于 stage: kto。需要省掉参考模型显存时,应在 DPO 下选择 ORPO 或 SimPO,而不是去找一个不存在的 stage: orpo

选型可以按数据记忆。有同 prompt 的 chosen/rejected,用 DPO;若还要给后续 PPO 当评分器,先训 RM。只有零散的好/坏反馈,用 KTO。已经有可靠奖励模型,并且需要在线采样优化,用 PPO。标签可能有噪声时,DPO 的 sigmoid 可以配合标签平滑;这一项不能套到其他 pref_loss 上。v1 的 DPO 目前只接受部分损失,不能假定这六种都能原样搬过去。

参考模型何时出现,也值得单独记一笔。标准 DPO 需要参考概率:显式给出 ref_model 就独立加载;LoRA 且未指定时可以返回空,计算参考对数概率时临时禁用 adapter;全参或冻结微调且未指定时,会再加载一份冻结底座。ORPO 与 SimPO 关掉参考模型,所以同卡显存往往更宽松,但它们仍然是 DPO workflow,数据仍按配对 RM 语义处理。KTO 默认也使用参考模型,LoRA 时同样用禁用 adapter 的办法得到参考对数概率。不要看到“没有 ref_model 字段”就断定没有参考分布,也不要看到“DPO 数据 stage 是 rm”就去改奖励头。

2. 分布式:四层模型,三种开关形态

“多卡”常常被写成一个开关,源码里却至少有四层。最外层是进程启动:launcher.pyllamafactory-cli train 下自动 torchrun。多设备且未启用 Ray/KTransformers 时会重启;FORCE_TORCHRUN=1 也会强制这条路径。src/train.py 没有自动 torchrun,多卡必须走 CLI。再往里是集群调度,即 Ray 的 worker 与 placement group。再往里是参数与状态分片:DDP、DeepSpeed ZeRO、FSDP/FSDP2,由 Hugging Face Trainer 与 Accelerate 配置驱动。最里层是替代训练后端:MCA 与 HyperParallel。KTransformers 是模型加载和算子后端,不是普通数据并行,也不是第四种推理 infer_backend

开关的写法不一致,这是配置错误的第一来源:

能力 开启方式 覆盖范围
Ray 环境变量 USE_RAY=1 调度 worker;内部仍跑原 Trainer
KTransformers 环境变量 USE_KT=1 排除自动 torchrun;训练侧限制为 LoRA
MCA 环境变量 USE_MCA=1 pt/sft/dpo;launcher 会强制 torchrun
HyperParallel YAML 字段 use_hyper_parallel pt/sft

只写 ray_num_workers 不会打开 Ray。USE_MCA=1 在导入参数类时就把 TrainingArguments 换成 Megatron 适配实现,不能在进程已经 import 之后再临时切换。USE_KT=1 会让“按可见设备数自动 DDP”失效,这是有意的。HyperParallel 与 MCA 在默认 stage 路由之前截获;stage 不匹配时静默落回默认 workflow,而不是报“后端不支持”。因此排错时要同时看环境变量、YAML 字段和最终进入的 workflow 目录。

DeepSpeed 通过 deepspeed: path/to/config.json 交给 Trainer;FSDP 通常先准备 Accelerate 配置再启动 CLI。Board 发现 DeepSpeed 参数时会设置 FORCE_TORCHRUN=1。Ray 示例存在于 examples/train_lora/qwen3_lora_sft_ray.yaml,但没有 USE_RAY=1 时这份 YAML 不会进入 Ray 分支。KT 面向 MoE 的异构加载,可与专用 FSDP2 配置组合,却不能写成 infer_backend: ktransformers

选型时按目标选层,而不是按名词堆叠。单机多卡的常规 SFT,让 CLI 自动 torchrun 再走 DDP 即可。优化器状态或参数显存不够,再加 DeepSpeed ZeRO 或 FSDP2。多机资源要交给集群调度时才开 Ray,并记住 Ray 只负责放置 worker,不会自动变成张量并行。需要 Megatron 那一套 TP/PP/EP 时才开 MCA;需要在 PT/SFT 上组合 FSDP/TP/CP 时才开 HyperParallel。巨型 MoE 的 CPU/GPU 异构加载才轮到 KT。把这些名字同时写进一份配置,并不会得到“全部加速”,只会得到互相抢入口的路由。

3. 进阶能力,以及 v1 为什么不能原地迁移

GaLore、APOLLO、BAdam、LoRA+、PiSSA、Liger、FP8 分散在三组参数里,分别注入自定义 optimizer、adapter 初始化或 kernel patch。它们多数互斥:LoRA 不能与 GaLore/APOLLO/BAdam 同时打开,后三者也不能彼此叠加。Web UI 只暴露其中一部分字段,完整契约仍是 dataclass 与 YAML。把这些算法理解成“再勾一个加速”,很容易在 __post_init__ 被拒绝。

v1 用 USE_V1=1 整栈切换,配置改成嵌套插件块,训练循环也不再复用 Hugging Face Trainer。它目前提供 sftdpormchatmerge,没有 v0 的 apiwebuiexport。第 10 章的 Board 与三条 HTTP 路由都属于 v0。v0 YAML 不能原地迁移:字段名、默认值和结构都不同,默认遇到遗留键会报错。要把实验路径跑起来,应使用 examples/v1/,而不是给旧文件加一个环境变量。

无论对齐还是分布式,都建议先用第 9 章那条冒烟命令证明主路径仍然健康:

1
llamafactory-cli train examples/train_lora/qwen3_lora_sft.yaml max_samples=16

确认解析、数据与 Trainer 可用后,再改 stage 或加一层分布式。一次只改一层:先算法,再进程启动,再 ZeRO/FSDP,最后才是 MCA、HyperParallel 或 KT。把文档里出现过的名字写成独立 stage、把环境变量写成 YAML 字段、或把 v1 当成 v0 的加速开关,都会在 parser 或 launcher 处失败。按调用链核对,比按功能清单记忆更稳。

把对齐与分布式放在同一章,是因为两者都会改“入口之后的路由”,却改的不是同一层。换 stagepref_loss,改变的是损失与数据形态;换 USE_RAYuse_hyper_parallel,改变的是进程与并行实现。先改损失再改并行,失败时至少知道应当看 Trainer 还是看 launcher。反过来同时改两层,日志里会出现“像算法错误的分布式问题”,或“像多卡问题的数据 stage 错误”。第 8 章的调用链在这里仍然够用:先问自己现在站在 launcher、parser、workflow 还是引擎门面。站对层,再查本章的表。

4. 四章应留下的对照表

  • 第 8 章:Python 与依赖边界、cli → launcher 双架构、多卡必须走 llamafactory-cli train
  • 第 9 章:五个 dataclass、数据的三层 schema、六个 stage 的公共骨架;QLoRA 写 bnb
  • 第 10 章:三种推理后端、Board 只是 CLI 子进程生成器、API 只有三条路由;eval 已拆除。
  • 本章:ORPO/SimPO 属于 pref_loss;Ray/KT/MCA 是环境变量,use_hyper_parallel 才是 YAML;v1 不能原地迁移。

至此,LLaMA Factory 主线四章读完。下一章进入本系列第 12/17 章。

文章互动

阅读 --

留言

0 条留言

正在加载留言…