GRPO Plus (v0.50.0)
22 features. Unsloth + axolotl GRPO parity.
7 GRPO variants
task: grpo
training:
grpo_variant: gspo # standard | gspo | dapo | dr_grpo | bnpo | two_sided | rft
grpo_delta: 0.5 # required for two_sided, optional for gspo (clip radius,
# default 0.2). (0, 1]. Rejected on every other variant
grpo_fp16: true # explicit FP16 mixed precisionThe KL penalty: every variant applies grpo_beta (v0.76.0)
gspo, dapo, dr_grpo, bnpo, two_sided and rft train with a KL penalty of training.grpo_beta (default 0.1) against the reference policy (#1232). Each variant adds trl 0.29's per-token estimator exp(ref - logp) - (ref - logp) - 1, weighted by grpo_beta, to its per-token loss before its own reduction; rft applies it only to the completions it accepts and trains on. On a real trainer, the dapo loss and gradient equal trl's stock dapo ones at beta 0.1, 1 and 10 on the same generated batch. No speed or quality effect of the penalty is claimed.
(Since closed in v0.76.0: through v0.75.2 these variants validated grpo_beta and dropped it. The variant loss replaces trl's _compute_loss, the one place trl adds the KL term on Soup's path, so neither grpo_beta nor the beta the reward-hack controller sets at runtime changed the loss or the gradient, while trl still ran the reference forward on every step.) A variant config from v0.75.x trained with no KL term, and a v0.76.0 run of the same config will not reproduce it. If a recipe relied on the old behaviour (a dapo or dr_grpo recipe that expects to be KL-free), set grpo_beta: 0 explicitly.
grpo_beta: 0is valid (#1247). It turns the KL penalty off, as the KL-free DAPO and Dr. GRPO recipes do, and it skips the reference-model forward pass. It is refused together withreward_hack_mitigation: kl_controlorpid_lagrangian, because the controller needs a positive beta to steer:grpo_beta: 0 is mutually exclusive with reward_hack_mitigation='kl_control' (the mitigation controller requires a positive beta to steer); use grpo_beta > 0 or disable mitigation. A boolean or NaNgrpo_betais refused.- The
klmetric is logged again for a variant with a non-zerogrpo_beta, as trl's stock loss does: the masked batch mean of the per-token KL, averaged over the accepted tokens forrft(#1263). - Ratios are clamped before exponentiation (#1609). The kernels bound the importance ratio and the sequence ratio from above with a bound that adapts to the advantage's magnitude, and mask padding with a boolean mask, so a diverging policy no longer turns infinite terms into NaN parameter gradients. A run that went to NaN under a non-standard
grpo_variantbefore v0.76.0 may have hit this. - Non-finite steps are skipped, for every
task: grporun (#342). A gradient watchdog zeroes non-finite gradients before the optimizer step, so that step updates nothing and the adapter is preserved. The step still counts toward the step total and the learning-rate schedule. The skipped-step count and fraction are saved intrainer_state.json, a run that skipped 5% or more of its steps prints aGradient watchdog:warning at the end, andsoup adapters auditreports the figure. - Validation.
task: grpodoes not evaluate by default and does not holddata.val_splitout of training: the split is ignored, every row trains, and the run prints a one-line note saying so. Settraining.eval_stepsto hold the split out and evaluate it; the validation number is then the held-out reward,eval_reward(#1223, #1389). See Training methods. - Gold answers.
reward_fn: accuracyand the verifiablemathdomain now read the gold the way they read the completion, and a gold that states no single final answer is refused before generation. See RLVR.
Re-run this
| If you trained | What was wrong | What to do |
|---|---|---|
task: grpo with grpo_variant other than standard | The variant dropped grpo_beta, so it trained with no KL term while trl still ran the reference forward each step (#1232). With reward_hack_mitigation, the controller moved a beta the loss ignored | Re-run if you need the KL-regularised behaviour. Set grpo_beta: 0 to keep the KL-free behaviour on purpose |
task: grpo with grpo_variant other than standard, and a run that went to NaN | Importance ratios were exponentiated without a bound, so a diverging policy could produce infinite terms and NaN gradients (#1609) | Re-run. v0.76.0 clamps the ratio |
task: grpo with reward_fn: accuracy, or reward_fn: verifiable with verifiable_domain: math | See RLVR: the gold was compared raw, and accuracy paid 0.5 for a gold that merely appeared in the completion | Re-run if the logged reward sat near 0.0 |
Long-context & vision GRPO
task: grpo
training:
vllm_sleep_mode: true # free vLLM memory between rolloutslong_context_grpo and vision_grpo are validation gates, not features: they check the task, the backend and, for vision, a known VLM base (and the vision modality), and nothing reads them afterwards. long_context_grpo does not extend rope scaling into rollouts, and no Tiled MLP code stands behind it. vision_grpo does not make GRPO multimodal: the GRPO trainer loads the base with AutoModelForCausalLM and a tokenizer, not a vision processor. Both are on the list of 29 settings that are accepted and read by nothing: set to a non-default value they print Warning: training.long_context_grpo is accepted but read by nothing; v0.77 will refuse it when the config loads, and the run proceeds. "Refused from v0.77" is upstream's stated deadline, printed by the CLI. vllm_sleep_mode is read by the GRPO trainer.
Async rollout backends
task: grpo
training:
rollout_backend: openenv # art | ruler | nemo_gym | openenv
rollout_func: soup_cli.envs.calculator:rollout # required by openenvopenenv is the only backend that runs at v0.76.0. rollout_func is a module:function that receives the dataset prompts as seeds and returns the rows GRPO then trains on, which replace the dataset's prompts. It is not given the model and runs no interactive multi-turn episodes; the bundled soup_cli.envs.calculator:rollout is a single-shot seeder (see PRM-guided GRPO). art (OpenPipe ART), ruler and nemo_gym are accepted names whose adapters are not wired: they raise an ImportError naming the missing package, and a "not yet validated" error when it is installed.
Stability knobs (accepted; mostly record-only)
task: grpo
training:
ref_model_ema_alpha: 0.99 # EMA-style ref refresh
replay_buffer_size: 50000
tis_threshold: 1.5 # truncated importance sampling
mask_truncated_completions: true
defer_rerolling: true
skip_zero_advantage: true
off_policy_mask_threshold: 0.7
async_grpo_prefetch: trueAt v0.76.0 these eight keys are accepted for task: grpo and attach a callback that writes counters (replay_size, tis_alerts, ema_alpha) into the training log. The one thing that callback does to training is the gradient watchdog described above, which skips non-finite optimizer steps and is attached to every task: grpo run, with or without these keys. async_grpo_prefetch, mask_truncated_completions, defer_rerolling, skip_zero_advantage and off_policy_mask_threshold do not change what the trainer does: the callback's own notes call them advisory, a hint or record-only. The replay buffer is never fed and the TIS counter is never called. ref_model_ema_alpha can only act if the callback is handed a separate reference model, and the Hugging Face callback handler does not hand it one, so there is nothing for it to update; a LoRA run has no separate reference model anyway (read from the code, not run on a GPU). These eight keys are not on the list of fields that warn at load, so nothing prints and no refusal date is attached to them. What does work on this page: the seven grpo_variant objectives (with the grpo_beta KL penalty on the six non-standard ones), grpo_delta, grpo_fp16, vllm_sleep_mode and the openenv rollout.
New task: prm
task: prm (Process Reward Model) wired through the standard reward-model trainer. Gates: vision + GRPO compat checked.
v0.50.0 shipped the schema. v0.53.3 wired grpo_fp16 routing + the known-VLM-base gate for vision_grpo; v0.53.11 lit up real loss kernels for every non-standard variant (gspo / dapo / dr_grpo / bnpo / two_sided / rft) via make_grpo_trainer_variant, made task: prm live with per-step MSE + reward head, and attached GRPOStabilityCallback, which logs counters for the stability knobs above (most of them are record-only, as that section says). See v0.53.11 — GRPO Plus finish.
Soup is free and Apache-2.0. If it saved you a training run, starring the repo costs nothing and helps most. You can also fund the GPU time behind the work a 4 GB laptop cannot reach.