From Base Model to Assistant: SFT, RLHF, DPO and GRPO
Ask a base model for a haiku and it writes the same sentence five times. Then watch a reward model learn to prefer length over correctness.
On this page
Ask GPT-2 — a competently pretrained language model — to write a haiku about the sea:
prompt: Write a haiku about the sea.
The sea is a beautiful place.
The sea is a beautiful place.
The sea is a beautiful place.
The sea is a beautiful place.
The sea is a beautiful place.It is not confused, and it has not failed at its job. It is doing exactly what Chapter 10 trained it to do: given some text, produce plausible continuing text. On the internet, a line like Write a haiku about the sea. is often followed by prose about the sea, and a sentence that has just appeared is unusually likely to appear again. The model is a superb next-token predictor and a useless assistant.
Now the same request to a model built the same way — Qwen2.5, half a billion parameters, four times the size of the GPT-2 above and still tiny by any 2026 standard — after the training stages this chapter is about:
Whispers of the ocean,
Silent depths where waves meet,
Mysteries in the vast blue.Four times the parameters does not teach a model to stop talking. The gap between those two outputs is not scale, not architecture and not data volume. It is post-training: a second phase, orders of magnitude smaller than pretraining, that takes a text predictor and turns it into something that answers.
Stage one: showing it what an answer looks like
Link to the section: Stage one: showing it what an answer looks likeThe first step is the least glamorous and does most of the work. Collect examples of instructions paired with good responses, and continue training on them with exactly the loss from Chapter 8 — predict the next token — but only on the response part. This is supervised fine-tuning, or SFT.
Nothing new is being taught about language. What is being taught is a format: that text of this shape is followed by text of that shape, and then it stops. Look again at the base model's failure. It answered the question in the first sentence and then could not stop, because nothing in its training ever marked the end of a response. Stopping is a learned behaviour.
That is also why the model needs to be told where the boundaries are, which is what a chat template is:
<|im_start|>system
You are Qwen, created by Alibaba Cloud. You are a helpful assistant.<|im_end|>
<|im_start|>user
What is the capital of France?<|im_end|>
<|im_start|>assistantThose <|im_start|> and <|im_end|> markers are real tokens in the vocabulary, added before fine-tuning, and the model saw millions of them in exactly these positions. They are how it knows whose turn it is and where a turn ends.
Skip the template and hand the model a bare question, and you are giving it a sequence it has not seen in training. Measured, same model, same question, same greedy decoding:
Without the template — the raw string What is the capital of France?:
The capital of France is Paris.
To verify this, I will use a simple
Python code snippet to confirm that
Paris is indeed the capital city of
France.
[...and then it starts writing a
Python script to check its own answer]With the template:
The capital of France is Paris.The answer is right in both, but without the markers the model drifts into writing Python to check itself, because the prompt it received resembles nothing it was fine-tuned on. This is the single most common cause of "the model got dumber when I called it directly": the template is not decoration around the model, it is part of the model, and a wrong template is a silent degradation with no error attached.
Stage two, and the problem it exists to solve
Link to the section: Stage two, and the problem it exists to solveSFT has a ceiling, and the ceiling is the data. To fine-tune on a demonstration you need somebody to write the ideal response — and for most interesting questions, writing a good answer is hard, slow, expensive, and produces exactly one answer whose quality you cannot verify.
What people are good at is comparison. Shown two responses, an annotator can reliably say which is better in a few seconds, without being able to produce either. This is the fact the entire second stage is built on, and it is the part most explanations get backwards:
Humans do not write the answers. They rank pairs.
So the data is pairs — a prompt, two responses, and which one won. That cannot be plugged into a next-token loss, because there is no target sequence. It needs a different machine.
The reward model, and what it actually learns
Link to the section: The reward model, and what it actually learnsYou cannot ask a human to score every response during training — that is millions of judgements. So you train a model to imitate the humans: a reward model that takes a response and returns a scalar.
Training it from comparisons uses a result from 1952. The Bradley–Terry model2 says that if two items have latent strengths, the probability that one beats the other is the logistic function of their difference. Turn that around and it becomes a loss: given that a human preferred over , maximise
which in code is the entire training loop:
loss = -F.logsigmoid(reward(chosen) - reward(rejected)).mean() Notice what the model never sees: an absolute score. It only ever learns differences, which is exactly what the data contains.
Now the part worth measuring. A reward model learns what the annotators rewarded, and annotators are people. Here is a simulation where the true quality of a response depends only on being useful and correct — length is worth nothing — but the simulated annotator has a mild preference for longer answers when everything else is close, which is a well-documented human bias. Train the reward model on 2000 comparisons and read its weights:
| annotator's length bias | learned weight on useful | on correct | on length |
|---|---|---|---|
| 0.0 | +1.00 | +1.00 | +0.01 |
| 0.3 | +0.98 | +1.00 | +0.15 |
| 0.6 | +0.97 | +1.00 | +0.27 |
| 1.2 | +1.00 | +0.99 | +0.59 |
The reward model is working perfectly. It has faithfully learned the preferences it was shown — including the part of those preferences that has nothing to do with quality. A reward model is not a measure of good; it is a measure of what the annotators picked, and every bias in the annotation pool is now a coefficient in a differentiable function that a much larger model is about to optimise against.
Reward hacking, measured
Link to the section: Reward hacking, measuredWhich brings us to what happens when you optimise it. Give the policy a fixed budget of effort to spend across the response's properties, with a realistic asymmetry: being useful and being correct are expensive, and being longer is cheap — you just keep writing.
Reward per unit of effort, for the model trained above: useful 8.26, correct 8.31, length 31.70. Length pays nearly four times better than correctness, not because the reward model is broken, but because it is cheap.
Optimise against that reward and watch both numbers:
| reward model's score | true quality | length produced | |
|---|---|---|---|
| starting policy | 12.588 | 0.974 | 3.365 |
| after optimisation | 31.696 | 0.000 | 12.497 |
The reward went up by a factor of 2.5. The thing the reward was supposed to measure went to zero. The policy discovered that it could score enormously well by writing at length and saying nothing, and no part of the training loop had any way to notice, because the reward model is the definition of good inside the loop.
This is reward hacking, and if you have ever wondered why chat models are so verbose, this table is a large part of the answer.
What the KL penalty actually buys
Link to the section: What the KL penalty actually buysThe standard defence is to penalise the policy for moving too far from where it started, measuring distance with the KL divergence from Chapter 4:
The reference is the SFT model — the policy before the reinforcement stage. The claim is that this prevents the model from wandering off into degenerate behaviour. Let us find out how much of that claim survives measurement. Same setup, sweeping :
| reward | true quality | length | KL | |
|---|---|---|---|---|
| 0 | 31.699 | 0.000 | 12.498 | 2.994 |
| 1 | 31.697 | 0.000 | 12.497 | 2.993 |
| 5 | 28.318 | 0.285 | 10.700 | 2.163 |
| 15 | 12.860 | 1.542 | 2.552 | 0.151 |
| 30 | 10.426 | 1.719 | 1.303 | 0.025 |
| 60 | 9.632 | 1.769 | 0.908 | 0.005 |
| the reference model alone | 9.162 | 1.791 | 0.687 | 0 |
Read the last row against the rest. At and the penalty does nothing at all: the reward is worth so much more than the KL that the optimiser pays the fine and hacks anyway. Between 5 and 15 the behaviour swings. And by , true quality has climbed back to 1.769 — which is still below the 1.791 the reference model had before any of this started.
One caveat before that number is quoted anywhere: the 1.791 of the last row and the 0.974 that the first table gives the starting policy are two different measurements of the same pre-RL model, taken by the two experiments separately. Compare rows within a table, never across them — the conclusion of each table stands on its own rows, and neither depends on the other's baseline.
So the honest summary is not "the KL penalty prevents reward hacking". It is:
The KL penalty does not prevent reward hacking. It limits how far the policy can move from the reference — and since the failure requires moving, that helps. But it is a leash, not a corrective: at low the leash snaps, and at high you get the reference model back and the whole expensive stage bought nothing.
The useful band is narrow, its location depends on the reward model, and there is no way to find it except by looking. That is why the reference model must be good — the KL is a floor at the reference's quality, not a ceiling on the failure — and it is a large part of why this stage is difficult in practice rather than in principle.
PPO, and why DPO ate it
Link to the section: PPO, and why DPO ate itThe algorithm that made this work at scale is Proximal Policy Optimization.3 In one paragraph: it estimates the advantage of each response, updates the policy to increase the probability of above-baseline responses, and clips the size of any single update so a large advantage estimate cannot destroy the policy in one step. Applied to language models4 it means keeping four models in play at once — the policy, the reference, the reward model, and a critic — with the policy generating fresh samples throughout training.
It works, it produced InstructGPT and everything descended from it, and it is genuinely difficult: four models in memory, sampling in the training loop, and a reputation for instability that is deserved. Pretending you can implement it in a blog post would be dishonest, so this chapter does not.
What replaced it for most purposes came from noticing something. The KL-regularised objective above has a closed-form optimal policy, and that expression can be inverted: the reward can be written in terms of the optimal policy and the reference. Substituting that back into the Bradley–Terry loss makes the reward model disappear entirely. What remains is a supervised loss on preference pairs — no sampling, no critic, no reward model, two models in memory instead of four.
That is Direct Preference Optimization,5 and it is two lines:
def dpo_loss(pi_w, pi_l, ref_w, ref_l, beta=0.1):
"""pi_* and ref_* are summed log-probabilities of a full response."""
logits = beta * ((pi_w - ref_w) - (pi_l - ref_l))
return -F.logsigmoid(logits) Read what it says. The quantity being pushed up is how much more the policy prefers the winner than the reference did, minus how much more it prefers the loser. The reference is not a penalty bolted on afterwards — it is inside the loss, which is why DPO does not need a separate KL term.
The property that matters most is in the gradient. Evaluate the loss and its gradient on the same pair in five different states of the policy:
| state of the policy | loss | gradient magnitude |
|---|---|---|
| already strongly prefers the winner | 0.5130 | 0.0401 |
| already prefers it, weakly | 0.6685 | 0.0488 |
| identical to the reference | 0.6931 | 0.0500 |
| prefers the loser | 0.7981 | 0.0550 |
| strongly prefers the loser | 1.0055 | 0.0634 |
The gradient grows as the policy gets it more wrong. Pairs the model already handles contribute almost nothing; pairs it gets backwards dominate the update. DPO weights every example by how wrong the policy currently is, automatically, with no scheduling — and that self-weighting is the mechanism doing the work that PPO's advantage estimate and critic were doing. (The loss at the third row is exactly , which is the anchor to check any implementation against: a policy identical to its reference has learned nothing and should sit at .)
GRPO6 takes a different route out of the same problem. It keeps the sampling loop but deletes the critic: instead of training a model to predict the baseline, it samples a group of responses to the same prompt and uses the group's mean reward as the baseline directly. The advantage of a response is how much better it was than its siblings. That trades a whole model for a larger batch, and it is what made verifiable-reward training — the subject of Chapter 12 — practical.
Show details
Three more pieces of the post-training landscape, briefly.
RLAIF and Constitutional AI.7 The annotator does not have to be human. Give a model a written set of principles and ask it to critique and revise its own outputs, or to choose between two candidates, and you have a preference dataset produced at machine speed and cost. The obvious objection — the model is grading its own homework — is real, and the honest answer is that it works better than it sounds because judging is easier than generating, which is the same asymmetry the whole chapter rests on.
LIMA, and how little data this needs.8 A thousand carefully curated demonstrations produced a competitive assistant. The proposed explanation is that pretraining already installed the knowledge and the format, and post-training only has to select which of the model's existing behaviours to surface. If that is right, post-training data quality dominates quantity — and the field's behaviour since suggests people believe it.
LoRA and QLoRA.910 Fine-tuning every weight of a large model requires memory for the weights, their gradients and the optimiser state — Chapter 10's sixteen bytes per parameter, over the two averages Chapter 6 built by hand — at a scale that needs a cluster. LoRA freezes the original weights and trains a low-rank pair of matrices alongside them, cutting trainable parameters by orders of magnitude; QLoRA additionally quantizes the frozen base to 4 bits. Both are covered here as technique. Whether fine-tuning is the right thing to spend money on at all is a different question, and it is Chapter 20's.
The alignment tax, and the question nobody has answered
Link to the section: The alignment tax, and the question nobody has answeredTwo things to carry forward.
The first is that this stage has a cost, and it shows up as capability. Models often get measurably worse at some benchmark tasks after alignment training — the alignment tax — because the objective changed: a response that is safe, hedged and formatted well is not always the response that maximises accuracy. Some of that gap has been engineered away, and some of it is a real trade rather than a bug to fix.
The second is the question the word aligned hides. Aligned with whom? The chain is: a company writes guidelines, contractors interpret them, their comparisons train a reward model, the reward model shapes a policy, and the policy answers a question from someone who saw none of it. Every link is a choice made by specific people, and none of the algorithms in this chapter has any opinion about whether those choices are good.
That is not a rhetorical flourish. It is the concrete reason two frontier models refuse different requests, why the same model changes its mind between versions, and why "aligned" is a description of a process rather than a property of an artefact. The mathematics in this chapter is settled. That part is not.
Where this goes next
Link to the section: Where this goes nextPost-training taught the model to answer. It did not teach it to think before answering, and the two are different in a way that turns out to be trainable.
Chapter 12 is about what happens when you let a model spend more computation on a hard question at answer time rather than at training time — chain of thought, reinforcement learning from verifiable rewards, and the reason a model that shows its working is not merely explaining itself but computing differently. It also cashes the debt from this chapter: GRPO exists in it, doing the job PPO's critic used to do, on rewards that need no annotator at all because a proof either checks or it does not.
Sources and method
Link to the section: Sources and methodThe generations above come from gpt2 and Qwen/Qwen2.5-0.5B-Instruct with greedy decoding, so they reproduce exactly. Chapter 11 of the Hugging Face LLM Course walks through SFT and DPO with trl and peft if you want to run the real thing rather than the simulation; chapter 7 of Sebastian Raschka's Build a Large Language Model (From Scratch) implements instruction fine-tuning end to end without a library.
References
Link to the section: References-
Sutton, R. S. and Barto, A. G. Reinforcement Learning: An Introduction, 2nd edition (MIT Press, 2018). The delegation is deliberate: the vocabulary box above is the smallest usable subset, and the real subject is a book. ↩
-
Bradley, R. A. and Terry, M. E. Rank Analysis of Incomplete Block Designs: I. The Method of Paired Comparisons. Biometrika 39(3/4), pp. 324–345 (1952). The pairwise-comparison model underneath every reward model in use today. ↩
-
Schulman, J., Wolski, F., Dhariwal, P., Radford, A. and Klimov, O. Proximal Policy Optimization Algorithms. arXiv:1707.06347 (2017). ↩
-
Ouyang, L. et al. Training language models to follow instructions with human feedback. arXiv:2203.02155 (2022). InstructGPT — the paper that made the three-stage recipe standard. Preceded by Christiano et al. (arXiv:1706.03741), which introduced learning a reward model from human comparisons, and Stiennon et al. (arXiv:2009.01325), which applied it to summarisation. ↩
-
Rafailov, R., Sharma, A., Mitchell, E., Ermon, S., Manning, C. D. and Finn, C. Direct Preference Optimization: Your Language Model is Secretly a Reward Model. arXiv:2305.18290 (2023). The derivation that removes the reward model is in section 4 and is worth reading in full; it is shorter than its reputation. ↩
-
Shao, Z. et al. DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models. arXiv:2402.03300 (2024). Introduces GRPO in section 4.1. ↩
-
Bai, Y. et al. Constitutional AI: Harmlessness from AI Feedback. arXiv:2212.08073 (2022). ↩
-
Zhou, C. et al. LIMA: Less Is More for Alignment. arXiv:2305.11206 (2023). ↩
-
Hu, E. J. et al. LoRA: Low-Rank Adaptation of Large Language Models. arXiv:2106.09685 (2021). ↩
-
Dettmers, T., Pagnoni, A., Holtzman, A. and Zettlemoyer, L. QLoRA: Efficient Finetuning of Quantized LLMs. arXiv:2305.14314 (2023). ↩