Skip to content

The RLHF Pipeline: Reward Models and PPO

A reward-model-based RLHF pipeline

Collect comparisons
Sample responses and collect preferences for the same prompts.
Fit a reward model
Learn scores whose differences predict those preferences.
Collect policy rollouts
Generate fresh responses and score them with the reward model.
Update the policy
Use estimated advantages and a policy optimizer such as PPO. A separate KL penalty discourages drift from a frozen reference.

Preference collection and policy optimization are distinct stages. PPO clipping is not a hard bound on policy change.

The previous post trained a model on demonstrated responses. Those demonstrations can encode human preferences, but they do not directly label comparisons among the model’s alternative answers.

Preference data adds that comparison: for the same prompt, which response did the annotator favor? RLHF uses those judgments to guide further training.

A reward-model-based RLHF pipeline turns preference judgments into scores, then uses those scores to optimize a language model. It is one way to use comparative feedback; direct preference methods are another.

Prerequisites

This post assumes you've read:


The shape of the pipeline

Take an SFT model, sample responses from it, ask humans which is better, fit a reward model to those preferences, then use the reward model to steer the language model with reinforcement learning.

Four moving pieces:

  1. SFT model (πSFT\pi_{\text{SFT}}). Frozen as the reference for this policy-training stage.
  2. Preference dataset. Pairs (x,yw,yl)(x, y_w, y_l) where ywy_w is the chosen response and yly_l is the rejected one, given the same prompt xx.
  3. Reward model (rϕr_\phi). For example, a pretrained transformer with the language-modeling head swapped out for a single scalar. Trained to rank the chosen response above the rejected one.
  4. Policy (πθ\pi_\theta). Starts as a copy of πSFT\pi_{\text{SFT}}, and PPO gradually updates it to produce responses the reward model likes. The KL penalty tethers it back to πSFT\pi_{\text{SFT}} to discourage drift.

A learned critic often estimates values during PPO as well. PPO’s old rollout policy and the frozen reference serve different roles: the first appears in the surrogate ratio, the second in the KL penalty.


Reward model: turning "A > B" into a scalar

Pairwise judgments can be easier to collect consistently than absolute ratings, though agreement depends on the task, rubric, and annotators.

Given a prompt xx and two candidate responses yay_a and yby_b, a labeler picks one. That's the entire data format: (x,yw,yl)(x, y_w, y_l), where ww means "won" and ll means "lost."

The reward model learns to assign a scalar rϕ(x,y)r_\phi(x, y) to any (prompt, response) pair, such that the chosen response scores higher than the rejected one. The objective comes from the Bradley–Terry preference model, which has been the workhorse for pairwise ranking for over seventy years. The model says: the probability that ywy_w is preferred over yly_l is

P(yw≻yl∣x)=σ(rϕ(x,yw)−rϕ(x,yl))P(y_w \succ y_l \mid x) = \sigma(r_\phi(x, y_w) - r_\phi(x, y_l))

where σ\sigma is the logistic sigmoid. It converts the reward gap to a binary preference probability.

The training loss is the negative log-likelihood of the observed preferences:

LRM(ϕ)=−E(x,yw,yl)∼D[log⁡σ(rϕ(x,yw)−rϕ(x,yl))]\mathcal{L}_{\text{RM}}(\phi) = -\mathbb{E}_{(x, y_w, y_l) \sim \mathcal{D}}\bigl[\log \sigma(r_\phi(x, y_w) - r_\phi(x, y_l))\bigr]

Scores for one labeled preference pair

Example prompt: “What is the capital of France?” The preference label stays fixed; choose a set of toy reward scores to see how the loss changes.

Preferred response, yw

Paris is the capital of France.

Reward score: 2.40

Rejected response, yl

Lyon is the capital of France.

Reward score: -1.10

Margin: rw − rl
3.50
Preference probability: σ(margin)
0.9707
Pairwise loss: −ln(probability)
0.0298 nats

The probability describes the model’s preference between these responses. Reversing the scores gives the labeled preference less probability and a larger loss.

For the same labeled pair, select three assumed reward-score cases and compare the Bradley–Terry preference probability and loss. Ranking the rejected response higher increases the loss; these scores are constructed examples.

