VAPO (Value-model-based Augmented Proximal Policy Optimization) is a recipe for training long chain-of-thought reasoning models with PPO and a learned value function, rather than with the critic-free group baselines that became standard after DeepSeek-R1. It keeps PPO's actor-critic structure and fixes the specific ways a critic breaks on responses thousands of tokens long: a biased initial value model, a GAE decay that wipes out the reward before it reaches early tokens, and length-dependent bias and variance. This article covers VAPO together with its two closest relatives: VC-PPO, the earlier paper from the same group that introduced value pretraining and decoupled GAE, and VinePPO, which removes the value network altogether and estimates values by Monte Carlo rollouts from intermediate states. All three sit in the RL stage after SFT or a cold start, in the same slot as GRPO and DAPO, and all three argue the same thing: per-token credit assignment is worth paying for when responses are long.
Where it came from#
By early 2025, value-free methods dominated reasoning RL. PPO with a critic had a reputation for collapsing on long chain-of-thought: responses shrink, the model stops reasoning and answers directly. Yufeng Yuan, Yu Yue, Ruofei Zhu, Tiantian Fan and Lin Yan at ByteDance Seed diagnosed that collapse in What's Behind PPO's Collapse in Long-CoT? Value Optimization Holds the Secret (Yuan et al., 2025), the paper that introduced VC-PPO (Value-Calibrated PPO). Their explanation: the critic is usually initialised from the reward model, but a reward model is trained to score complete responses at the end-of-sequence token, while a value model must predict expected return at every prefix. Initialising one from the other gives a systematic bias that GAE propagates backwards through the whole response. Separately, GAE's shrinks the terminal reward by only 100 tokens back, so on long responses the critic's own targets are almost entirely bootstrapped from its own (biased) predictions.
VC-PPO's fixes were value pretraining (train the critic on Monte Carlo returns from a frozen policy before RL starts) and decoupled GAE ( for the critic's targets, for the policy's advantages). On Qwen2.5-32B with a 16K context it reached 48.8 pass@1 on AIME 2024 against 38.9 for GRPO in the same setting; plain PPO in the ablation scored 5.6.
A month later, VAPO (Yue et al., 2025), from Yu Yue, Yufeng Yuan, Qiying Yu and colleagues at ByteDance Seed, combined those two fixes with five more: length-adaptive GAE, a token-level policy loss, DAPO's clip-higher, an NLL loss on correct samples, and group sampling. Starting from a Qwen 32B pre-trained model, VAPO scored 60.4 on AIME 2024, against 50 for DAPO and 47 for DeepSeek-R1-Zero-Qwen-32B, reached that within 5,000 steps, and reported no training crashes across three independent runs that each peaked at 60 to 61.
VinePPO (Kazemnejad et al., 2024), by Amirhossein Kazemnejad, Milad Aghajohari, Eva Portelance, Alessandro Sordoni, Siva Reddy, Aaron Courville and Nicolas Le Roux at Mila, came at the problem from the other side. Measuring value networks during PPO training on MATH and GSM8K, they found them poor at ranking candidate next steps even when explained variance looked fine (0.7 to 0.9). Since a language environment can be reset to any prefix by simply feeding it back to the model, they replaced the network with sampled continuations per reasoning step, in the spirit of the "vine" variant of TRPO.
Background: what the critic is for#
Treat generation as a token-level MDP: state is the prompt plus tokens so far, action is the next token, and the only reward is at the final token. PPO maximises the clipped surrogate
written here in VAPO's final form, with the token-level normaliser and asymmetric clip. The ratio is . The advantage comes from Generalized Advantage Estimation (Schulman et al., 2015) with a value function :
With and terminal reward only, two limits are worth keeping in mind. At the sum telescopes to : an unbiased Monte Carlo advantage whatever the critic is, with the critic acting only as a baseline. At , : low variance, fully dependent on the critic being right. GRPO and RLOO are, in this language, with the critic replaced by a group-mean baseline, so every token in a response gets the same advantage. A critic is the only way, short of extra rollouts, to give different tokens of the same response different credit.
VAPO's seven modifications, with the math#
1. Value pretraining
Before policy training, sample responses from a fixed policy (the SFT model) and regress the value model on Monte Carlo returns, which with a single terminal reward and is just the response's final reward for every prefix:
Train until value loss and explained variance stabilise, then start RL from that checkpoint. The VAPO paper's training details describe a 50-step value warm-up from the reward-model initialisation. Removing it was the single most damaging ablation: AIME 2024 dropped from 60 to 11, the same collapse seen with vanilla PPO (5).
2. Decoupled GAE
Use two different values. The critic is trained towards targets, , which are unbiased and do not decay with distance from the end. The policy uses advantages from a smaller , trading some bias for lower variance and faster convergence. Removing decoupling cost 27 points (60 to 33).
3. Length-adaptive GAE
A fixed treats a 200-token and an 8,000-token response very differently. VAPO sets the effective horizon of the GAE sum proportional to the response length :
This gives at 200 tokens, 0.98 at 1,000 and 0.9975 at 8,000. A useful way to read it: the terminal reward's weight on a token at fractional distance from the end is , the same curve for every length (Figure 2). One consequence the paper does not discuss: the formula is only meaningful for tokens. Below that is zero or negative, so implementations need a floor. Removing length adaptation cost 15 points.
4. Token-level policy loss
Average the per-token PPO terms over all tokens in the batch rather than first within each response (the normaliser in the loss above). Long responses then carry weight proportional to their length, which matters because problems in long responses (repetition, drift) are exactly what needs suppressing. Taken from DAPO; worth 7 points.
5. Clip-higher
Separate clip bounds, and , leave more room to raise low-probability tokens without letting the model push tokens to zero, which counters entropy collapse. Also from DAPO; removing it limited the run to 46.
6. Positive-example LM loss
When most samples are wrong, the rare correct ones are expensive. VAPO adds a negative log-likelihood term on correct samples :
This is rejection-sampling fine-tuning run inside the RL loop. Worth about 6 points.
7. Group sampling
For a fixed budget, sample fewer prompts more times: VAPO uses 512 prompts with 16 samples each instead of the baseline's 8,192 prompts with one sample. Contrasting correct and incorrect responses to the same prompt gives a richer signal even with a critic; worth 5 points.
VinePPO: values without a value network#
VinePPO keeps PPO but replaces with an empirical mean. From an intermediate state of a training trajectory, sample continuations and average their returns:
The auxiliary rollouts are used only for value estimation, never as training samples. For any the resulting policy gradient is unbiased; only controls variance. To keep cost manageable, VinePPO estimates values at reasoning-step boundaries (lines or sentences) and assigns each step's advantage to all its tokens. Default . With DeepSeekMath 7B and RhoMath 1.1B on MATH and GSM8K it beat PPO, GRPO, RLOO, RestEM and DPO+, and it reached PPO's peak accuracy in 2.8 and 9 times fewer steps and 1.51 and 3.0 times less wall-clock time (7B and 1.1B respectively), even though each iteration was up to 2 and 5 times slower.
Put the three approaches side by side, for a token in a response with terminal reward :
| Method | Advantage of token t | Extra cost |
|---|---|---|
| GRPO / RLOO | , the same for every token | group sampling |
| PPO | GAE with learned , | critic (memory, training) |
| VC-PPO | GAE with pretrained , , | critic plus a pretraining phase |
| VAPO | as VC-PPO with , plus NLL on positives | critic plus pretraining |
| VinePPO | at step boundaries | rollouts per step |
Worked example: GAE on five tokens#
A five-token response earns . The critic predicts at the five prefixes, and at the terminal state. With , the TD errors are
At the advantages are . Every token is credited positively; the ordering follows the critic's baseline, not what each token did. At , working backwards with :
Now token 2, the one after which the critic's estimate jumped from 0.40 to 0.70, gets the most credit, and token 1, after which the estimate fell, gets almost none. That is the per-token credit a critic buys, and it is only as good as the critic: if is biased, those differences are wrong. At the numbers are , close to the values because five tokens is short. The decoupling in VC-PPO and VAPO is exactly this split: train the critic towards the honest targets, and use a smaller only for the policy's advantages.
Toy run: which estimator finds the mistake?#
Credit assignment is easy to state and hard to see, so we simulated it directly. A response is 1,000 tokens split into 20 reasoning steps of 50 tokens. Each token has a 0.07% chance of being a fatal error, after which the answer is wrong; otherwise the answer is right. That gives a 49.3% success rate over 2,000 simulated rollouts, 1,013 of them failures. The true value of a prefix is known in closed form, before the error and 0 after it. For each failed rollout we compute per-token advantages with several estimators, average them within each step, and ask whether the step containing the fatal token gets the most negative advantage. Chance is 5%.
The estimators: GAE at with the exact value function; the same with a noisy critic (smooth AR(1) error, standard deviation 0.15, correlation 0.99 per token); the noisy critic with an extra constant bias of +0.3; GAE at with the noisy critic; and VinePPO-style Monte Carlo values at step boundaries with , 3 and 9.
Three things stand out. First, finds the error only 8.8% of the time even though its policy gradient is unbiased: mostly reflects the critic's baseline, not which step mattered. This is why VAPO keeps and why a value model is needed at all. Second, GAE at 0.95 does well with a good critic (78.5% exact, 75.6% noisy) and loses about 9 points when the critic is biased (66.8%), the mechanism VC-PPO's value pretraining targets. Even the exact critic misses about a fifth of the time, because GAE smears credit roughly 20 tokens backwards, into the previous step when the error falls early in a step. Third, Monte Carlo values are poor with one rollout (35.0%), competitive with three (66.5%) and best with nine (93.9%), which is VinePPO's default for a reason. The toy has a single fatal-error mechanism and a known value function, so it flatters any method that estimates values well; it says nothing about how hard a real 32B value model is to train.
The VAPO training loop#
# Phase 0: value pretraining (frozen policy, Monte Carlo targets)
for step in range(value_warmup_steps): # VAPO: about 50 steps
outs = policy_sft.generate(sample(prompts), n=1)
R = verifier(outs) # +1 / -1 or 1 / 0
value_loss = mse(value(outs), R.broadcast_to_tokens()) # lambda = 1 targets
value_loss.backward(); value_opt.step()
# Phase 1: RL
for step in range(num_steps):
batch = sample(prompts, 512)
outs = policy.generate(batch, n=16, temperature=1.0) # group sampling
R = verifier(outs)
with no_grad():
V = value(outs) # (N, T+1), V[:, T] = 0
logp_old = policy.logprobs(outs)
lam_pol = clamp(1 - 1 / (0.05 * outs.lengths), min=0.0) # length-adaptive, per response
A = gae(R, V, gamma=1.0, lam=lam_pol) # policy advantages
returns = gae(R, V, gamma=1.0, lam=1.0) + V[:, :-1] # critic targets (= R)
for mb in minibatches(outs, A, returns, logp_old, size=512):
ratio = exp(policy.logprobs(mb) - mb.logp_old)
pg = -minimum(ratio * mb.A, clip(ratio, 1 - 0.2, 1 + 0.28) * mb.A)
loss = token_mean(pg, mb.mask) # over all tokens in the minibatch
loss += 0.1 * token_mean(-policy.logprobs(mb), mb.mask * mb.correct[:, None])
loss.backward(); policy_opt.step()
value_loss = token_mean((value(mb) - mb.returns) ** 2, mb.mask)
value_loss.backward(); value_opt.step()
Data is the same as for any reasoning RL run: prompts with verifiable answers. VC-PPO trained on past AIME problems plus constructed hard problems, with a cold start of "dozens" of formatted examples to teach the <think> format; rewards were +1 for correct and for incorrect, with KL coefficient 0 because a rule-based reward is hard to hack. For VinePPO, the extra step is splitting responses into reasoning steps (newlines work for maths solutions) and generating continuations from each step boundary.
Hyperparameters#
| Parameter | VAPO value | How to think about it |
|---|---|---|
| Actor / critic learning rate | 1e-6 / 2e-6 | The critic must keep pace with a moving policy, so it learns faster. |
| 1.0 | Unbiased targets; non-negotiable for long responses. | |
| in | 0.05 | Effective horizon is 5% of the response; larger means more Monte Carlo, more variance. |
| , | 0.2, 0.28 | DAPO's clip-higher. |
| NLL weight | 0.1 | Raise for very low pass rates; too high turns RL into SFT on positives. |
| Prompts x samples | 512 x 16, minibatch 512 | Baseline PPO used 8,192 x 1. |
| Value warm-up | 50 steps | Stop on explained variance and value loss, not on a step count. |
| 1.0 | No discounting with a single terminal reward. | |
| VinePPO | 9 | Ablation: higher improved accuracy and overall wall-clock efficiency. |
The VC-PPO paper also swept between 0.9 and 1.0 with fixed at 1, and VAPO's evaluation used avg@32 on AIME 2024 with top-p 0.7 and temperature 1.0, which is worth matching when comparing against its numbers.
Compute and memory#
VAPO pays PPO's full memory bill. With full fine-tuning in mixed precision and Adam, each trainable model costs about 16 bytes per parameter, and the critic is usually the same size as the policy:
For a 32B policy and a 32B critic that is roughly 1 TB of training state before activations, so the critic alone adds about 512 GB, the price of the per-token signal. Per step, the critic adds a forward pass over every rollout and a forward and backward pass for its update; value pretraining is a one-off phase of generation plus critic training. A smaller critic cuts this but makes the bias problem harder.
VinePPO has no critic memory but multiplies generation. With step boundaries per response and rollouts from each, the extra tokens generated per response are roughly
so for , and , about 90 times the response itself, before any prefix caching. VinePPO's measured slowdown per iteration was 2 to 5 times on MATH-scale solutions, which shows how much an inference engine with prefix caching absorbs; but the formula grows with , and for responses of tens of thousands of tokens it is the reason long-CoT recipes such as VAPO kept a learned critic.
Failure modes#
Length collapse. The VC-PPO signature: mean response length falling steadily early in training while accuracy stalls and the model starts answering without reasoning. Cause: a biased critic. Check explained variance of the critic on fresh rollouts before and during training; if it is low or negative at step 0, you skipped or under-ran value pretraining.
Critic lag. Value loss rising as the policy improves means the critic cannot track the policy. Raise the critic learning rate relative to the actor (VAPO uses 2 times) or take more critic steps per batch.
Entropy too low. VAPO's entropy ended lower than DAPO's; the authors judged the stability worth it. If pass@k on held-out problems starts falling while pass@1 rises, exploration is shrinking. Raise or lower .
NLL overfitting. With few prompts and a large , the model memorises its own correct solutions. Watch the gap between training and held-out accuracy.
Short responses with adaptive . For responses under 20 tokens, is negative unless clamped; for responses just above, it is near 0 and the advantage is pure one-step critic difference. Mixed-format tasks with very short answers need a floor on .
VinePPO variance at low . With the advantage at each step is the difference of two Bernoulli draws, mostly noise; our toy identified the right step 35% of the time. If you cannot afford , use fewer, longer steps rather than fewer rollouts.
When to use VAPO, VinePPO or a value-free method#
| Situation | Use | Why |
|---|---|---|
| Long CoT (thousands of tokens), large compute budget, need the best final score | VAPO | Per-token credit with a calibrated critic beat DAPO by 10 points on AIME 2024 in the paper's setting. |
| Short to medium reasoning (hundreds of tokens), memory-limited | VinePPO | Unbiased values without a critic; generation is cheap at these lengths. |
| Want simplicity and robustness, moderate budget | DAPO, Dr. GRPO, REINFORCE++ | No critic to pretrain or babysit. |
| Step-level labels or a process reward model available | PRM-shaped rewards with PPO or GRPO | Dense supervision instead of estimated values. |
| MoE policy, off-policy minibatches | GSPO | Sequence-level ratios avoid routing noise; value-based recipes have not been shown at that scale. |
| Non-verifiable chat quality | PPO-RLHF or DPO | VAPO's design assumes sparse, binary, verifier rewards. |
Minimal implementation#
The parts that differ from a standard PPO trainer are the GAE with a per-response , the decoupled targets and the extra NLL term. A vectorised sketch in PyTorch:
import torch
def gae_per_seq(rewards, values, mask, lam):
"""rewards, mask: (N, T); values: (N, T+1) with values[:, T] = 0; lam: (N,) or float."""
N, T = rewards.shape
lam = torch.as_tensor(lam, dtype=values.dtype, device=values.device).expand(N)
adv = torch.zeros_like(rewards); last = torch.zeros(N, device=rewards.device)
for t in reversed(range(T)):
delta = rewards[:, t] + values[:, t + 1] * mask[:, t] - values[:, t]
last = (delta + lam * last) * mask[:, t]
adv[:, t] = last
return adv
def vapo_targets(rewards, values, mask, alpha=0.05, lam_floor=0.0):
lengths = mask.sum(1).clamp(min=1)
lam_policy = (1 - 1 / (alpha * lengths)).clamp(min=lam_floor) # length-adaptive
adv = gae_per_seq(rewards, values, mask, lam_policy)
returns = gae_per_seq(rewards, values, mask, 1.0) + values[:, :-1] # lambda_critic = 1
return adv, returns
def vapo_policy_loss(logp, logp_old, adv, mask, correct, eps_low=0.2, eps_high=0.28, mu=0.1):
ratio = torch.exp(logp - logp_old)
pg = -torch.minimum(ratio * adv, ratio.clamp(1 - eps_low, 1 + eps_high) * adv)
pg_loss = (pg * mask).sum() / mask.sum() # token-level
pos = mask * correct[:, None].float()
nll = -(logp * pos).sum() / pos.sum().clamp(min=1)
return pg_loss + mu * nll
def vine_values(policy, prefixes, verifier, K=9):
"""Monte Carlo value at each step boundary: mean reward of K continuations."""
outs = policy.generate(prefixes, n=K) # (len(prefixes) * K)
return verifier(outs).view(-1, K).float().mean(1)
verl, the framework VC-PPO was trained with, ships GAE-based PPO with separate actor and critic configurations; the length-adaptive , decoupled targets and NLL term are a few lines on top. The VinePPO authors released their code at the repository linked from the paper. In POFE, value-based PPO is a recipe option with a value-pretraining phase and critic explained variance shown on the run page, because that one number predicts most PPO collapses on long responses.
Further reading#
Yue et al. (2025) for VAPO and its ablation table; Yuan et al. (2025) for the VC-PPO diagnosis of value-initialisation bias and the first version of decoupled GAE; Kazemnejad et al. (2024) for VinePPO and the most careful measurement of how wrong value networks are on reasoning. Schulman et al. (2015) defines GAE and Schulman et al. (2017) PPO. Yu et al. (2025) for DAPO, from which VAPO takes clip-higher and the token-level loss, and Hu et al. (2025) for Open-Reasoner-Zero, a value-based PPO recipe that uses Monte Carlo () estimates instead of GAE.
Frequently asked questions#
What is VAPO?
Value-model-based Augmented PPO, a reasoning-RL recipe from ByteDance Seed (Yue et al., 2025). It keeps PPO with a learned critic and adds seven changes: value pretraining, decoupled GAE, length-adaptive GAE, token-level loss, clip-higher, an NLL loss on correct samples and group sampling. On Qwen 32B it reported 60.4 on AIME 2024 versus 50 for DAPO.
Why does PPO collapse on long chain-of-thought?
VC-PPO traced it to the critic. Initialising the value model from the reward model gives a biased value function, and GAE with lambda 0.95 decays the terminal reward to almost nothing a few hundred tokens back, so the critic's targets are mostly its own biased predictions. Responses shrink and the model stops reasoning.
What is decoupled GAE?
Using different lambda values for the critic and the policy. The critic is trained on lambda = 1 targets, which for a single terminal reward equal the final reward at every token and are unbiased. The policy uses a smaller lambda for lower-variance advantages.
How does length-adaptive GAE work?
VAPO sets the policy's lambda to 1 - 1/(alpha * l) with alpha = 0.05, where l is the response length, so the effective horizon is always 5% of the response. That gives lambda 0.9 at 200 tokens and 0.9975 at 8,000. The formula needs a floor for responses under 20 tokens.
How is VinePPO different from VAPO?
VinePPO removes the value network. At each reasoning-step boundary it samples K continuations (K = 9 by default) from the current policy and uses their mean reward as the value, which is unbiased for any K. It saves critic memory but multiplies generation cost, which grows with response length.
Should I use VAPO or GRPO?
GRPO-family methods are simpler and need no critic. VAPO is worth its extra memory and the value-pretraining phase when responses are very long and you need per-token credit assignment for the best final score; for short or medium reasoning, VinePPO or DAPO are usually the better trade.
References#
- Yu Yue, Yufeng Yuan, Qiying Yu, Xiaochen Zuo, Ruofei Zhu, Wenyuan Xu, Jiaze Chen, Chengyi Wang, TianTian Fan, et al. (2025). VAPO: Efficient and Reliable Reinforcement Learning for Advanced Reasoning Tasks. arxiv.org/abs/2504.05118
- Yufeng Yuan, Yu Yue, Ruofei Zhu, Tiantian Fan, Lin Yan (2025). What's Behind PPO's Collapse in Long-CoT? Value Optimization Holds the Secret. arxiv.org/abs/2503.01491
- Amirhossein Kazemnejad, Milad Aghajohari, Eva Portelance, Alessandro Sordoni, Siva Reddy, Aaron Courville, Nicolas Le Roux (2024). VinePPO: Refining Credit Assignment in RL Training of LLMs. arxiv.org/abs/2410.01679
- John Schulman, Philipp Moritz, Sergey Levine, Michael Jordan, Pieter Abbeel (2015). High-Dimensional Continuous Control Using Generalized Advantage Estimation. arxiv.org/abs/1506.02438
- John Schulman, Filip Wolski, Prafulla Dhariwal, Alec Radford, Oleg Klimov (2017). Proximal Policy Optimization Algorithms. arxiv.org/abs/1707.06347
- Qiying Yu, Zheng Zhang, Ruofei Zhu, Yufeng Yuan, Xiaochen Zuo, Yu Yue, et al. (2025). DAPO: An Open-Source LLM Reinforcement Learning System at Scale. arxiv.org/abs/2503.14476
- Jingcheng Hu, Yinmin Zhang, Qi Han, Daxin Jiang, Xiangyu Zhang, Heung-Yeung Shum (2025). Open-Reasoner-Zero: An Open Source Approach to Scaling Up Reinforcement Learning on the Base Model. arxiv.org/abs/2503.24290
- DeepSeek-AI (2025). DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning. arxiv.org/abs/2501.12948
- McGill-NLP (2024). VinePPO code repository. github.com/McGill-NLP/VinePPO