← All tutorials

Aligning Language Models with RL

RLHF, reinforcement learning from human feedback, turns people's rankings of answers into a reward and trains a language model to earn it.

On this page

1 Why RLHF 2 RLHF in three stages 3 InstructGPT results 4 Reward over-optimization 5 Newer alignment methods 6 References
1Why RLHF2RLHF inthree stages2.1The language modelas an agent3InstructGPTresults4Rewardover-optimization5Newer alignmentmethods
Figure 1. Tap a box to jump there.

1 Why RLHF

A large language model (LLM) is a neural network trained to predict the next token, a word or piece of a word, of web text. People want something else from it: to "follow the user's instructions helpfully and safely". Ouyang et al. 2022 call next-token prediction misaligned with that goal and built InstructGPT by tuning GPT-3 with RLHF.

PromptExplain the moon landing to a 6 year old in a few sentences.
GPT-3

Explain the theory of gravity to a 6 year old.

Explain the theory of relativity to a 6 year old in a few sentences.

Explain the big bang theory to a 6 year old.

Explain evolution to a 6 year old.

InstructGPTPeople went to the moon, and they took pictures of what they saw, and sent them back to the earth so we could all see them.
Figure 2. Same prompt: GPT-3 continues the list, InstructGPT answers (OpenAI 2022).

Writing the ideal answer is slow; picking the better of two takes seconds. Copying written answers alone has limits (why copying an expert falls short, on RL Basics), so RLHF also learns from people's rankings of the model's own attempts. The idea comes from Christiano et al. 2017, who trained Atari and simulated-robot agents from people’s picks between two clips.

2 RLHF in three stages

Supervised fine-tuning (SFT) teaches by example, a reward model (RM) learns a score from people's rankings, and RL with PPO, proximal policy optimization (Schulman et al. 2017), raises that score while a KL penalty charges the model for moving away from the SFT model. The stages run in order, and stages 2 and 3 can repeat on rankings of the newest policy’s answers (the InstructGPT paper).

Stage 1, supervised fine-tuning (SFT)Stage 2, reward model (RM)Stage 3, RL with PPOpretrainedmodelSFT modeltuned onanswers writtenby labelersone prompt,4 to 9 answers,ranked bylabelersreward modellearns to scorethe preferredanswer higherpolicystarts as theSFT model,writes an answerreward modelscores theanswerPPO updateraises the score,minus theKL penaltySFT model copysets the KLpenalty forstraying from itfrozen; dashed line, SFT model carried to stage 3about 13,000 promptsabout 33,000 promptsabout 31,000 promptsStage 1, supervised fine-tuning (SFT)pretrained modelSFT modeltuned on answerswritten by labelersabout 13,000 promptsStage 2, reward model (RM)one prompt,4 to 9 answers,ranked by labelersreward modellearns to scorethe preferredanswer higherabout 33,000 promptsStage 3, RL with PPOpolicystarts as theSFT model, writesan answerreward modelscores the answerPPO updateraises the score,minus theKL penaltySFT model copysets the penaltyfor driftingfrom itabout 31,000 promptsfrozen; dashed line, SFT model carried to stage 3
Figure 3. People write and rank answers; in stage 3 the frozen reward model does all the judging.

2.1 The language model as an agent

A model writing an answer runs the reinforcement learning loop, and each token it writes is one move.

RL looplanguage modelstatethe prompt plus thetokens written so faractionthe next tokenpolicythe language model,next-token probabilitiesrewardscore for the finished answer,minus a KL penalty per token
Figure 4. The RL Basics loop, with tokens as actions and a reward model as judge.

The score arrives once per answer, which ends the episode (InstructGPT paper, section 3.5). Sampling a token has no gradient, so RLHF uses a policy-gradient update, the REINFORCE idea that PPO refines in stage 3: raise the log-probability of tokens in better-than-expected answers and lower it in worse ones.

In this code, GPT-2 from Hugging Face writes one answer, one token per loop pass; the reward model would score the finished state once.

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

MAX_TOKENS = 40
tok = AutoTokenizer.from_pretrained("gpt2")
policy = AutoModelForCausalLM.from_pretrained("gpt2")
END_ID = tok.eos_token_id

state = tok("Explain the moon landing.", return_tensors="pt").input_ids
with torch.no_grad():
    for _ in range(MAX_TOKENS):
        logits = policy(state).logits[0, -1]   # next-token scores
        probs = torch.softmax(logits, dim=-1)
        token = torch.multinomial(probs, 1)    # the move
        state = torch.cat([state, token[None]], dim=1)
        if token.item() == END_ID:
            break
  1. 1Loads GPT-2 as the policy and sets the answer length limit.
  2. 2The prompt is the first state.
  3. 3Scores the next tokens, turns the scores into probabilities and samples one token, the move in Figure 4.
  4. 4Appends the token to the state and stops at the end token.

