核心摘要

RLHF(Reinforcement Learning from Human Feedback,基于人类反馈的强化学习)把人类判断转化为模型策略可优化的训练信号。在经典 InstructGPT 流程中,团队先得到能遵循指令的初始策略,再收集回答排序、训练奖励模型,并用 PPO 优化策略,同时约束它与参考模型的偏移。奖励仍然只是代理:分数升高不能证明回答真实、安全,也不能代表所有用户的价值判断。因此,生产级 RLHF 的核心不只是优化算法,还包括数据契约、独立评测、发布门禁和回滚能力。

核心要点

  • RLHF 是一类从人类反馈优化行为的方法;SFT、奖励建模和 PPO 只是其中影响最广的一种实现。
  • 成对奖励模型学习的是“评审者更偏好 A 还是 B”的概率,并没有恢复一个普适的人类效用函数。
  • PPO Clipping 与 KL 惩罚作用不同:前者约束相对采样策略的单次更新,后者限制策略偏离冻结参考模型。
  • 奖励模型准确率只是起点,还要检查校准、标注分歧、分布漂移和奖励过度优化。
  • 发布前必须让候选策略与 SFT 基线在独立的能力、安全、事实性和业务切片上同口径比较。

RLHF 是什么

RLHF 是一种利用人类判断构建奖励信号,再用强化学习优化模型策略的训练方法。它适合“目标很难直接写成损失函数,但人能比较候选行为”的问题,例如判断两段回答哪一段更切题、更谨慎,或更符合明确的产品策略。

业界经常把所有偏好优化都称为 RLHF,容易混淆数据、算法和风险边界。更准确的区分如下:

方法 训练信号 策略更新 名称能证明什么
SFT 目标回答 最大似然训练 模型学习模仿示范
基于 PPO 的 RLHF 由奖励模型表示的人工比较 On-policy 强化学习 策略优化的是既定偏好的代理
DPO 通常是 chosen-rejected 样本对 离线偏好损失 不需要独立奖励模型和 PPO 循环
RLAIF AI 生成或 AI 辅助的反馈 RL 或直接偏好优化 反馈提供方发生变化,评分规则仍可能来自人
RLVR 程序或其他可验证结果 强化学习 奖励可验证,不是学习得到的人类偏好代理

三阶段流程不是 RLHF 的定义。2017 年的 Deep Reinforcement Learning from Human Preferences 用轨迹片段的人工比较学习控制任务奖励;后续的 Learning to Summarize from Human Feedback 与 InstructGPT 才把这一路径系统应用到文本生成。

更关键的边界是:RLHF 只会把模型推向某个提示词分布、标注政策和评审群体表达出来的偏好。InstructGPT 论文也明确说明,其结果是对齐到标注者与研究人员表达的偏好,而不是抽象的“全人类价值观”。

一套完整的 RLHF 系统

RLHF 不是单次训练任务,而是由数据、模型、优化和评测组成的闭环。任何一个环节改变,最终奖励分数的含义都可能变化。

flowchart LR A["目标提示词分布"] --> B["SFT 或初始策略"] B --> C["采样候选回答"] C --> D["按评分准则进行人工比较"] D --> E["偏好数据集"] E --> F["训练并验证奖励模型"] F --> G["从当前策略生成 Rollout"] G --> H["奖励加参考策略约束"] H --> I["PPO 策略更新"] I --> G I --> J["独立人工与任务评测"] J --> K{"通过发布门禁?"} K -->|否| L["修改数据、目标或策略"] K -->|是| M["灰度、监控并保留回滚"]

工程上要明确四份契约:

  1. 行为契约: 哪些提示词、用户、语言和失败场景属于目标范围。
  2. 反馈契约: 谁负责评审,按什么规则判断,怎样处理平局、跳过和升级复核。
  3. 优化契约: 使用哪个奖励、参考策略、约束和停止条件。
  4. 发布契约: 哪些独立指标可以阻断发布并触发回滚。

只要其中一份契约没有版本化,持续上涨的 Reward Curve 就可能掩盖产品质量下降。

阶段零:先定义目标与基线

