Chapter 13

源码导读:Trainer 继承关系图

📌 commit 8221a9f读懂 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建议阅读顺序

#文件读什么
1trl/__init__.py公共 API 边界
2trl/trainer/sft_trainer.py最简单的 Trainer,建立心智模型
3trl/trainer/sft_config.py看 SFTConfig 加了哪些字段
4trl/trainer/dpo_trainer.py::compute_lossDPO 的 loss 怎么写
5trl/trainer/utils.pymasked_log_prob / pad / cat 等共用工具
6trl/trainer/reward_trainer.pyBradley-Terry 实现
7trl/trainer/grpo_trainer.pyR1 同款算法实现
8trl/trainer/ppo_trainer.py四模型 PPO 全流程
9trl/extras/vllm_client.pyvLLM 集成原理

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-03v0.1:SFTTrainer + PPOTrainer 老版本
2023-09DPOTrainer
2024-02KTO / IPO / CPO
2024-04ORPO 集成
2024-06SimPO / RPO
2024-08online DPO + Nash-MD + XPO
2024-10PPOTrainer 重构(声明式)
2024-12GRPOTrainer 上线(R1 同款)
2025-Q1vLLM 原生集成 + colocate/server 模式
2025-Q2multi-reward function / RLOO / GKD

13.5对照其他对齐框架

TRLOpenRLHFverl
定位HF 官方,最广用高性能 PPO/GRPO字节火山 HybridFlow
覆盖算法13+5-7
分布式accelerate + DeepSpeedRay + DeepSpeedRay + Megatron
易用性★★★★★★★★★★
极致性能★★★★★★★★★★★★

13.6社区入口

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 那张继承图缺一层:_BaseTrainertrl/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 明确写的):

这个哲学的好处:读 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这章你需要带走的