2.2 Stage 1, supervised fine-tuning

The pretrained model is fine-tuned on answers written by hired labelers, with the usual next-token loss, for 16 epochs.

2.3 Stage 2, the reward model

The reward model, a language model whose last layer outputs one number, learns to score answers the way people rank them. Every pair in a labeler’s ranking becomes a training example. It trains for a single epoch, since more epochs quickly overfit.

Take the prompt of Figure 2 and its two answers, yw the InstructGPT answer, which people prefer, and yl the GPT-3 list, as if these were the only two answers. The reward model scores them 1.5 and 0.3; it must turn that into a chance that people prefer the first (Figure 5).

e1.5 = 4.48ywscore 1.5e0.3 = 1.35ylscore 0.3gap 1.2shares of the total0.770.23chance peopleprefer yw 0.77loss 0.26
Figure 5. Two toy scores become a preference chance through e to the score.
The reward model learns by making the preferred answer score higher than the other, pair by pair.
gap = r(x, yw) − r(x, yl)
The score gap: how much higher the reward model scores the answer people preferred, r(x, yw) (w for won), than the other answer, r(x, yl) (l for lost), for the same prompt x, 1.2 in Figure 5. rw and rl below are short for the two scores.
chance = erwerw + erl = sigmoid(gap)
The Bradley-Terry chance that people prefer yw: its share of e to the score, a softmax over two answers. It depends only on the gap, so it equals sigmoid(gap), 0.77 here.
loss = −log sigmoid(gap)
The reward-model loss: minus the log of that chance; log is the natural log on this page. It is near 0 when the model agrees with people, 0.26 here, 1.46 if the scores were swapped and 0.69 if they tied. Together: logistic regression on which answer won (the InstructGPT paper, section 3.5, eq. 1). Builds on the reward of RL Basics, here learned from people, and the sigmoid; the stage 3 card uses its r, and the DPO card reuses this loss.

A toy reward model on 8 random pairs, each answer 16 made-up numbers instead of text.

import torch
import torch.nn.functional as F

N_FEATURES, N_PAIRS = 16, 8
reward_model = torch.nn.Linear(N_FEATURES, 1)   # toy RM
chosen = torch.randn(N_PAIRS, N_FEATURES)     # y_w; rejected is y_l
rejected = torch.randn(N_PAIRS, N_FEATURES)
r_w = reward_model(chosen).squeeze(-1)
r_l = reward_model(rejected).squeeze(-1)
gap = r_w - r_l
loss = -F.logsigmoid(gap).mean()   # stable -log sigmoid
loss.backward()
  1. 1A toy reward model and 8 random answer pairs.
  2. 2Gap, eq card in Section 2.3, line 1.
  3. 3Loss, line 3, then the gradient.

2.4 Stage 3, RL with PPO

The policy, a copy of the SFT model, answers a fresh prompt, the frozen reward model scores it, and PPO updates the policy to raise the score. InstructGPT ran about 256,000 such episodes.

Training moved the policy away from the SFT model; one answer’s drift can even be negative, the average cannot; both are measured in nats, the unit the natural log gives (Figure 6).

0.50.8drift +0.47SFTpolicyyw0.50.2drift −0.92SFTpolicyylaverage drift,KL = 0.19 natsobjective for ywwith β 0.02: 1.49
Figure 6. One answer’s drift is below 0; their weighted average, KL, is not (toy).
Stage 3 maximizes reward minus a drift price, averaged over prompts and sampled answers.
drift(y) = log π(y |⁠ x)πSFT(y |⁠ x)
The drift of one answer. π(y | x) is the chance the policy being trained writes answer y to prompt x, and πSFT(y | x) the chance the frozen SFT model would. The drift is 0 when both agree, positive when the policy favors y more, +0.47 for yw, and negative when less, −0.92 for yl (Figure 6). π(y | x) is the product of y’s token chances, so the drift is a sum of per-token log ratios.
KL(π ‖ πSFT) = Σy π(y |⁠ x) · drift(y)
The KL divergence, read “KL of π from πSFT”: the average drift over the answers the policy writes, never negative, zero only when they match. It is the general KL(p ‖ q) with p = π and q = πSFT, measured in nats, 0.19 here.
objective = r(x, y) − β · drift(y)
The stage 3 objective: the score r(x, y) minus β times the drift; averaged over prompts and sampled answers, the penalty is β times KL. β, InstructGPT’s KL reward coefficient, is 0.02 (the InstructGPT paper, eq. 2): 1.49 for yw. The penalty is charged on every token, the score on the last (code below), and stops the policy from drifting into answers that fool the reward model (Section 4). Together: reward minus a drift price, maximized with PPO, whose critic predicts the reward still to come from each partial answer to form the advantage (Policy Gradients, section 2). Builds on the reward-model card; the best-policy card asks which policy maximizes it.

