Requirements
- A model with generator support and
num_generator_replicasof one or more. Trainer-only models can’t run GRPO. - Your dataset and reward function, or one of the cookbook’s four built-in datasets with rewards.
- For the cookbook, export
WANDB_API_KEY, setWANDB_MODE=offline, or disable logging withwandb_project=None.GRPOConfiglogs to Weights & Biases by default, and missing setup fails after provisioning. See Monitoring.
How post-training runs GRPO

sample: Generators returngroup_sizecompletions per prompt and each generated token’s log-probability.- Reward: Your reward function scores each completion.
- Advantages: Your code subtracts the group’s mean reward from each completion’s reward.
forward_backward: WithLOSS_TYPE_GRPO, the trainer computes clipped policy-gradient loss and accumulates gradients. Samples carry completion tokens, advantages, and generator log-probabilities.optim_step: The optimizer applies the gradients with the learning rate, gradient clipping, and other optimizer settings inadam_params.weights_sync: The trainer publishes the updated weights to the generators before the nextsample. Async training describes deferred sync modes.
Run a GRPO recipe
PassGRPOConfig to the cookbook’s train_single_turn recipe. Its dataset field names a registered dataset, which supplies the prompt format and the reward. To use another schema, register your own dataset and reward. The RL quickstart runs GSM8K end to end:
train_single_turn provisions a resource with num_generator_replicas generators (one by default) and one session, then stops both when it returns. Set model_resources_id instead of model to use an existing resource.
learning_rate defaults to 1e-5. Try 5e-6 for steadier training or 2e-5 for faster convergence. Change one setting at a time in small increments. To compare several rates at once, train multiple adapters on one resource.
The cookbook reference lists every field.
Rewards and advantages