收集偏好前必须先说明“偏好优化要修复什么”。“让模型更好”无法被评测,也无法判断 RLHF 是否值得投入。

一份可执行的行为规范至少要写清:

  • 目标 Prompt 分布和明确排除的场景;
  • 评审需要判断的回答维度;
  • 多个维度冲突时的优先级;
  • 可接受的拒答与不确定性表达;
  • 受保护人群与高影响场景;
  • 能力、安全、隐私、延迟和成本约束。

随后用同一评测协议记录 Base Model、Prompt-only 方案和 SFT 基线。只有更简单的方法仍留下可量化的偏好问题时,RLHF 才有充分理由。

SFT 常被用作初始策略,是因为原始的 Next-token Prediction 不一定能稳定生成适合评审的交互格式。但它不是理论上的强制步骤。真正的要求是:初始策略能在目标域生成可比较的候选回答,而且发布评测中的基线必须冻结。

阶段一:把偏好数据当作版本化契约

偏好数据 记录候选回答之间的判断,但一个 chosen-rejected 标签不足以还原判断发生的条件。可用记录应保留下列上下文:

字段 工程价值
Prompt 与对话状态 说明回答针对的真实任务
候选文本与生成策略版本 识别分布漂移和模型专属特征
Rubric 与版本 说明采集时“更好”的确切含义
标注者或 Cohort 标识 支持可靠性、分歧与人群分析
选择、平局、跳过和置信度 保留歧义,不强迫每组比较产生赢家
展示顺序与随机化信息 检测位置偏差和界面偏差
数据来源、Consent 与 License 证明数据是否可以合法使用
Split Group 防止 Prompt、会话、用户或模板泄漏

成对比较只表达相对偏好

Pairwise Comparison 往往比绝对打分更容易校准,但它只说明:在当前上下文和评分准则下,某位评审更偏好其中一个回答。它没有说明差距多大、两个回答是否都合格,也没有保证其他评审会同意。

候选回答的生成方式同样会改变学习结果。如果所有 rejected 都是明显错误,模型只能学到表面区分;如果某个来源模型总是更长,奖励模型可能学到篇幅或模型身份,而不是质量。正式采集前应随机展示顺序、混合候选来源、删除完全重复,并先检查长度、格式、拒答率等简单特征。

标注分歧不是纯噪声

不要把所有分歧都压成多数票。2026 年修订的 Diverging Preferences 在两个偏好数据集中观察到大量标注分歧,其中很多来自任务描述不完整、篇幅、回答风格和拒答选择。标准标量奖励模型却可能把分裂的判断转化为一个看似确定的分数。

因此,要按评分维度、Prompt 切片、语言和标注者群体报告一致性,并保留 Tie 与 Skip 原因。对于强主观任务,更合理的方案可能是按用户偏好条件化生成,或把歧义请求路由到澄清流程,而不是训练一个全局唯一答案。

必须先分组,再划分数据集

如果同一 Prompt 派生出多组比较,随机按行切分会导致泄漏。一个 Prompt 的全部候选回答和派生 Pair 必须进入同一 Split;条件允许时,还要独立留出用户、时间、领域和标注者。

InstructGPT 的实际处理说明了这个问题:每个 Prompt 会展示 4 到 9 个回答,最多派生 K choose 2 个高度相关的 Pair。论文发现,若把这些 Pair 独立打乱,一轮训练就可能让奖励模型过拟合,因此按 Prompt 聚合为一个 Batch Element。

阶段二:训练并审计奖励模型

奖励模型 把 Prompt 与回答映射到一个标量:

text
r_theta(x, y) -> 实数分数

常见的 Bradley-Terry 偏好模型用分数差计算成对偏好概率:

text
P(y_chosen > y_rejected | x)
  = sigmoid(r_theta(x, y_chosen) - r_theta(x, y_rejected))

L_RM
  = -E[log sigmoid(r_theta(x, y_chosen) - r_theta(x, y_rejected))]

成对偏好只识别分数差。给所有 Reward 同时加上相同常数,不会改变比较概率。因此,除非系统定义并验证了独立校准流程,否则一个绝对奖励值没有跨模型、跨版本的通用含义。

