Part III · RL for LLMs · Chapter 12

RLHF: reward models and PPO

The InstructGPT recipe: preference data, a Bradley–Terry reward model, and PPO with a KL penalty.

~150 minBefore this: PPO, LLM as a policyUpdated 2026-10

Try to write down a reward function for “a helpful answer”. It has to work for a question about tax law, a request for a limerick, a bug report and a medical worry, and it has to return a number. You can’t write it. You can’t write the perfect answer to every prompt either, which is what supervised fine-tuning needs. But show someone two answers to the same question and ask “which is better?”, and they can usually tell you in a few seconds.

Reinforcement learning from human feedback (RLHF) turns that one ability into a training signal. Collect many “this one is better” judgments, fit a model that predicts them, and use that model’s score as the reward for reinforcement learning. Chapter 11 ended with the objective “maximize reward, but stay close to the reference model” and left the reward as a black box r(x,y)r(x, y). This chapter opens the box: where rr comes from (a reward model fitted to comparisons), and how the objective gets optimized (PPO from Chapter 9, run one token at a time). This is the recipe behind InstructGPT and the first ChatGPT.

The recipe in one picture

RLHF as practiced from 2020 to about 2024 has three steps. Each uses a different kind of human data.

Step 1  Supervised fine-tuning (SFT)
        humans write good answers (x, y*)  ──>  fine-tune the pretrained LM  ──>  π_SFT

Step 2  Reward model (RM)
        prompts x ──> sample K answers from π_SFT ──> humans rank them ──> pairs (x, y_w, y_l)
        fit a scalar model r_φ(x, y) so that r_φ(x, y_w) > r_φ(x, y_l) as often as humans say

Step 3  Reinforcement learning (PPO)
        π_θ ← π_SFT,  π_ref ← π_SFT (frozen)
        repeat: sample y ~ π_θ(·|x), reward = r_φ(x, y) − β·KL to π_ref, PPO update

Each step fixes a weakness of the one before. SFT is behavior cloning (Chapter 10): it gets the model into the right style, but it can only copy what demonstrators wrote, and writing good demonstrations is slow. The reward model needs only judgments, which are much cheaper, and once trained it can score millions of answers that no human will ever read. RL then optimizes the model’s own samples against that score, so the model learns from its own mistakes rather than from someone else’s successes.

InstructGPT, the paper that made this recipe famous, used about 13,000 prompts for SFT, 33,000 for the reward model and 31,000 for PPO, labeled by a team of about 40 contractors (Ouyang et al., 2022).

Five papers that built it

YearPaperWhat it added
2017Christiano et al., Deep RL from human preferencesLearn a reward model from pairwise comparisons of short clips of agent behavior, then optimize it with RL (Atari, simulated robots). Covered in Chapter 10.
2019Ziegler et al., Fine-tuning LMs from human preferencesThe same idea on a pretrained language model (GPT-2, 774M parameters), with PPO and a KL penalty folded into the reward. Stylistic continuation from 5,000 comparisons.
2020Stiennon et al., Learning to summarize from human feedbackReddit TL;DR summaries. Their 1.3B RLHF model was preferred over a supervised model 10 times its size, and human-feedback summaries were preferred to the human-written references.
2022Ouyang et al., InstructGPTGeneral instruction following. Labelers preferred outputs of the 1.3B InstructGPT model to those of the 175B GPT-3.
2022Bai et al. (Anthropic), Helpful and harmless assistantThe HH-RLHF dataset; iterated “online” RLHF with fresh human data every week; a study of the tension between helpfulness and harmlessness.

ChatGPT followed in November 2022. OpenAI’s announcement says it was trained with RLHF “using the same methods as InstructGPT, but with slight differences in the data collection setup”.

Collecting preferences

Why comparisons and not scores

The obvious way to get a reward is to ask people for one: “rate this answer from 1 to 7”. In practice this works badly. Your 5 is my 6. My 5 at 9 a.m. is my 6 at 5 p.m., after I’ve seen a hundred bad answers. A score depends on an internal scale that differs between people and drifts over time, and the reward model would have to learn all of that noise.

A comparison cancels the scale. Whatever personal offset you add to every score, it cancels when you only say which of two answers is better. Ziegler et al. (2019) note that labelers found it hard to give consistent fine-grained numbers, and that on synthetic tasks comparisons were almost as informative as absolute scores. Comparisons are also easier: judging is faster than writing, and much faster than calibrating.

Rankings: more pairs per prompt read

The expensive part of labeling is reading the prompt and understanding what a good answer would look like. Once that’s done, comparing more answers is cheap. So instead of one pair, show the labeler KK answers and ask for a ranking. A ranking of KK answers contains (K2)=K(K−1)/2\binom{K}{2} = K(K-1)/2 pairwise comparisons: 6 for K=4K = 4, 36 for K=9K = 9. InstructGPT’s labelers ranked between 4 and 9 answers per prompt.

There is a catch. The 36 pairs from one ranking are strongly correlated: each answer appears in 8 of them. InstructGPT reports that when they shuffled all pairs into one big dataset, the reward model overfit within a single pass. Their fix was to put all (K2)\binom{K}{2} pairs from one prompt into the same batch element, which also needs only KK forward passes instead of 2(K2)2\binom{K}{2}.

Quick check A labeler ranks K = 6 answers to one prompt. How many pairwise comparisons does that ranking give the reward model?

Labelers disagree, a lot

How often do two careful people agree on which answer is better? For InstructGPT, the training labelers agreed with each other 72.6 ± 1.5% of the time; held-out labelers 77.3 ± 1.3%. In Stiennon et al.’s summarization work, researchers agreed with each other 73 ± 4% of the time. Roughly one comparison in four goes the other way depending on who you ask.

That number shapes everything that follows. A preference label is not a fact about the two answers; it is a noisy sample. So we need a probabilistic model of how preferences arise, and a reward model that predicts probabilities, not verdicts.

The Bradley–Terry model

A worked example first

Suppose three answers to one prompt have rewards rA=2r_A = 2, rB=1r_B = 1, rC=−1r_C = -1. The Bradley–Terry model says the probability that a labeler prefers one answer to another depends only on the difference of their rewards, through the logistic sigmoid σ(z)=1/(1+e−z)\sigma(z) = 1/(1+e^{-z}):

PairReward differenceP(first≻second)P(\text{first} \succ \text{second})
A vs B2−1=12 - 1 = 1σ(1)=0.731\sigma(1) = 0.731
A vs C2−(−1)=32 - (-1) = 3σ(3)=0.953\sigma(3) = 0.953
B vs C1−(−1)=21 - (-1) = 2σ(2)=0.881\sigma(2) = 0.881

A reward gap of 1 means “preferred about 73% of the time” (by coincidence, about the inter-labeler agreement from the last section). A gap of 3 means “almost always”. Add 10 to all three rewards and nothing in the table changes.

The model

For a prompt xx and two responses y1,y2y_1, y_2:

P(y1≻y2∣x)  =  σ(r(x,y1)−r(x,y2))  =  er(x,y1)er(x,y1)+er(x,y2).P(y_1 \succ y_2 \mid x) \;=\; \sigma\big(r(x, y_1) - r(x, y_2)\big) \;=\; \frac{e^{r(x, y_1)}}{e^{r(x, y_1)} + e^{r(x, y_2)}}.

Here ≻\succ reads “is preferred to”. The second form is the same thing (divide top and bottom by er(x,y1)e^{r(x,y_1)}), and it is the more illuminating one: each response gets a weight ere^{r}, and the chance of winning is your share of the total weight. Bradley and Terry proposed it in 1952, in statistics, for ranking items from paired comparisons.

Where it comes from: noisy utilities

Why this formula and not some other S-shaped curve? Here is one clean story. When a labeler looks at an answer, they form a momentary impression u=r+εu = r + \varepsilon: the answer’s true quality rr plus noise ε\varepsilon (attention, mood, which details they happened to notice). They prefer whichever answer has the larger uu. If the noise terms are independent and follow a standard Gumbel distribution (the distribution that maxima of many independent variables tend to follow; here it is simply a convenient modeling choice), then

P(u1>u2)=σ(r1−r2)P(u_1 > u_2) = \sigma(r_1 - r_2)

exactly. The derivation is short.

∂ From Gumbel noise to Bradley–Terry

The standard Gumbel distribution has CDF F(ε)=exp⁡(−e−ε)F(\varepsilon) = \exp(-e^{-\varepsilon}) and density f(ε)=e−εexp⁡(−e−ε)f(\varepsilon) = e^{-\varepsilon}\exp(-e^{-\varepsilon}).

