Part III · RL for LLMs · Chapter 16
The critic-free algorithm zoo
RLOO, GRPO, Dr. GRPO, DAPO, GSPO, CISPO and friends — one estimator, different knobs.
Open three reinforcement-learning papers from 2025 and you will meet three new acronyms: DAPO, Dr. GRPO, GSPO. A month later there are three more. Each paper prints a long objective full of sums, mins, clips and fractions, and claims it fixes something the previous one got wrong. It feels like learning a new algorithm every week.
It isn’t. Almost every method in this family computes the same thing: REINFORCE from Chapter 7, with a baseline taken from a group of samples, applied to the tokens of a response. The papers differ in a handful of choices: what to subtract from the reward, whether to divide by a standard deviation, how to average over tokens, how to clip the importance ratio, whether to keep a KL term, and which samples to keep. This chapter calls those choices knobs. You will learn the master formula once, see what each knob does on a batch of eight responses small enough to compute by hand, and then read every algorithm in the zoo as a setting of the knobs. After that, the next new acronym will take you five minutes to place.
You should know GRPO from Chapter 15 (group sampling, group-normalized advantages, the clipped token-level objective) and PPO’s clip from Chapter 9. We recap what we need.
One estimator, six knobs
Where we start: REINFORCE on a response
Take one prompt and treat the whole response as a single action, as in the contextual-bandit view of Chapter 11. The reward arrives at the end. The policy gradient with a baseline (Chapter 7) is
The log-probability of a response is the sum of its token log-probabilities, so the same gradient, written token by token, is
Read it as an instruction: every token of the response gets the same push, of size . Tokens of better-than-expected responses become more likely, tokens of worse-than-expected ones less likely. This is the true gradient. Everything below is a way of estimating it from a finite batch, more cheaply, more stably, or (sometimes) of deliberately estimating something slightly different.
The master formula
Sample responses for each prompt. A batch has responses in total (prompts × ). Every critic-free method computes an update of this form:
In words: each token’s log-probability is pushed by the response’s advantage , times a per-token weight that corrects (or clips) for the batch having been sampled by a slightly older policy, times a normalizing constant that decides how tokens are averaged. Here are the six knobs:
| Knob | Question it answers | Typical settings |
|---|---|---|
| 1. Baseline | What do we subtract from ? | nothing, batch mean, group mean, leave-one-out, greedy reward |
| 2. Scale | Do we divide by a standard deviation? | no, group std, batch std |
| 3. Aggregation | How do we average over tokens? | per-response mean, per-token mean, constant |
| 4. Ratio and clip | How do we handle off-policy samples? | none, PPO clip, asymmetric clip, clipped weight, sequence ratio |
| 5. KL | Do we leash the policy to , and how? | in reward, in loss, dropped |
| 6. Data | Which samples enter the batch at all? | all, drop zero-signal groups, drop or penalize overlong ones |
GRPO as a setting of the knobs
Here is GRPO’s objective as the DeepSeekMath paper writes it (their is our , their is our ; Chapter 15 derives it):
Match it against the knobs. Baseline: the group mean. Scale: the group std. Aggregation: , an average over tokens inside each response, then over responses. Ratio and clip: PPO’s clip on a per-token ratio . KL: in the loss, with the estimator, . Data: every group is used. At the first update on a fresh batch, , every , nothing is clipped, and the gradient of the bracket is exactly the master formula with and .
Every other algorithm turns one or more of these knobs. Before the zoo, let’s understand each knob on a concrete batch.
The running example: eight responses
Two prompts, responses each, a verifier that says right (1) or wrong (0). The lengths differ on purpose.
| Response | Prompt 1: reward, length | Prompt 2: reward, length |
|---|---|---|
| 1 (right), 12 tokens | 0, 6 tokens | |
| 0 (wrong), 4 tokens | 0, 16 tokens | |
| 0 (wrong), 20 tokens | 0, 10 tokens | |
| 1 (right), 8 tokens | 1, 14 tokens |
Prompt 1 is the rewards 1, 0, 0, 1 group from Chapter 15: half right. It has a short wrong answer (, 4 tokens) and a long wrong one (, 20 tokens). Prompt 2 is harder: one right answer out of four. The batch has responses and 90 tokens. The generation budget is tokens. The demo later in the chapter uses exactly this batch.
Knob 1: the baseline
What a baseline is for
Chapter 7 proved two facts. Subtracting any baseline that does not depend on the sampled response leaves the gradient unbiased, because . And a good baseline (close to the expected reward) cuts the variance, often enormously. With 0/1 rewards and no baseline, every wrong answer has and gets no push at all: the policy learns only from its successes. With a baseline, wrong answers get a negative advantage and are pushed down.
The ideal baseline is , the expected reward for this prompt. PPO learns it with a critic (Chapter 8). For a language model the critic is a second network as large as the policy, and per-token values for reasoning traces are hard to learn. Critic-free methods estimate from the samples themselves. They differ in how.
Five baselines, computed
None (plain REINFORCE). .
Batch mean. Average all rewards in the batch: here. Cheap, but it uses one number for an easy and a hard prompt alike.
Group mean (GRPO). Average the rewards of the same prompt: for prompt 1, for prompt 2. This is a Monte Carlo estimate of for this prompt.
Leave-one-out (RLOO). For response , average the other rewards of its group:
The idea goes back to Kool, van Hoof and Welling (2019), “Buy 4 REINFORCE samples, get a baseline for free!”. Ahmadian et al. (2024) brought it to RLHF as RLOO (REINFORCE Leave-One-Out). Because never looks at , it does not depend on the sampled response , and the estimator is exactly unbiased.
Greedy reward (ReMax, Li et al. 2023). Decode one extra response greedily (always the most likely token) and use its reward as the baseline. One extra generation per prompt instead of a group.
Here are the advantages on our batch, before any scaling:
| Response | none | batch mean | group mean | leave-one-out | |
|---|---|---|---|---|---|
| P1 , (right) | 1 | 1 | 0.625 | 0.5 | 0.667 |
| P1 , (wrong) | 0 | 0 | −0.375 | −0.5 | −0.667 |
| P2 , , (wrong) | 0 | 0 | −0.375 | −0.25 | −0.333 |
| P2 (right) | 1 | 1 | 0.625 | 0.75 | 1.0 |
Look at prompt 2’s lone success. The group baselines give it the biggest advantage in the batch (0.75 or 1.0): a rare success on a hard prompt is the most surprising thing that happened, so it gets the biggest push. The batch mean misses this: it gives the same 0.625 to every right answer, easy prompt or hard.
Quick check A group has rewards (1, 0, 0, 0). With GRPO's group-mean baseline and no std division, what advantage does the correct response get?
The group mean is 0.25, so the correct response gets 1 − 0.25 = 0.75 and each wrong one gets −0.25. With leave-one-out the correct one would get 1 − 0 = 1 (the other three are all 0), and each wrong one −1/3.
Group mean versus leave-one-out: a rescaling
Look at the last two columns: the leave-one-out advantages are the group-mean ones multiplied by . That is no coincidence. Write for the group’s total. Then
The group-mean advantage is exactly times the leave-one-out advantage, response by response. Since the leave-one-out estimator is unbiased, the group-mean estimator has expectation : it is biased, but only by a constant factor shared by every prompt with the same . A constant factor is absorbed by the learning rate (and almost entirely ignored by Adam). So GRPO’s baseline “includes the sample itself” in a harmless way. Exercise 16.2 asks you to prove the expectation directly.
Knob 2: the scale (to divide by std, or not)
What GRPO’s std does
GRPO divides each group’s centered rewards by the group’s standard deviation. For prompt 1 (rewards 1, 0, 0, 1) the std is 0.5, so the advantages become ±1. For prompt 2 (0, 0, 0, 1) it is , giving for the wrong answers and for the right one. (We use the population std, dividing by . Some implementations use ; the difference is a constant factor .)
The intent is sensible: put every prompt’s advantages on the same scale, as in Chapter 8’s advantage normalization. But a group’s std is not a neutral number. With binary rewards and pass rate , the std is . It is largest at and goes to zero as approaches 0 or 1. Dividing by it up-weights the prompts the model almost always gets right and the prompts it almost always gets wrong.
How much, exactly?
Ask what each prompt contributes to the expected gradient. Without std, using the true mean as the baseline,
where is the probability that a sample for prompt is right. So mean-centering follows the gradient of , the expected accuracy, with every prompt weighted equally. With the std, every term is divided by :
The extra factor is a prompt weight:
| Pass rate | 0.5 | 0.9 or 0.1 | 0.99 or 0.01 |
|---|---|---|---|
| Weight with std, | 2.0 | 3.3 | 10.1 |
| Weight without std | 1 | 1 | 1 |
A prompt the model solves 99% of the time is pushed five times harder per unit of than a prompt it solves half the time. Liu et al. (2025) call this the question-level difficulty bias of GRPO and remove the std in Dr. GRPO (“GRPO Done Right”).
Is the difficulty bias good or bad?
Reasonable people disagree, and the evidence is mixed:
- Against the std. Dr. GRPO removes it. Olmo 3’s recipe and DeepSeek-V3.2 use mean-centered advantages without std. Cursor’s Composer 2 report drops it because “small behavioral differences get massively upweighted” when all rollouts are about equally good. You can see why with non-binary rewards: a group with rewards 0.80, 0.81, 0.79, 0.80 has std 0.007, so the advantages become 0, +1.41, −1.41, 0. Noise of one hundredth becomes a full-sized training signal.
- For some reweighting. DAPO and GSPO keep the group std. REINFORCE++ (Hu et al. 2025) argues that per-prompt (“local”) std normalization is biased and unstable when the std is near zero, and divides by one global batch std instead. That keeps the overall scale but weights every prompt the same.
- Go further the other way. MaxRL (Tajwar et al. 2026) argues we should up-weight hard prompts much more, by aiming at (the log-likelihood of success) instead of . Its gradient is , a weight of 100 at and about 1 at . That is asymmetric: hard prompts count, easy ones don’t.
- It may not matter much at the end. ScaleRL (Khatri et al. 2025) fit compute-performance curves for many recipe variants and found that advantage normalization mainly changes how fast a run improves, not the level it eventually reaches.
The three weightings in one picture: mean-only weights every prompt 1; std weights both extremes; MaxRL weights only the hard extreme. Each one is the exact gradient of a different objective (, , ). “Bias” just means “not the objective you thought you were optimizing”.
Knob 3: aggregation, and the length bias
Three ways to average over tokens
After computing a per-token term (advantage times ratio, clipped or not), you have a ragged array: response has terms. You must turn it into one number to differentiate. Three choices are in use:
| Name | Formula | Used by |
|---|---|---|
| Sequence-mean | GRPO (as written), GSPO | |
| Token-mean | DAPO, CISPO, Olmo 3 | |
| Constant | Dr. GRPO |
They look like bookkeeping. They are not, because they decide the weight each token gets, and that weight can depend on the length of the response the token sits in.
The worked example
Take prompt 1’s two wrong answers under GRPO’s advantages ( for both). The short one has 4 tokens, the long one 20. Each token’s weight :
| Aggregation | Each token of (4 tokens) | Each token of (20 tokens) | Total push, vs |
|---|---|---|---|
| Sequence-mean, | vs | ||
| Token-mean, | vs | ||
| Constant, | vs |
Under sequence-mean, each response gets the same total push no matter how long it is, so each token of the long wrong answer is pushed down five times less than each token of the short one. Under the other two, every token is pushed equally, and the long answer, with five times as many tokens, gets five times the total push.
Which one is the policy gradient? Go back to the first section: the true gradient gives every token of response the same weight , with no . The constant normalizer gives exactly that, up to one global factor. Token-mean is almost that: its normalizer is shared by the whole batch, so it only rescales the step, by an amount that varies a little from batch to batch. Sequence-mean is the odd one out.
Quick check Under sequence-mean aggregation, two wrong answers have the same advantage. One is 100 tokens long, the other 1000. How hard is each token of the long answer pushed down, compared with each token of the short one?
Sequence-mean gives each response the same total push, divided over its tokens: 1/100 of it per token for the short answer, 1/1000 for the long one. Each token of the long answer gets one tenth of the push.
What sequence-mean actually optimizes
There is a cleaner way to see the bias. Under sequence-mean, response contributes
That is the REINFORCE estimator for a different reward, (treating the baseline as fixed; with the leave-one-out baseline it is exactly independent of ). Now look at what prefers, with :
- A right answer earns : shorter is better. A 100-token right answer earns 0.005; a 1000-token one earns 0.0005.
- A wrong answer earns : longer is better. A 100-token wrong answer costs 0.005; a 1000-token one costs only 0.0005.
So GRPO as written pays the model to be brief when it is right and to ramble when it is wrong. Liu et al. (2025) call this the response-level length bias: “longer responses are penalized less” when they are incorrect, so incorrect responses grow. It matters whenever the model can tell, mid-response, that it is going wrong, which language models can (they hedge, loop, re-check). Part of the famous growth in response length during R1-Zero-style training may come from this bias rather than from useful reasoning, which is one of the paper’s points.
Dr. GRPO’s fix is to replace each response’s by one constant, the generation budget . The paper also points out that the same per-response length normalization was already present in open-source PPO implementations before GRPO, so this is not a GRPO-only issue.
∂ Why does the constant normalizer give the unbiased gradient?
The true gradient for one prompt, with any baseline independent of the sampled response, is
The sample estimate from responses is
so when is leave-one-out. Dr. GRPO’s loss gives , which is : the same direction, one fixed scale. Token-mean gives . The factor is one over the batch’s average length. It is the same for every token in the batch, so it does not reweight responses against each other; it only makes the step size depend slightly on how long this batch happened to be. Sequence-mean instead multiplies each response by its own , which changes the expected direction: , the gradient of a different objective, as in the main text.
What the lab shows
The lab for this chapter includes a tiny “language model” built to expose the bias. A response is an answer token followed by filler tokens; the filler never changes the reward, but the policy may learn to emit more filler after some answers than after others. With everything else equal, sequence-mean aggregation (the GRPO preset) roughly doubles the average length of wrong responses within 300 updates (from about 4 tokens to about 8, with noisy spikes past 10), and shortens right responses from about 3.5 tokens to 2.2. Under Dr. GRPO’s constant normalizer and DAPO’s token-mean, both stay flat. The effect is not subtle once length is something the policy controls.
Knob 4: importance ratios and clipping
Why ratios appear at all
If you generated a batch and took exactly one gradient step on it, you would need no ratio: the samples come from the current policy. In practice you reuse a batch for several minibatch updates, and in large systems the samples are also a few versions stale (asynchronous training) and come from an inference engine whose probabilities differ slightly from the trainer’s (Chapter 20). So from the second update on, , and as in Chapter 9 each token’s term is reweighted by the importance ratio
PPO’s clip then keeps the update from running away. Using , the weight a token gets in the master formula under the PPO clip is
Here and are the lower and upper edges of the clip band; standard PPO and GRPO use one value for both, . A token that has already moved far enough in the direction its advantage wants stops contributing a gradient (the “four cases” of Chapter 9). The methods in this section disagree about three things: where the band should be, whether a clipped token should lose its gradient entirely, and whether the ratio should be computed per token at all.
Clip-higher: give rare tokens room to grow (DAPO)
The symmetric clip treats a ratio of 1.2 the same for every token. In probability, that is very unequal. A token with may rise to 0.72 before its gradient switches off: a gain of 0.12. A rare token with , say the word “Wait” that starts a self-correction, may only rise to 0.012: a gain of 0.002. Rare tokens are exactly the ones whose probability the policy needs to raise to explore new behaviour, and the upper clip throttles them sixty times harder in absolute terms.
DAPO (Yu et al. 2025) argues that this throttle is one cause of entropy collapse, where the policy becomes nearly deterministic early and stops improving (Chapter 19). Its fix, clip-higher, decouples the two edges: but . In DAPO’s ablation on Qwen2.5-32B, adding clip-higher raised AIME 2024 accuracy from 36 to 38 points. (AIME 2024 is a set of 30 competition-math problems, a standard reasoning benchmark; avg@32 means accuracy averaged over 32 sampled answers per problem, which reduces the noise of a single sample.) The lower edge stays at 0.2 because pushing bad tokens’ probabilities toward zero too fast is the other way to collapse entropy.
CISPO: clip the weight, keep the gradient (MiniMax-M1)
MiniMax’s M1 report observed that low-probability “fork” tokens such as “However”, “Recheck” and “Wait” get large ratios after the first on-policy update and are then clipped out, losing their gradient for all the remaining off-policy updates on that batch (they used 16). Their fix, CISPO (Clipped IS-weight Policy Optimization), does not clip the objective. It clips the importance weight and stops its gradient:
where means stop-gradient: the weight is treated as a constant. In practice only the upper bound is used. The gradient weight is then , which is never zero: every token keeps a gradient, but no token’s weight can exceed . This is truncated importance sampling, an old idea in off-policy RL, applied to REINFORCE. MiniMax reports that in a controlled comparison on Qwen2.5-32B, CISPO reached DAPO’s performance with half the training steps.
Compare the two rules on four tokens (with for PPO, and only an upper bound of 1.28 for CISPO):
| Token ratio | Advantage | PPO weight | CISPO weight |
|---|---|---|---|
| 1.5 | +1 | 0 (clipped) | 1.28 (capped) |
| 1.5 | −1 | 1.5 | 1.28 |
| 0.5 | +1 | 0.5 | 0.5 |
| 0.5 | −1 | 0 (clipped) | 0.5 |
PPO’s zeros are where it believes the token has “done enough”. CISPO never believes that; it only refuses to let one token’s weight explode. Note the second row: CISPO caps a weight that PPO would leave unclipped. The two rules are different trade-offs, not one a superset of the other.
Quick check A token has ratio ρ = 0.6 and a negative advantage. Which rule still gives it a gradient: PPO-clip with ε = 0.2, or CISPO with only an upper bound?
ρ = 0.6 is below 1 − ε = 0.8, and the advantage is negative: the token is already less likely than before, so PPO's min picks the flat clipped term and its gradient is zero. CISPO's weight is min(0.6, 1.28) = 0.6, so the token keeps a gradient of 0.6 × Â.
Sequence-level ratios (GSPO)
The reward belongs to a whole response, so the “correct” importance weight for a response is the ratio of sequence probabilities, . Its trouble is variance: a product of hundreds of ratios near 1 can still land anywhere from 0.01 to 100. GRPO’s per-token ratios dodge that, but each token is then weighted by its own noisy ratio. The GSPO paper argues that this is not a proper importance correction for a sequence-level reward at all, only noise injected token by token.
GSPO (Group Sequence Policy Optimization; Zheng et al. 2025, the Qwen team) takes the principle “the unit of optimization should match the unit of reward” and uses one ratio per response, the geometric mean of its token ratios:
Every token of a response now shares one weight, and the whole response is clipped or not, together. A worked example: three tokens with ratios 1.3, 0.8, 1.0 and . GRPO’s token clip (ε = 0.2) zeroes the first token’s gradient and keeps the other two with weights 0.8 and 1.0. GSPO computes and gives all three tokens the same weight, unless is outside its band.
That band is tiny. Because is an average per-token log-ratio, it barely moves even when individual tokens move a lot. The GSPO paper uses a clip range of on the left and on the right, against 0.2 and 0.27 for its GRPO baseline. Even so, it reports that GSPO clips about two orders of magnitude more tokens than GRPO, yet trains more efficiently, which the authors read as evidence that GRPO’s token-level gradients are noisy.
The motivation that made GSPO matter in practice is mixture-of-experts (MoE) models. In an MoE, a small change in the weights can route a token to different experts, so a single token’s ratio can jump wildly between and . The GSPO paper reports that GRPO on its MoE models needed Routing Replay (reuse the old policy’s expert choices when computing ratios) to converge, and GSPO did not. The Qwen team credits GSPO for improvements in Qwen3.
Knob 5: the KL leash
Chapter 11 introduced the KL-regularized objective and three per-token estimators of : , , and . The zoo uses three placements:
- In the reward. Subtract from each response’s reward before computing advantages. This is classic RLHF (Chapter 12) and RLOO.
- In the loss. Add per token to the loss, outside the advantage. This is GRPO, with in DeepSeekMath. REINFORCE++ puts in the loss instead.
- Dropped. DAPO, Dr. GRPO, CISPO, Magistral, Olmo 3 and ScaleRL train RLVR with no KL term at all. DAPO’s argument: for long chain-of-thought reasoning “the model distribution can diverge significantly from the initial model, thus this restriction is not necessary.”
Why would anyone drop the leash? Its main job in RLHF is to keep the policy where a learned reward model is still trustworthy (Chapter 19). A verifier that checks a final answer cannot be fooled by moving off-distribution in the same way, and reasoning models are supposed to move far from the base model. Dropping the KL also saves a forward pass through the reference model. On the other side, DeepSeek-V3.2 keeps an importance-corrected and says the right strength is domain-dependent (weak or none for math), and NVIDIA’s ProRL keeps the KL and periodically resets the reference model to sustain long training runs.
There is also a subtlety about which placement gives the gradient you think it does. “A Comedy of Estimators” (Shah et al. 2025) analyzed the on-policy gradients: in the reward gives an unbiased gradient of the reverse KL; GRPO’s in the loss gives a biased gradient that nevertheless trains stably; in the reward led to collapse in their runs. The lab implements all three placements so you can check the formulas; Chapter 11 has the estimator math.
Knob 6: which samples enter the batch
Zero-signal groups
If all responses to a prompt get the same reward, every baseline that uses the group (mean or leave-one-out) gives every advantage exactly 0. The group costs a full round of generation and contributes no gradient. How often does that happen? With pass rate , all right or all wrong has probability :
| 0.5 | 12.5% | 0.8% | 0.003% |
| 0.9 | 65.6% | 43.0% | 18.5% |
| 0.95 | 81.5% | 66.3% | 44.0% |
As training succeeds, more prompts become easy, and a growing share of the batch is dead weight. Worse, the dead groups still count in the normalizer ( for sequence-mean, for token-mean), so they also shrink everyone else’s step.
Quick check With pass rate p = 0.5 and G = 4, what fraction of groups give zero signal?
All four right has probability 0.5⁴ = 1/16, all four wrong another 1/16, so 2/16 = 12.5%.
Dynamic sampling (DAPO) over-samples prompts and filters out groups whose rewards are all equal, refilling until the batch is full of informative groups. In DAPO’s ablation it was the largest single step, from 42 to 50 on AIME 2024 avg@32. Olmo 3 uses a more efficient variant it calls active sampling, and ScaleRL adds “No-Positive-Resampling”: prompts with a pass rate of at least 0.9 are retired from the dataset for good.
Overlong responses
Responses that hit the generation limit are cut off and usually scored as wrong, even if the reasoning was on track. That injects noise: the model is punished for a good but long attempt. DAPO’s overlong filtering masks truncated responses out of the loss. Its soft overlong punishment adds a length penalty that ramps up in a buffer zone of tokens before the hard limit:
With DAPO’s settings, and , responses up to 16,384 tokens are not penalized at all; an 18,000-token response sits 1,616 tokens into the buffer and gets . In the ablation, overlong filtering and the soft punishment were worth +6 and +3 points. Note this is a reward-design knob more than an estimator knob; Chapter 19 discusses length penalties as a defence against verbosity.
Build an algorithm
Everything so far fits in one picture. The demo shows the running example’s eight responses as rows of tokens. Each cell is one token; its color is the gradient weight that multiplies for that token (blue: pushed up; orange: pushed down; hatched: clipped to exactly zero). The bar at the right of each row is the response’s total push. The numbers are relative: the largest per-token weight in the batch reads 1.00, and so does the largest total. Under the bars, three readouts compare the short and long wrong answers, the signal each prompt gets, and how many tokens are clipped. Tap a response’s label (for example “y₂ ✗”) to flip its reward.
What to try: start on GRPO and read the Length line: each token of the short wrong answer is pushed 5× harder than each token of the long one. Click Dr. GRPO: per-token weights equalize and the long answer now gets 5× the total push. Switch back to GRPO and tap prompt 1's y₁ and y₄ to make them wrong: the whole group goes grey (zero signal); tick dynamic sampling to drop it. Reset, then raise the staleness slider to 0.1 and compare GRPO, DAPO (clip-higher), CISPO and GSPO: count the hatched cells. At 0.001 GSPO already clips whole rows while GRPO clips nothing.
A few things to notice as you play:
- On-policy, half the knobs are invisible. With staleness 0 every ratio is 1, so GRPO and GSPO give identical weights, and every clip setting does nothing. Ratio and clip knobs only matter for the second and later updates on a batch, or under asynchronous or mismatched sampling.
- Baselines change who learns from failure. On REINFORCE, wrong answers have no color at all. On every group baseline they are pushed down, and prompt 2’s single success is the brightest row in the batch.
- The std changes the balance between prompts. Compare the “signal per prompt” line for GRPO and Dr. GRPO: the std inflates the 1-of-4 prompt relative to the 2-of-4 prompt. Flip prompt 2’s to make it a 0-of-4 group and its signal vanishes. Make it 3 of 4 instead and it gets exactly the same signal as 1 of 4: is symmetric in and .
The zoo, species by species
The comparison table
Each row follows the cited paper (dates are arXiv v1 months). “Seq-mean”, “token-mean” and “constant” are the three aggregations above. “Group” means computed within the samples of one prompt.
| Method | Year | Baseline | Scale | Aggregation | Ratio and clip | KL | Key idea or claim |
|---|---|---|---|---|---|---|---|
| REINFORCE | 1992 | none (or a learned one) | none | sequence sum | none | none | unbiased, high variance |
| ReMax (Li et al.) | Oct 2023 | reward of a greedy response | none | sequence sum | none | optional | no critic; the value model and its optimizer took 46% of GPU memory in their 7B PPO setup |
| RLOO (Ahmadian et al.) | Feb 2024 | leave-one-out | none | sequence sum | none | in reward | REINFORCE-style RLOO beats PPO, DPO and RAFT for RLHF; PPO’s clip fired in under 5% of cases |
| GRPO (Shao et al.) | Feb 2024 | group mean | group std | seq-mean | token, symmetric ε | in loss, β = 0.04 | drops PPO’s critic; in DeepSeekMath |
| REINFORCE++ (Hu et al.) | Jan 2025 | group mean (or none) | batch std | token-mean | token, symmetric ε | in reward or in loss | per-prompt std is biased and unstable; normalize globally |
| Dr. GRPO (Liu et al.) | Mar 2025 | group mean | none | constant | token, symmetric ε | none | removes the length and difficulty biases |
| DAPO (Yu et al.) | Mar 2025 | group mean | group std | token-mean | token, 0.2 / 0.28 | none | + dynamic sampling, overlong shaping: AIME 2024 from 30 (naive GRPO) to 50 on Qwen2.5-32B |
| CISPO (MiniMax) | Jun 2025 | group | group std | token-mean | clipped, stop-grad weight | none | every token keeps its gradient; 2× faster than DAPO in their study |
| GSPO (Zheng et al.) | Jul 2025 | group mean | group std | one term per response | sequence ratio, 3e-4 / 4e-4 | none | stable MoE training without Routing Replay; used for Qwen3 |
| ScaleRL (Khatri et al.) | Oct 2025 | group | batch std | prompt-level mean | CISPO | none | fits sigmoid compute-scaling curves; most knobs change efficiency, not the ceiling |
| SAPO (Gao et al.) | Nov 2025 | group | group std | seq-mean | soft sigmoid gate | not part of the method | smooth, sign-dependent down-weighting instead of a hard cut |
| OlmoRL (Olmo 3) | Dec 2025 | group mean | none | token-mean | token, clip-higher, × truncated IS | none | an open “consensus” recipe: GRPO + the 2025 fixes |
| MaxRL (Tajwar et al.) | Feb 2026 | n/a | ÷ number of successes | n/a | n/a | n/a | aims at instead of : up-weights hard prompts |
Species notes
RLOO is the cleanest member: leave-one-out baseline, no std, no clip, the KL folded into the reward. Ahmadian et al. argue that the RLHF setting doesn’t need PPO’s machinery: with a good starting policy and a sequence-level reward, the clip rarely fires, and treating the whole response as one action (a bandit) works as well as modeling partial completions with a critic, at a fraction of the cost.
GRPO is the reference point everyone modifies. Its group mean and std came from DeepSeekMath, which used a learned reward model. Its popularity came with DeepSeek-R1 and verifiable rewards (Chapter 15).
Dr. GRPO is a correction, not an invention: drop the two divisions ( and the std) that make GRPO optimize something other than expected reward. Its paper also contains useful skepticism about R1-Zero-style training, including evidence that some base models already show “aha”-style self-reflection before any RL.
DAPO is a bundle of four engineering fixes found while reproducing R1-Zero at 32B scale: clip-higher, dynamic sampling, token-level loss, and overlong shaping. Its ablation table is one of the best places to see how much each knob is worth in one setting:
| DAPO ablation (Qwen2.5-32B base) | AIME 2024 avg@32 |
|---|---|
| naive GRPO | 30 |
| + overlong filtering | 36 |
| + clip-higher | 38 |
| + soft overlong punishment | 41 |
| + token-level loss | 42 |
| + dynamic sampling (= DAPO) | 50 |
Remember these are cumulative and measured once, in one setting; the order of addition affects how much each step appears to contribute.
CISPO and GSPO both attack the off-policy knob, in opposite directions. CISPO keeps per-token ratios but never discards a token’s gradient. GSPO discards per-token ratios entirely in favour of one per sequence, and clips whole responses. Both appear in ScaleRL’s comparison as having a higher performance ceiling than DAPO’s loss.
REINFORCE++ and ScaleRL prefer a batch-level std: one number for the whole batch, so no prompt is up-weighted for having low variance.
Critics strike back
“Critic-free” is a trend, not a law. VAPO (Yue et al. 2025, ByteDance Seed) is PPO with a value model, made to work for long chain-of-thought: the value network is pretrained, GAE uses different λ for critic and policy, and λ adapts to response length. It reports 60.4 on AIME 2024 from Qwen2.5-32B base, more than 10 points above DAPO in the same setting. VinePPO (Kazemnejad et al. 2024) replaces the learned critic with Monte Carlo value estimates: because a language environment can be reset to any prefix, you can sample a few continuations from the middle of a response and average their rewards, giving unbiased per-step values (Chapter 17 uses the same trick for process rewards). It reports beating PPO and RLOO-style baselines with up to 3× less wall-clock time to peak. The honest summary: group baselines give up per-token credit assignment in exchange for simplicity and memory. When credit assignment within a long response matters, critics (learned or Monte Carlo) can win back the difference, at a cost.
Does the choice matter?
Less than the number of papers suggests, and more than zero. Yue et al. (2025), the pass@ paper (not the VAPO authors), compared six popular RLVR algorithms and found they performed similarly, all far from the base model’s large- pass@ (Chapter 15 discusses that debate). ScaleRL found that most knobs change how quickly a run reaches its ceiling rather than the ceiling itself, with a few exceptions (the loss type, FP32 precision for the LM head, batch size, generation length). The lab’s TinyLM experiment shows the same flavour at toy scale: REINFORCE, RLOO, GRPO and Dr. GRPO all improve the addition task by similar amounts within noise. Knob choices matter most when they interact with a specific failure: lengths that the model can inflate, entropy that collapses, MoE ratios that explode, prompts that become too easy.
Beyond the knobs: changing the objective
One 2026 line of work changes not the estimator but the target. MaxRL (Tajwar et al. 2026) observes that with binary rewards the log-probability of success expands as
so ordinary RL () keeps only the first term of the maximum-likelihood gradient. Its estimator is a one-line change to REINFORCE: average the score function over the successful samples only, dividing by the number of successes instead of by . That turns the per-prompt weight (mean-centered) into roughly , the third of the three weightings compared in Knob 2. The authors report it Pareto-dominates the baselines they tested; it is recent, so treat it as a promising direction rather than settled practice.
Reading the next acronym
When a new critic-free method appears, ask six questions, in order:
1. Baseline: what is subtracted from r? (none / group mean / leave-one-out / batch / greedy / learned)
2. Scale: divided by a std? whose? (group / batch / none)
3. Aggregation: how are token terms averaged? (1/|y| per response, 1/total tokens, constant)
4. Ratio & clip: per token or per sequence? clipped, capped, masked, or soft-gated? which band?
5. KL: in the reward, in the loss (which estimator?), or absent?
6. Data: which groups are dropped or refilled? how are truncated responses treated?
Then ask the question that separates a real improvement from a knob shuffle: which failure does the change target, and does the paper show that failure in its baseline? A method that fixes length bias should show lengths growing without the fix. A method that fixes entropy collapse should show entropy collapsing. If the paper only shows a better final number, on one model family, with one seed, read it skeptically (Chapter 21 has a checklist).
Here is the full step every method in the table implements, with the knobs marked:
for each training step:
1. sample a batch of prompts; for each prompt sample G responses from π_old (the current policy)
2. score them: r_i = verifier(x, y_i)
(knob 6) drop groups with all-equal rewards and refill; mask or penalize truncated responses
3. (knob 5a) if KL in reward: r_i ← r_i − β Σ_t log(π_old/π_ref)
4. (knobs 1-2) A_i = (r_i − baseline_i) / scale_i
5. record log π_old(y_t) for every token (and log π_ref(y_t) if KL in loss)
6. for each of K minibatch updates:
ratio: ρ_t = π_θ/π_old per token, or s_i per response (knob 4)
term_t = clip rule(ρ, A_i) (knob 4)
term_t ← term_t − β · KL estimate_t if KL in loss (knob 5b)
loss = − aggregate(term) (knob 3)
gradient step on loss
Summary
- The critic-free family is one estimator: each token’s log-probability gradient is weighted by an advantage, an off-policy weight, and an aggregation constant. Algorithms differ in six knobs: baseline, scale, aggregation, ratio and clip, KL, and data.
- Baselines: group mean (GRPO) is exactly times leave-one-out (RLOO), a harmless rescaling; leave-one-out is unbiased; no baseline means wrong answers are never pushed down.
- Dividing by the group std reweights prompts by , up-weighting nearly-always-right and nearly-always-wrong prompts (Dr. GRPO’s difficulty bias), and amplifies noise when rewards barely differ. Batch std, no std, and MaxRL’s are alternatives, each the gradient of a different objective.
- Sequence-mean aggregation optimizes : it pays the model to be short when right and long when wrong. Token-mean and constant normalizers give every token equal weight and remove the bias.
- Clipping matters only off-policy. Clip-higher (DAPO) lets rare tokens grow; CISPO caps the importance weight but never zeroes a gradient; GSPO uses one geometric-mean ratio per response with a tiny band, which stabilizes MoE training.
- KL can go in the reward, in the loss, or nowhere; most 2025 RLVR recipes dropped it, and the estimator and placement change which gradient you actually get.
- Data knobs (dynamic sampling, overlong filtering) were among the largest single gains in DAPO’s ablation, because zero-variance groups and truncated responses waste compute or inject noise.
- Measured head to head, many variants perform similarly; the knobs pay off when they target a failure you can actually see in your run.
Exercises
A prompt gets responses with rewards . Compute the advantage of a right and of a wrong response under: (a) the group-mean baseline, (b) leave-one-out, (c) GRPO (group mean, divided by the population std), (d) ReMax, if the greedy response happens to be right. Check that (a) is times (b).
Solution
The group mean is .
(a) Right: . Wrong: .
(b) For a right response, the other five rewards contain one 1: baseline , advantage . For a wrong response, the other five contain two 1s: baseline , advantage .
Check: and . They match.
(c) Population std: with , so . Right: . Wrong: . (Exactly and .)
(d) The greedy response scored 1, so : right answers get and wrong ones get . ReMax learns only from failures here. If the greedy answer had been wrong, and it would learn only from successes. A single extra sample is a noisier baseline than a group mean.
Responses are sampled independently from . Write and .
(a) Show that , where and .
(b) Show that with , .
(c) Why is the bias in (b) harmless in practice, and when would it stop being harmless?
(d) In one batch, prompt A keeps only 2 of its responses (the others were masked out as truncated) and prompt B keeps all 8. Relative to the true gradient, by what factor is each prompt’s expected contribution scaled under the group-mean baseline? Under leave-one-out?
If you did Exercise 15.3, parts (a) and (b) are a quick recap; (c) and (d) are the new part.
Hint
Solution
(a) Split the expectation: . For , depends only on and only on , which are independent, so . Hence . Unbiased.
(b) . So . The term that survives is the response competing with its own share of the mean.
(Equivalently, use the identity from the chapter: for every sample, then take expectations and use (a).)
(c) The factor is the same for every prompt as long as every prompt uses the same , so it only rescales the gradient, which the learning rate (and Adam’s normalization) absorbs. It stops being harmless if group sizes vary across prompts in a batch (for example after filtering or with variable sampling budgets): then prompts with small groups are down-weighted relative to large ones, a real reweighting. With the factor is , with it is .
(d) Under the group mean, prompt A’s contribution is scaled by and prompt B’s by . So A is down-weighted relative to B by , a real reweighting that the learning rate cannot absorb. Under leave-one-out both factors are exactly 1: every prompt is unbiased whatever its group size. This is one practical reason to prefer leave-one-out when group sizes vary.
(a) Show that under sequence-mean aggregation, response ‘s contribution to the gradient equals the REINFORCE estimator for the modified reward , with held fixed.
(b) Let (a hard prompt). Compute for a right answer of 50 tokens and of 500 tokens, and for a wrong answer of 50 and of 500 tokens. Which lengths does the modified reward prefer for right and for wrong answers?
(c) Suppose the model’s correctness on a prompt is decided by its first few tokens, and after that it chooses how many more tokens to write. Explain qualitatively what sequence-mean training will do to the length of right and wrong responses, and what token-sum (constant normalizer) training will do.
Hint
Solution
(a) Sequence-mean gives response the term , using and the sum of token log-probs. This is : the REINFORCE estimator, with no baseline, for reward . Its expectation is (with fixed). (If you use the std as well, is divided by a constant per prompt; the conclusion is the same.)
(b) Right answers: and . Wrong answers: and . The modified reward prefers short right answers (0.015 > 0.0015) and long wrong answers (−0.0005 > −0.005).
(c) Under sequence-mean, the policy is effectively rewarded by . After its first tokens have committed it to a wrong answer, writing more tokens raises toward 0, so the policy learns to ramble when it is wrong; after a right start, it learns to stop early. Wrong responses grow, right ones shrink, and overall length can rise as a symptom of failure rather than of reasoning. Under the constant normalizer, the expected gradient is the true , and the reward is independent of length, so the length decisions get no systematic gradient (only noise). This is exactly what the lab’s LengthToy shows: under the GRPO preset wrong responses roughly double in length (about 4 to about 8 tokens), while Dr. GRPO and DAPO stay flat.
A prompt has binary reward with pass rate . Use the true mean as the baseline and the true std as the scale.
(a) Show that , and that this is for .
(b) Fill in the per-prompt weights (the factor multiplying ) for mean-only, std-normalized, and MaxRL (weight , the gradient of ) at .
(c) In one or two sentences each: which prompts does each scheme emphasize, and why might each be a reasonable choice?
Hint
Solution
(a) , by the log-derivative trick (). Dividing by the constant (treated as fixed, as the algorithm does) gives . Now , so by the chain rule .
(b)
| 0.01 | 0.1 | 0.5 | 0.9 | 0.99 | |
|---|---|---|---|---|---|
| mean-only | 1 | 1 | 1 | 1 | 1 |
| std, | 10.05 | 3.33 | 2.00 | 3.33 | 10.05 |
| MaxRL, | 100 | 10 | 2 | 1.11 | 1.01 |
(c) Mean-only treats a gain of 0.01 in pass rate the same on every prompt: it maximizes expected accuracy, the quantity usually reported. The std emphasizes both extremes symmetrically: it measures progress in Fisher-distance units, so polishing a nearly solved prompt (0.98 → 0.99) and cracking a nearly hopeless one (0.01 → 0.02) both count a lot. That stabilizes step sizes across prompts but spends effort on easy prompts that may not need it. MaxRL emphasizes only hard prompts: going from 0.01 to 0.02 doubles the likelihood of success and is worth as much as going from 0.5 to 1.0, which favours learning to solve new problems (and pass@ at large ) over perfecting ones already solved. Remember that in expectation itself is small on very hard prompts (few successes to learn from), so the weights partly compensate for a weak raw signal.
(a) Fill in the gradient weight (the factor multiplying , so a weight of 0 means no gradient) for PPO-clip with , DAPO’s clip-higher ( / ), and CISPO (upper bound 1.28 only), for these tokens: (i) , ; (ii) , ; (iii) , ; (iv) , .
(b) A response has three tokens with ratios 1.3, 0.8, 1.0 and . Compute GSPO’s sequence ratio. Is it inside GSPO’s band (, )? What weights do the three tokens get under GSPO, and under GRPO’s token clip with ?
Hint
Solution
(a)
| Token | PPO ε = 0.2 | clip-higher 0.2 / 0.28 | CISPO, cap 1.28 |
|---|---|---|---|
| (i) ρ = 1.25, Â > 0 | 0 (above 1.2) | 1.25 (inside) | 1.25 |
| (ii) ρ = 1.4, Â > 0 | 0 | 0 (above 1.28) | 1.28 |
| (iii) ρ = 0.7, Â < 0 | 0 (below 0.8) | 0 (below 0.8) | 0.7 |
| (iv) ρ = 0.7, Â > 0 | 0.7 | 0.7 | 0.7 |
Row (i) is clip-higher’s whole point: a good token that has grown 25% keeps learning. Row (ii) is CISPO’s: even past the cap, the token keeps a gradient, with its weight capped. Row (iv) is the “wrong way” case of Chapter 9: no rule clips a good token whose probability has fallen; all of them pull it back up.
(b) . That is far above , and , so GSPO clips the whole response: all three tokens get weight 0. Under GRPO’s token clip, token 1 () gets 0, token 2 gets 0.8, token 3 gets 1.0. The example shows why GSPO’s band must be so narrow: these token ratios are much larger than in a real LLM update (where per-token log-ratios are typically tiny), and their geometric mean still moves by only 1.3%.
(a) With pass rate and group size , show that the probability that a group carries signal (rewards not all equal) is .
(b) DAPO-style dynamic sampling keeps sampling prompts until it has informative groups. If every prompt has the same , how many prompts does it need on average? Evaluate for , and , , .
(c) Real batches mix easy and hard prompts. Why does ScaleRL’s “No-Positive-Resampling” (retire prompts with pass rate at least 0.9) save more compute late in training than early?
Hint
Solution
(a) A group gives zero signal exactly when all rewards are 1 (probability ) or all are 0 (probability ). These are disjoint, so .
(b) Each sampled prompt is informative with probability , independently, so collecting informative ones takes prompts on average.
- : , about 512 prompts.
- : , , , about prompts: 23% extra generation.
- : , , about prompts: 79% extra.
(c) Early in training few prompts are near-solved, so few groups are all-correct and filtering wastes little. Late in training many prompts have ; each of them is sampled, generated with long responses, and then (often) thrown away. Retiring them from the dataset avoids paying for those generations at all, and the saving grows as more prompts become easy.
For each training symptom, name the knob(s) you would turn first and say why, citing the method that introduced the fix.
(a) Policy entropy drops to near zero in the first hundred steps, and accuracy plateaus early.
(b) Average response length keeps growing, but almost all the growth is in incorrect responses.
(c) Training a mixture-of-experts model, the per-token ratios occasionally spike to 50 and training diverges.
(d) Late in training, 60% of groups are all-correct and the gradient norm keeps shrinking.
(e) RLHF with a learned reward model: reward climbs steadily, but human raters say outputs got worse.
(f) Rewards are continuous scores from a judge, and groups often have nearly identical scores; training is noisy.
Solution
(a) Knob 4, clip-higher (DAPO): raise so that low-probability tokens can grow, or switch to CISPO so clipped tokens keep their gradient. Entropy-specific methods (Chapter 19) are the next step.
(b) Knob 3, aggregation: replace sequence-mean with a constant normalizer (Dr. GRPO) or token-mean (DAPO). Sequence-mean penalizes long wrong answers less per token. Also check knob 6: if truncated responses get reward 0, overlong shaping prevents noise from cut-off answers.
(c) Knob 4, ratio level: use a sequence-level ratio (GSPO), or keep token ratios but add Routing Replay; on the systems side, align training and inference routing (Chapter 20). Also reduce the number of off-policy updates per batch.
(d) Knob 6, data: dynamic sampling (DAPO) or active sampling (Olmo 3) to refill with informative groups, and retiring easy prompts (ScaleRL’s No-Positive-Resampling); add harder prompts to the dataset. Knob 3 matters too: under token-mean, zero groups also dilute the denominator.
(e) Knob 5, KL: this is reward-model overoptimization. Keep (or strengthen) a KL leash to , preferably in the reward with for an unbiased gradient; the “drop the KL” recipes were designed for verifiable rewards, not learned ones (Chapter 19).
(f) Knob 2, scale: stop dividing by the group std (it turns score noise into full-size advantages); use mean-only advantages (Dr. GRPO) or a batch-level std (REINFORCE++), which keeps a sensible scale without amplifying near-ties.
Use the demo to answer these.
(a) On the GRPO preset (staleness 0), what is the ratio of per-token push between the short wrong and the long wrong ? Which presets make it 1.00?
(b) On REINFORCE, which responses get any push? Explain from the advantage column.
(c) Flip prompt 2’s to wrong. What happens to prompt 2 under GRPO, and what changes when you tick dynamic sampling?
(d) Set staleness to 0.1. How many tokens get zero gradient under GRPO, DAPO and CISPO? Now set staleness to 0.001 and compare GRPO with GSPO.
(e) Set GRPO’s knobs by hand, then change only the aggregation to “constant” and the scale to “none”. Which preset lights up?
Solution
(a) 5.00: sequence-mean gives each response the same total, spread over 4 vs 20 tokens. GSPO also shows 5.00 (it uses sequence-mean too). Dr. GRPO, DAPO, CISPO and RLOO show 1.00 per token (with the long answer getting 5× the total), since none divides by the response’s own length. REINFORCE shows no ratio at all: with no baseline both wrong answers have and get no push, which is part (b).
(b) Only the three right answers (P1 , , P2 ). With no baseline, , which is 0 for every wrong answer, so wrong answers are never pushed down.
(c) Prompt 2 becomes all wrong: zero variance, every advantage 0, the rows go grey, and the readout says the group is still generated but carries no signal. With dynamic sampling the group is dropped (and in a real system refilled with a fresh prompt). In a real loss the remaining tokens’ weights would also grow, because the dropped group no longer counts in the normalizer ( for sequence-mean, the token count for token-mean). The demo’s colours are relative to the largest weight, so you see this only as the dropped rows fading out.
(d) With the demo’s fixed scenario at staleness 0.1: about 11 of 90 tokens are clipped under GRPO, about 9 under DAPO (clip-higher spares some positive-advantage tokens), and 0 under CISPO (it caps a few weights instead). At staleness 0.001, GRPO clips nothing (all token ratios are within 1 ± 0.2), but GSPO already clips most of the responses whole, because its band is ±0.0004 on the geometric-mean ratio. Real GSPO training uses much smaller updates than this toy, but the pattern (many more clipped tokens, in whole-response blocks) matches the paper’s report.
(e) Dr. GRPO. The two presets differ only in those two knobs (and in GRPO’s KL term, which the demo leaves out).
In zoo.py, implement in order:
group_advantages(rewards, group_ids, baseline, scale): knobs 1 and 2.aggregate(per_token, mask, aggregation, max_len): knob 3.token_surrogate(logp, old_logp, adv, mask, cfg): knob 4, token or sequence ratio, with no clip, PPO clip, or CISPO weights.kl_per_token(logp, ref_logp, estimator): knob 5, the , , estimators.pg_loss(...): all of them together, with KL in the reward or in the loss.
Every algorithm in the chapter is then one line in common.PRESETS. The Task 5 tests compare each preset’s loss and gradient with the formula as its paper writes it (explicit loops), so a passing test means your knob-based loss is GRPO, Dr. GRPO, DAPO, GSPO, CISPO, RLOO and REINFORCE.
Hint
.detach()ed and multiplied by logp, not by the ratio.Solution
The reference is solutions/zoo.py. The key lines:
- Advantages. Per-group sums and counts (with
index_add_, or a loop over groups), thenb = sums[g]/counts[g]for the group mean andb = (sums[g] - r)/(counts[g] - 1)for leave-one-out; divide by the group’s population std pluseps, or re-centre and divide by the batch std. - Aggregation.
seq_mean:((x*mask).sum(1) / mask.sum(1)).mean();token_mean:(x*mask).sum() / mask.sum();constant:(x*mask).sum() / (N*max_len). - Surrogate.
rho = exp((logp - old_logp)*mask), or for sequence ratioss = exp(((logp - old_logp)*mask).sum(1)/len)broadcast withs[:, None].expand_as(logp). Thenrho*A,torch.min(rho*A, clamp(rho, lo, hi)*A), orclamp(rho, lo, hi).detach()*A*logp, all times the mask. - KL. With
d = ref_logp - logp:-d,0.5*d**2,exp(d) - d - 1. - Loss. Shape the rewards if
kl == "reward", compute advantages, the surrogate, subtractbeta*KL*maskifkl == "loss", return minus the aggregate.
Two tests are worth reading even after they pass: test_task1_group_mean_is_rescaled_rloo (Exercise 16.2 in code) and test_task2_length_bias_in_gradients (each token’s weight under seq-mean is ).
Run python run.py (about 2 minutes). It trains four presets on the TinyLM addition task from the same SFT checkpoint, and three presets on the LengthToy, and saves zoo_comparison.png.
(a) On TinyLM, do the presets differ by more than the evaluation noise (about ±2 percentage points with 500 prompts)? Why does the mean response length barely move?
(b) On LengthToy, describe the wrong-answer and right-answer length curves for GRPO, DAPO and Dr. GRPO, and connect them to Exercise 16.3.
(c) Run python run.py --toy-presets grpo gspo and explain why the two curves coincide exactly.
(d) Optional: run python run.py --presets grpo dapo cispo gspo. With two updates per batch, does the clip knob make a visible difference on this task? What would you change to make it matter more?
Solution
(a) With the reference solution, all four presets go from about 0.51 sampled accuracy to roughly 0.63–0.70 in 120 steps, and the ranking changes between evaluations: the differences are mostly within noise, the same “algorithms perform similarly” picture as in larger studies. The length barely moves because in this task the answer’s length is fixed by the sum (two or three digits plus <eos>); the model has almost no freedom to be longer or shorter, so the length bias has nothing to act on.
(b) Under GRPO (sequence-mean), the average length of wrong answers climbs from about 4 to about 8 tokens (with noisy spikes past 10), and right answers shrink from about 3.5 to about 2.2 tokens: the modified reward of Exercise 16.3 at work, since the toy lets the policy choose its filler length after choosing its answer. Under DAPO (token-mean) and Dr. GRPO (constant), both curves stay near their starting values, drifting only by noise: the true reward does not depend on length, so the unbiased gradient leaves length alone. All three solve the task (reward near 1); only GRPO picks up the length habit along the way. The wrong-answer curve gets noisy late in training because few wrong answers remain.
(c) The toy trains with one update per batch, so when the gradient is computed. Every sequence ratio is exactly 1, nothing is clipped, and GSPO’s gradient, , equals GRPO’s on-policy gradient term for term (both have the group std and the ). With seeded sampling, the two runs are identical.
(d) In one reference run (seed 0), final sampled accuracies were about 0.66 (GRPO), 0.73 (DAPO), 0.62 (CISPO) and 0.66 (GSPO). Two cautions before reading a winner into that. First, it is one seed, and differences of a few points move around between evaluations. Second, DAPO differs from GRPO in more than its clip: its dynamic sampling trains only on informative groups, which is the most likely source of its edge here. The printed clip fractions tell you how much the clip knob itself did: for the token-level presets only a few percent of tokens leave the band on the second update, so the clip barely acts; for GSPO the fraction is close to 1, because almost every response’s geometric-mean ratio leaves the ±0.0004 band after one update, so GSPO effectively takes a single update per batch. To make the clip matter, take more updates per batch (updates_per_batch=8 in train), raise the learning rate, or simulate asynchrony by sampling with an older copy of the model. Then the PPO-style presets clip far more tokens, and you can test whether CISPO, which never zeroes a gradient, behaves differently.
Files: README.md, zoo.py, common.py, test_zoo.py, run.py
cd 16-policy-gradient-zoo
python -m pytest -q # your code: tests fail until you fill in the TODOs
RL_SOLUTIONS=1 python -m pytest -q # reference solutions: all passFirst time? See Exercises & setup.
Further reading
- Liu et al. (2025), Understanding R1-Zero-Like Training: A Critical Perspective. Dr. GRPO. The clearest statement of GRPO’s length and difficulty biases, plus useful skepticism about what R1-Zero-style training really teaches. Start with the section on GRPO’s biases.
- Yu et al. (2025), DAPO: An Open-Source LLM Reinforcement Learning System at Scale. Four fixes (clip-higher, dynamic sampling, token-level loss, overlong shaping) and an ablation table that prices each one.
- Ahmadian et al. (2024), Back to Basics: Revisiting REINFORCE Style Optimization for Learning from Human Feedback in LLMs. RLOO, and the argument that PPO’s machinery is mostly unnecessary for LLM fine-tuning. Short and well argued.
- Zheng et al. (2025), Group Sequence Policy Optimization. GSPO: sequence-level ratios, the gradient comparison with GRPO, and the MoE motivation.
- MiniMax (2025), MiniMax-M1: Scaling Test-Time Compute Efficiently with Lightning Attention. The CISPO section, with the “fork tokens” diagnosis, plus the FP32 LM-head fix for train–inference mismatch (Chapter 20).
- Khatri et al. (2025), The Art of Scaling Reinforcement Learning Compute for LLMs. ScaleRL. Hundreds of thousands of GPU-hours spent asking which knobs change the asymptote and which only change the speed.
- Hu et al. (2025), REINFORCE++: Stabilizing Critic-Free Policy Optimization with Global Normalization. The case for batch-level rather than per-prompt normalization.
- Shao et al. (2024), DeepSeekMath. Where GRPO started; its section on a “unified paradigm” of SFT, rejection sampling, DPO, PPO and GRPO as different gradient coefficients is an early version of this chapter’s master formula.
Next, Chapter 17 asks what to do when one reward at the end of a long response is not enough: rewarding individual steps, and spending more compute at test time instead of training time.