RLHF人类反馈强化学习训练Agent完整流水线:SFT到PPO三阶段2026教程

RLHF人类反馈强化学习训练Agent完整流水线:SFT到PPO三阶段2026教程

RLHF(Reinforcement Learning from Human Feedback,人类反馈强化学习)是大模型对齐训练的经典范式,也是ChatGPT取得突破性成功的核心技术之一。RLHF通过三阶段流水线——SFT行为克隆、奖励模型(RM)训练、PPO策略优化——将人类偏好注入模型策略中。尽管2026年涌现了DPO、GRPO等更简洁的方法,RLHF凭借其完整的理论框架和在线探索能力,仍然是需要精细控制和对齐复杂偏好的Agent训练的首选方案。本文将完整拆解RLHF三阶段的实现细节。

三阶段
SFT→RM→PPO
KL散度
防止策略漂移
clip 0.2
PPO策略裁剪
RM模型
奖励信号来源

一、RLHF概述:三阶段对齐框架

RLHF的核心思想是:直接用人类偏好作为训练信号太昂贵,因此先训练一个奖励模型来模拟人类偏好判断,然后用这个奖励模型作为RL的奖励信号来优化策略。整个流程分为三个阶段,每个阶段都有明确的目标和独立的训练流程。

阶段1 SFT(监督微调):用专家演示数据训练基座模型,让模型学会指令遵循和基本的Agent格式。这一阶段的目标不是对齐偏好,而是建立基础能力。SFT模型将作为后续RM训练的基线模型和PPO阶段的初始策略。

阶段2 RM(奖励模型训练):训练一个独立的奖励模型,输入是(prompt, response),输出是一个标量奖励分数。训练数据是人类标注的偏好对比——对于同一prompt的两个response,人类标注哪个更好。RM学习预测人类的偏好判断。

阶段3 PPO(策略优化):用RM作为奖励信号,通过PPO算法优化SFT模型。模型生成response→RM打分→PPO更新策略。关键创新是KL散度惩罚,防止策略偏离SFT基线太远导致输出质量下降。

二、SFT阶段:行为克隆建立基础能力

RLHF的SFT阶段与独立的SFT训练流程基本一致,但有一个重要区别:这里的SFT模型不仅要学会Agent格式,还要为RM训练提供高质量的基线。SFT模型的质量直接决定RM训练和PPO优化的上限。

以下是SFT阶段的核心配置,重点关注与后续阶段的衔接:

# RLHF Stage 1: SFT训练
from trl import SFTConfig, SFTTrainer
from transformers import AutoModelForCausalLM

# 基座模型选择 (RLHF推荐使用较强的基座)
base_model = AutoModelForCausalLM.from_pretrained(
    "Qwen/Qwen3-14B",  # RLHF推荐14B以上
    torch_dtype="bfloat16",
    device_map="auto"
)

sft_config = SFTConfig(
    output_dir="./rlhf_sft",
    num_train_epochs=3,
    per_device_train_batch_size=4,
    gradient_accumulation_steps=4,
    learning_rate=2e-4,
    warmup_ratio=0.03,
    lr_scheduler_type="cosine",
    bf16=True,
    max_seq_length=2048,
    save_strategy="epoch",
    gradient_checkpointing=True,
)

# SFT训练 (与标准SFT流程相同)
trainer = SFTTrainer(
    model=base_model,
    args=sft_config,
    train_dataset=sft_dataset,
    peft_config=lora_config,  # 使用LoRA
)
trainer.train()

# 保存SFT模型 (后续RM和PPO都要用到)
trainer.save_model("./rlhf_sft_final")
# 关键: 保存合并后的完整模型用于RM训练
merged = trainer.model.merge_and_unload()
merged.save_pretrained("./rlhf_sft_merged")

SFT阶段完成后,需要进行严格评估。RLHF对SFT模型的质量要求比独立SFT更高——因为RM是在SFT模型生成的response上训练的,如果SFT模型生成的response质量太差,RM学到的偏好判断也会不可靠。建议SFT模型在测试集上的格式准确率达到95%以上、任务完成率达到80%以上后再进入RM阶段。

三、RM训练:学习人类偏好判断