奖励模型指标分别能证明什么

指标 有效信号 不能证明
Pairwise Accuracy 偏好回答通常是否排在更前 概率是否校准、产品质量是否提高
Pairwise Log Loss 是否惩罚“高置信度但判断错误” 分布外行为是否正确
Brier Score / Calibration Curve 预测概率与实际频率是否接近 一个标量足以表达多元偏好
Slice Accuracy 哪些领域、语言、策略或回答类型较弱 未覆盖攻击上的安全性
Reward 与长度、风格关系 是否存在篇幅或格式捷径 不存在其他隐藏捷径
Cross-policy Evaluation 能否判断更新后策略生成的新回答 激进优化后的持续鲁棒性

验证集必须来自未参与训练的人工判断,并覆盖预期生产分布。一个能正确排序旧候选的奖励模型,未必能判断它随后训练出来的新策略。

用 Go 审计冻结的 Reward 输出

深度学习框架负责训练奖励模型,但发布流水线仍需要独立、可复核的冻结分数审计。下面的 Go 程序不依赖第三方库,计算整体和各切片的 Pairwise Accuracy、Log Loss 与 Brier Score,并拒绝非法数值。

go
package main

import (
	"fmt"
	"math"
	"os"
	"sort"
)

type pair struct {
	slice          string
	chosenReward   float64
	rejectedReward float64
}

type metrics struct {
	count   int
	correct int
	logLoss float64
	brier   float64
}

func softplus(x float64) float64 {
	switch {
	case x > 30:
		return x
	case x < -30:
		return math.Exp(x)
	default:
		return math.Log1p(math.Exp(x))
	}
}

func (m *metrics) add(chosenReward, rejectedReward float64) error {
	if math.IsNaN(chosenReward) || math.IsNaN(rejectedReward) ||
		math.IsInf(chosenReward, 0) || math.IsInf(rejectedReward, 0) {
		return fmt.Errorf("reward must be finite")
	}

	margin := chosenReward - rejectedReward
	probability := 1 / (1 + math.Exp(-margin))

	m.count++
	if margin > 0 {
		m.correct++
	}
	m.logLoss += softplus(-margin)
	m.brier += math.Pow(1-probability, 2)
	return nil
}

func (m metrics) report(name string) {
	fmt.Printf(
		"%s n=%d accuracy=%.1f%% log_loss=%.3f brier=%.3f\n",
		name,
		m.count,
		100*float64(m.correct)/float64(m.count),
		m.logLoss/float64(m.count),
		m.brier/float64(m.count),
	)
}

func main() {
	pairs := []pair{
		{slice: "coding", chosenReward: 2.4, rejectedReward: 0.3},
		{slice: "coding", chosenReward: 0.2, rejectedReward: 0.7},
		{slice: "coding", chosenReward: -0.1, rejectedReward: -0.4},
		{slice: "safety", chosenReward: 1.1, rejectedReward: 0.8},
		{slice: "safety", chosenReward: 0.4, rejectedReward: 1.2},
		{slice: "safety", chosenReward: 1.6, rejectedReward: 0.2},
	}

	overall := &metrics{}
	bySlice := map[string]*metrics{}

	for _, item := range pairs {
		if bySlice[item.slice] == nil {
			bySlice[item.slice] = &metrics{}
		}
		if err := overall.add(item.chosenReward, item.rejectedReward); err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
		if err := bySlice[item.slice].add(item.chosenReward, item.rejectedReward); err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
	}

	overall.report("overall")

	names := make([]string, 0, len(bySlice))
	for name := range bySlice {
		names = append(names, name)
	}
	sort.Strings(names)
	for _, name := range names {
		bySlice[name].report(name)
	}
}

预期输出:

text
overall n=6 accuracy=66.7% log_loss=0.598 brier=0.213
coding n=3 accuracy=66.7% log_loss=0.548 brier=0.193
safety n=3 accuracy=66.7% log_loss=0.649 brier=0.232