Let u1=r1+ε1u_1 = r_1 + \varepsilon_1 and u2=r2+ε2u_2 = r_2 + \varepsilon_2 with ε1,ε2\varepsilon_1, \varepsilon_2 independent standard Gumbel, and write Δ=r1−r2\Delta = r_1 - r_2. Response 1 wins when ε2<ε1+Δ\varepsilon_2 < \varepsilon_1 + \Delta. Condition on ε1\varepsilon_1:

P(u1>u2)=∫−∞∞f(ε1) F(ε1+Δ) dε1=∫−∞∞e−εexp⁡ ⁣(−e−ε)exp⁡ ⁣(−e−εe−Δ) dε.P(u_1 > u_2) = \int_{-\infty}^{\infty} f(\varepsilon_1)\, F(\varepsilon_1 + \Delta)\, d\varepsilon_1 = \int_{-\infty}^{\infty} e^{-\varepsilon}\exp\!\big(-e^{-\varepsilon}\big)\exp\!\big(-e^{-\varepsilon}e^{-\Delta}\big)\, d\varepsilon .

Combine the two exponentials: exp⁡ ⁣(−e−ε(1+e−Δ))\exp\!\big(-e^{-\varepsilon}(1 + e^{-\Delta})\big). Now substitute t=e−εt = e^{-\varepsilon}, so dt=−e−ε dεdt = -e^{-\varepsilon}\,d\varepsilon and the limits ε:−∞→∞\varepsilon: -\infty \to \infty become t:∞→0t: \infty \to 0:

P(u1>u2)=∫0∞exp⁡ ⁣(−t(1+e−Δ)) dt=11+e−Δ=σ(r1−r2).P(u_1 > u_2) = \int_0^{\infty} \exp\!\big(-t(1 + e^{-\Delta})\big)\, dt = \frac{1}{1 + e^{-\Delta}} = \sigma(r_1 - r_2).

Another way to say the same thing: the difference η=ε2−ε1\eta = \varepsilon_2 - \varepsilon_1 of two independent standard Gumbel variables has the standard logistic distribution, whose CDF is exactly σ\sigma. Response 1 wins when η<Δ\eta < \Delta, which has probability σ(Δ)\sigma(\Delta). So Bradley–Terry is often described as a “logistic noise” model: only the noise on the comparison matters, and it is logistic.

The same trick with KK answers gives the probability that answer ii has the largest uu:

P(i is best)=eri∑j=1Kerj,P(i \text{ is best}) = \frac{e^{r_i}}{\sum_{j=1}^K e^{r_j}},

a softmax. Sorting all KK answers by r+εr + \varepsilon gives a full random ranking whose distribution is called the Plackett–Luce model; Bradley–Terry is its K=2K = 2 case. Ziegler et al. (2019) used exactly this softmax: labelers picked the best of four continuations, and the reward model was trained to predict which one.

With Gaussian instead of Gumbel noise you get the Thurstone model, P=Φ((r1−r2)/2)P = \Phi\big((r_1 - r_2)/\sqrt 2\big) with Φ\Phi the normal CDF. The two curves are hard to tell apart with real data; the logistic one is used because its log-likelihood is simple and its gradient is clean.

Three ways to read the formula

  • Chess ratings. The Elo system predicts that a player rated RAR_A beats one rated RBR_B with probability 1/(1+10−(RA−RB)/400)1/(1 + 10^{-(R_A - R_B)/400}). That is Bradley–Terry with r=Rln⁡10/400r = R \ln 10 / 400. One unit of reward is about 174 Elo points. Christiano et al. (2017) make this analogy themselves.
  • Logistic regression. If you only look at the difference Δ=r(x,y1)−r(x,y2)\Delta = r(x, y_1) - r(x, y_2), Bradley–Terry is logistic regression of “was y1y_1 preferred?” on Δ\Delta, with the slope fixed to 1.
  • A two-state Boltzmann system. Treat each answer as a state with energy E=−rE = -r at temperature T=1T = 1. The probability of finding the system in state 1 is e−E1/(e−E1+e−E2)e^{-E_1}/(e^{-E_1} + e^{-E_2}), the Bradley–Terry probability. With KK answers it is the canonical ensemble. Two facts carry over directly. Energies are defined up to a constant, and so are rewards. And the temperature sets the scale: noisier labelers act like a higher temperature, so the same quality differences produce probabilities closer to 1/2. Since the model fixes T=1T = 1, a reward model fitted to noisy labelers comes out with smaller reward gaps. Reward units are “log-odds of being preferred”, not an absolute measure of quality.

The demo lets you feel the model. Drag the three answers along the reward axis and watch the pairwise probabilities move along the sigmoid; then use the shift buttons.

Interactive Bradley–Terry: preferences from reward differences

What to try: press 'Shift all +1' a few times. Every probability stays the same, because only differences matter. Now press 'Gaps × 2': probabilities move toward 0 and 1. Drag A until P(A ≻ B) = 0.90 and read off the gap (it is ln 9 ≈ 2.2). Drag B on top of C: P(B ≻ C) = 0.5, and A's chance of being picked as best of all three (about 0.91) is lower than either of its pairwise wins (0.95), because with two rivals there are two ways to lose.

Quick check A reward model gives answer A a reward of 3 and answer B a reward of 1. You add 100 to every reward the model outputs. What is the predicted P(A ≻ B) now?

What Bradley–Terry cannot express

The model assumes every answer has one number, so preferences must be transitive in probability: if A usually beats B and B usually beats C, then A beats C even more often. Real people are not always like that, and a population of labelers with different tastes can produce cycles (A ≻ B ≻ C ≻ A) even when each individual is consistent. Bradley–Terry averages such disagreements into one scalar. Some later work drops the scalar reward entirely and learns a pairwise preference model, then looks for a policy that wins such comparisons against any opponent (for example, Nash learning from human feedback, Munos et al. 2023). Almost all deployed RLHF has used a scalar reward model, so that is what we build.

Training a reward model

Architecture: a language model with a one-number head

A reward model rϕ(x,y)r_\phi(x, y) reads a prompt and a response and outputs one real number. To judge text it has to understand text, so it starts from a pretrained language model, usually the SFT model itself:

tokens:     [ prompt x ............ ][ response y ...... ][EOS]
                         │  transformer (initialized from π_SFT)
hidden:      h_1  h_2  ...                         ...   h_last ∈ R^d
                                                            │  linear head  w·h + b   (replaces the
                                                            ▼                          vocabulary head)
                                                       r_φ(x, y)  ∈ R

The language model’s final layer, which maps the hidden state to logits over the vocabulary, is removed and replaced by a linear layer with one output. The score is read at the last token (usually the end-of-sequence token). In a causal transformer only the last position has attended to the whole prompt and the whole response, so it is the natural place to summarize them. InstructGPT used one 6B-parameter reward model for policies of every size (1.3B, 6B and 175B); they report that 175B reward models trained unstably.

The loss

Fitting Bradley–Terry by maximum likelihood gives the reward model loss: for each labeled pair (x,yw,yl)(x, y_w, y_l), where ywy_w won and yly_l lost,

L(ϕ)=− E(x,yw,yl)[log⁡σ(rϕ(x,yw)−rϕ(x,yl))].\mathcal L(\phi) = -\,\mathbb E_{(x, y_w, y_l)}\Big[\log \sigma\big(r_\phi(x, y_w) - r_\phi(x, y_l)\big)\Big].

This is binary cross-entropy where the “logit” is the reward difference and the label is always “the first one won”. Its gradient tells you what training does to each pair. Write Δ=rϕ(x,yw)−rϕ(x,yl)\Delta = r_\phi(x, y_w) - r_\phi(x, y_l). Since ddΔ[−log⁡σ(Δ)]=−(1−σ(Δ))\frac{d}{d\Delta}\big[-\log\sigma(\Delta)\big] = -(1 - \sigma(\Delta)),

∇ϕL=− E[(1−σ(Δ)) (∇ϕrϕ(x,yw)−∇ϕrϕ(x,yl))].\nabla_\phi \mathcal L = -\,\mathbb E\Big[\big(1 - \sigma(\Delta)\big)\,\big(\nabla_\phi r_\phi(x, y_w) - \nabla_\phi r_\phi(x, y_l)\big)\Big].

Every step raises the winner’s score and lowers the loser’s, weighted by 1−σ(Δ)1 - \sigma(\Delta), the probability the model currently assigns to the wrong outcome:

Δ=rw−rl\Delta = r_w - r_lLoss −log⁡σ(Δ)-\log\sigma(\Delta)Weight 1−σ(Δ)1 - \sigma(\Delta)Reading
−22.1270.881confidently wrong: big push
00.6930.500can’t tell them apart
20.1270.119right, fairly confident: small push
50.0070.007right and sure: almost ignored

Pairs the model already gets right with confidence stop mattering, so the effort goes to the pairs it gets wrong. And a pair that labelers disagree on (the same two answers labeled once each way) pulls in both directions until Δ=0\Delta = 0: the reward model learns the labelers’ rate of preference, not a verdict (Exercise 12.4).

The reward is only defined up to a constant per prompt

The two responses in a pair always share the prompt xx. So if you add any function of the prompt alone to the reward,

r′(x,y)=rϕ(x,y)+c(x),r'(x, y) = r_\phi(x, y) + c(x),

every difference r′(x,yw)−r′(x,yl)r'(x, y_w) - r'(x, y_l) is unchanged and so is the loss. The data cannot tell rϕr_\phi from r′r'. This is the “only differences are measurable” idea again, now with a separate zero point for every prompt.

Three consequences:

  1. Scores across prompts are not comparable. A reward of 2.0 on one prompt and 0.5 on another doesn’t mean the first answer is better; the two prompts may just have different offsets.
  2. RL doesn’t care, in principle. A per-prompt constant changes neither the optimal KL-regularized policy (it cancels in the normalization of π∗\pi^*; Exercise 12.3) nor the expected policy gradient (it acts like a baseline, Chapter 7). It does add variance, which the critic or advantage normalization has to absorb.
  3. So normalize. InstructGPT adds a bias so that the human demonstrations score 0 on average before RL starts. Ziegler et al. rescale the reward to mean 0 and variance 1 under the initial policy. This also makes β\beta mean roughly the same thing from one reward model to the next.

The scale of the reward, unlike its zero point, is fixed by the data: the sigmoid’s slope is 1, so a gap of 1 always means 73%. As the Boltzmann reading predicted, noisier labelers produce a reward model with smaller gaps.

Accuracy and calibration

Two numbers tell you whether a reward model is any good.

  • Accuracy: on held-out pairs, how often is rϕ(x,yw)>rϕ(x,yl)r_\phi(x, y_w) > r_\phi(x, y_l)? Because labels are noisy, 100% is impossible. Suppose a pair is truly preferred one way with probability pp. Even a perfect model, which always predicts the more likely side, is right only max⁡(p,1−p)\max(p, 1-p) of the time. Averaged over pairs, that is the accuracy ceiling. It sits somewhat above the inter-labeler agreement p2+(1−p)2p^2 + (1-p)^2: for p=0.75p = 0.75, the ceiling is 75% but two labelers agree only 62.5% of the time, because the reward model predicts the average labeler, while each of the two labelers adds its own noise. Stiennon et al.’s 6.7B reward model, tested on a new domain (news articles), agreed with labelers about as often as labelers agreed with each other. On human preference data, accuracies in the high 60s or low 70s are normal, not a sign of failure.
  • Calibration: when the model says σ(Δ)=0.8\sigma(\Delta) = 0.8, do labelers prefer ywy_w about 80% of the time? Bai et al. (2022a) check this and find their preference models trained on helpfulness data very well calibrated, and slightly less so when harmlessness data is mixed in. Calibration matters because RL treats reward differences as meaningful amounts, not just orderings.

Now watch a reward model learn. The demo has six responses with hidden true qualities (rings). A simulated labeler compares random pairs with Bradley–Terry noise, and a reward model with one free score per response (dots, all starting at 2) is fit by gradient descent on the loss above, plus a tiny L2 penalty on the spread of the scores. κ (kappa) sets how consistent the simulated labeler is: labels follow σ(κ(si−sj))\sigma(\kappa(s_i - s_j)) for true qualities ss, so κ plays the role of an inverse temperature. The “spread ratio” is the standard deviation of the fitted scores divided by that of the true ones.

Interactive Fitting a reward model to noisy comparisons
true quality s (hidden)fitted score r̂ (starts at 2 for everyone)

What to try: press Play. The dots line up parallel to the rings but stay shifted up: the dashed mean line never moves, because the loss can't see a constant. Press 'Subtract the mean' and they match. Then set κ = 0.25 (inconsistent labelers): the fitted scores bunch together, and the spread ratio drops to about κ. Finally set 10 comparisons with κ = 4: the training loss goes near 0, but held-out accuracy falls well short of the ceiling, because 10 labels are too few and the model is overconfident.

Quick check Your reward model scores 71% on held-out human comparisons. Labelers agree with each other on about 73% of pairs. What is the most reasonable conclusion?

Optimizing the reward with PPO

The objective, again

With a reward model in hand, step 3 solves the problem from Chapter 11:

max⁡θ    Ex∼D[ Ey∼πθ(⋅∣x)[rϕ(x,y)]  −  β KL(πθ(⋅∣x) ∥ πref(⋅∣x))].\max_\theta \;\; \mathbb E_{x \sim \mathcal D}\Big[\, \mathbb E_{y \sim \pi_\theta(\cdot\mid x)}\big[r_\phi(x, y)\big] \;-\; \beta\, \mathrm{KL}\big(\pi_\theta(\cdot\mid x) \,\Vert\, \pi_\text{ref}(\cdot\mid x)\big) \Big].

Its exact optimum is the reference model tilted by the reward, π∗(y∣x)∝πref(y∣x) erϕ(x,y)/β\pi^*(y\mid x) \propto \pi_\text{ref}(y\mid x)\, e^{r_\phi(x, y)/\beta} (Chapter 10 derives it as a Gibbs variational principle; Chapter 11 restates it for language models). We can’t sample from π∗\pi^* directly: its normalizer sums over every possible response. So we use RL to move πθ\pi_\theta toward it, one gradient step at a time.

The KL term matters more here than anywhere else in the course. The reward model was trained on answers from πSFT\pi_\text{SFT}. Far from those answers it has never seen a label, and its scores there are extrapolation. The KL leash keeps the policy where the reward model knows what it’s talking about. (Chapter 11 gives two more reasons: it preserves fluency and diversity, and it stops the policy from collapsing onto one answer.) The lab shows what happens when you cut the leash.

Four models

PPO-based RLHF juggles four networks of similar size:

ModelJobTrained during RL?Initialized from
Policy πθ\pi_\theta (actor)generates responses; the thing we are trainingyesSFT model
Reference πref\pi_\text{ref}anchor for the KL penaltyno, frozenSFT model
Reward model rϕr_\phiscores each finished responseno, frozenSFT model, then trained on comparisons
Value model VψV_\psi (critic)predicts future reward from each partial responseyesreward model (InstructGPT)

There is also πold\pi_\text{old} from Chapter 9, the policy that generated the current batch, but it isn’t a fifth network: it is just the policy’s log-probabilities, recorded once at sampling time. Two of the four models need gradients and optimizer states, which is why PPO-RLHF is memory-hungry (Exercise 12.8, and Chapter 20 for systems).

Stiennon et al. give the critic its own parameters rather than a value head on the policy: when they shared them, early value-function updates damaged the pretrained policy.

The language model as an RL agent

From Chapter 11: the state sts_t is the prompt plus the tokens so far, (x,y<t)(x, y_{<t}); the action is the next token yty_t; transitions are deterministic (append the token); the episode ends at the end-of-sequence token or a length limit. Episodes are short and finite, so there is no discounting: γ=1\gamma = 1. InstructGPT states “no discount is applied”.

Per-token rewards

The reward model gives one number for the whole response. The KL penalty, on the other hand, splits naturally over tokens, because the log-probability of a sequence is a sum of token log-probabilities:

log⁡πθ(y∣x)πref(y∣x)=∑t=1Tlog⁡πθ(yt∣x,y<t)πref(yt∣x,y<t).\log\frac{\pi_\theta(y\mid x)}{\pi_\text{ref}(y\mid x)} = \sum_{t=1}^{T} \log\frac{\pi_\theta(y_t\mid x, y_{<t})}{\pi_\text{ref}(y_t\mid x, y_{<t})}.

So PPO-RLHF gives every token tt of a response with TT tokens a per-token reward