奖励模型(Reward Model)是RLHF的核心组件。它的输入是(prompt, response)对,输出是一个标量奖励分数。RM通常使用与策略模型相同架构的模型,但将语言模型头替换为标量输出头(一个线性层将hidden state映射到1维)。

RM的训练数据是偏好对比数据。对于每个prompt,SFT模型生成多个不同的response,人类标注员对这些response进行排序或两两比较。最常见的数据格式是(prompt, response_A, response_B, preference),其中preference标记A和B哪个更好。

# RLHF Stage 2: 奖励模型训练
from transformers import AutoModelForSequenceClassification
from trl import RewardTrainer, RewardConfig

# RM使用与策略模型相同的基座, 但替换为序列分类头
reward_model = AutoModelForSequenceClassification.from_pretrained(
    "./rlhf_sft_merged",        # 从SFT模型初始化
    num_labels=1,               # 输出标量奖励
    torch_dtype="bfloat16",
    device_map="auto"
)

# 偏好数据格式
# {"chosen": "好的回答", "rejected": "差的回答"}
rm_dataset = load_preference_dataset("rm_training_data.jsonl")

# RM训练配置
reward_config = RewardConfig(
    output_dir="./reward_model",
    num_train_epochs=2,
    per_device_train_batch_size=8,
    gradient_accumulation_steps=2,
    learning_rate=5e-6,         # RM需要较小的学习率
    warmup_ratio=0.1,
    lr_scheduler_type="cosine",
    bf16=True,
    max_length=1024,
    logging_steps=10,
    save_strategy="epoch",
    gradient_checkpointing=True,
)

# RM损失: Bradley-Terry模型
# L = -log(sigmoid(r(chosen) - r(rejected)))
reward_trainer = RewardTrainer(
    model=reward_model,
    args=reward_config,
    train_dataset=rm_dataset,
    tokenizer=tokenizer,
)
reward_trainer.train()

RM训练的关键挑战是泛化性。RM需要在训练分布外的prompt上也能准确判断偏好。如果RM只在特定领域的偏好数据上训练,它在其他领域可能给出不准确的奖励信号,导致PPO优化方向错误。提升RM泛化性的方法包括:增加偏好数据的领域多样性、使用更大的RM模型、采用集成方法(训练多个RM取平均)。

RM评估指标计算方法合格阈值
偏好准确率r(chosen)>r(rejected)的比例>70%
奖励边际r(chosen)-r(rejected)均值>0.5
泛化准确率分布外测试集准确率>65%
校准误差ECE (Expected Calibration Error)<0.1
相关性与人类评分的Spearman相关>0.6

四、PPO优化:用奖励信号提升策略

PPO(Proximal Policy Optimization)是RLHF第三阶段的核心算法。它使用RM作为奖励信号,通过在线生成和策略更新的循环来优化SFT模型。PPO需要同时维护四个模型:策略模型(actor,待训练)、价值模型(critic,待训练)、奖励模型(RM,冻结)、参考模型(SFT模型,冻结,用于KL计算)。

PPO的一次完整训练迭代包括以下步骤:1) 策略模型对一批prompt生成response(Rollout);2) RM对每个response打分得到奖励;3) Critic估计每个状态的价值;4) 计算优势函数A = R - V;5) 用clipped surrogate loss更新策略模型;6) 用MSE loss更新critic模型;7) 计算KL散度作为惩罚项。

# RLHF Stage 3: PPO训练
from trl import PPOConfig, PPOTrainer
from trl.core import LengthSampler

# PPO配置
ppo_config = PPOConfig(
    output_dir="./rlhf_ppo",
    # 策略模型学习率
    learning_rate=1e-6,         # 1e-6到5e-6
    # Critic模型学习率
    critic_learning_rate=5e-6,
    # PPO核心超参数
    clip_range=0.2,             # clip_ratio: 限制策略更新幅度
    kl_penalty="kl",            # KL散度惩罚类型
    target_kl=0.05,             # 目标KL散度
    beta=0.1,                   # KL散度系数: 0.05-0.2
    # 训练参数
    batch_size=32,
    mini_batch_size=8,
    gradient_accumulation_steps=4,
    ppo_epochs=4,               # 每批数据更新4次
    max_new_tokens=512,         # 生成最大长度
    # 价值函数
    vf_coef=0.1,                # 价值损失权重
    # 其他
    seed=42,
    bf16=True,
)