整体平均值不能掩盖关键切片回退。正式评测还应为结果提供置信区间,并比较多个 Seed 或 Checkpoint;如果 Safety Slice 低于门槛,即使大量简单样本把总体分数抬高,也必须阻断发布。

Bandit 方法在 RLHF 中适用于哪里

在一个决策边界内,系统选择一种回答策略或模型方案,并且只观察所选方案的反馈,这与多臂老虎机相似;当 Prompt、用户或请求特征会改变最佳方案时,更接近上下文老虎机。上置信界与 Thompson Sampling 可以服务于显式路由或实验选择,但不能直接替代 PPO:自回归生成包含巨大的结构化动作空间、由 Token 条件化的状态,以及延迟到序列结束的奖励。

有模拟器或可信 Oracle 提供反事实价值时,可以用 Regret比较探索策略;普通生产日志却看不到未选回答的奖励。离策略评估只有在决策时上下文、动作 Propensity、Outcome Timing 与 Support 都有效时,才能用另一条策略的日志估计冻结 Target Policy。确定性偏好日志即使同时保存 Chosen 与 Rejected 文本,也不能据此证明任意反事实策略价值。

阶段三:用 PPO 优化策略

PPO 是一种 On-policy Policy Gradient 方法:当前策略生成回答,系统计算奖励和 Advantage,再用这批 Rollout 更新策略。

面向 LLM 的实现通常包含四个逻辑角色:

组件 职责 PPO 阶段通常是否更新
Policy / Actor 生成回答并接收梯度 是
Reference Policy 提供 KL 参照 否
Reward Model 为完整回答生成偏好分数 否
Value Function / Critic 估计 Return,降低梯度方差 是

四个角色不等于必须同时驻留四份完整模型。框架可以共享 Backbone、挂载 Value Head、做模型切分或 Offload。评估工程成本时应记录真实拓扑、精度、序列长度、Batch 和检查点策略,不能把参数量简单乘四当成通用显存要求。

PPO Clipping 不等于 KL 惩罚

这两个约束经常被混为一谈:

  1. PPO Clipping 约束一次参数更新相对生成当前 Rollout 的 Behavior Policy 变化过大。
  2. Reference-policy KL Regularization 惩罚策略偏离一个冻结参考模型,参考模型通常来自 SFT。

简化后的 PPO Clipped Surrogate 为:

text
L_clip(theta)
  = E[min(r_t(theta) * A_t,
          clip(r_t(theta), 1-epsilon, 1+epsilon) * A_t)]

r_t(theta)
  = pi_theta(a_t | s_t) / pi_old(a_t | s_t)

常见的奖励塑形还会加入独立的参考策略项:

text
R(x, y)
  = r_phi(x, y)
    - beta * sum_t(
        log pi_theta(y_t | x, y_<t)
        - log pi_ref(y_t | x, y_<t)
      )

PPO 原始论文 定义的是 Clipped Policy Update。RLHF 系统在此基础上加入 Reward Model、参考策略约束与语言模型 Rollout。Reward Aggregation、KL Estimator、Value Target、Generation Policy 和 Stale Rollout 处理都属于需要版本化的实现选择。

奖励模型通常只为完成后的整段回答给出一个 Scalar Reward,并不是独立评价每个 Token。实现可以把 Terminal Reward 分配到 Token-level Return,再叠加逐 Token 的 KL Reward Shaping,最后计算 Advantage。

监控完整优化路径

每个 Checkpoint 至少要记录:

  • Proxy Reward 与独立人工或任务指标;
  • 在固定测量协议下相对 Reference 的 KL;
  • 回答长度、Entropy、Truncation 与 Repetition;
  • Advantage 均值和方差、Value Loss 与 Explained Variance;
  • PPO Clip Fraction、Ratio Distribution 与 Gradient Norm;
  • 拒答、事实性、策略遵循与能力切片;
  • Rollout Policy、Reward Model、Tokenizer、Prompt Template 与代码版本。

停止条件必须引用独立质量门禁,而不是 Reward 是否收敛。真实质量达到峰值后,策略仍可能继续提高代理奖励。

奖励过度优化与其他失败模式