rt=−βlog⁡πθ(yt∣x,y<t)πref(yt∣x,y<t)  +  {rϕ(x,y)t=T (the last token)0otherwise.r_t = -\beta \log\frac{\pi_\theta(y_t\mid x, y_{<t})}{\pi_\text{ref}(y_t\mid x, y_{<t})} \;+\; \begin{cases} r_\phi(x, y) & t = T \text{ (the last token)}\\ 0 & \text{otherwise.}\end{cases}

The rewards of a response add up to rϕ(x,y)−βlog⁡πθ(y∣x)πref(y∣x)r_\phi(x, y) - \beta \log\frac{\pi_\theta(y\mid x)}{\pi_\text{ref}(y\mid x)}. Its expectation over y∼πθy \sim \pi_\theta is exactly the objective above, since the expected log-ratio is the KL. In Chapter 11’s terms, each token’s penalty is the k1k_1 estimator of the KL, and the policy pays it as it goes.

Worked example. Prompt: “Capital of France?”. The policy samples a three-token response, “Paris”, ”.”, EOS. The reward model scores it rϕ=1.5r_\phi = 1.5, and β=0.1\beta = 0.1.

Token ttyty_tlog⁡πθ\log\pi_\thetalog⁡πref\log\pi_\text{ref}log-ratiortr_t
1Paris−0.3−0.8+0.5−0.1×0.5=−0.05-0.1 \times 0.5 = -0.05
2.−0.9−0.7−0.2−0.1×(−0.2)=+0.02-0.1 \times (-0.2) = +0.02
3EOS−0.1−0.10.00+1.5=1.500 + 1.5 = 1.50

The total is 1.47=1.5−0.1×0.31.47 = 1.5 - 0.1 \times 0.3. The policy has made “Paris” more likely than the reference does, so it pays 0.05 for that token. It made ”.” less likely, so that token earns a small refund: single-token log-ratios can be negative, even though their expectation, the KL, can’t.

Two details. These rewards are computed once, at sampling time, from πold\pi_\text{old}‘s log-probabilities, with no gradient flowing through them: the KL is part of the reward, not the loss. (GRPO, in Chapter 15, instead adds a KL estimate to the loss, which gives a different gradient; Chapter 16 compares the two.) And the reward model must actually see an end-of-sequence token, because that’s where it reads its score: implementations give a fixed penalty to responses that hit the length limit without one (Huang et al. 2024 call this the “EOS trick”).

Advantages from a value head

With per-token rewards and a critic, advantages are computed exactly as in Chapter 8: TD errors δt=rt+V(st+1)−V(st)\delta_t = r_t + V(s_{t+1}) - V(s_t) with γ=1\gamma = 1, combined by GAE, A^t=∑l≥0λlδt+l\hat A_t = \sum_{l \ge 0} \lambda^l \delta_{t+l}. The state after the last token is terminal, with value 0.

What does the critic predict? At each prefix, the total reward still to come: the final reward-model score, minus the KL penalties still to be paid. In plain words, “how good will this half-written answer end up?” Initializing it from the reward model gives it a head start, since the reward model already judges text.

Worked example, continued. Say the critic outputs V(s1)=1.0V(s_1) = 1.0 before “Paris”, V(s2)=1.2V(s_2) = 1.2 before ”.”, and V(s3)=1.4V(s_3) = 1.4 before EOS. Then

δ3=1.50+0−1.4=0.10,δ2=0.02+1.4−1.2=0.22,δ1=−0.05+1.2−1.0=0.15.\delta_3 = 1.50 + 0 - 1.4 = 0.10, \qquad \delta_2 = 0.02 + 1.4 - 1.2 = 0.22, \qquad \delta_1 = -0.05 + 1.2 - 1.0 = 0.15.

With λ=1\lambda = 1 the advantages are Monte Carlo returns minus values: A^3=0.10\hat A_3 = 0.10, A^2=0.32\hat A_2 = 0.32, A^1=0.47\hat A_1 = 0.47 (check: the whole return 1.47 minus V(s1)=1.0V(s_1) = 1.0). With λ=0.95\lambda = 0.95: A^3=0.10\hat A_3 = 0.10, A^2=0.22+0.95×0.10=0.315\hat A_2 = 0.22 + 0.95 \times 0.10 = 0.315, A^1=0.15+0.95×0.315≈0.449\hat A_1 = 0.15 + 0.95 \times 0.315 \approx 0.449. All three tokens get pushed up, “Paris” the most: the critic didn’t expect this answer to go so well.

The PPO-RLHF loop

Putting it together:

PPO-based RLHF  (InstructGPT-style)
inputs: π_SFT, reward model r_φ, prompt set D, KL coefficient β, clip ε, GAE λ
π_θ ← π_SFT;   π_ref ← π_SFT (frozen);   V_ψ ← copy of r_φ (trainable)
for iteration = 1, 2, ...:
  1. Rollout: sample prompts x ~ D; generate y ~ π_θ(·|x) (temperature 1, max length L).
     Record per token:  logp_old_t = log π_θ(y_t | x, y_<t),   V_old_t = V_ψ(x, y_<t)
  2. Score:   s = r_φ(x, y) at the EOS token (fixed penalty if there is no EOS)
              ref_t = log π_ref(y_t | x, y_<t)
  3. Rewards: r_t = −β·(logp_old_t − ref_t);   r_T += s
  4. Advantages: Â_t = GAE(γ = 1, λ) from r_t and V_old_t;   targets R_t = Â_t + V_old_t
                 normalize  over the batch's tokens
  5. Update, for n_epochs passes over minibatches:
       ρ_t      = exp(log π_θ(y_t|·) − logp_old_t)
       L_policy = − mean over tokens of min(ρ_t Â_t, clip(ρ_t, 1−ε, 1+ε) Â_t)
       L_value  =   mean over tokens of (V_ψ(x, y_<t) − R_t)²
       (PPO-ptx) add − γ_ptx · mean log π_θ(pretraining text)
       one optimizer step on L_policy + c·L_value (+ the ptx term)    (c ≈ 0.5: value-loss weight)
  6. Optionally adapt β toward a target KL.

Steps 4 and 5 are Chapter 9’s PPO unchanged, with tokens as time steps. “Mean over tokens” means padding and prompt tokens are masked out: only generated tokens are actions.

The details that make it work

PPO on language models has a reputation for being fiddly, and much of the craft lives in details. The most important ones:

  • Small, careful updates. InstructGPT used batches of 512 rollouts split into 8 minibatches of 64, a single PPO epoch per batch, clip ϵ=0.2\epsilon = 0.2, sampling temperature 1, β=0.02\beta = 0.02, and an exponential moving average of the policy weights, for 256k episodes in total.
  • Reward normalization or whitening. Rescale reward-model scores (or per-batch rewards) to a standard range, so β\beta, the learning rate and the clip mean the same thing across reward models. Advantage normalization (Chapter 9) is standard too. Xu et al. (2024) name advantage normalization, large batches and a moving-average reference model as the key factors for PPO in RLHF.
  • An adaptive KL coefficient. Runs with the same fixed β\beta can end up at very different KLs. Ziegler et al. adapt it toward a target with a proportional controller: et=clip⁡((KLt−KLtarget)/KLtarget,−0.2,0.2)e_t = \operatorname{clip}\big((\mathrm{KL}_t - \mathrm{KL}_\text{target})/\mathrm{KL}_\text{target}, -0.2, 0.2\big), βt+1=βt(1+0.1 et)\beta_{t+1} = \beta_t(1 + 0.1\, e_t). It plays the same role as PPO-penalty’s adaptive β\beta in Chapter 9, but for the leash rather than the trust region.
  • Length limits and the EOS trick. Cap the generation length; penalize responses that hit the cap without finishing, since the reward model can only score finished ones.
  • Dropout off. With dropout, recomputing a token’s log-probability gives a different number each time, so the ratio ρt\rho_t and the KL penalty are not well defined. Ziegler et al. and later reproductions switch it off.
  • PPO-ptx, against the alignment tax. InstructGPT’s RLHF models got worse than GPT-3 on some public benchmarks (SQuAD, DROP, HellaSwag, WMT French-to-English translation). The authors call this an alignment tax: a capability cost of alignment. Their fix, PPO-ptx, mixes ordinary next-token training on pretraining data into the RL updates, γptx Ex∼Dpretrain[log⁡πθ(x)]\gamma_\text{ptx}\,\mathbb E_{x\sim\mathcal D_\text{pretrain}}[\log\pi_\theta(x)] with γptx=27.8\gamma_\text{ptx} = 27.8 (the paper calls it γ\gamma; it has nothing to do with the discount). It greatly reduced the regressions without lowering labelers’ preference scores. Bai et al. (2022a) report that only their smaller models pay such a tax; their 13B and 52B RLHF models did better on most zero-shot NLP evaluations than the corresponding plain language models.

Quick check During PPO-based RLHF, which of the four models receive gradient updates?

When the reward model is wrong

Everything above optimizes rϕr_\phi, a model of human judgment fitted to tens of thousands of comparisons. Optimize hard enough against any model and you will find its mistakes.

Stiennon et al. (2020) measured this directly. They trained policies against one reward model with a range of KL coefficients and asked humans to judge the results. Under light optimization, real human preference improved along with the reward model’s score. Pushed further, the reward model’s score kept rising while actual preference fell, until the reward model became anti-correlated with what people wanted. Bai et al. (2022a) report that during RLHF the reward rises roughly linearly in the square root of the KL from the initial policy. Gao et al. (2022) turned these observations into scaling laws for reward model overoptimization; Chapter 19 is about them and about reward hacking in general.

The lab reproduces the shape in miniature. A tiny reward model learns, from noisy rankings, that the hidden labeler likes answers ending in an even digit. It works well on the SFT model’s answers. But it adds up a weight per digit, so it has a blind spot: more even digits always score higher, even past the point where the answer stops being well formed. Run PPO with β=0\beta = 0 and, after about 30 iterations of genuine improvement, the policy discovers the blind spot. It stops emitting EOS, pads its answers with even digits (4444), and drives the reward model’s score up while the hidden labeler’s score falls to its minimum. With β=0.1\beta = 0.1 the hack never happens, and with PPO-ptx the arithmetic skill that the labeler never asked about survives too.

The mitigations are the subject of later chapters. Keep β\beta honest, and watch the KL. Collect fresh comparisons on the current policy’s outputs and retrain the reward model, as Bai et al. did every week (“iterated online RLHF”). Replace human labels with AI feedback or rubrics where possible (Chapter 14). Fold the reward model into the policy and skip RL altogether (Chapter 13). Or move to tasks where the reward can be checked instead of predicted (Chapter 15).

Summary

  • RLHF has three steps: SFT on demonstrations, a reward model fitted to human comparisons, and PPO against that reward model with a KL penalty to the SFT model.
  • People compare more reliably than they score. A ranking of KK answers gives (K2)\binom{K}{2} correlated pairs. Labelers agree only about 73% of the time, so labels are noisy samples.
  • Bradley–Terry: P(y1≻y2)=σ(r1−r2)P(y_1 \succ y_2) = \sigma(r_1 - r_2). It follows from Gumbel noise on utilities, it is Elo with a different unit, and it is a two-state Boltzmann distribution with energy −r-r. Rewards are defined only up to a constant per prompt; their scale reflects labeler consistency.
  • The reward model is an LM with a scalar head read at the last token, trained with −log⁡σ(rϕ(x,yw)−rϕ(x,yl))-\log\sigma(r_\phi(x, y_w) - r_\phi(x, y_l)). Each pair is weighted by how wrong the model still is. Good accuracy is near the label-noise ceiling, not near 100%; calibration matters too.
  • PPO-RLHF uses four models (policy, frozen reference, frozen reward model, critic). Each token gets −βlog⁡πθπref-\beta\log\frac{\pi_\theta}{\pi_\text{ref}}; the last token also gets rϕ(x,y)r_\phi(x, y). GAE with γ=1\gamma = 1 turns this into per-token advantages, and Chapter 9’s clipped loss does the rest.
  • The clip is a trust region to πold\pi_\text{old}; the β\beta term is a leash to πref\pi_\text{ref}. Practical keys: normalized rewards and advantages, small conservative updates, an adaptive β\beta, the EOS trick, dropout off, and PPO-ptx against the alignment tax.
  • A reward model is a proxy. Optimized hard, its score keeps rising while true quality falls. The KL leash is the first line of defense.

Exercises

Exercise 12.1Why compare instead of score?Concept●○○

A colleague proposes to skip comparisons: labelers will rate each answer from 1 to 10, and the reward model will regress on the ratings with a squared loss. Give two reasons this tends to work worse than pairwise comparisons, and one thing ratings can tell you that comparisons cannot.

Solution

Why comparisons work better.

  1. Personal scales cancel. Each labeler uses the 1–10 scale differently (one gives 7 to anything acceptable, another reserves 7 for excellent), and their scale drifts during a session. A regression on raw ratings has to fit all of that labeler-specific offset and stretch as if it were signal. In a comparison, any per-labeler offset (and any monotone distortion of their scale) cancels: only the ordering is reported.
  2. Judging relative quality is easier and more consistent. Deciding which of two answers is better, with both side by side, is a simpler task than placing one answer on an absolute scale. Ziegler et al. (2019) report that labelers found consistent fine-grained numbers hard to give, and that comparisons were nearly as informative on synthetic tasks.

A third, related point: the RL step only needs reward differences between responses to the same prompt (a per-prompt constant acts like a baseline), and differences are exactly what comparisons measure.

What ratings tell you that comparisons don’t: absolute level. If both answers are terrible, a comparison still says one “won”. A rating can say “both are 2/10”, which is useful for spotting prompts where the model needs new demonstrations, for filtering data, or for an evaluation that is comparable across prompts. (InstructGPT did collect 1–7 Likert ratings, but as evaluation metadata, not to train the reward model.)

Exercise 12.2Bradley–Terry from a noise modelPen & paper●●○

A labeler’s impression of answer ii is ui=ri+εiu_i = r_i + \varepsilon_i, with ε1,ε2\varepsilon_1, \varepsilon_2 independent, and they prefer the answer with the larger uu.

(a) Show that if the εi\varepsilon_i are standard Gumbel (CDF F(ε)=exp⁡(−e−ε)F(\varepsilon) = \exp(-e^{-\varepsilon})), then P(1≻2)=σ(r1−r2)P(1 \succ 2) = \sigma(r_1 - r_2).

(b) Suppose instead the labelers are noisier, εi=s gi\varepsilon_i = s\,g_i with gig_i standard Gumbel and s>0s > 0. What is P(1≻2)P(1 \succ 2) now? If you fit a Bradley–Terry reward model (which assumes s=1s = 1) to such labels, how do the fitted rewards relate to the true rir_i?

Hint
For (a), condition on ε1\varepsilon_1 and integrate f(ε1)F(ε1+Δ)f(\varepsilon_1)F(\varepsilon_1 + \Delta); the substitution t=e−εt = e^{-\varepsilon} finishes it. For (b), divide the inequality u1>u2u_1 > u_2 by ss.
Solution

(a) Let Δ=r1−r2\Delta = r_1 - r_2. Answer 1 wins when ε2<ε1+Δ\varepsilon_2 < \varepsilon_1 + \Delta. Conditioning on ε1=ε\varepsilon_1 = \varepsilon, this has probability F(ε+Δ)F(\varepsilon + \Delta), so

P(1≻2)=∫−∞∞f(ε)F(ε+Δ) dε,f(ε)=e−εexp⁡(−e−ε).P(1 \succ 2) = \int_{-\infty}^\infty f(\varepsilon)F(\varepsilon + \Delta)\,d\varepsilon, \qquad f(\varepsilon) = e^{-\varepsilon}\exp(-e^{-\varepsilon}).

Since F(ε+Δ)=exp⁡(−e−εe−Δ)F(\varepsilon + \Delta) = \exp(-e^{-\varepsilon}e^{-\Delta}), the integrand is e−εexp⁡ ⁣(−e−ε(1+e−Δ))e^{-\varepsilon}\exp\!\big(-e^{-\varepsilon}(1 + e^{-\Delta})\big). Substitute t=e−εt = e^{-\varepsilon}, dt=−e−εdεdt = -e^{-\varepsilon}d\varepsilon; as ε\varepsilon runs from −∞-\infty to ∞\infty, tt runs from ∞\infty to 00:

P(1≻2)=∫0∞e−t(1+e−Δ) dt=11+e−Δ=σ(Δ).P(1 \succ 2) = \int_0^\infty e^{-t(1 + e^{-\Delta})}\,dt = \frac{1}{1 + e^{-\Delta}} = \sigma(\Delta).

As a byproduct, you have computed the CDF of η=ε2−ε1\eta = \varepsilon_2 - \varepsilon_1: P(η<Δ)=σ(Δ)P(\eta < \Delta) = \sigma(\Delta). The difference of two independent standard Gumbels is standard logistic. So “Gumbel noise on each utility” and “logistic noise on the comparison” are the same model.

(b) u1>u2  ⟺  r1+sg1>r2+sg2  ⟺  r1/s+g1>r2/s+g2u_1 > u_2 \iff r_1 + s g_1 > r_2 + s g_2 \iff r_1/s + g_1 > r_2/s + g_2. That is case (a) with rewards ri/sr_i/s:

P(1≻2)=σ ⁣(r1−r2s).P(1 \succ 2) = \sigma\!\left(\frac{r_1 - r_2}{s}\right).

A Bradley–Terry model fitted to these labels (with enough data) recovers rewards r^i=ri/s+c\hat r_i = r_i/s + c for some constant cc: the true rewards divided by the noise scale, up to a shift. Noisier labelers (s>1s > 1) give a reward model with smaller gaps, more consistent ones larger gaps. In the Boltzmann language, ss is the temperature, and the fitted reward is the true reward measured in units of ss. The demo’s κ\kappa is 1/s1/s: with κ=0.25\kappa = 0.25 the fitted spread is about a quarter of the true one.

Exercise 12.3The constant you can't learn, and why RL doesn't carePen & paper●●○

(a) Show that the reward-model loss −E[log⁡σ(r(x,yw)−r(x,yl))]-\mathbb E[\log\sigma(r(x, y_w) - r(x, y_l))] is unchanged if you replace r(x,y)r(x, y) by r(x,y)+c(x)r(x, y) + c(x) for any function cc of the prompt alone. Is it also unchanged under r→a rr \to a\,r for a constant a>0a > 0?

(b) Show that the optimal KL-regularized policy π∗(y∣x)∝πref(y∣x) er(x,y)/β\pi^*(y\mid x) \propto \pi_\text{ref}(y\mid x)\,e^{r(x,y)/\beta} is the same for rr and for r+c(x)r + c(x).

(c) Why would the comparison data be unable to pin down c(x)c(x) even with infinitely many labels? What would you need to collect to identify it?

Hint
(b): write out the normalizer Z(x)=∑yπref(y∣x)er(x,y)/βZ(x) = \sum_y \pi_\text{ref}(y\mid x)e^{r(x,y)/\beta} for the shifted reward and see what happens to the factor ec(x)/βe^{c(x)/\beta}.
Solution

(a) In each pair both responses share the prompt, so

(r(x,yw)+c(x))−(r(x,yl)+c(x))=r(x,yw)−r(x,yl),\big(r(x, y_w) + c(x)\big) - \big(r(x, y_l) + c(x)\big) = r(x, y_w) - r(x, y_l),

and every term of the loss is unchanged. Scaling is different: −log⁡σ(aΔ)≠−log⁡σ(Δ)-\log\sigma(a\Delta) \ne -\log\sigma(\Delta) unless a=1a = 1. The sigmoid’s slope fixes the unit, so the scale is identified by the data (a gap of 1 means 73%); only the zero point is not.

(b) For the shifted reward,

π′(y∣x)=πref(y∣x) e(r(x,y)+c(x))/β∑y′πref(y′∣x) e(r(x,y′)+c(x))/β=ec(x)/β πref(y∣x) er(x,y)/βec(x)/β∑y′πref(y′∣x) er(x,y′)/β=π∗(y∣x).\pi'(y\mid x) = \frac{\pi_\text{ref}(y\mid x)\,e^{(r(x,y) + c(x))/\beta}}{\sum_{y'}\pi_\text{ref}(y'\mid x)\,e^{(r(x,y') + c(x))/\beta}} = \frac{e^{c(x)/\beta}\,\pi_\text{ref}(y\mid x)\,e^{r(x,y)/\beta}}{e^{c(x)/\beta}\sum_{y'}\pi_\text{ref}(y'\mid x)\,e^{r(x,y')/\beta}} = \pi^*(y\mid x).

The factor ec(x)/βe^{c(x)/\beta} is the same for every yy and cancels in the normalization. (Equivalently, Z′(x)=ec(x)/βZ(x)Z'(x) = e^{c(x)/\beta}Z(x).) The policy gradient is unaffected in expectation too: c(x)c(x) acts as a baseline, and Ey∼πθ[∇θlog⁡πθ(y∣x) c(x)]=0\mathbb E_{y\sim\pi_\theta}[\nabla_\theta\log\pi_\theta(y\mid x)\,c(x)] = 0 (Chapter 7).

(c) Every label compares two responses to the same prompt, so the data only ever constrain differences within a prompt. Infinitely many such labels determine r(x,⋅)r(x, \cdot) up to a separate constant for each xx. To tie prompts together you would need cross-prompt judgments (“is this answer to question 1 better than that answer to question 2?”), or absolute ratings, or a convention such as InstructGPT’s “human demonstrations score 0 on average”.

Exercise 12.4One gradient step on a reward modelPen & paper●●○

A linear reward model scores a response by r(y)=w⊤f(y)r(y) = \mathbf w^\top f(y), where f(y)f(y) is a vector of two features and w\mathbf w is the weight vector being learned. Currently w=(0.5,0.25)\mathbf w = (0.5, 0.25). A labeler preferred the response with features fw=(1,2)f_w = (1, 2) over the one with fl=(2,0)f_l = (2, 0). (The subscripts ww and ll mean winner and loser, as everywhere in this chapter, and have nothing to do with the weights w\mathbf w.)

(a) Compute both rewards rw=w⊤fwr_w = \mathbf w^\top f_w and rl=w⊤flr_l = \mathbf w^\top f_l, the loss −log⁡σ(rw−rl)-\log\sigma(r_w - r_l), and its gradient with respect to w\mathbf w.

(b) Take one gradient-descent step with learning rate 0.5. What are the new reward difference and loss?

(c) Now suppose the dataset contains this same pair 4 times: 3 labelers preferred fwf_w and 1 preferred flf_l. At the minimum of the total loss, what is σ(rw−rl)\sigma(r_w - r_l), and what is the reward difference?

Hint
The gradient of −log⁡σ(Δ)-\log\sigma(\Delta) with respect to Δ\Delta is −(1−σ(Δ))-(1 - \sigma(\Delta)), and Δ\Delta is linear in w\mathbf w. For (c), write the total loss as a function of Δ\Delta alone and set its derivative to zero.
Solution

(a) rw=0.5⋅1+0.25⋅2=1.0r_w = 0.5 \cdot 1 + 0.25 \cdot 2 = 1.0 and rl=0.5⋅2+0.25⋅0=1.0r_l = 0.5 \cdot 2 + 0.25 \cdot 0 = 1.0, so Δ=0\Delta = 0 and the loss is −log⁡σ(0)=ln⁡2≈0.693-\log\sigma(0) = \ln 2 \approx 0.693. Since Δ=w⊤(fw−fl)\Delta = \mathbf w^\top(f_w - f_l) with fw−fl=(−1,2)f_w - f_l = (-1, 2),

∇wL=−(1−σ(0)) (fw−fl)=−0.5 (−1,2)=(0.5,−1).\nabla_{\mathbf w}\mathcal L = -(1 - \sigma(0))\,(f_w - f_l) = -0.5\,(-1, 2) = (0.5, -1).

(b) w←(0.5,0.25)−0.5 (0.5,−1)=(0.25,0.75)\mathbf w \leftarrow (0.5, 0.25) - 0.5\,(0.5, -1) = (0.25, 0.75). Now rw=0.25+1.5=1.75r_w = 0.25 + 1.5 = 1.75, rl=0.5r_l = 0.5, Δ=1.25\Delta = 1.25, and the loss is log⁡(1+e−1.25)≈log⁡(1.2865)≈0.252\log(1 + e^{-1.25}) \approx \log(1.2865) \approx 0.252. The step raised the weight of the feature the winner had more of and lowered the other.

(c) With 3 votes one way and 1 the other, the total loss as a function of Δ\Delta is

L(Δ)=−3log⁡σ(Δ)−log⁡σ(−Δ).\mathcal L(\Delta) = -3\log\sigma(\Delta) - \log\sigma(-\Delta).

Its derivative is −3(1−σ(Δ))+σ(Δ)-3(1 - \sigma(\Delta)) + \sigma(\Delta), using ddΔ[−log⁡σ(−Δ)]=σ(Δ)\frac{d}{d\Delta}[-\log\sigma(-\Delta)] = \sigma(\Delta). Setting it to zero gives 4σ(Δ)=34\sigma(\Delta) = 3, so σ(Δ)=0.75\sigma(\Delta) = 0.75 and Δ=ln⁡3≈1.10\Delta = \ln 3 \approx 1.10. The reward model learns the fraction of labelers who preferred fwf_w, not a verdict. With unanimous labels the optimum would be Δ→∞\Delta \to \infty; real reward models avoid that only because they share parameters across many pairs and are trained for about one epoch.

Exercise 12.5Per-token rewards and advantages by handPen & paper●●○

A policy samples a 4-token response. With β=0.05\beta = 0.05:

Token tt1234 (EOS)
log⁡πθ(yt∣⋅)\log\pi_\theta(y_t\mid\cdot)−1.2−0.4−2.0−0.1
log⁡πref(yt∣⋅)\log\pi_\text{ref}(y_t\mid\cdot)−1.0−0.9−2.0−0.3
critic V(st)V(s_t)0.50.60.60.7

The reward model scores the response rϕ=0.8r_\phi = 0.8.

(a) Compute the per-token rewards r1,…,r4r_1, \dots, r_4 and check that they sum to rϕ−βlog⁡πθ(y∣x)πref(y∣x)r_\phi - \beta\log\frac{\pi_\theta(y\mid x)}{\pi_\text{ref}(y\mid x)}.

(b) Compute the advantages with γ=1\gamma = 1 and λ=1\lambda = 1, and with λ=0\lambda = 0.

(c) Token 2 gets a negative advantage with λ=0\lambda = 0 but a positive one with λ=1\lambda = 1. Explain in words what each estimate is saying about token 2.

Hint
The state after token 4 is terminal: its value is 0. With λ=1\lambda = 1, A^t\hat A_t is the sum of the rewards from tt to the end minus V(st)V(s_t). With λ=0\lambda = 0, A^t=δt\hat A_t = \delta_t.
Solution

(a) The log-ratios log⁡πθ−log⁡πref\log\pi_\theta - \log\pi_\text{ref} are −0.2,+0.5,0,+0.2-0.2, +0.5, 0, +0.2. Multiply by −β=−0.05-\beta = -0.05: +0.01,−0.025,0,−0.01+0.01, -0.025, 0, -0.01. Add rϕ=0.8r_\phi = 0.8 to the last token:

r1=0.01,r2=−0.025,r3=0,r4=0.79.r_1 = 0.01, \quad r_2 = -0.025, \quad r_3 = 0, \quad r_4 = 0.79.

Sum: 0.7750.775. Check: the sequence log-ratio is −0.2+0.5+0+0.2=0.5-0.2 + 0.5 + 0 + 0.2 = 0.5, and 0.8−0.05×0.5=0.7750.8 - 0.05 \times 0.5 = 0.775.

(b) With λ=1\lambda = 1 (Monte Carlo): the rewards-to-go are G4=0.79G_4 = 0.79, G3=0.79G_3 = 0.79, G2=0.765G_2 = 0.765, G1=0.775G_1 = 0.775, so

A^=G−V=(0.775−0.5,  0.765−0.6,  0.79−0.6,  0.79−0.7)=(0.275,  0.165,  0.19,  0.09).\hat A = G - V = (0.775 - 0.5,\; 0.765 - 0.6,\; 0.79 - 0.6,\; 0.79 - 0.7) = (0.275,\; 0.165,\; 0.19,\; 0.09).

With λ=0\lambda = 0 (one-step TD errors, δt=rt+V(st+1)−V(st)\delta_t = r_t + V(s_{t+1}) - V(s_t), and V(s5)=0V(s_5) = 0):

δ4=0.79−0.7=0.09,δ3=0+0.7−0.6=0.10,δ2=−0.025+0.6−0.6=−0.025,δ1=0.01+0.6−0.5=0.11.\delta_4 = 0.79 - 0.7 = 0.09, \quad \delta_3 = 0 + 0.7 - 0.6 = 0.10, \quad \delta_2 = -0.025 + 0.6 - 0.6 = -0.025, \quad \delta_1 = 0.01 + 0.6 - 0.5 = 0.11.

Check: ∑tδt=0.275=A^1(λ=1)\sum_t \delta_t = 0.275 = \hat A_1(\lambda = 1), as GAE’s telescoping promises (Chapter 8).

(c) With λ=0\lambda = 0, token 2 is judged only by its immediate consequence: it cost a KL penalty of 0.025 and the critic’s estimate didn’t change (V(s3)=V(s2)=0.6V(s_3) = V(s_2) = 0.6), so it looks slightly bad. With λ=1\lambda = 1, token 2 is credited with everything that followed it, including the final score of 0.8, which beat the critic’s expectation of 0.6. The λ=0\lambda = 0 estimate trusts the critic (low variance, but biased if the critic is wrong); the λ=1\lambda = 1 estimate trusts the actual outcome (unbiased, but noisy). This is GAE’s bias–variance knob.

Exercise 12.6The trust region and the leashConcept●●○

For each scenario, say whether the clip ϵ\epsilon (trust region to πold\pi_\text{old}), the KL coefficient β\beta (leash to πref\pi_\text{ref}), or neither is the right tool, and why.

(a) Over 200 iterations, the policy drifts slowly toward long, flattering answers that the reward model loves. Each individual update is small.

(b) On one batch, a few prompts happen to get very high reward, and a single update makes some tokens 5 times more likely than they were when the batch was sampled.

(c) The reward model is excellent, and you want the best possible answers whatever their distance from the SFT model.

(d) After RLHF, the model’s arithmetic got worse, though nothing in the reward penalized arithmetic.

Solution

(a) The leash, β\beta. Each step is within the trust region, so clipping never triggers; the problem is cumulative drift away from the region where the reward model is reliable. Only a penalty anchored at a fixed point (πref\pi_\text{ref}) stops cumulative drift. An adaptive β\beta with a KL target is the standard tool. (Fixing the reward model’s length bias would be better still.)

(b) The clip, ϵ\epsilon. This is one update overshooting on one batch, exactly what PPO’s trust region exists for: once ρt>1+ϵ\rho_t > 1 + \epsilon for tokens with positive advantage, their gradient is zero. The leash would barely notice a single step.

(c) Lower β\beta, but not zero. If you really trusted the reward everywhere, you would want a small β\beta. In practice the leash also preserves fluency and diversity and protects against reward-model errors you haven’t found yet, so β\beta is lowered carefully while you watch a held-out measure of quality, not the reward model’s score.

(d) Neither alone; this is the alignment tax. A larger β\beta helps somewhat, because staying closer to the SFT model keeps its skills (the lab shows this). The targeted fix is PPO-ptx: mix a supervised loss on pretraining-style data into the updates, so the skill is actively maintained, as InstructGPT did.

Exercise 12.7Rankings, pairs and overfittingConcept●●○

(a) A labeler ranks K=9K = 9 answers. How many pairs does that give, and in how many of them does each answer appear?

(b) InstructGPT found that shuffling all pairs from all rankings into one dataset made the reward model overfit within one epoch, while treating all pairs from one ranking as a single batch element didn’t. Explain why, and name a computational benefit of the second approach.

(c) Is a ranking of 9 answers worth 36 times as much as one pairwise label? Argue briefly.

Hint
Think about how many times the reward model sees each individual response per epoch in the shuffled version.
Solution

(a) (92)=36\binom{9}{2} = 36 pairs; each answer is compared with the 8 others, so it appears in 8 pairs.

(b) In the shuffled version, each response appears in K−1=8K - 1 = 8 separate training examples spread over the epoch, so one epoch is really 8 passes over each response. With a large model, that is enough to memorize individual responses, which is overfitting. Grouping all 36 pairs of a ranking into one batch element means each response is used once per epoch, with its 8 comparisons combined into one gradient. It is also cheaper: you run the reward model once on each of the 9 responses (9 forward passes) and form all 36 differences from those 9 scores, instead of 2×36=722 \times 36 = 72 forward passes.

(c) No. The 36 pairs are not independent: they are all determined by one ordering of 9 items, produced by one labeler reading one prompt, with that labeler’s particular biases. A full ranking carries log⁡29!≈18.5\log_2 9! \approx 18.5 bits at most, versus 1 bit for one pair, and much of it is redundant with what transitivity implies. It is still a very good deal per minute of labeler time, which is why rankings are used, but it is worth far less than 36 independent labels from 36 different prompts and labelers.

Exercise 12.8How much memory does PPO-RLHF need?Pen & paper●●○

You run PPO-RLHF with a 7B-parameter policy. The reference, reward model and critic are also 7B. Frozen models are stored in bf16 (2 bytes per parameter). Trained models use the standard mixed-precision Adam layout: bf16 weights and gradients plus fp32 master weights and two fp32 Adam moments, 16 bytes per parameter in total.

(a) Estimate the memory for model states alone (no activations, no KV cache).

(b) Repeat for DPO (Chapter 13: a trained policy and a frozen reference) and for GRPO with a rule-based verifier (Chapter 15: a trained policy and a frozen reference, no reward model, no critic).

(c) What does this suggest about why the field moved toward critic-free methods?

Solution

(a) Trained: policy and critic, 2×7B×162 \times 7\text{B} \times 16 bytes =224= 224 GB. Frozen: reference and reward model, 2×7B×22 \times 7\text{B} \times 2 bytes =28= 28 GB. Total: about 252 GB of model state, before activations, the KV cache for generation, and any separate copy of the weights in an inference engine.

(b) DPO and GRPO-with-verifier both have one trained model and one frozen one: 7B×16+7B×2=112+14=1267\text{B}\times 16 + 7\text{B}\times 2 = 112 + 14 = 126 GB, half of PPO-RLHF. (Some recipes drop the reference too when they set the KL coefficient to 0, saving another 14 GB.)

(c) The critic is as big as the policy and needs its own optimizer state, so it roughly doubles the trained-parameter memory; the reward model adds more. On top of that, a per-token value function for a language model is hard to train well. Removing the critic (GRPO, RLOO) and the learned reward model (verifiable rewards) halves the memory and removes two sources of error, which is a large part of why critic-free methods spread from 2024 on (Chapters 15, 16 and 20).

Exercise 12.9Experiments with the two demosExplore the demo●○○

(a) In the Bradley–Terry demo, make P(A ≻ B) = 0.90. What reward gap does that take? What gap gives 0.99?

(b) Still in that demo, put A and B at the same reward and C far below. Compare P(A ≻ C) with A’s probability of being picked as best of all three. Why is the second number at most 0.5?

(c) In the reward-fitting demo, use 5,000 comparisons and try κ = 0.5, 1, 2, 4. Record the “spread ratio” and the “two labelers agree” percentage each time. What relation do you see?

(d) Set 10 comparisons and κ = 4. Compare training loss with held-out accuracy and the ceiling. What has happened, and what are two ways to fix it?

Solution

(a) σ(Δ)=0.9⇒Δ=ln⁡(0.9/0.1)=ln⁡9≈2.20\sigma(\Delta) = 0.9 \Rightarrow \Delta = \ln(0.9/0.1) = \ln 9 \approx 2.20. For 0.99: Δ=ln⁡99≈4.60\Delta = \ln 99 \approx 4.60. Going from 90% to 99% preference takes about twice the reward gap: the log-odds grow linearly in Δ\Delta, the probability doesn’t.

(b) With rA=rBr_A = r_B and rCr_C very low, P(A ≻ C) is close to 1, but A’s softmax share is about erA/(2erA)=0.5e^{r_A}/(2e^{r_A}) = 0.5, because B is equally strong. “Best of three” probabilities must sum to 1 over the three answers, and A can’t beat its twin more than half the time. Pairwise probabilities don’t have to sum to anything across pairs.

(c) With the demo’s default labels: κ = 0.5 gives a spread ratio of about 0.48 and 57% agreement; κ = 1 gives 0.98 and 69%; κ = 2 gives 1.76 and 84%; κ = 4 gives about 2.5 and 95%. For small κ the spread ratio tracks κ closely: the reward model’s scale measures how consistent the labelers are, and the same true qualities give larger reward gaps when labelers are more consistent. This is Exercise 12.2(b) in action.

At κ = 2, and much more at κ = 4, the ratio falls short of κ. The culprit is the demo’s tiny L2 penalty, 0.001∑k(r^k−rˉ)20.001\sum_k(\hat r_k - \bar r)^2. (Without it, the same data fit to a ratio of about 4.2, but only after about 9,000 gradient steps.) Why can such a small penalty win? When labelers are this consistent, nearly every comparison between distant responses goes the same way. A comparison won 99.9% of the time says almost nothing about how far apart the two are: σ\sigma is flat out there, so the loss barely changes as the gap grows, and the data pull on large gaps only weakly. Comparisons measure small differences well and large ones poorly, so on large gaps any regularizer dominates. Notice that the held-out accuracy still reaches the ceiling (about 0.975): the ordering is right, only the scale has shrunk. A shrunken scale makes the model’s probabilities underconfident, which is a calibration problem that accuracy cannot see.

(d) The training loss goes nearly to 0: with 10 labels the model can satisfy every one of them, and the scores spread far apart, held back only by the small penalty. But held-out accuracy stays well below the ceiling (with the default labels, about 0.86 against 0.97). Ten comparisons cannot even cover the 15 possible pairs of six responses, and each pair seen was seen once or twice; the model treats each of those few labels as a certainty and has to guess the order of pairs it never saw compared. Fixes: collect more comparisons, regularize more strongly (a larger L2 penalty, early stopping, or about one epoch, as real reward models are trained), or share parameters across responses through features, which is what a neural reward model does.

Exercise 12.10Lab: build the pipeline, then break itCode●●●

In the coding lab (exercises/12-rlhf/), implement the five tasks in rlhf.py:

  1. bt_loss: the reward model loss.
  2. ranking_to_pairs: rankings of K answers into (K2)\binom{K}{2} pairs.
  3. kl_penalized_rewards: the per-token rewards from this chapter’s worked example.
  4. gae_per_token: GAE with γ=1\gamma = 1 that ignores padding.
  5. ppo_rlhf_loss: the clipped policy loss and the value loss, as token means.

Then run python run.py and answer:

(a) For the β = 0 run, at roughly which iteration does the hidden labeler’s score peak, and what does the policy output afterwards? Print the reward model’s digit weights and explain from them why that output gets a high score.

(b) Compare β = 0.1 with β = 1 on all four panels. Which run is “better”? Why does the answer depend on what you care about?

(c) What does PPO-ptx buy, and what does it cost?

Hint
Work through the tasks in order with python -m pytest -q -k task1 and so on; the test messages say which case is wrong. Task 3: the last real token of row b sits at index mask[b].sum() - 1. Task 4: loop backwards over t, and treat both the value and the advantage after the last real token as 0. Task 5: compute the per-token objective, multiply by the mask, and divide by the number of real tokens.
Solution

The reference implementation is in solutions/rlhf.py. The key lines:

  • Task 1: -F.logsigmoid(r_chosen - r_rejected).mean(). Using logsigmoid keeps the loss finite when Δ\Delta is very negative.
  • Task 3: rewards = -beta * (logp - ref_logp) * mask, then rewards[arange(B), mask.sum(1).long() - 1] += score.
  • Task 4: for t from T-1 down to 0: delta = r[:, t] + gamma * V[:, t+1] * mask[:, t+1] - V[:, t] and adv[:, t] = (delta + gamma * lam * adv[:, t+1]) * mask[:, t], with the t+1 terms set to 0 past the end of the tensor. Returns are adv + values.
  • Task 5: ratio = exp(logp - old_logp); policy loss -masked_mean(min(ratio*A, clamp(ratio, 1-eps, 1+eps)*A), mask); value loss 0.5 * masked_mean((values - returns)**2, mask).

What the reference run shows (your numbers will be close):

(a) The hidden score rises along with the reward model’s score for about 30 iterations, then collapses to −1 over the next 20 to 30. Afterwards the policy answers every prompt with four even digits and no EOS, such as 4444. The digit weights are about +0.4 to +0.5 for even digits and −0.5 to −0.9 for odd ones. The reward model adds weights over digits, so four even digits (about 4×0.5=24 \times 0.5 = 2) beat any well-formed answer. The reward model never saw a malformed answer during training (the SFT model almost never produces one), so it never learned that they are bad. The reward-model score climbs to about +2.5 and the KL to about 40 nats.

(b) β = 0.1 reaches the higher hidden score (about +1 against +0.7) but moves further (KL about 2.6 against 0.25 nats) and loses most of the arithmetic (accuracy about 0.17 against 0.44). If all you care about is the labeler’s preference, β = 0.1 wins. If you also care about a skill the labeler never rewarded, β = 1 is better. The reward is only a partial description of what you want, and the KL leash is a blunt way to protect everything else.

(c) PPO-ptx (β = 0.1 with a supervised loss on correct additions) keeps accuracy at about the SFT level (≈ 0.46) while still raising the hidden score to about +0.8. It costs some reward (+0.8 instead of +1), extra compute for the supervised batches, and it needs data that represents the skills you want to keep. This is the same trade InstructGPT made against its alignment tax.

Files: README.md, rlhf.py, prefs.py, test_rlhf.py, run.py

cd 12-rlhf
python -m pytest -q          # your code: tests fail until you fill in the TODOs
RL_SOLUTIONS=1 python -m pytest -q   # reference solutions: all pass

First time? See Exercises & setup.

Further reading

Next: Chapter 13 shows that the reward model and PPO can be folded into a single supervised loss, using the closed-form optimum π∗\pi^* and the fact that Bradley–Terry only ever sees reward differences.