A reward model can start from a pretrained or instruction-tuned transformer with a scalar readout on the final token. It need not match the policy’s size or architecture. Its ability to generalize preference judgments affects which errors policy optimization may exploit.

In this setup, the reward model scores a full response, not each token. It reads the whole thing, then outputs one number. In PPO we'll assign that terminal reward to the last token of the sequence and treat every token before it as having reward zero.

Pairwise training identifies score differences. Adding the same prompt-dependent constant to both scores leaves this loss unchanged. A raw score such as +1.3+1.3 therefore has no intrinsic quality meaning, and preference calibration still needs evaluation.


PPO for language models

Proximal Policy Optimization (PPO) uses the reward model’s scores to update the policy initialized from SFT.

A direct policy-gradient estimate can have high variance, and several updates on the same rollout can move the policy far from the one that generated it. PPO’s clipped surrogate reduces the incentive for large changes on individual samples.

PPO-Clip uses a clipped surrogate objective. At each update, we compute the probability ratio

rt(θ)=πθ(at∣st)πθold(at∣st)r_t(\theta) = \frac{\pi_\theta(a_t \mid s_t)}{\pi_{\theta_{\text{old}}}(a_t \mid s_t)}

between the current policy and the policy we used to sample the data. If the ratio is one, nothing has changed. If it's 1.5, we've made the action 50% more likely. PPO limits the objective’s incentive for certain changes in that ratio; it does not impose a hard bound on the ratio itself. Specifically, the clipped surrogate objective is

LCLIP(θ)=Et[min⁡(rt(θ)A^t, clip(rt(θ), 1−ε, 1+ε)A^t)]\mathcal{L}^{\text{CLIP}}(\theta) = \mathbb{E}_t\Bigl[\min\bigl(r_t(\theta) \hat{A}_t,\ \text{clip}(r_t(\theta),\ 1-\varepsilon,\ 1+\varepsilon) \hat{A}_t\bigr)\Bigr]

where A^t\hat{A}_t is the advantage (how much better this action was than the baseline) and ε\varepsilon is typically 0.20.2.

For positive advantage, the surrogate becomes flat when the ratio exceeds 1+ε1+\varepsilon. For negative advantage, it becomes flat below 1−ε1-\varepsilon. In the opposite directions it remains sloped. Shared parameters and other samples can still move a clipped sample’s probability, so clipping is not a hard trust-region constraint.

L = min(rA, clip(r, 0.8, 1.2)A), maximized

A = 1: L = 1.00

Slope +1: increasing this ratio improves the surrogate.

A = -1: L = -1.00

Slope −1: decreasing this ratio improves the surrogate.

Clipping removes an incentive on one side for each advantage sign. It does not constrain the actual ratio to [0.8, 1.2]; other samples and shared parameters still affect it.

Change the ratio and compare positive and negative advantages. Only the beneficial extreme for each sign becomes flat; the actual ratio is not constrained to the clipping interval.

The distinction matters when debugging: a ratio outside the interval does not by itself tell you whether that sample’s surrogate gradient is zero. You also need the advantage sign.


Reward, minus a baseline, minus KL

The PPO loss needs an advantage estimate A^t\hat{A}_t. In the actor-critic recipe here, that estimate combines rewards, a value baseline, and a reference penalty:

  1. Terminal reward. A response-level reward is placed at the last valid response token; intermediate tokens can still have KL penalties.
  2. Returns and baseline. Discounted returns or generalized advantage estimation propagate later rewards to earlier actions. A value function commonly supplies the baseline. Subtracting a batch mean from immediate token rewards is not an equivalent calculation.
  3. Reference penalty. A sampled log ratio to a frozen reference estimates KL under the policy that sampled that token. Its sum has the sequence-KL interpretation when sampling and probability accounting match. Temperature changes or truncated sampling require care.

For the rollout-return construction illustrated here, freeze the sampled log probabilities and use

r~t=rtRM−β⋅log⁡πold(yt∣⋅)πSFT(yt∣⋅)\tilde{r}_t = r^{\text{RM}}_t - \beta \cdot \log \frac{\pi_{\text{old}}(y_t \mid \cdot)}{\pi_{\text{SFT}}(y_t \mid \cdot)}