Toy numbers for one 12-token answer.

import torch

BETA, N_TOKENS = 0.02, 12   # InstructGPT's beta
log_pi = -torch.rand(N_TOKENS)       # toy log pi per token
log_pi_sft = -torch.rand(N_TOKENS)
score = torch.tensor(1.3)
drift = log_pi - log_pi_sft
reward = -BETA * drift
reward[-1] += score   # score on the last token
objective = reward.sum()
  1. 1Toy per-token log-probabilities and a reward model score.
  2. 2Per-token drift, eq card in Section 2.4, line 1, scaled by β.
  3. 3Adds the score on the last token and sums, line 3.

If training finds the best policy, with β 1 it writes yw 77 times in 100, the same split as Figure 5; with β 0.1, almost always.

This is the best policy under the drift price: it reweights the SFT model’s answers by their reward.
weight = expr(x, y)β
Each answer’s weight is exp of its reward r(x, y) divided by β. A small β makes the top-reward answer’s weight dwarf the rest; a large one keeps every weight near 1.
π*(y |⁠ x) ∝ πSFT(y |⁠ x) · weight
The best policy multiplies each SFT probability by that weight, then rescales to sum to 1; ∝ reads “proportional to” (the DPO paper). β near 0 is pure reward seeking. Together: drift is allowed exactly as far as reward pays for it. Builds on the stage 3 card; the DPO card turns it around.
SFT modelpolicyreward, 0 to 1

Figure 7. Answers 1 to 5 with toy rewards; β is on the toy’s scale, not InstructGPT’s.

2.5 RLHF in practice

Runssample a batch of 512 answers, score each once, one PPO epoch in minibatches of 64, repeat
Carriesthe policy, a critic, the frozen SFT model and the frozen reward model
Costper round, generate 512 whole answers, run policy, critic, SFT copy and reward model on each, then 8 PPO minibatch steps
βweights KL in the objective; higher stays near SFT, 0 lets the policy exploit the reward model’s flaws, very high leaves SFT unchanged; 0.02 in InstructGPT
CodeHugging Face TRL PPO trainer
Gotchaswatch the logged KL (objective/kl in TRL); a rising reward with fast-rising KL is the failure in Section 4

3 InstructGPT results

Labelers preferred InstructGPT’s answers to GPT-3’s (Figure 8), with the setup below.