只要被测偏好与真实目标存在差异,RLHF 就可能失败,而且问题可以在训练前、训练中或上线后出现。

失败层 例子 如何检测 主要缓解方法
目标定义 规则奖励自信回答,但正确行为应是承认不确定 Rubric 评审与对抗样本 定义维度优先级和可接受的不确定性
数据采样 候选只覆盖简单中文问答 覆盖率与 Cohort 报告 分层采样和困难样本挖掘
人工标注 评审对篇幅或拒答分歧 按切片统计 Tie 与 Agreement 保留分歧、澄清 Prompt、细分偏好
奖励建模 Reward 追随长度或生成模型身份 Counterfactual 与简单特征探针 平衡数据、去除伪特征、按切片校准
策略优化 Proxy Reward 上升但独立质量下降 Reward-Human Checkpoint Curve Early Stop、限制偏移、刷新反馈
生产部署 线上用户和 Prompt 偏离采集分布 灰度与上线后切片指标 路由、补采标签或回滚

Scaling Laws for Reward Model Overoptimization 在受控的合成实验中展示了典型 Goodhart 现象:持续优化学习得到的代理奖励时,更大的 Gold Reward 会先上升再下降,而 Proxy Reward 仍继续上升。论文中的具体曲线依赖该实验设置,只能证明这种机制存在,不能当作所有系统的通用停止阈值。

KL Regularization 能限制策略移动范围,但不能证明 Reward 有效。策略可能在很小的 KL 距离内利用局部捷径,过强约束也可能压制真实改进。Reward Ensemble 与 Uncertainty Penalty 同样只能缓解特定失败;产品是否改善,最终仍需独立评测。

InstructGPT 研究真正证明了什么

InstructGPT 是重要的 RLHF 案例,但不是可以直接复制的生产配方。它的实验细节恰好说明结果有多依赖数据和评测设计:

  • 研究通过筛选招募了 40 名 Contractor。
  • SFT、Reward Model 和 PPO 分别使用约 1.3 万、3.3 万和 3.1 万个训练 Prompt;这些数字是 Prompt 数量,不能与派生出的 Pairwise Comparison 数量混用。
  • 每个 RM Prompt 展示 4 到 9 个回答,因此一份 Ranking 会产生多组高度相关的 Pair。
  • 一个 6B Reward Model 被用于优化 1.3B、6B 和 175B 三种规模的策略。
  • 数据中超过 96% 的 Prompt 是英文。
  • 主测试集来自未出现在训练数据中的 API Customer Prompt,论文还单独分析了公共 NLP 任务和 Held-out Labeler。

在这项研究的 Prompt、标注者、模型和协议下,评审更偏好 1.3B InstructGPT 的回答,而不是 175B GPT-3 的回答。论文也报告了特定真实性和毒性测试上的改善,同时明确保留了简单错误、两个偏见基准没有显著改善,以及公共 NLP 能力回退等限制;后者促使研究加入 Pretraining Gradient。

这些结果不能证明通用数据量、模型拓扑、超参数或“RLHF 会让所有模型更安全”。它们证明的是:一条经过严格测量的偏好训练链路,可以显著改变目标分布上的模型行为。

RLHF、SFT、DPO、RLAIF 与 RLVR 如何选择

选型应从“你能信任什么反馈、需要改变什么行为”出发,而不是从方法热度出发。

方法 适用条件 主要工程风险
SFT 能直接示范期望回答 模仿数据伪特征,难表达相对取舍
基于 PPO 的 RLHF 需要围绕学习得到的偏好做 On-policy 探索,并能承担持续评测 奖励过度优化与多组件训练复杂度
DPO 已有固定且有代表性的成对数据,希望先建立较简单的离线基线 偏好过拟合、参考策略敏感、无法自动覆盖数据集之外行为
RLAIF 人工评审是瓶颈,且可用书面规则约束 AI Judge 评审模型偏差和相关性盲区
RLVR 正确性可以由 Test、Solver 或 Environment Outcome 验证 Verifier Bug、奖励漏洞与稀疏奖励