where rtRMr^{\text{RM}}_t is zero except at the last valid response token. A sampled log ratio can be negative; the corresponding exact KL is nonnegative after expectation under the sampling policy.

The reference penalty discourages exploiting a reward model by moving far from the reference distribution. Its strength trades reward against divergence, but it cannot guarantee correctness or prevent all reward hacking.

Toy two-response policy: reference gives response A probability 0.20. Assumed reward is 1 for A and 0 for B.

Expected reward
0.200
KL to reference
0.000 nats
Reward − 0.3 KL
0.200

At P(A)=1 the KL is log(1/0.2), a finite 1.609 nats.

A computed two-response example with assumed rewards. KL is finite even at a deterministic endpoint because the reference gives both responses positive probability.

Why RLHF is hard: the reward model is the bottleneck

If the reward model favors length, confident tone, or plausible errors, policy optimization can amplify those patterns. Check them against independent evaluations rather than assuming a higher reward implies better answers.

Constructed curves: reward and independent quality can diverge
toy position 0 / 120
0.000.250.500.751.000306090120illustrative optimization progressRM reward (what PPO optimizes)human-judged quality (what we want)reward: 0.080quality: 0.226

Scroll horizontally to read the full diagram.

Constructed curves illustrate a possible divergence between optimized reward and independently judged quality. They are not a measured PPO run.

The usual mitigations are all imperfect: regularize harder with KL (limits drift but also improvement), re-train the RM periodically on fresh policy samples (expensive), use multiple RMs and take a conservative aggregate, or cap training steps with humans watching for drift. Their effectiveness depends on the reward model and evaluation coverage.

The Helpful and Harmless paper and Casper et al.’s review examine these limitations.


Worked example

Consider one PPO update for a single prompt, using constructed rewards and token probabilities.

Prompt: "Explain gradient descent briefly."

Step 1: rollout. Sample four completions from the rollout policy. This toy assumes sampling from the same policy distribution whose log probabilities are recorded.

Step 2: score. We run each (x,yi)(x, y_i) through the reward model.

Step 3: toy advantage. To isolate clipping, omit KL and use each completion’s reward minus the mean 0.40.4 as a fixed advantage for every shown token. This is a constructed sequence-level baseline example, not a full GAE implementation.

Step 4: compute ratios. The update runs for a couple of inner epochs on this same rollout, so by the time we compute gradients, πθ\pi_\theta has drifted from πθold\pi_{\theta_{\text{old}}}. We compute the per-token ratio rt=πθ(yt∣⋅)/πθold(yt∣⋅)r_t = \pi_\theta(y_t \mid \cdot) / \pi_{\theta_{\text{old}}}(y_t \mid \cdot). The token-level ratio goes into the token-level clipped surrogate; do not replace it with a product across the whole response.

Step 5: clip. Positive-advantage terms flatten above 1.2; negative-advantage terms flatten below 0.8. Elsewhere the unclipped term supplies the slope.

Constructed PPO surrogate example (KL omitted) · prompt: "Explain gradient descent briefly." · mean reward baseline b = 0.40
#
completion y_i
RM r(x,y)
advantage A
ratios π_new / π_old (first 5 tokens)
1
"I'd be happy to. Gradient descent is an optimization…"
Σ log π_old = -9.2
+2.40
+2.00
1.051.091.021.071.11
2
"Sure — it's an iterative method that moves opposite…"
Σ log π_old = -11.5
+1.10
+0.70
1.020.981.011.030.99
3
"gradient descent goes downhill"
Σ log π_old = -14.2
-0.30
-0.70
0.910.860.790.820.88clipped
4
"JACKPOT!!! AMAZING QUESTION!!! GRADIENT…"
Σ log π_old = -21.0
-1.60
-2.00
0.550.420.360.580.71clipped
A = r(x, y) − b with b = 0.40. These toy advantages are fixed across the five shown tokens. Red ratios lie on the flat side of the surrogate for this advantage sign; clipping is not a hard bound on the policy.

Constructed rewards average 0.4, giving advantages 2.0, 0.7, −0.7, and −2.0. Red tokens lie on the flat side of the surrogate for their negative advantage.

