whileai/simulations/defaults.py with their
sources; equation numbers are the papers’. Each method’s own page says
where it runs: the hosted trainer (wai.train), prime-rl
(wai.prime_rl_config), or your own loop (method.update).
Notation
A batch holds trajectories. Trajectory answers prompt with reward and action tokens , each with history (the prompt and the tokens before it). Two policies can see every token: , the policy that wrote it (a row’sbehavior_logprobs; the rollout engine, or last week’s served model), and
, the one being trained (logprobs). Their per-token ratio is
and is a frozen reference (the starting weights) where a
method keeps one. A token the environment wrote (tool output, an
observation) has action_mask false: it is not one of the , gets
, and the critic methods bootstrap over it. When behavior_logprobs
is absent the row is taken as on-policy, .
The hosted four: wai.train(method=)
SFT. Maximum likelihood on the rows as pushed, over the assistant
tokens the loss mask keeps (the trainer does not filter on reward, so
push scored.passes()):
GRPO (Shao et al. 2024, arXiv:2402.03300). = generations
rollouts of the same prompt form a group; the advantage is the reward
centered on its siblings, and the coefficient is PPO’s clipped surrogate
with a KL to the reference:
A group whose rollouts all pass or all fail has for every
member, which is why select(mode="rl") drops unanimous groups before
the GPU is spent. loss_type picks , the length weight:
grpo averages each sequence’s tokens then averages sequences
(); bnpo pools every token in the batch ();
dr_grpo (Liu et al. 2025, arXiv:2503.20783) drops the standard deviation
from and uses one constant length (), removing the
bias toward long wrong answers. truncated="mask" gives a reply the token
cap cut ; "zero" scores it instead. Defaults: = 8,
= 0.2, = 0 (DAPO, Dr. GRPO and CISPO all run without
the KL term).
DPO (Rafailov et al. 2023, arXiv:2305.18290). A pass and a fail
of the same prompt, length matched; no sampling, no reward model:
RM. The same pairs train a scalar head under the
Bradley-Terry model; reward_model(run) is then a judge:
Distillation: wai.OPD, wai.OPSD
OPD, on-policy distillation (Agarwal et al. 2023, arXiv:2306.13649;
Thinking Machines 2025). The student samples its own reply; a frozen
teacher scores every token of it. The per-token loss is the
reverse KL from the student to the teacher over the teacher’s top-
tokens (Li et al. 2026, arXiv:2604.13016; Fu et al. 2026, arXiv:2603.25562),
and its sampled-token form is a policy gradient whose advantage is the
log-probability gap:
No reward, no group, no discount: a token the teacher liked more than the
student did is pushed up by the gap. divergence offers forward_kl and
jsd for a trainer that has them. Defaults: = top_k = 32,
samples = 4, temperature 1.0 on both sides so the teacher scores the
distribution the student drew from.
OPSD, on-policy self-distillation (SDFT, Shenfeld et al. 2026,
arXiv:2601.19897; SDPO, Hübotter et al. 2026, arXiv:2601.20802). The same
loss, with the teacher the student’s own weights shown a hint the
student never sees (a passing demonstration, the reference answer, a hint,
or a rollout plus the environment’s feedback, privileged):
The anchor is what keeps the teacher from chasing the student:
"ema:0.01" is the moving average above, "initial" freezes the starting
weights (Zhao et al. 2026, arXiv:2601.18734, with forward_kl), "live"
is the unanchored student prime-rl runs. samples = 1: there is no group
to form.
Staleness: wai.Async
Any method above, trained on rollouts that lag the policy by at most
off_policy_steps = optimizer steps, with one per-token correction
for the sampler/trainer gap that exists even at zero lag (Yao et al. 2025):
ipo masks on probability moved (prime-rl’s default), icepop masks
outside a ratio band (Ring-1T, arXiv:2510.18855), tis caps the ratio
(verl). Default = 8 (ScaleRL, arXiv:2510.13786; one step is free,
Noukhovitch et al. 2024, arXiv:2410.18252).
The group baselines prime-rl runs: "grpo", "max_rl", "rae"
Three string methods prime_rl_config writes, differing only in :
max_rl (arXiv:2602.02710) divides by the group mean rather than its
standard deviation, which makes the gradient unbiased for the
maximum-likelihood objective and weights a rarely solved prompt by about
; a group whose mean is 0 carries nothing. rae (SPIRAL,
arXiv:2506.24119) is a per-agent running average, the one baseline that
stands at one rollout per prompt, and on a single-agent taskset it is
REINFORCE against that average.
One rollout per prompt: wai.FlashReinforce, wai.SAO, wai.BPCO
The shape a production trace arrives in. With one rollout per prompt every
group above is the rollout itself, , and the update is
empty. Each of these three replaces the group with something a single
trajectory can supply, and each one’s update(batch) returns the
below as coefficients.
FlashReinforce
Baseline from the batch, a gate on drift, equal weight per trajectory. is the KL between two Bernoullis, “this token versus everything else,” so it needs only the one probability the sampler already stored. A trajectory over the gate drops out whole; the ratio is never clipped, only kept finite. Defaults: =trust = 0.003, a lag of
off_policy_steps = 8 updates.
SAO
A critic in place of the group, credit passed back over tool output, and a band that masks a drifted token instead of clipping it. Over the action tokens of one trajectory, in order, with on the last one and before it, the critic’s value at that token and past the end: The bootstrap is the next action token, so an observation between two actions is skipped, not scored. grows with length so the terminal reward reaches the first token with weight whatever is. No normalization: the critic is the baseline. The critic trains toward the Monte Carlo return, at every action token, with a squared-error loss,critic_steps
= 2 updates per policy update after critic_warmup = 10 critic-only
steps. Defaults: = gae_alpha = 1.5, = 1, the band
ratio = = (0.7, 6.0).
BPCO
A critic that cannot leave the reward’s range, trained on the reward the rollout earned, an advantage left at its natural scale, and a clip on probability rather than on ratio. The clip range is : a token the old policy gave probability 0.05 may move its ratio four times further than one it gave 0.2, because the same ratio change moves less probability mass. The loss sums a sequence’s tokens and averages over sequences, so no length weight enters . The critic trains alone forcritic_warmup = 15 updates first.
Defaults: = clip = 0.2, = gae_alpha = 0.4,
reward_range = = (0, 1).
From symbol to field
For the three single-rollout methods,update(batch) returns an Update:
For the rest, the symbols are the knobs: is
generations, is
beta, is the trainer’s clip, is loss_type, is
off_policy_steps, is the rate in anchor, and every one is a
named constant in defaults.py with the paper it came from. What the
single-rollout three did on a GPU, against their own ablations, is the
table in lesson 9
and the three recipes under papers.