# 加载四个模型
policy_model = AutoModelForCausalLM.from_pretrained("./rlhf_sft_merged")
ref_model = AutoModelForCausalLM.from_pretrained("./rlhf_sft_merged")  # 冻结
reward_model = AutoModelForSequenceClassification.from_pretrained("./reward_model")  # 冻结
value_model = AutoModelForSequenceClassification.from_pretrained("./rlhf_sft_merged", num_labels=1)

# 初始化PPO Trainer
ppo_trainer = PPOTrainer(
    config=ppo_config,
    model=policy_model,
    ref_model=ref_model,
    reward_model=reward_model,
    tokenizer=tokenizer,
    dataset=ppo_dataset,
)

# PPO训练循环
for epoch in range(num_epochs):
    for batch in dataloader:
        prompts = batch["prompt"]
        
        # Step 1: 策略模型生成response (Rollout)
        responses = ppo_trainer.generate(
            prompts, 
            max_new_tokens=512,
            temperature=0.7,
            do_sample=True,
        )
        
        # Step 2: RM计算奖励
        rewards = reward_model.score(prompts, responses)
        
        # Step 3: PPO策略更新 (包含KL惩罚)
        stats = ppo_trainer.step(prompts, responses, rewards)
        
        # Step 4: 监控关键指标
        print(f"Epoch {epoch}: "
              f"reward={stats['mean_reward']:.4f}, "
              f"kl={stats['kl']:.4f}, "
              f"policy_loss={stats['policy_loss']:.4f}, "
              f"value_loss={stats['value_loss']:.4f}")

五、KL散度控制:防止策略漂移

KL散度惩罚是RLHF中防止灾难性遗忘的关键机制。在PPO优化过程中,如果策略模型完全自由地最大化RM奖励,它可能找到RM的漏洞(reward hacking),生成RM给高分但人类认为质量差的response。KL散度惩罚通过约束策略模型不偏离SFT参考模型太远来防止这一问题。

KL散度的计算方式是:对每个生成的response,计算策略模型和参考模型对该response的log概率差异,然后在batch上取平均。这个差异越大,说明策略偏离参考模型越远。PPO将这个KL散度作为惩罚项加入总损失:

# KL散度计算和惩罚
import torch
import torch.nn.functional as F

def compute_kl_penalty(policy_model, ref_model, 
                       input_ids, attention_mask, beta=0.1):
    """
    计算策略模型与参考模型之间的KL散度惩罚
    beta: KL系数, 0.05-0.2
    """
    # 策略模型的log概率
    policy_logits = policy_model(input_ids, attention_mask=attention_mask).logits
    policy_log_probs = F.log_softmax(policy_logits, dim=-1)
    
    with torch.no_grad():
        # 参考模型的概率 (冻结)
        ref_logits = ref_model(input_ids, attention_mask=attention_mask).logits
        ref_probs = F.softmax(ref_logits, dim=-1)
        ref_log_probs = F.log_softmax(ref_logits, dim=-1)
    
    # KL(policy || ref) = sum(policy * (log_policy - log_ref))
    kl_per_token = (policy_log_probs.exp() * 
                    (policy_log_probs - ref_log_probs)).sum(-1)
    
    # 对序列取平均 (排除padding)
    mask = attention_mask.float()
    kl_mean = (kl_per_token * mask).sum() / mask.sum()
    
    # KL惩罚项
    kl_penalty = beta * kl_mean
    
    return kl_penalty

# PPO总损失 = 策略损失 + 价值损失 + KL惩罚
total_loss = (
    policy_loss           # clipped surrogate loss
    + vf_coef * value_loss  # 价值函数损失
    + kl_penalty            # KL散度惩罚
)

# 自适应KL控制: 如果KL超过target_kl, 自动增大beta
if current_kl > target_kl * 2:
    beta *= 1.5  # 增大惩罚力度
elif current_kl < target_kl * 0.5:
    beta *= 0.9  # 减小惩罚, 允许更多探索