DPO 与 RLHF 对比 详细推导了目标函数和选型矩阵;LLM 微调指南 则回答更上层的 Prompt、RAG、SFT、参数高效微调与偏好优化选型问题。

这些方法可以串联,但阶段更多不等于模型更好。每增加一个阶段,都应绑定一项被独立评测证实的问题,并保留同口径基线。

生产评测与发布门禁

可信的 RLHF 评测必须把“用于优化的指标”和“批准发布的指标”分开。

数据门禁

  • 固定 Prompt、Candidate Policy、Rubric、Annotator Cohort 与 Sampling Weight 版本。
  • 报告 Agreement、Tie、Skip、Adjudication、Duplicate、Leakage、语言覆盖和敏感数据处理。
  • 条件允许时,测试 Prompt 和评审者都应与训练独立。

奖励模型门禁

  • 与回答长度、来源模型等简单基线比较。
  • 按关键切片报告 Pairwise Accuracy、Log Loss、Calibration 与置信区间。
  • 测试更新后 Policy 的回答、对抗 Pair、候选顺序变化和只改变风格的 Counterfactual。
  • 总体收益掩盖 Safety 或关键人群回退时,拒绝该 Reward Model。

策略门禁

  • 在相同 Decoding 参数下比较 Base、SFT 和候选策略。
  • 同时使用 Blind Human Comparison 与任务可用的确定性指标。
  • 分开报告事实性、Groundedness、拒答 Precision / Recall、隐私、偏见、鲁棒性和能力回退。
  • 追踪篇幅和格式,暴露只迎合风格的偏好捷径。

运行门禁

  • 固定 Model、Dataset、Tokenizer、Prompt Template、Reward 与 Evaluation 版本。
  • 灰度发布,监控分布漂移,并保留上一版本的快速回滚能力。
  • 用户反馈是新的数据源,必须重新处理 Consent、Provenance、滥用防护与质量审核。
  • 运行时 Guardrails、Authorization 与副作用控制必须独立于模型训练。

RLHF 只能改变行为概率,不能执行 Tenant Isolation、批准转账、验证医疗事实,也不能保证 Agent 操作获得授权。

常见问题

RLHF 是什么?

RLHF 利用人类判断学习奖励信号,再用强化学习优化模型策略。它最适合“人能稳定比较候选结果,但目标很难写成固定规则”的行为问题。

RLHF 一定要经过 SFT、奖励模型和 PPO 三个阶段吗?

不一定。这是 InstructGPT 推广的经典流程。其他系统可以采用不同初始策略、反馈格式、奖励表示或 RL Optimizer。DPO 等直接偏好方法会使用相似的比较数据,但通常不归入狭义 RLHF,因为它们没有独立的 Reward Model 与 RL Loop。

RLHF 和 DPO 有什么区别?

基于 PPO 的 RLHF 会训练显式 Reward Model,并在优化过程中从当前策略采样。DPO 则在 Reference-policy 公式下直接对 chosen-rejected Pair 使用离线偏好损失。DPO 通常减少了在线训练组件,但没有消除标注偏差、分布漂移、过拟合与独立安全评测。

RLHF 能消除幻觉或保证模型安全吗?

不能。评审可能偏好听起来更自信但未经验证的回答,Reward Model 还可能放大这类捷径。产品必须独立评测事实性与策略遵循,需要证据时强制 Grounding,并把权限与高影响操作交给模型外部的可信控制。

训练 RLHF 需要多少偏好数据?

没有可靠的通用门槛。先用有代表性的小规模试验建立真正未触碰的评测集,再相对 SFT 基线绘制 Learning Curve。应该在分歧、校准或关键切片显示覆盖不足时增加数据,而不是用记录总量宣称已经对齐。

总结

RLHF 的本质是优化“人类判断的学习代理”。真正困难的部分不只是运行 PPO,而是说明谁的偏好有效、保留判断发生的条件、验证奖励模型能否迁移到新策略,并在代理分数取代真实质量前停止优化。

把 SFT 作为强基线,只为已经测量的偏好问题引入 RLHF,并让独立产品指标、安全评测和运行时控制始终留在发布链路中。

一手来源