Chapter 13
源码导读:Trainer 继承关系图
TRL 大约 3 万行核心代码,骨架是十几个 Trainer。本章给一份阅读路线。
13.1仓库结构
trl/
├── trl/
│ ├── trainer/
│ │ ├── sft_trainer.py / sft_config.py
│ │ ├── dpo_trainer.py / dpo_config.py
│ │ ├── grpo_trainer.py / grpo_config.py
│ │ ├── ppo_trainer.py / ppo_config.py
│ │ ├── reward_trainer.py / reward_config.py
│ │ ├── kto_trainer.py / kto_config.py
│ │ ├── orpo_trainer.py / orpo_config.py
│ │ ├── cpo_trainer.py / cpo_config.py
│ │ ├── rloo_trainer.py 离线 PPO 变种
│ │ ├── nash_md_trainer.py / xpo_trainer.py / gkd_trainer.py
│ │ ├── online_dpo_trainer.py / online_dpo_config.py
│ │ ├── utils.py GAE / log-prob / mask
│ │ └── callbacks.py wandb / sync_ref_model
│ ├── models/
│ │ ├── modeling_value_head.py AutoModelForCausalLMWithValueHead
│ │ ├── modeling_base.py
│ │ └── utils.py
│ ├── extras/
│ │ ├── vllm_client.py
│ │ └── profiling.py
│ ├── scripts/
│ │ └── vllm_serve.py trl vllm-serve 命令
│ ├── data_utils.py
│ └── core.py
├── examples/scripts/ 13 个跑得通的 CLI 脚本
├── tests/
└── docs/source/
13.2建议阅读顺序
| # | 文件 | 读什么 |
|---|---|---|
| 1 | trl/__init__.py | 公共 API 边界 |
| 2 | trl/trainer/sft_trainer.py | 最简单的 Trainer,建立心智模型 |
| 3 | trl/trainer/sft_config.py | 看 SFTConfig 加了哪些字段 |
| 4 | trl/trainer/dpo_trainer.py::compute_loss | DPO 的 loss 怎么写 |
| 5 | trl/trainer/utils.py | masked_log_prob / pad / cat 等共用工具 |
| 6 | trl/trainer/reward_trainer.py | Bradley-Terry 实现 |
| 7 | trl/trainer/grpo_trainer.py | R1 同款算法实现 |
| 8 | trl/trainer/ppo_trainer.py | 四模型 PPO 全流程 |
| 9 | trl/extras/vllm_client.py | vLLM 集成原理 |
13.3Trainer 继承图
transformers.Trainer
│
├── SFTTrainer
│
├── DPOTrainer
│ ├── compute_loss 覆盖
│ └── 支持 loss_type=sigmoid/ipo/kto_pair/...
│
├── KTOTrainer / ORPOTrainer / CPOTrainer
│ └── 各自实现 compute_loss
│
├── RewardTrainer
│ └── Bradley-Terry compute_loss
│
├── PPOTrainer (v0.10+)
│ ├── 重写 train()(自带 rollout/update 循环)
│ └── 用 reward_model + value_model
│
└── GRPOTrainer
├── 类似 PPO 但去掉 value
└── 支持 reward_funcs 列表
trl/models/AutoModelForCausalLMWithValueHead
└── 在 base 上挂 nn.Linear(d, 1) 当 critic / RM
13.4关键 commit 时间线
| 时间 | 变更 |
|---|---|
| 2023-03 | v0.1:SFTTrainer + PPOTrainer 老版本 |
| 2023-09 | DPOTrainer |
| 2024-02 | KTO / IPO / CPO |
| 2024-04 | ORPO 集成 |
| 2024-06 | SimPO / RPO |
| 2024-08 | online DPO + Nash-MD + XPO |
| 2024-10 | PPOTrainer 重构(声明式) |
| 2024-12 | GRPOTrainer 上线(R1 同款) |
| 2025-Q1 | vLLM 原生集成 + colocate/server 模式 |
| 2025-Q2 | multi-reward function / RLOO / GKD |
13.5对照其他对齐框架
| TRL | OpenRLHF | verl | |
|---|---|---|---|
| 定位 | HF 官方,最广用 | 高性能 PPO/GRPO | 字节火山 HybridFlow |
| 覆盖算法 | 13+ | 5-7 | 多 |
| 分布式 | accelerate + DeepSpeed | Ray + DeepSpeed | Ray + Megatron |
| 易用性 | ★★★★★ | ★★★ | ★★ |
| 极致性能 | ★★★ | ★★★★ | ★★★★★ |
13.6社区入口
- GitHub:
https://github.com/huggingface/trl(18k+ ⭐) - 官方文档:
https://huggingface.co/docs/trl - HF Discord / Forum
- 每月 RLHF roundup(HF 博客)
13.727 个 Trainer 全表(v1 实际状态)
13.3 的继承图是简化版。截至本书基线,TRL 实际有 27 个 Trainer 散落在 stable / experimental 两区。下面这张表是实战选型时的查表:
| Trainer | 位置 | 状态 | 用途 |
|---|---|---|---|
SFTTrainer | trl/trainer/sft_trainer.py:811 | stable | 监督微调 |
DPOTrainer | trl/trainer/dpo_trainer.py:406 | stable | 偏好对齐(15 种 loss) |
GRPOTrainer | trl/trainer/grpo_trainer.py:133 | stable ⚡ | R1 同款 |
RLOOTrainer | trl/trainer/rloo_trainer.py:105 | stable ⚡ | 无 critic RL |
RewardTrainer | trl/trainer/reward_trainer.py | stable | 训 ORM |
KTOTrainer | trl/trainer/kto_trainer.py → experimental 包装 | stable wrapper | Kahneman-Tversky 单标签 |
PPOTrainer | trl/experimental/ppo/ppo_trainer.py:305 | experimental 🧪 | 经典 PPO(已退役) |
OnlineDPOTrainer | trl/experimental/online_dpo/ | experimental ⚡🧪 | 在线偏好 |
NashMDTrainer | trl/experimental/nash_md/ | experimental ⚡🧪 | 博弈论 nash |
XPOTrainer | trl/experimental/xpo/ | experimental ⚡🧪 | exploration PO |
ORPOTrainer | trl/experimental/orpo/ | experimental 🧪 | odds-ratio PO |
BCOTrainer | trl/experimental/bco/ | experimental 🧪 | Binary Classifier |
CPOTrainer | trl/experimental/cpo/ | experimental 🧪 | Conditional PO |
PRMTrainer | trl/experimental/prm/ | experimental 🧪 | 过程奖励模型 |
GKDTrainer | trl/experimental/gkd/ | experimental 🧪 | Generative KD |
MiniLLMTrainer | trl/experimental/minillm/ | experimental 🧪 | 大模型蒸馏小 |
SDFTTrainer | trl/experimental/sdft/ | experimental 🧪 | speculative SFT |
SDPOTrainer | trl/experimental/sdpo/ | experimental 🧪 | speculative DPO |
SSDTrainer | trl/experimental/ssd/ | experimental 🧪 | Speculative Self-Decoding |
GFPOTrainer | trl/experimental/gfpo/ | experimental 🧪 | Group filtering PO |
GOLDTrainer | trl/experimental/gold/ | experimental 🧪 | — |
PAPOTrainer | trl/experimental/papo/ | experimental 🧪 | Pairwise Advantage PO |
TPOTrainer | trl/experimental/tpo/ | experimental 🧪 | — |
DistillationTrainer | trl/experimental/distillation/ | experimental 🧪 | 通用蒸馏 |
AsyncGRPOTrainer | trl/experimental/async_grpo/ | experimental 🧪 | 异步 GRPO |
GRPOWithReplayBufferTrainer | trl/experimental/grpo_with_replay_buffer/ | experimental 🧪 | GRPO + 经验回放 |
DPPOTrainer | trl/experimental/dppo/ | experimental 🧪 | — |
符号约定:⚡ = 支持 vLLM;🧪 = experimental(patch 版本可能动 API)。共 6 stable + 21 experimental = 27 个。
13.8_BaseTrainer 与"自包含"设计哲学
13.3 那张继承图缺一层:_BaseTrainer(trl/trainer/base_trainer.py:30)。所有主 trainer 都先继承它再才到 transformers.Trainer:
transformers.Trainer
│
└── trl._BaseTrainer # 只放 model card / telemetry 等共享逻辑
│
├── SFTTrainer
├── DPOTrainer
├── GRPOTrainer
├── RLOOTrainer
├── RewardTrainer
└── OnlineDPOTrainer
│
├── NashMDTrainer
└── XPOTrainer
设计要点(仓库 CLAUDE.md 明确写的):
- 故意代码重复:每个 trainer 文件几乎自包含,
dpo_trainer.py不靠grpo_trainer.py的任何工具; - _BaseTrainer 极薄:只放真正所有 trainer 都用的(model card 生成、telemetry,等),不做"算法基类";
- 很多子类重写
train():PPO / GRPO / Online DPO 都不复用 HF Trainer 的 step 循环,因为它们要 rollout; - online preference 单独成系:OnlineDPO / NashMD / XPO 才是真正的"继承链"。
这个哲学的好处:读 dpo_trainer.py 不用跳来跳去;改 grpo_trainer.py 不会破坏 DPO。代价:grep "_compute_loss" 会出现 5 处近似实现。
13.9跟着测试读 API
每个 trainer 的最小可跑示例都在 tests/。下表是 5 份高密度入口:
| 测试文件 | 展示了什么 |
|---|---|
tests/test_sft_trainer.py | SFTConfig + 数据格式(messages/text/prompt-completion)+ chunked CE |
tests/test_dpo_trainer.py | DPOConfig + DataCollatorForPreference + 15 种 loss_type |
tests/test_grpo_trainer.py | GRPOConfig + reward function callable + vLLM mock + tool use(multiply_tool 示例) |
tests/test_rloo_trainer.py | RLOOConfig + group sampling |
tests/test_reward_trainer.py | RewardConfig + pairwise data collator |
"想用 X trainer 但官方文档没写细" → 直接 grep tests/test_X_trainer.py,比文档准。
13.104 个 reward function 锚点
ch07.8 已经讲过 4 个内置 reward。这里给行号速查:
| 函数 | 位置 |
|---|---|
accuracy_reward | trl/rewards/accuracy_rewards.py:27 |
reasoning_accuracy_reward | trl/rewards/accuracy_rewards.py:117 |
think_format_reward | trl/rewards/format_rewards.py:18 |
get_soft_overlong_punishment | trl/rewards/other_rewards.py:18 |
"我要自己写一个 reward" → 复制 accuracy_reward 的签名改 body。函数签名是 fn(completions, **kw) → list[float | None] 这一种就够用。
13.11这章你需要带走的
- TRL 实际有 27 个 Trainer:6 stable + 21 experimental;
- 所有 trainer 走
_BaseTrainer,但故意"自包含 + 代码重复"; - online preference 系是个独立小继承链(OnlineDPO → Nash-MD / XPO);
- 选 trainer 时优先 stable 6 个,experimental 用前看自己接受 API 变化;
- 不知道怎么用某 trainer 时 grep
tests/test_*_trainer.py比 doc 准。