KL系数(beta)的控制策略至关重要。beta过小(<0.05)会导致策略漂移过远,可能出现reward hacking或输出质量下降;beta过大(>0.2)会过度限制策略更新,模型几乎学不到新东西。推荐使用自适应KL控制:设定目标KL值(如0.05),当实际KL超过目标时增大beta,低于目标时减小beta。

六、训练配置:RLHF完整参数清单

RLHF是所有Agent训练方法中超参数最多的。以下是三阶段完整训练的参数配置清单和推荐值:

RLHF人类反馈强化学习训练Agent完整流水线:SFT到PPO三阶段2026教程

阶段参数推荐值说明
SFTlearning_rate2e-4LoRA微调
SFTepochs32-3轮
RMlearning_rate5e-6全量微调
RMepochs2避免过拟合
PPOlearning_rate1e-6到5e-6极小学习率
PPOclip_range0.2策略更新限制
PPObeta (KL)0.05-0.2KL散度系数
PPOtarget_kl0.05自适应KL目标
PPOppo_epochs4每批更新次数
PPOtemperature0.7Rollout采样温度
PPOvf_coef0.1价值损失权重

RLHF训练的资源需求是所有方法中最高的。以7B模型为例,PPO阶段需要同时加载四个模型:策略模型(14GB)、参考模型(14GB)、奖励模型(14GB)、价值模型(14GB),加上优化器状态和Rollout缓存,总计需要约80-120GB显存。这意味着至少需要4张A100 40GB或2张A100 80GB。使用LoRA可以降低到约40-60GB(参考模型和RM可以量化到4-bit)。

七、评估方法:RLHF全链路评估体系

RLHF的评估需要覆盖三个阶段。SFT阶段评估格式遵循和基础能力;RM阶段评估偏好准确率和泛化性;PPO阶段评估最终模型的综合质量。以下是PPO阶段的核心评估方法:

# RLHF PPO阶段评估
def evaluate_rlhf_model(policy_model, reward_model, ref_model, 
                        eval_prompts):
    """全面评估RLHF训练后的模型"""
    results = {
        "avg_reward": [],
        "kl_divergence": [],
        "format_accuracy": [],
        "response_length": [],
    }
    
    for prompt in eval_prompts:
        # 生成response
        response = policy_model.generate(prompt, max_new_tokens=512)
        
        # 1. RM奖励分数 (越高越好)
        reward = reward_model.score(prompt, response)
        results["avg_reward"].append(reward)
        
        # 2. KL散度 (监控策略漂移)
        kl = compute_kl(policy_model, ref_model, prompt, response)
        results["kl_divergence"].append(kl)
        
        # 3. 格式准确率
        format_ok = check_agent_format(response)
        results["format_accuracy"].append(format_ok)
        
        # 4. 响应长度 (监控长度异常)
        results["response_length"].append(len(response))
    
    # 汇总指标
    print(f"平均奖励: {mean(results['avg_reward']):.4f}")
    print(f"KL散度: {mean(results['kl_divergence']):.4f}")
    print(f"格式准确率: {mean(results['format_accuracy']):.2%}")
    print(f"平均响应长度: {mean(results['response_length']):.0f}")
    
    # 与SFT模型对比 (A/B测试)
    print("\\n--- 与SFT模型对比 ---")
    win_rate = ab_test(policy_model, ref_model, eval_prompts)
    print(f"vs SFT 胜率: {win_rate:.2%} (目标: >60%)")
    
    return results

RLHF评估中最重要的是人类评估。自动化指标(如RM奖励分数)可能存在偏差——RM自身的偏好判断不一定完全代表人类偏好。建议定期进行大规模人类评估:让标注员对PPO模型和SFT模型的输出进行盲选比较,计算真实胜率。如果RM奖励上升但人类评估胜率下降,说明出现了reward hacking,需要调整训练策略。

另一个关键评估维度是安全性。RLHF训练后的模型可能产生新的安全风险,如更擅长生成有害内容(因为RM可能无法准确判断某些安全边界)。必须进行红队测试(red-teaming),主动尝试诱导模型产生有害输出,确保RLHF没有降低模型的安全性。

RLHF人类反馈强化学习训练Agent完整流水线:SFT到PPO三阶段2026教程

八、FAQ:常见问题解答

Q1:RLHF三阶段训练总共需要多长时间?