advantage = reward - group_mean. It leaves advantages on the reward’s scale instead of dividing by the group’s standard deviation as in the GRPO paper.
Groups with identical rewards carry no signal, so the cookbook builds no samples from them, though their generation is still billed. zero_variance_skip_ratio reports the fraction skipped.
Group size: group_size defaults to 8. Larger groups, such as 16, give steadier advantages and fewer zero-variance groups, with proportionally more sampling.
Temperature: temperature defaults to 0.7. Raise it toward 1.0 for more varied completions when groups collapse, or lower it toward 0.5 to exploit the current policy.
Write your own GRPO loop
Customize data preparation, sampling, rewards, or sample construction in your own loop. This example uses in-memory math problems and rewards a correct answer after####:
reward_fn.
compute_group_advantages returns values=None for identical rewards, so skip that group. build_policy_sample aligns input and target tokens and puts the advantage on every trained position.
sample_batch sends all prompts together, with num_samples requesting a whole group at once. Use _async variants for concurrent independent calls. Sampling overlaps other sampling and trainer operations, but synchronous weights_sync waits for in-flight sampling.
One SamplingParams applies to every prompt in a sample_batch call. The API reference lists fields and defaults. Two fields need care:
stop: For models without stop-string support, omit it and truncate completions in your code. Unsupported stop strings fail as invalid input.seed: Leave it unset. It’s unsupported and causes an internal error when the generator uses multiple inference engines.
session.generator.compute_logprobs(prompt) or compute_logprobs_batch(prompts). Call weights_sync first if the trainer has stepped since the last sync. Entry 0 is a 0 placeholder because the first token has no preceding context. sample uses the same placeholder with prompt_logprobs=True.
The recipe adds cosine learning-rate decay, dynamic sampling, overlong handling, length budgets, validation, and periodic checkpoints.
Dynamic sampling
Dynamic sampling, from the DAPO paper, draws fresh batches until it collectsbatch_size groups with varied rewards or reaches max_sampling_attempts. Set that cap above 1 to enable it. The default is 1, and the GSM8K quickstart uses 3.
Each attempt generates a full batch, so a step can cost up to max_sampling_attempts batches of generation. With no usable groups, the cookbook skips the step and logs skipped: 0/<groups> groups had non-zero reward variance (single-turn) or samples=0 (multi-turn).
If zero_variance_skip_ratio stays high, also adjust task difficulty and temperature.
Clipping
Clipping limits how far an update moves the policy. For each token, the service computes the ratio of the trainer’s probability to the generator’s probability at sampling time. It suppresses gradients for positive-advantage tokens whose ratio exceedsclip_high_threshold, and for negative-advantage tokens whose ratio falls below clip_low_threshold.
Thresholds are absolute ratio bounds, not offsets from 1.0, so a DAPO epsilon pair (ε_low, ε_high) maps to (1 - ε_low, 1 + ε_high). Move either bound toward 1.0 for stronger clipping.
The cookbook leaves both thresholds unset (None), using the service’s [0.8, 1.2] default. To use DAPO’s asymmetric “Clip-Higher” band, set them to 0.8 and 1.28, allowing more room to raise underweighted tokens’ probabilities.
forward_backward.metrics reports clip rates, logged as fb/loss/clip/high_fraction and fb/loss/clip/low_fraction. See Service-emitted metrics.
Overlong responses
The cookbook offers two independent controls for completions near the token budget:- Overlong penalty (on by default): A DAPO reward penalty that ramps up linearly over the last
overlong_buffer_lentokens of the budget. The buffer defaults tomax_sample_tokens // 8.overlong_penalty_factorscales the penalty, and0disables it. - Overlong masking (off by default):
overlong_masking=Trueexcludes truncated completions from training while retaining their rewards in the group baseline. Single-turn training skips steps left with fewer thangroup_sizesamples.
overlong_masking=True and overlong_penalty_factor=0.
Length budgets
The cookbook derives two budgets frommax_model_length (default 2048):
max_sample_tokens: Generated tokens per completion, defaulting tomax_model_length.max_prompt_length: Single-turn prompt filter, defaulting tomax_model_length - max_sample_tokens. Longer prompts are dropped before training.
max_sample_tokens or max_prompt_length explicitly. Leaving both unset makes the prompt limit 0, dropping every prompt. With num_steps set, the run fails after provisioning and billing begin. Otherwise it exits before provisioning with no training needed.
Keep max_sample_tokens below max_model_length to leave room for the prompt. A truncated_ratio above about 30% indicates a tight budget or runaway-length output.
GLM-5.3 always thinks, at maximum reasoning effort by default. Allow a generous completion budget or set thinking_effort="high" or "low" to avoid truncating reasoning. Its codec rejects enable_thinking=False.
Variants
The cookbook keeps group sampling and advantages unchanged when switching objectives. Configure variants with theseGRPOConfig fields:
- Policy loss:
lossdefaults to"grpo". The alternatives are"ppo","cispo","dppo","dro", and"importance_sampling", described in Built-in loss functions. The alternatives sum token losses rather than averaging them, so their loss grows with trained-token count and may require learning-rate retuning. - Clip band:
clip_low_thresholdandclip_high_thresholdapply to"grpo","ppo", and"cispo". Leave themNonefor service defaults:[0.8, 1.2]for GRPO/PPO and[0, 4]for CISPO, or set your own bounds. - Metrics: GRPO/PPO report
fb/loss/clip/*andfb/loss/ratio/mean. Other objectives use keys such asfb/ratio_mean. CISPO reportsfb/clip_fraction, and scales gradients with clipping instead of zeroing them. - DRO penalty:
"dro"requiresdro_betafor its quadratic log-ratio penalty. - Loss aggregation:
loss_agg_typedefaults toGRPO_LOSS_AGGREGATION_TYPE_FIXED_HORIZON, dividing the masked sum by all batch tokens, including padding.TOKEN_MEANdivides by trained tokens.SEQUENCE_MEANaverages within each sequence, then across sequences, giving each equal weight. Keep aggregation fixed when comparing runs because it changes the effective learning rate. - GSPO: Set
ratio_type="GRPO_LOSS_RATIO_TYPE_SEQUENCE"for a sequence-level importance ratio and clipping over the whole completion.
loss_agg_type and ratio_type apply only to "grpo". The config rejects changes to these, clip bounds, or dro_beta for objectives that don’t use them.
For a Kullback-Leibler (KL) reference-policy penalty, use your own loop with GrpoLossParams.beta > 0 and a reference_logprobs row per sample. The cookbook config has no KL setting. For other objectives, write a custom loss function.
Built-in loss functions
In your own loop, pass aLossConfig to forward_backward, selecting the objective with type and configuring its matching *_params. Mismatched params fail client-side. Each objective reads the loss_fn_inputs rows below. See the API reference for params and defaults.
The advantage-based objectives accept an optional binary
weights mask. Use 1 on completion tokens and 0 elsewhere. Omitting it trains every position, including the prompt. Only cross-entropy accepts fractional weights.
Async training

train_multi_turn, where long, variable-length episodes create larger idle gaps. train_single_turn rejects max_steps_off_policy.
Three settings control async training:
max_steps_off_policy:Nonemeans lockstep. An integer enables continuous rollout workers and sets the maximum group age in optimizer steps, measured from rollout start.0admits only groups started under the current policy.groups_in_flight: Concurrent rollout groups, defaulting tobatch_size.weight_sync_type:WEIGHT_SYNC_TYPE_SYNCHRONOUSpublishes inline by default.WEIGHT_SYNC_TYPE_BACKGROUND_PUBLISHreturns immediately after handing publication to a server worker.WEIGHT_SYNC_TYPE_PIPELINEalso defers publication and lets in-flight generation finish under updated weights.
max_steps_off_policy to bound and measure drift.
Pass this config, your tasks, and an environment factory to train_multi_turn, as in Multi-turn environments:
max_steps_off_policy=1. At 0, arriving groups are often already one version behind and get dropped.
Watch async/train_wait_s and async/dropped_stale_groups in the async collection metrics. Stale groups are counted separately and don’t inflate zero_variance_skip_ratio. Run recipes/grpo/tool_use_game_async.py for a complete example.
Troubleshooting
zero_variance_skip_ratiostays above 50%: Checkidentical_nonzero_reward_skip_ratio(single-turn only) to distinguish identical nonzero rewards from all-zero rewards. For easy tasks, use harder data or raisetemperature. For hard tasks, use easier data or a stronger model. Increasinggroup_sizeto16ormax_sampling_attemptsabove1also recovers more groups, at the cost of extra sampling.- Checkpoint creation fails with
You need to complete at least one training step before you can create an inference checkpoint: Every step was skipped, although sampling was billed. Checkskipped:(single-turn) orsamples=0(multi-turn). Adjust difficulty for identical rewards, or the length budget if overlong masking left too few samples. fb/loss/ratio/meanis far from1.0on the first step: The trainer and generator initially share weights, so the ratio should start near1.0. In a hand-built loop, checklogprobsalignment withtarget_tokens: drop the first value of each per-token array. Misalignedadvantagesdon’t affect this metric.- Out of memory or timeouts: Reduce
batch_size,max_model_length, orgroup_size, or raisetimeouton the config. - The session isn’t active: It expired after an hour without operations, was stopped, or hit an error. See Manage model resources troubleshooting.
Next steps
Reward functions
Bring your own dataset and reward to the loop.
Multi-turn environments
Train tool-use agents over whole episodes.
Monitoring
Every metric the loop logs and how to act on it.
Cookbook reference
Every
GRPOConfig field and its default.