PartInstructGPT setup
Peopleabout 40 hired labelers
Promptssent by customers to earlier InstructGPT models on the OpenAI API (OpenAI's paid web service), plus some written by the labelers
ModelsGPT-3 architecture at 1.3B, 6B and 175B parameters (B = billion)
Reward modelone 6B reward model for every policy size
Judged bythe same labelers, on prompts from customers held out of training
Final modelsPPO plus a next-token loss on pretraining text (PPO-ptx), used for the results here; the best-policy line in Section 2.4 ignores this extra loss
① Preferred over GPT-3, both 175B 85% ± 3 tie, 50% ② Made-up information, lower is better InstructGPT 21% GPT-3 41% share of answers, input-only tasks
Figure 8. ① Preference at equal size; ② tasks whose answer is in the input.

Labelers also preferred 1.3B InstructGPT over 175B GPT-3, and held-out labelers, who wrote no training data, agreed about as often.

InstructGPT aligns to one group, mostly the labelers and researchers, and still makes simple mistakes.

4 Reward over-optimization

A reward model is a learned reward with flaws, and stage 3 finds and exploits them: reward hacking, as with the toy agent on RL Basics. Gao et al. 2022 measured this with a reward model standing in for people:

PartOver-optimization setup
Stand-in for peoplea fixed 6B "gold" reward model in the InstructGPT setting
Proxy reward models (what training sees)3M to 3B parameters (M = million), trained on the gold model's preferences
Policy1.2B parameters, trained with PPO against one proxy, no KL penalty in the main runs
Measuredgold and proxy reward model scores as the policy drifts from its starting model, drift measured by KL divergence
proxy reward model score (what training sees)gold score (stand-in for people)

Figure 9. Training sees the top curve; people would judge by the bottom one.

A KL penalty did not lift the gold curve: at the same KL distance the gold score came out about the same, so the penalty acted like stopping early.

Answer length is one measured flaw. PPO lengthened answers on all three preference datasets Singhal et al. 2023 tested, among them the WebGPT comparisons, people’s picks between two web-search answers. Judged by OpenAI models standing in for people (AlpacaFarm), a reward for length alone nearly matched standard PPO.

① 58%, standard PPO ② 56%, length only tie, 50% win rate over the SFT model
Figure 10. Win rate over SFT on WebGPT, judged by OpenAI models in AlpacaFarm.

5 Newer alignment methods

Newer methods drop parts of the RLHF pipeline (Figure 11).

PPO-based RLHFfresh answers, scored by the reward modelreward modelsamplingcriticDPOfixed preference pairsreward modelsamplingcriticGRPOfresh answers, each against its groupreward modelsamplingcriticDeepSeek-R1-Zerofresh answers, checked by rulesreward modelsamplingcritic
Figure 11. Solid boxes are used in training; dashed, struck-through boxes are dropped.

DPO, direct preference optimization (Rafailov et al. 2023), trains the language model directly on preference pairs collected beforehand, sampling nothing during training.

Read the best-policy line backwards and the policy’s own drift is a reward (Figure 12).

β · drift, β 0.1+0.047yw−0.092ylgap 0.139loss 0.63, downfrom 0.69 while thepolicy equals SFT
Figure 12. DPO with β 0.1: the policy’s own drift, scaled by β, plays the reward.
This is the DPO loss: DPO reads a reward off the policy and reuses the reward-model loss.
rDPO(x, y) = β · (log π(y |⁠ x)
− log πSFT(y |⁠ x))
rDPO(x, y) is β times the drift of answer y: +0.047 and −0.092 at β 0.1 (Figure 12). It is the best-policy line solved for the reward, minus a prompt-only term (the DPO paper), so the policy carries its own reward. The paper writes πref for the frozen SFT model.
gap = rDPO(x, yw) − rDPO(x, yl)
The preferred answer’s DPO reward minus the other’s, as in stage 2, 0.139 here; the prompt-only term is the same for both answers and cancels.
loss = −log sigmoid(gap)
The stage 2 loss on that gap: 0.63, against 0.69 while the policy equals SFT. Together: the reward-model loss with the policy carrying its own reward; no reward model, no sampling. Builds on the best-policy and reward-model cards; no card builds on it: GRPO drops the critic instead and keeps sampling (Figure 11).

One DPO loss on a batch of pairs. Each input is the summed log-probability of a whole answer; the ref_ ones come from the frozen SFT model without gradients.

import torch.nn.functional as F

BETA = 0.1   # the DPO paper's value

def dpo_loss(logp_w, logp_l, ref_logp_w, ref_logp_l):
    r_w = BETA * (logp_w - ref_logp_w)   # r_DPO(x, y_w)
    r_l = BETA * (logp_l - ref_logp_l)   # r_DPO(x, y_l)
    gap = r_w - r_l
    return -F.logsigmoid(gap).mean()
  1. 1rDPO for both answers, eq card in Section 5, line 1.
  2. 2Gap, line 2.
  3. 3Loss, line 3.

5.1 DPO in practice

Runsordinary training passes over a fixed set of pairs; batch 64, RMSprop learning rate 0.000001, 150 warmup steps (the paper)
Carriesa frozen reference, run on both answers of each pair; TRL can precompute it (precompute_ref_log_probs)
Costper pair, two forward passes of the policy and two of the reference, one backward pass, no generation
βscales rDPO; higher keeps the policy near the reference, near 0 the policy can move far from the reference; 0.1 in the paper
CodeHugging Face TRL DPO trainer
Gotchasthe gap can grow by lowering the rejected answer’s probability; watch rewards/margins in TRL

5.2 GRPO

GRPO, group relative policy optimization (Shao et al. 2024, the DeepSeekMath paper), is PPO with its clipped step kept and the critic dropped. It samples a group of answers to one question and judges each against the group.

GRPO judges each answer only against its siblings (Figure 13).

10mean 0.5A +0.871A −0.872A −0.873A +0.874answerspread0.58
Figure 13. 4 answers to one math question (toy rewards: right 1, wrong 0).
This is the GRPO advantage: GRPO scores each answer against its own group.
Ai = ri − mean(r)std(r)
The advantage Ai of answer i is its reward ri minus the group average, divided by the group spread std(r). The average plays the baseline of Policy Gradients and the critic of PPO; dividing by std gives advantages a similar size across questions. In Figure 13 the mean is 0.5 and the spread 0.58, the sample std, torch’s std() default (the paper’s equation does not choose a form), so A is +0.87 for a right answer and −0.87 for a wrong one. Together: the clipped PPO step with the group average in place of a critic, plus the KL price of the stage 3 card. Builds on the baseline, PPO and the stage 3 card; it is the last card on this page.

One GRPO loss for one question: the group’s rewards become Ai, and the rest is PPO’s clipped objective per token, without the KL term.

import torch

EPS_CLIP = 0.2   # PPO's clip

def grpo_loss(log_pi, old_log_pi, rewards):
    # log_pi, old_log_pi: (G, T) per-token log-probs
    A = (rewards - rewards.mean()) / (rewards.std() + 1e-8)
    A = A[:, None]   # same A_i for every token of answer i
    ratio = torch.exp(log_pi - old_log_pi.detach())
    clipped = ratio.clamp(1 - EPS_CLIP, 1 + EPS_CLIP)
    objective = torch.min(ratio * A, clipped * A)
    return -objective.mean()
  1. 1Group advantage, eq card in Section 5.2, line 1, one value per answer.
  2. 2PPO’s ratio, clip and objective, the PPO clipping eq card in Policy Gradients: REINFORCE, Actor-Critic and PPO.
  3. 3Loss for the group; the KL term to the reference (β in Section 5.3) is left out to keep the snippet short.

5.3 GRPO in practice

Runssample 64 answers per question up to 1,024 tokens, score them, then a single update per sampling round; batch 1,024 (DeepSeekMath)
Carriesno critic; the sampling policy’s log-probabilities and a reference for the KL term
Costgenerating 64 answers per question and a reward for each, then one backward pass per round
Group size Ganswers per question; more gives a steadier group average, 1 gives no comparison at all; 64 in DeepSeekMath
KL βweights the KL term like RLHF’s β; higher stays closer to the reference, 0 turns the term off; 0.04 in DeepSeekMath, 0 by default in TRL
Clip εas in PPO: wider allows bigger changes per round, 0 freezes the policy; 0.2 in the PPO paper
CodeHugging Face TRL GRPO trainer
Gotchasa group where every answer scores the same gives A = 0 and teaches nothing (TRL logs frac_reward_zero_std); dividing by std can bias toward question difficulty (TRL scale_rewards)

When an answer can be checked automatically, a rule replaces the reward model. DeepSeek-R1-Zero (DeepSeek-AI 2025) used GRPO and checked a final math answer against the known one, ran code against set test cases, and required reasoning inside marked tags, with no learned reward model, since a learned one can be gamed.

In the on-policy and off-policy terms of Value-Based RL, PPO-based RLHF and GRPO are on-policy, learning from answers the current policy just wrote, while DPO learns offline from a fixed set of pairs (the GRPO paper).

6 References

  1. Ouyang, L., et al. (2022). Training language models to follow instructions with human feedback. NeurIPS 2022. https://arxiv.org/abs/2203.02155
  2. OpenAI (2022, January 27). Aligning language models to follow instructions. OpenAI blog.
  3. Christiano, P., et al. (2017). Deep reinforcement learning from human preferences. NeurIPS (then NIPS) 2017. https://arxiv.org/abs/1706.03741
  4. Schulman, J., et al. (2017). Proximal policy optimization algorithms. https://arxiv.org/abs/1707.06347
  5. Gao, L., et al. (2022). Scaling laws for reward model overoptimization. ICML 2023. https://arxiv.org/abs/2210.10760
  6. Singhal, P., Goyal, T., Xu, J., and Durrett, G. (2023). A long way to go: investigating length correlations in RLHF. COLM 2024. https://arxiv.org/abs/2310.03716
  7. Rafailov, R., et al. (2023). Direct preference optimization: your language model is secretly a reward model. NeurIPS 2023. https://arxiv.org/abs/2305.18290
  8. Shao, Z., et al. (2024). DeepSeekMath: pushing the limits of mathematical reasoning in open language models. https://arxiv.org/abs/2402.03300
  9. DeepSeek-AI (2025). DeepSeek-R1: incentivizing reasoning capability in LLMs via reinforcement learning. https://arxiv.org/abs/2501.12948v1 (version 1)