The advantage signs explain the clipping in the table:

  • Completion 1 has advantage +2.0+2.0 (positive). Its per-token ratios hover just above 1 (the policy now mildly prefers it). All ratios stay inside [0.80,1.20][0.80, 1.20], so the full gradient flows and the policy gets nudged further toward completion 1.
  • Completion 4 has advantage −2.0-2.0 (strongly negative). Its ratios have already dropped to [0.36,0.71][0.36, 0.71], meaning the policy has already moved substantially away. Every one of those ratios is outside 1−ε=0.801 - \varepsilon = 0.80. PPO clips the gradient contribution to zero. The policy already moved; PPO stops further churn on this particular sample.
  • Completion 3 also has negative advantage, but its ratios are only at [0.79,0.91][0.79, 0.91], mostly inside the clipping interval. The 0.79 ratio is on the flat side for a negative advantage; the other four still contribute gradients.

Implementation sketch

The following tensor functions implement reward-model loss, rollout-return construction, and the clipped policy surrogate. They can run independently, but a complete PPO trainer also needs sampling, a value estimator, and an optimizer loop.

import torch
import torch.nn.functional as F
 
def rm_loss(chosen_scores, rejected_scores):
    return F.softplus(-(chosen_scores - rejected_scores)).mean()
 
@torch.no_grad()
def rollout_returns(logp_old, logp_ref, rm_rewards, response_mask, beta=0.02):
    # Right-padded response tokens. Log-probs come from the rollout policy.
    mask = response_mask.bool()
    lengths = mask.sum(-1)
    if (lengths == 0).any():
        raise ValueError("each response must contain a valid token")
    expected = torch.arange(mask.size(1), device=mask.device)[None, :] < lengths[:, None]
    if not torch.equal(mask, expected):
        raise ValueError("response mask must be right-padded")
    rewards = -beta * torch.where(mask, logp_old - logp_ref, 0.0)
    rewards[torch.arange(mask.size(0), device=mask.device), lengths-1] += rm_rewards
    # Undiscounted returns: each earlier action sees subsequent rewards.
    returns = rewards.flip(-1).cumsum(-1).flip(-1)
    return returns * mask
 
def ppo_loss(logp_new, logp_old, advantages, response_mask, eps=0.2):
    # Advantages are fixed rollout estimates, e.g. returns minus a baseline.
    mask = response_mask.bool()
    if not mask.any():
        raise ValueError("no response tokens to score")
    # Select valid entries before arithmetic: padded sentinels may be infinite.
    ratio = (logp_new[mask] - logp_old.detach()[mask]).exp()
    advantage = advantages.detach()[mask]
    objective = torch.minimum(ratio * advantage,
                              ratio.clamp(1-eps, 1+eps) * advantage)
    return -objective.mean()
 
 

softplus(-(r_w − r_l)) computes −log⁡σ(rw−rl)-\log \sigma(r_w - r_l) in a numerically stable form.

The rollout helper places the terminal reward at the last valid token, then computes backward cumulative returns. A production PPO trainer commonly uses a learned value function and GAE. The surrogate accepts detached advantages and masks padding; it does not differentiate through reward construction.

The reference and recorded rollout log probabilities are fixed during a surrogate update. Recomputing new-policy log probabilities supplies the gradient path for the policy loss; a critic has a separate value loss.


Misconceptions

"The reward model directly measures human values." It learns from judgments over a particular set of samples and instructions. Its generalization to new languages, tasks, or policy outputs requires evaluation, especially when the policy is optimized against its scores.

"PPO keeps every ratio inside the clip interval." It does not. The surrogate becomes flat only on one side for each advantage sign. Other terms and parameter sharing can change those ratios further.

"The KL penalty guarantees the policy stays useful." It penalizes distribution shift from a chosen reference. A useful setting depends on reward scale and training recipe, and some recipes use different regularization.

"RLHF makes the model honest / aligned / safe." It optimizes feedback-derived objectives. The data, reward model, sampling distribution, optimizer, and evaluation all affect the result. Preferences can miss factual errors or reward style over substance, so an improved preference score is not a guarantee of any broader property.

What's next

The next post covers DPO and its variants, the supervised shortcut that replaces the entire RM-plus-PPO pipeline with a single closed-form loss on preference pairs, and the assumptions behind that replacement.


Additional reading (and watching)