以7B模型为例:SFT阶段约2-4小时(取决于数据量),RM训练约2-3小时,PPO阶段最长约12-24小时(需要大量在线生成)。三阶段总计约16-31小时。PPO是最耗时的阶段,因为每次参数更新都需要先让模型生成response(Rollout),这比前向传播慢得多。使用vLLM加速生成可以将PPO阶段缩短30%-50%。

Q2:PPO的clip_range为什么是0.2?

clip_range=0.2是PPO论文中的经典设定,在大量实验中被证明是策略更新的安全边界。它将重要性采样比ratio限制在[0.8, 1.2]范围内,防止单次更新导致策略变化过大。如果clip_range太小(如0.05),策略更新太慢,训练效率低;如果太大(如0.5),策略可能剧烈变化导致不稳定。对于语言模型,0.1-0.3都是合理范围,0.2是经过大量验证的稳健选择。

Q3:如何判断是否出现了reward hacking?

Reward hacking的典型信号:RM奖励分数持续上升但人类评估质量下降、模型输出变得异常长或重复、模型生成RM给高分但语义不通的内容。检测方法:1) 定期进行人类评估,对比RM奖励趋势和人类质量评分趋势;2) 监控输出长度和多样性指标;3) 使用独立于训练RM的评估RM进行检查;4) 增大KL散度系数beta来约束策略偏离。

Q4:RM训练需要多少偏好数据?

RM训练通常需要10k-100k条偏好对比数据。数据量取决于偏好判断的复杂度——如果偏好差异明显(如好回答vs差回答),1万条即可;如果偏好差异微妙(如两个都不错的回答中选更好的),需要更多数据。关键原则是数据多样性比数量更重要:覆盖不同领域、不同难度、不同长度区间的prompt。建议每增加一个新的应用领域,至少补充5000条该领域的偏好数据。

Q5:RLHF和DPO在效果上差距大吗?应该如何选择?

在大多数偏好对齐任务上,RLHF和DPO效果接近。RLHF的优势在于:1) 在线探索能力——PPO可以通过实时生成发现新的好策略;2) 更精细的控制——通过RM和KL系数可以精确控制对齐强度。DPO的优势在于:1) 训练简单稳定,无需维护四个模型;2) 计算成本低约50%。选择建议:如果任务有明确的可验证奖励,用GRPO;如果只需偏好对齐且资源有限,用DPO;如果需要复杂的偏好控制和在线探索,用RLHF。

Q6:PPO训练中critic模型的作用是什么?能否去掉?

Critic模型(价值模型)的作用是估计每个状态的价值函数V(s),用于计算优势函数A = R - V(s)来降低策略梯度的方差。如果没有critic,优势函数退化为纯奖励R,梯度方差很大,训练不稳定。虽然可以去掉critic(类似REINFORCE算法),但训练效率会大幅下降。GRPO通过组内相对排名巧妙地避开了critic,这是GRPO相比PPO的核心优势之一。如果资源有限,可以考虑用GRPO替代PPO来省去critic的开销。

Q7:RLHF训练需要多大的计算资源?

以7B模型为例,PPO阶段需要同时加载4个模型(策略+参考+RM+critic),每个约14GB(bf16),加上优化器状态和Rollout缓存,总计约80-120GB显存。最低配置:4张A100 40GB或2张A100 80GB。使用LoRA+量化可以降低到40-60GB(2张RTX 4090或1张A100 80GB)。对于14B模型,资源需求翻倍。如果资源不足,强烈建议改用DPO或GRPO——它们的效果接近但资源需求大幅降低。

Q8:RLHF训练后模型在通用能力上退化了怎么办?

这是RLHF的已知问题,称为"对齐税"(alignment tax)。解决方案:1) 增大KL散度系数beta(0.1→0.2),限制策略偏离SFT模型;2) 在PPO训练数据中混入通用任务数据,确保模型不遗忘通用能力;3) 采用多奖励模型——一个偏好RM加一个能力保持RM,综合两者的奖励信号;4) 使用迭代式RLHF——分多轮进行RLHF,每轮后评估通用能力,退化严重时回退checkpoint;5) 考虑使用DPO替代PPO,DPO的KL约束天然更强,对齐税通常更小。