AReaL 偏好对齐实战:基于 Anthropic/hh-rlhf 的奖励模型(RM)训练与 DPO 直接偏好优化
【免费下载链接】AReaLThe RL Bridge for LLM-based Agent Applications. Made Simple & Flexible.项目地址: https://gitcode.com/GitHub_Trending/are/AReaL
导读
本文以 AReaL 仓库中的 examples/alignment 为例,系统讲解如何在Anthropic/hh-rlhf偏好数据集上完成两类最常用的对齐训练:奖励模型(Reward Model,RM)训练与直接偏好优化(Direct Preference Optimization,DPO)。两种方法消费同一份 chosen/rejected 偏好对,但对偏好信号的使用方式截然不同。读完本文,你将掌握:两条技术路线的适用场景与取舍、可直接复制的启动命令、完整 YAML 配置逐项拆解、AReaL 中 DPO 在线参考模型(ref engine)的实现原理,以及如何解读训练曲线验证对齐效果。
说明:本文所有命令与配置均以当前仓库
examples/alignment目录下的真实文件为准;涉及的源码路径可直接在仓库中继续深挖。
一、路线总览:RM 与 DPO 如何选择
examples/alignment目录同时提供奖励模型训练与 DPO 训练两套示例,二者使用完全相同的偏好对(chosen优于rejected),区别在于把偏好信号转化为何种目标:
| 方法 | 输出产物 | 适用场景 |
|---|---|---|
| RM | 一个标量奖励模型 | 为响应打分,作为 PPO/GRPO/RL 训练中的奖励信号 |
| DPO | 一个偏好对齐的策略模型 | 直接对齐后的模型,无需单独维护奖励模型 |
选择要点:如果你的下游是 PPO/GRPO 这类在线强化学习管线,需要先训练 RM 作为奖励来源;如果目标是"直接得到一个对齐后的策略",DPO 的端到端闭式优化更轻量,不需要显式奖励模型。
二、数据准备与代码结构
2.1 示例目录组成
examples/alignment/ ├── README.md # 本文对应的官方指南 ├── hhrlhf_rw.py # RM 训练入口脚本 ├── hhrlhf_rw.yaml # RM 训练配置 ├── hhrlhf_dpo.py # DPO 训练入口脚本 ├── hhrlhf_dpo.yaml # DPO 训练配置 ├── rw_loss_formula.png # Bradley-Terry 损失公式 ├── rw_curve.png # RM 训练曲线 └── dpo_curve.png # DPO 训练曲线2.2 偏好数据如何被处理
数据集处理逻辑集中在 areal/dataset/hhrlhf.py,其中:
get_hhrlhf_rw_dataset:将每条样本的chosen/rejected文本分别编码为chosen_ids/rejected_ids(末尾追加eos_token),供 RM 训练使用;可选max_length过滤超长序列。get_hhrlhf_dpo_dataset:额外生成chosen_loss_mask/rejected_loss_mask。实现上通过逐 token 比较chosen 与 rejected 的 token id 找到公共前缀长度prompt_len,前缀部分(提示词)置 0 不参与损失,响应部分置 1 参与损失,即 DPO 只对响应片段做对比学习。
在入口脚本 hhrlhf_rw.py 和 hhrlhf_dpo.py 中,均通过areal.dataset.get_custom_dataset按train_dataset.type(rw或dpo)自动分派到上述处理函数,再交给RWTrainer/DPOTrainer训练。
三、奖励模型(Reward Model)训练
3.1 原理:Bradley-Terry 奖励建模
奖励建模是让语言模型与人类偏好对齐的关键步骤:训练一个模型为响应打分,该分数随后可作为强化学习(PPO/GRPO)中指导策略优化的奖励信号。AReaL 采用 Bradley-Terry 奖励建模损失:
直观理解:模型为chosen响应给出比rejected响应更高的分数时损失降低,从而学会"复刻人类偏好排序"。
3.2 快速启动
使用仓库提供的配置直接启动 RM 训练:
python3 examples/alignment/hhrlhf_rw.py \ --config examples/alignment/hhrlhf_rw.yaml \ experiment_name=hhrlhf-rw \ trial_name=trial1 \ actor.path=Qwen/Qwen2.5-7B \ train_dataset.path=Anthropic/hh-rlhf \ valid_dataset.path=Anthropic/hh-rlhf \ scheduler.type=local \ stats_logger.wandb.mode=online # Set to 'disabled' if you don't use Weights & Biases命令行中key=value形式的参数会作为配置覆盖项,与 YAML 中的同名键合并(优先级更高),因此你无需修改配置文件即可切换模型、数据集、调度器和日志后端。
3.3 配置文件逐项拆解
完整配置见 hhrlhf_rw.yaml,核心字段如下:
| 配置段 | 关键字段 | 说明 |
|---|---|---|
| 顶层 | total_train_epochs: 1 | 训练轮数,示例仅 1 个 epoch |
| 顶层 | tokenizer_path: ${actor.path} | 支持${}变量引用,tokenizer 直接复用 actor 模型路径 |
cluster | n_nodes/n_gpus_per_node | 集群规模,示例为单机 8 卡 |
cluster.name_resolve | type: nfs | 名称解析后端,多机时通过 NFS 记录根目录交换地址 |
scheduler | type: local | 调度器类型,可选local/ray/slurm |
actor | backend: "fsdp:d8p1t1" | 训练后端为 FSDP,8 张卡数据并行、张量并行度为 1 |
actor | is_critic: true | RM 训练的关键开关,将 actor 配置为打分模型 |
actor | disable_dropout: true | 训练时关闭 dropout(对齐训练惯例) |
actor | gradient_checkpointing: true/dtype: bfloat16 | 显存优化与精度 |
actor.optimizer | lr: 2e-5、weight_decay: 0.01、lr_scheduler_type: cosine、gradient_clipping: 1.0 | Adam 优化器参数:RM 通常用偏大的学习率 |
actor.mb_spec | max_tokens_per_mb: 4096 | 微批按 token 数切分,granularity: 2表示按 2 的幂对齐 |
actor.scheduling_spec | cmd: python3 -m areal.infra.rpc.rpc_server | 每个 worker 进程启动的 RPC 服务命令 |
train_dataset/valid_dataset | batch_size: 256、type: rw | RM 数据集类型标识;训练/验证批大小均为 256 |
saver/recover/evaluator | freq_epochs: 1 | 按 epoch 频率保存 checkpoint、恢复点与执行评估 |
stats_logger.wandb | mode: disabled | WandB 开关,CLI 中可覆盖为online |
3.4 源码级原理:RWTrainer 如何跑起来
RM 训练的驱动类是 areal/trainer/rw_trainer.py 中的RWTrainer:
- 数据装配:
rw_modeling_collate_fn把每个样本的chosen_ids与rejected_ids拆成两个独立的[1, seqlen]张量(chosen 在前),并附带全 1 的attention_mask——即一个偏好对在 batch 中表现为两条序列。 - 引擎分派:
_create_actor根据actor.backend选择FSDPRWEngine/MegatronRWEngine/ArchonRWEngine,示例配置走 FSDP 路径。 - 训练主循环:
train()中以epoch = global_step // steps_per_epoch组织迭代,每步调用self.actor.train_rw(batch)执行一次打分损失的反向更新,随后依次推进 LR scheduler、保存 HF 格式权重(Saver)、落恢复 checkpoint(RecoverHandler)、执行验证集评估(Evaluator)并提交统计(StatsLogger)。 - 模型加载时若存在可恢复的 checkpoint,会从上次
global_step续训,因此支持断点续跑。
3.5 训练曲线解读
典型的 RM 训练曲线表现为:loss持续下降,模型对 chosen 的打分逐渐高于 rejected(偏好准确率上升)。训练结束后产出的就是一个可打分、可接入 RL 管线的标量奖励模型。
四、直接偏好优化(DPO)训练
4.1 原理:什么是 DPO
直接偏好优化(Direct Preference Optimization,Rafailov et al., 2023)无需训练单独的奖励模型,而是直接优化策略,使模型对人类偏好响应(chosen)的生成概率高于被拒绝响应(rejected)。其核心是一个基于可训练策略与冻结参考模型之间 log 概率比的闭式对比损失:
$$ \mathcal{L}{\mathrm{DPO}}(\pi\theta; \pi_{\mathrm{ref}}) = -\mathbb{E}_{(x, y_w, y_l) \sim \mathcal{D}} \left[ \log \sigma\left( \beta \log \frac{\pi_\theta(y_w \mid x)}{\pi_{\mathrm{ref}}(y_w \mid x)} - \beta \log \frac{\pi_\theta(y_l \mid x)}{\pi_{\mathrm{ref}}(y_l \mid x)} \right) \right] $$
其中:
- $\pi_\theta$ 为可训练策略(actor);
- $\pi_{\mathrm{ref}}$ 为冻结的参考模型(ref);
- $y_w$、$y_l$ 分别为 chosen 与 rejected 响应;
- $\beta$ 控制策略允许偏离参考模型的程度($\beta$ 越大 → KL 约束越紧);
- $\sigma$ 为 sigmoid 函数。
4.2 AReaL 的 DPO 实现要点:在线 ref 引擎
AReaL 的 DPO 实现有一个值得注意的设计:每一步都在线计算 $\pi_{\mathrm{ref}}$ 的 log 概率,通过 YAML 中ref:字段配置的共置(colocate)参考引擎完成,与 PPO/GRPO 的 ref-model 模式保持一致。无需在磁盘上预存参考 logprob 文件。
在 areal/trainer/dpo/dpo_engine.py 中可以看到完整的损失计算链路:
DPOEngine.compute_logp:ref 引擎在前向模式下为 batch 中的 chosen/rejected 序列计算逐 token log 概率,结果以ref_logprobs形式挂回数据字典,供训练步使用;compute_dpo_loss:dpo_pair_logratios从 packed batch 中按cu_seqlens切分序列、用loss_mask对齐下一 token 的 log 概率(mask 右移一位、末位清零),并以fp64 累加避免长序列(约 2k+ token)fp32 累加导致 log 比符号翻转的精度问题,得到(policy_logps, ref_logps, completion_lens)各为(K, 2)的配对张量;dpo_preference_loss(见 areal/utils/functional/functional.py):sigmoid变体返回-logsigmoid(beta * logits),ipo变体返回(logits - 1/(2*beta))²;- 训练/评估时同时无梯度地统计
chosen_reward、rejected_reward(定义为beta * (policy_logp - ref_logp))、reward_accuracy(chosen_reward > rejected_reward的比例)与reward_margin,这些指标正是后文判断对齐是否有效的依据。
4.3 快速启动
python3 examples/alignment/hhrlhf_dpo.py \ --config examples/alignment/hhrlhf_dpo.yaml \ experiment_name=hhrlhf-dpo \ trial_name=trial1 \ actor.path=Qwen/Qwen2.5-7B \ ref.path=Qwen/Qwen2.5-7B \ train_dataset.path=Anthropic/hh-rlhf \ valid_dataset.path=Anthropic/hh-rlhf \ scheduler.type=local \ stats_logger.wandb.mode=online # Set to 'disabled' if you don't use Weights & Biases注意 DPO 比 RM 多一个ref.path参数——参考模型与 actor 初始为同一检查点,训练中 ref 保持冻结。
4.4 配置文件解析:actor 与 ref 的协同
完整配置见 hhrlhf_dpo.yaml。与 RM 配置的核心差异:
| 配置段 | 关键字段 | 说明 |
|---|---|---|
actor | is_critic: false | DPO 中 actor 是策略而非打分器 |
actor | beta: 0.1 | DPO 的 KL 约束强度,见损失公式 |
actor.optimizer | lr: 5e-6、warmup_steps_proportion: 0.1、min_lr_ratio: 0.1、gradient_clipping: 10.0 | DPO 学习率显著小于 RM(5e-6 vs 2e-5),并带 10% 步数 warmup 与更宽松的梯度裁剪 |
ref | path: ${actor.path}、optimizer: null | 参考模型不训练,无优化器 |
ref | scheduling_strategy.type: colocation、target: actor | ref 与 actor 共置调度,复用 actor 的卡资源,避免额外占卡 |
ref.mb_spec | max_tokens_per_mb: 10240 | 前向(推理)微批可更大,提升 logprob 计算吞吐 |
train_dataset/valid_dataset | batch_size: 64、type: dpo、max_length: 2048 | DPO 批大小更小(每条样本含两条序列);超长样本被过滤 |
DPOTrainer(见 areal/trainer/dpo_trainer.py)的训练主循环非常清晰地体现了上述设计:每步先调self.ref.compute_logp(batch)在线获取参考 logprob,再调self.actor.train_dpo(batch)用compute_dpo_loss做反向更新;batch 清理阶段同时回收 actor 与 ref 两侧的缓存。由于 DPO 一条样本包含 chosen/rejected 两条序列,DPOController在 RPC 分发时使用group_size=2保证同一偏好对落在同一数据并行 rank 上。
4.5 支持的 loss_type:sigmoid 与 ipo
在 areal/api/cli_args.py 中loss_type字段限定为两个取值:
sigmoid:原始 DPO 损失(Rafailov et al. 2023),即上文的-logsigmoid(beta * logits);ipo:Identity Preference Optimization(Azar et al. 2023),采用逐 token 平均的平方损失变体——compute_dpo_loss中先将每条序列的 log 比除以该序列 completion 长度(per-token 归一化),再套用(logits - 1/(2*beta))²,使 $\beta$ 在不同长度序列间可比。
4.6 推荐流程:Base → SFT → DPO
为了获得最佳对齐质量,官方推荐的完整流水线是Base → SFT → DPO:用 SFT 检查点同时初始化 actor 与参考模型。而本文示例为最小化验证成本,直接以 Base 模型启动 DPO(即不经过 SFT 预热),用于快速验证 AReaL 的 DPO 链路本身是否工作正常。
4.7 训练曲线解读
官方实验记录:用Qwen2.5-7B-Base在Anthropic/hh-rlhf上训练 1 个 epoch(无 SFT 预热),即可复现原始论文的经典 DPO 特征——
loss从约 $\log 2 \approx 0.693$ 起步并持续下降(初始 $\approx \log 2$ 正是 sigmoid 损失在"无偏好信号"时的理论起点);reward_accuracy(chosen 得分高于 rejected 的比例)从 0.50 升至约 0.70;reward_margin(chosen 与 rejected 得分差)单调增长;rejected_reward的下降速度快于chosen_reward。
这些曲线形态是 DPO 正常收敛的标志性"签名"(signature),可用于快速判断自己的实验是否跑对。
五、小结
在 AReaL 中,examples/alignment给出了两套可直接复现的偏好对齐范式:RM 训练产出可供 PPO/GRPO 使用的标量奖励模型(配置关键在actor.is_critic: true);DPO 则以在线共置的 ref 引擎计算参考 logprob,端到端产出对齐后的策略(配置关键在actor.beta与ref字段)。二者共享同一套Anthropic/hh-rlhf数据与数据服务、Saver/Recover/Evaluator/StatsLogger 等基建,从示例出发可平滑迁移到其他偏好数据集与更大规模模型。继续深入可阅读 RWTrainer、DPOTrainer 与 DPOEngine 的源码,理解每一步的底层实现。
【免费下载链接】AReaLThe RL Bridge for LLM-based Agent Applications. Made Simple & Flexible.项目地址: https://gitcode.com/GitHub_Trending/are/AReaL
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考