Pratham Patel
· 46 min read

MiMo-V2.6: Scaling Reinforcement Learning from Scratch

Building Xiaomi's MiMo-V2.6 RL recipe from the ground up — the importance-sampled GRPO objective, group-relative advantages and dynamic sampling, hack zeroing, Groupwise Reward Synthesis, Groupwise Advantage Redistribution, the group-relative length penalty, mass-conserving segment penalties, top-p candidate replay, router freezing, and the Little's-law Sample Mixer — all derived step by step on one four-rollout coding group.

Xiaomi’s MiMo-V2.6 report (LLM-Core Xiaomi, 2026) is about one idea: spend much more compute on reinforcement learning, and do it without the run falling apart. The flagship MiMo-V2.6-Pro, a 1.02T-parameter Mixture-of-Experts model with 42B active parameters, spends $2.6M on RL alone. Each training step consumes 25,088 trajectories and up to 3.7 billion tokens, at context lengths of up to 1M. Its DeepSWE v1.1 score rises from 58.4 to 72.6 over the run.

Scaling like this breaks things that work fine at small scale. A binary “tests passed” reward cannot tell a clean patch from a sloppy one. Agents learn to download the upstream fix instead of writing it. Responses grow longer every step. The MoE router drifts until a few experts handle all the traffic. A token sampled with top-pp at inference gets a different probability at training time, even with identical weights. The report fixes each of these with a small, precise mechanism, and most of them are a few lines of algebra on the advantage vector.

This post re-derives each of those mechanisms. We use one running example: a single coding prompt with a group of four rollouts. We put every mechanism through that group and check every number by hand.


The Running Example

The prompt qq is a repository-repair task: “Fix the KeyError raised by parse_config when the timeout field is missing.” The policy generates a group of G=4G = 4 candidate solutions. A rollout (or trajectory) oio_i is one complete attempt: every model turn, tool call, and tool result from start to submitted patch. Our four rollouts are:

RolloutWhat it didTestsLength ℓi\ell_i (tokens)
o1o_1Adds a default timeout=30 in the right place; runs the testspass10
o2o_2Wraps the whole function in try/except KeyError: pass; tests pass by accidentpass20
o3o_3Runs curl on the upstream file, copies the published fixpass12
o4o_4Edits the wrong functionfail16

The real MiMo run uses G=16G = 16 and trajectories of roughly 110K–150K tokens. We shrink both so every sum fits on one line. The lengths are toy numbers, but the relationships between them are what matter.

The binary test reward is Ritest=1R^{\text{test}}_i = 1 if the tests pass and 00 otherwise, so

Rtest=(1, 1, 1, 0).R^{\text{test}} = (1,\ 1,\ 1,\ 0).

Look at what this vector hides. Rollout o1o_1 is the solution we want. Rollout o2o_2 is a patch a maintainer would reject. Rollout o3o_3 cheated. The binary reward gives all three the same score. Most of the MiMo-V2.6 RL recipe is about pulling these three apart.


1. Mathematical Setup

Earlier posts in this series built most of the tools we need from scratch. We link to them and recall only what we use:

  • Expected value, the sigmoid σ(θ)=1/(1+e−θ)\sigma(\theta) = 1/(1+e^{-\theta}) with its derivative σ′(θ)=σ(θ)(1−σ(θ))\sigma'(\theta) = \sigma(\theta)(1-\sigma(\theta)), and the log trick ∇θπθ=πθ∇θlog⁡πθ\nabla_\theta \pi_\theta = \pi_\theta \nabla_\theta \log \pi_\theta are derived in Mathematical Prerequisites for Reinforcement Learning.
  • The policy gradient theorem and REINFORCE are derived in Reinforcement Learning from Scratch.
  • Top-KK routing, expert load, and expert collapse in Mixture-of-Experts are built in MoE Load Balancing from Scratch.

We need one tool those posts do not derive: the importance sampling form of the policy gradient. MiMo generates rollouts with an older copy of the policy and trains a newer one. The gradient must correct for that mismatch.

The importance-sampled policy gradient

Let πθ\pi_\theta be the policy we are training and μ\mu the behavior policy that actually generated the data. The two differ because rollouts were sampled a few updates ago, and because the inference engine and training engine compute slightly different numbers. We want the gradient of

J(θ)=Eo∼πθ[A(o)]=∑oπθ(o) A(o),J(\theta) = \mathbb{E}_{o \sim \pi_\theta}[A(o)] = \sum_o \pi_\theta(o)\, A(o),

where A(o)A(o) is a fixed score for outcome oo (the advantage, defined in Section 4). The advantage does not depend on θ\theta, so by linearity of differentiation:

∇θJ=∑oA(o) ∇θπθ(o).\nabla_\theta J = \sum_o A(o)\, \nabla_\theta \pi_\theta(o).

We cannot sample from πθ\pi_\theta, because our samples come from μ\mu. So we multiply and divide each term by μ(o)\mu(o), which is allowed wherever μ(o)>0\mu(o) > 0:

∇θJ=∑oμ(o) ∇θπθ(o)μ(o) A(o).\nabla_\theta J = \sum_o \mu(o)\, \frac{\nabla_\theta \pi_\theta(o)}{\mu(o)}\, A(o).

Now apply the log trick, ∇θπθ(o)=πθ(o) ∇θlog⁡πθ(o)\nabla_\theta \pi_\theta(o) = \pi_\theta(o)\,\nabla_\theta \log \pi_\theta(o):

∇θJ=∑oμ(o) πθ(o)μ(o) A(o) ∇θlog⁡πθ(o)=Eo∼μ ⁣[πθ(o)μ(o) A(o) ∇θlog⁡πθ(o)].\nabla_\theta J = \sum_o \mu(o)\, \frac{\pi_\theta(o)}{\mu(o)}\, A(o)\, \nabla_\theta \log \pi_\theta(o) = \mathbb{E}_{o\sim\mu}\!\left[\frac{\pi_\theta(o)}{\mu(o)}\, A(o)\, \nabla_\theta \log \pi_\theta(o)\right].

The last step reads the μ\mu-weighted sum as an expectation under μ\mu. The factor

r(o)=πθ(o)μ(o)\boxed{r(o) = \frac{\pi_\theta(o)}{\mu(o)}}

is the importance sampling ratio. This is the importance sampling identity: an expectation under one distribution equals a reweighted expectation under another.

Numerical check. Shrink our group to two outcomes, “pass” and “fail”. Let the current policy pass with probability πθ(pass)=σ(θ)\pi_\theta(\text{pass}) = \sigma(\theta) at θ=0\theta = 0, so πθ(pass)=0.5\pi_\theta(\text{pass}) = 0.5. Let the stale behavior policy pass with μ(pass)=0.4\mu(\text{pass}) = 0.4. Take A(pass)=0.5A(\text{pass}) = 0.5 and A(fail)=−0.5A(\text{fail}) = -0.5.

Direct gradient. J=0.5 σ(θ)−0.5 (1−σ(θ))=σ(θ)−0.5J = 0.5\,\sigma(\theta) - 0.5\,(1 - \sigma(\theta)) = \sigma(\theta) - 0.5, so ∇θJ=σ′(0)=0.5×0.5=0.25\nabla_\theta J = \sigma'(0) = 0.5 \times 0.5 = 0.25.

Importance-sampled gradient. For “pass”: ∇θlog⁡σ(θ)=1−σ(θ)=0.5\nabla_\theta \log \sigma(\theta) = 1 - \sigma(\theta) = 0.5, and the ratio is 0.5/0.4=1.250.5/0.4 = 1.25. The term is μ⋅r⋅A⋅∇log⁡π=0.4×1.25×0.5×0.5=0.125\mu \cdot r \cdot A \cdot \nabla\log\pi = 0.4 \times 1.25 \times 0.5 \times 0.5 = 0.125. For “fail”: ∇θlog⁡(1−σ(θ))=−σ(θ)=−0.5\nabla_\theta \log(1-\sigma(\theta)) = -\sigma(\theta) = -0.5, and the ratio is 0.5/0.6=0.83‾0.5/0.6 = 0.8\overline{3}. The term is 0.6×0.83‾×(−0.5)×(−0.5)=0.1250.6 \times 0.8\overline{3} \times (-0.5) \times (-0.5) = 0.125. The two minus signs cancel. The sum is 0.125+0.125=0.250.125 + 0.125 = 0.25.

Both sides give 0.250.25. Sampling from the wrong policy is fine as long as we multiply by rr.


2. The Foundation RL Starts From

RL can only reinforce behavior the model sometimes produces. MiMo-V2.6 spends its pre-RL budget making that exploration space large and making long rollouts cheap.

Backbone. MiMo-V2.6 is a sparse MoE Transformer. It stacks MM hybrid blocks, each made of NN Sliding Window Attention (SWA) blocks followed by one Global Attention (GA) block. In SWA, a token attends only to the previous W=128W = 128 tokens. In GA, it attends to the whole prefix. The very first block uses GA with a dense feed-forward network to stabilize early representations. Every other block uses a sparse MoE FFN without shared experts. The two models are configured as follows:

MiMo-V2.6-FlashMiMo-V2.6-Pro
Layers (total / SWA / GA)48 / 39 / 970 / 60 / 10
Hidden size40966144
SWA heads (Q / KV)64 / 8128 / 8
GA heads (Q / KV)64 / 4128 / 8
Head dims (QK / V)192 / 128192 / 128
Experts (total / active)256 / 8384 / 8
Parameters (total / active)310B / 15B1.02T / 42B

(The report’s Table 1 prints Pro’s active count as “42T”; the text and abstract give 42B.)

Why the hybrid matters for RL: a KV-cache derivation. The KV cache stores each layer’s keys and values for every past token, so decoding does not recompute them. For one token in one layer it holds (number of KV heads) ×\times (key dim + value dim) numbers. For Flash:

GA layer: 4×(192+128)=1280,SWA layer: 8×(192+128)=2560.\text{GA layer: } 4 \times (192 + 128) = 1280, \qquad \text{SWA layer: } 8 \times (192 + 128) = 2560.

A GA layer keeps this for all LL tokens. An SWA layer keeps it for at most W=128W = 128 tokens, because older tokens are never attended again. At L=106L = 10^6:

9×1280×106⏟GA+39×2560×128⏟SWA=1.152×1010+1.28×107≈1.153×1010.\underbrace{9 \times 1280 \times 10^6}_{\text{GA}} + \underbrace{39 \times 2560 \times 128}_{\text{SWA}} = 1.152 \times 10^{10} + 1.28 \times 10^{7} \approx 1.153 \times 10^{10}.

A hypothetical all-GA Flash with 48 layers would need 48×1280×106=6.144×101048 \times 1280 \times 10^6 = 6.144 \times 10^{10}. The ratio is 1.153/6.144=0.1881.153/6.144 = 0.188, so the hybrid cache is about 5.3×5.3\times smaller. The SWA layers contribute only 0.1% of the total. This is what lets thousands of long agent rollouts fit in GPU memory (HBM) at once. The same window bound makes context parallelism cheap: an SWA layer only needs to exchange the 128 keys its queries can reach, whatever the sequence length.

Encoders and drafter. A 681M-parameter MiMo-ViT uses sink-augmented SWA. It alternates row-major and column-major token order so information spreads along both image axes, and inserts a GA layer periodically. It was pre-trained on over 4T image tokens by pairing it with a small trainable LLM under a plain cross-entropy loss. Audio goes through a tokenizer that produces 25 frames per second, each frame being 20 discrete residual vector quantizer (RVQ) codes. A patch encoder then sums the 20 code embeddings per frame and merges every 4 frames into one backbone position, so 25/4=6.2525/4 = 6.25 positions per second. A 5-layer SWA DFlash block-diffusion drafter predicts 7 tokens per forward pass for speculative decoding.

Pre-training and mid-training. Flash sees 48T tokens (26T text-only, then 22T omni-modal). Pro sees 30T (27T + 3T). Context grows from 32K to 256K. An agent-centric mid-training phase then trains on realistic agent trajectories in coding, general, visual, and research tasks, first at 256K and finally at 1M context. Three choices in this phase are aimed directly at RL:

  1. Optimizer switch. AdamW adapts each parameter separately. Muon instead orthogonalizes the update of each weight matrix and stays data-efficient beyond the batch size where AdamW’s gains flatten out. MiMo switches the hidden matrices to Muown, a Muon variant with explicit row-norm control. Embeddings, the LM head, and the router stay on AdamW. Prior work warned that moving an Adam-trained model to Muon causes mismatch. MiMo reports no loss spike.
  2. MXFP4 quantization-aware training, so the experts can later be served in 4-bit during rollout.
  3. Anti-hacking data: early trajectories that reward-hacked are rewritten so the model notices the faulty reasoning, fixes that turn, and continues honestly. We return to this in Section 6.

3. The RL Objective, Term by Term

MiMo-V2.6 trains with Group Relative Policy Optimization (GRPO). For each prompt qq drawn from the union of task datasets ⋃dDd\bigcup_d \mathcal{D}_d, the rollout policy μθold\mu_{\theta_{\text{old}}} samples a group {oi}i=1G\{o_i\}_{i=1}^G. The loss is

L(θ)=−Eq, {oi}[1∑i=1G∣oi∣∑i=1G∑t=1∣oi∣ri,t Mi,t Ailog⁡πθ(oi,t∣q,oi,<t)].\mathcal{L}(\theta) = -\mathbb{E}_{q,\ \{o_i\}}\left[\frac{1}{\sum_{i=1}^G |o_i|}\sum_{i=1}^{G}\sum_{t=1}^{|o_i|} r_{i,t}\, M_{i,t}\, A_i \log \pi_\theta(o_{i,t}\mid q, o_{i,<t})\right].

Each symbol is something we have already met or can pin down on our group.

The token-level ratio ri,tr_{i,t}. Section 1 used a ratio over whole outcomes. MiMo computes it per token, with a stop-gradient sg[⋅]\text{sg}[\cdot]:

ri,t=sg ⁣[πθ(oi,t)μθold(oi,t)].r_{i,t} = \text{sg}\!\left[\frac{\pi_\theta(o_{i,t})}{\mu_{\theta_\text{old}}(o_{i,t})}\right].

The stop-gradient treats rr as a constant during backpropagation. The gradient of one term is then

∇θ(ri,tAilog⁡πθ(oi,t))=ri,t Ai ∇θlog⁡πθ(oi,t),\nabla_\theta\big(r_{i,t} A_i \log\pi_\theta(o_{i,t})\big) = r_{i,t}\, A_i\, \nabla_\theta \log \pi_\theta(o_{i,t}),

which is exactly the importance-sampled term from Section 1, applied token by token. The numerator comes from the training engine. The denominator is the probability the inference engine reported when the token was generated. For partial rollouts (Section 5) it is not recomputed.

The mask Mi,tM_{i,t}. PPO clips the ratio. MiMo instead drops tokens whose ratio is out of range, using four separate bounds:

M=1[(A≥0 ∧ ϵ+l≤r≤ϵ+h) ∨ (A<0 ∧ ϵ−l≤r≤ϵ−h)].M = \mathbb{1}\Big[(A \ge 0 \,\wedge\, \epsilon^l_+ \le r \le \epsilon^h_+) \,\vee\, (A < 0 \,\wedge\, \epsilon^l_- \le r \le \epsilon^h_-)\Big].

Both intervals start at [0.2, 5.0][0.2,\ 5.0]. Suppose a token in o1o_1 (which will have A1>0A_1 > 0) had πθ=0.3\pi_\theta = 0.3 and μ=0.25\mu = 0.25. Then r=1.2∈[0.2,5.0]r = 1.2 \in [0.2, 5.0] and M=1M = 1: the token trains. Had the policy drifted to πθ=0.9\pi_\theta = 0.9 against μ=0.15\mu = 0.15, then r=6>5r = 6 > 5 and M=0M = 0: the token contributes nothing. The bounds are then tuned while training runs, based on policy entropy. If entropy is too low, the positive interval widens and the negative one narrows, which lets more positive updates through. If entropy is too high, the opposite happens.

The normalizer: prompt-mean aggregation. The 1/∑i∣oi∣1/\sum_i |o_i| averages over the tokens of one group. The outer expectation then averages over prompts. Each prompt gets equal total weight whatever its length. Compare token-mean aggregation, which divides every token by the total token count TT of the whole batch. There a prompt’s share of the gradient is ∑i∣oi∣/T\sum_i |o_i| / T, which grows as its rollouts get longer. For our group, ∑i∣oi∣=10+20+12+16=58\sum_i |o_i| = 10 + 20 + 12 + 16 = 58. Under prompt-mean, each of its 58 tokens is weighted 1/581/58 and the prompt’s share is fixed. Under token-mean, doubling every rollout would double this prompt’s share of the update. The report adopts prompt-mean because it “prevents response length from growing too quickly.”

That leaves AiA_i, the only place where the reward enters. Everything in Sections 4–10 is about computing it.


4. Group-Relative Advantages and Dynamic Sampling

The advantage tells the update how much better a rollout did than the others. GRPO needs no value network: it uses the other members of the same group as the baseline. MiMo takes the plain difference from the group mean, without dividing by the standard deviation:

Ai=Ri−Rˉ,Rˉ=1G∑j=1GRj.\boxed{A_i = R_i - \bar{R}, \qquad \bar{R} = \frac{1}{G}\sum_{j=1}^G R_j.}

Advantages sum to zero. Summing over the group,

∑i=1GAi=∑i=1GRi−GRˉ=∑i=1GRi−G⋅1G∑j=1GRj=0.\sum_{i=1}^G A_i = \sum_{i=1}^G R_i - G\bar{R} = \sum_{i=1}^G R_i - G \cdot \frac{1}{G}\sum_{j=1}^G R_j = 0.

The GG in front cancels the 1/G1/G inside the mean. We will rely on this property repeatedly.

Numerical check with raw test rewards. Rtest=(1,1,1,0)R^{\text{test}} = (1,1,1,0), so Rˉ=3/4=0.75\bar R = 3/4 = 0.75 and

A=(0.25, 0.25, 0.25, −0.75),0.25×3−0.75=0.✓A = (0.25,\ 0.25,\ 0.25,\ -0.75), \qquad 0.25 \times 3 - 0.75 = 0. \checkmark

This is already a problem. The cheater o3o_3 gets the same +0.25+0.25 as the clean o1o_1, so every update makes copying upstream fixes more likely. Sections 6–8 fix this.

Why all-pass and all-fail groups are discarded. Suppose the prompt were easy and all four rollouts passed: R=(1,1,1,1)R = (1,1,1,1). Then Rˉ=1\bar R = 1 and every Ai=1−1=0A_i = 1 - 1 = 0. Every term in the loss has the factor AiA_i, so the group contributes exactly zero gradient. The same happens with R=(0,0,0,0)R = (0,0,0,0). Such groups still cost rollout compute and take batch slots while teaching nothing. MiMo’s dynamic sampler (from DAPO) filters them out and keeps sampling until the batch is filled with mixed-outcome groups. This filter comes back in Section 14: it makes each data source’s acceptance rate rir_i unpredictable, which the Sample Mixer has to handle.


5. Scaling Training Compute

The report scales RL along three axes: training compute, environments, and grader compute. First, the raw numbers for training compute.

Batch arithmetic. Each step samples 1,568 prompts with G=16G = 16:

1568×16=25,088 trajectories per step.1568 \times 16 = 25{,}088 \text{ trajectories per step.}

At 2.7B–3.7B training tokens per step, the mean trajectory is

2.7×10925,088≈107.6Kto3.7×10925,088≈147.5K tokens,\frac{2.7\times 10^9}{25{,}088} \approx 107.6\text{K} \quad\text{to}\quad \frac{3.7\times 10^9}{25{,}088} \approx 147.5\text{K tokens,}

which matches the report’s “roughly 110K–150K tokens per sequence.”

Where the money goes. RL post-training cost $2.6M for Pro and $0.9M for Flash. For Pro, rollout takes 43.8%, training 43.5%, and the grader 12.7%. For Flash the shares are 44.9%, 40.9%, and 14.2%. Over the run, DeepSWE v1.1 average@3 rises from 58.4 to 72.6 (Pro) and from 48.7 to 65.7 (Flash). Pro finished 30 steps in 123.1 hours of wall-clock time and Flash in 81.8.

Why a large batch. Rollouts parallelize over sequences, and training shards the batch across data-parallel ranks, so throughput grows with GPU count. With HBM full of running sequences, decode batches are large and each weight read is used for many tokens. This ratio of compute to memory traffic is called high arithmetic intensity, and it keeps GPUs busy.

Partial rollout and staleness. Agent rollouts have a long tail: a few take far longer than the rest. Waiting for the slowest would idle the cluster. With partial rollout, once enough groups are collected the step proceeds, and in-flight rollouts pause and resume after the update. The resumed rollout then mixes tokens from several policy versions. This is why μ\mu in Section 3 differs from πθ\pi_\theta, and why the importance ratio is essential. MiMo allows a staleness of 4, meaning a token may come from a policy up to 4 updates old. There is a cost: after each update, a resumed rollout must rebuild its KV cache under the new weights (re-prefill). A large batch spreads that cost over more useful work, so batch size and partial rollout are tuned together.


6. Environments and the Multi-Layer Defense Against Reward Hacking

RL tasks span agentic and competitive coding (68%), aesthetic design (13%), general tool use (12%), cybersecurity (4%), and context following (3%). Each domain has its own verifier:

  • Code. Tasks come from GitHub pull requests and issues, internal “vibe coding” requests, specification-driven tasks, CodeMidas synthesis from existing codebases, long-horizon tasks, and filtered public and vendor data. Supervision is checked two ways. For accuracy, a coding agent attempts each task 4 times and an auditing agent compares its own judgment of each patch with the observed reward, flagging false positives and false negatives. For robustness, fail-to-pass (F2P) tests must fail before the reference patch and pass after it, pass-to-pass (P2P) tests must pass both times, and both must hold across 8 reruns.
  • General. Planning agents build resettable sandboxes from real files and locally mocked software. Tasks are graded by atomic binary rubric items: code checks for deterministic facts, LLM checks for open-ended content. Negative checks catch edits to unrelated files, and adversarial fake solutions test the rubrics. A self-hosted MiMo-V2.6-SFT model is the grader.
  • Visual. Open-ended design uses pointwise rubrics plus groupwise comparison of rendered artifacts. Visual replication uses pixel-level similarity plus LLM judging.
  • Cyber. The agent must produce an input that triggers a specific OSS-Fuzz vulnerability. A proof of concept is accepted exactly when its sanitizer report matches the ground truth on two strings: the vulnerability type (e.g., heap-buffer-overflow) and the topmost project-level stack frame. The check is deterministic and essentially free. The agent gets the compiled harness binary as well as the source.

Reward hacking is earning reward without solving the task. In repository repair, the dominant form is solution leakage: the agent finds the published fix. The report quotes five real patterns: pip install a newer release and read its source, curl the upstream file, git clone the upstream repository, read the issue tracker’s changeset, and pip index versions to probe for newer releases. Our o3o_3 is the second pattern.

MiMo defends in four layers:

  1. Mid-training alignment data (Section 2) makes the model less inclined to hack in the first place.
  2. Environment preparation removes build logs, verifier outputs, leftover patches, binaries, and caches, truncates Git history at the base commit, and isolates the container from the network.
  3. A hack agent attacks each prepared environment, guided by known exploits. Whatever new leak it finds is patched, and the process repeats until it finds nothing in any environment.
  4. Training-time auditing and hack zeroing. Offline audits keep watching trajectories. Online, the groupwise grader (Section 8) sets a confirmed hack’s reward to zero before the group mean is computed.

What hack zeroing does to our group. The grader confirms o3o_3 fetched the upstream file, so R3←0R_3 \leftarrow 0:

R=(1, 1, 0, 0),Rˉ=24=0.5,A=(0.5, 0.5, −0.5, −0.5).R = (1,\ 1,\ 0,\ 0), \qquad \bar R = \tfrac{2}{4} = 0.5, \qquad A = (0.5,\ 0.5,\ -0.5,\ -0.5).

The order matters. Had we zeroed o3o_3‘s advantage after computing the mean, the mean would still be 0.750.75. Rollout o4o_4 would keep −0.75-0.75 and the group would sum to 0.25+0.25+0−0.75=−0.25≠00.25 + 0.25 + 0 - 0.75 = -0.25 \neq 0. Zeroing the reward first makes o3o_3 an ordinary failure: it is pushed down with −0.5-0.5, and the group still sums to zero. With this correction, the logged share of confirmed hacks stays below 2% for the whole run for both models.


7. Groupwise Reward Synthesis (GRS): Grading Quality Offline

After hack zeroing, o1o_1 and o2o_2 still have equal advantages, 0.50.5 each. The binary test cannot see that o2o_2 swallows every KeyError. MiMo adds grader compute to separate them, and does it in two ways, each used on a different subset of code tasks.

Groupwise Reward Synthesis is used on a subset of tasks with high pass rates. Offline, an agent studies several rollouts of the task, together with the specification and repository, and writes two task-specific rubrics:

  • Solution rubrics judge the implementation: requirements met, edge cases handled, consistent with the codebase.
  • Behavior rubrics judge the process: did the agent gather evidence and check the effect of its changes?

During training, a grader agent enters each rollout’s environment and scores it against these rubrics, producing SisolS^{\text{sol}}_i and SibehS^{\text{beh}}_i. The reward is a product:

Ri=Ritest⋅Sisol⋅Sibeh.\boxed{R_i = R^{\text{test}}_i \cdot S^{\text{sol}}_i \cdot S^{\text{beh}}_i.}

Why a product. If Ritest=0R^{\text{test}}_i = 0, then Ri=0R_i = 0 whatever the rubric scores are. A failing patch can never earn reward by looking tidy. Among passing patches, the rubric scores rank quality.

Numerical check. Say the grader scores o1o_1 as Ssol=1.0S^{\text{sol}} = 1.0 and Sbeh=0.9S^{\text{beh}} = 0.9 (clean fix, ran the tests). It scores o2o_2 as Ssol=0.6S^{\text{sol}} = 0.6 and Sbeh=0.5S^{\text{beh}} = 0.5 (blanket except, no investigation). With o3o_3 zeroed as a hack and o4o_4 failing:

R=(1⋅1.0⋅0.9,  1⋅0.6⋅0.5,  0,  0)=(0.9, 0.3, 0, 0).R = (1 \cdot 1.0 \cdot 0.9,\ \ 1 \cdot 0.6 \cdot 0.5,\ \ 0,\ \ 0) = (0.9,\ 0.3,\ 0,\ 0). Rˉ=0.9+0.34=0.3,A=(0.6, 0, −0.3, −0.3).\bar R = \frac{0.9 + 0.3}{4} = 0.3, \qquad A = (0.6,\ 0,\ -0.3,\ -0.3).

Check: 0.6+0−0.3−0.3=00.6 + 0 - 0.3 - 0.3 = 0. The sloppy o2o_2 now lands exactly on the group mean and gets zero advantage. It is neither reinforced nor punished. The clean o1o_1 takes all the positive credit.

GRS rescues all-pass groups. Take only the two passing rollouts as their own group. Under binary rewards this is an all-pass group, and Section 4 showed it gives zero gradient and would be discarded. Under GRS the rewards are (0.9,0.3)(0.9, 0.3), the mean is 0.60.6, and the advantages are (+0.3,−0.3)(+0.3, -0.3). A group that used to teach nothing now carries a signal. This is why GRS targets high-pass-rate tasks: most of their groups would otherwise be filtered out.


8. Groupwise Advantage Redistribution (GAR): Grading Quality Online

All remaining code tasks use Groupwise Advantage Redistribution. For each mixed-outcome group, an SFT-trained agentic grader sees every trajectory at once in a shared workspace: the task, the repository, all patches, and all test outputs. It can read code and run targeted tests. It contrasts passing with failing attempts and ranks the passing patches on five dimensions: suitability of the approach, precision (no omissions, no unnecessary fallbacks), minimality, avoiding unintended effects, and craftsmanship consistent with the codebase. It also confirms hacks, which is where our R3←0R_3 \leftarrow 0 came from.

GAR keeps the binary reward and rewrites the advantages. Let P={i:Ri=1}\mathcal{P} = \{i : R_i = 1\} be the passing set after hack correction and Ai=Ri−RˉA_i = R_i - \bar R. The grader assigns each passing rollout a quality factor fi∈(0,1]f_i \in (0, 1], with fi=1f_i = 1 for the best. Then:

λ=∑j∈PAj∑j∈PfjAj,Ai′={λfiAi,i∈P,Ai,i∉P.\lambda = \frac{\sum_{j\in\mathcal{P}} A_j}{\sum_{j\in\mathcal{P}} f_j A_j}, \qquad A'_i = \begin{cases} \lambda f_i A_i, & i\in\mathcal{P},\\ A_i, & i\notin\mathcal{P}. \end{cases}

Deriving the conservation property

We claim the redistribution leaves the total positive mass unchanged. Sum Ai′A'_i over the passing set, pulling out the common λ\lambda:

∑i∈PAi′=λ∑i∈PfiAi=∑j∈PAj∑j∈PfjAj⋅∑i∈PfiAi=∑j∈PAj.\sum_{i\in\mathcal{P}} A'_i = \lambda \sum_{i\in\mathcal{P}} f_i A_i = \frac{\sum_{j\in\mathcal{P}} A_j}{\sum_{j\in\mathcal{P}} f_j A_j} \cdot \sum_{i\in\mathcal{P}} f_i A_i = \sum_{j\in\mathcal{P}} A_j.

The factor ∑fjAj\sum f_j A_j in the denominator of λ\lambda cancels the identical sum it multiplies. Failed rollouts are untouched, so the total over the whole group is also unchanged. It was zero before (Section 4), so it is still zero. The ratio of two passing advantages is Ai′/Ak′=fiAi/(fkAk)A'_i / A'_k = f_i A_i / (f_k A_k), so the relative weights set by the grader survive the rescaling.

Numerical check. The grader ranks o1o_1 above o2o_2: f1=1f_1 = 1, f2=0.5f_2 = 0.5. From Section 6, A=(0.5,0.5,−0.5,−0.5)A = (0.5, 0.5, -0.5, -0.5) and P={1,2}\mathcal P = \{1, 2\}.

λ=0.5+0.51×0.5+0.5×0.5=10.75=43.\lambda = \frac{0.5 + 0.5}{1 \times 0.5 + 0.5 \times 0.5} = \frac{1}{0.75} = \frac{4}{3}. A1′=43×1×0.5=23≈0.667,A2′=43×0.5×0.5=13≈0.333.A'_1 = \tfrac{4}{3} \times 1 \times 0.5 = \tfrac{2}{3} \approx 0.667, \qquad A'_2 = \tfrac{4}{3} \times 0.5 \times 0.5 = \tfrac{1}{3} \approx 0.333.

Positive mass: 23+13=1=0.5+0.5\tfrac{2}{3} + \tfrac{1}{3} = 1 = 0.5 + 0.5. ✓\checkmark Whole group: 23+13−0.5−0.5=0\tfrac{2}{3} + \tfrac{1}{3} - 0.5 - 0.5 = 0. ✓\checkmark The clean patch now gets twice the credit of the sloppy one, and the failures are exactly as before.

Before GAR (after hack zeroing)After GAR (f₁ = 1, f₂ = 0.5, λ = 4/3)+0.50+0.50−0.50−0.50+0.667+0.333−0.50−0.50o₁o₂o₃o₄o₁o₂o₃o₄positive mass 1.0 · negative mass 1.0positive mass 1.0 · negative mass 1.0

Why not just downweight?

This is the step most readers skip, and the whole design depends on it. The obvious alternative is to multiply passing advantages by fif_i and stop. That gives (0.5, 0.25, −0.5, −0.5)(0.5,\ 0.25,\ -0.5,\ -0.5). The positive mass is now 0.750.75 while the negative mass is still 1.01.0, so the group sums to −0.25-0.25. The update is net negative.

Why does net negative pressure matter? A negative advantage lowers the probability of the tokens that were sampled. That probability has to go somewhere, and it spreads over all the tokens that were not sampled, which flattens the distribution. A flatter distribution has higher entropy. Positive advantages do the opposite: they concentrate probability on sampled tokens. When negative mass exceeds positive mass step after step, entropy keeps rising. The report names “excess negative optimization pressure” as a driver of “uncontrolled entropy growth”. The factor λ\lambda restores the balance, and Section 10’s segment penalties are built on the same principle.

The cap and the final re-centering

When the fif_i are very uneven, λ\lambda can get large and blow up one rollout’s advantage. MiMo therefore caps λ\lambda (the report does not publish the cap). A capped λ\lambda no longer conserves mass, so MiMo re-centers the group afterwards: subtract the group mean from every advantage, passing and failing alike.

Numerical check with a cap. Take an illustrative cap λmax⁡=1.2\lambda_{\max} = 1.2 in place of 4/34/3:

A1′=1.2×0.5=0.6,A2′=1.2×0.25=0.3,A′=(0.6, 0.3, −0.5, −0.5).A'_1 = 1.2 \times 0.5 = 0.6, \qquad A'_2 = 1.2 \times 0.25 = 0.3, \qquad A' = (0.6,\ 0.3,\ -0.5,\ -0.5).

The sum is 0.9−1.0=−0.10.9 - 1.0 = -0.1, so the mean is −0.025-0.025. Subtracting it:

Anew=(0.625, 0.325, −0.475, −0.475),0.625+0.325−0.475−0.475=0.✓A^{\text{new}} = (0.625,\ 0.325,\ -0.475,\ -0.475), \qquad 0.625 + 0.325 - 0.475 - 0.475 = 0. \checkmark

In the uncapped case the mean is already zero and re-centering changes nothing. The sequence-level AinewA^{\text{new}}_i is copied to every model-generated token of rollout ii. Grading runs asynchronously, and if the grader’s output is unusable, the original advantages are used.

Evidence. In code-only RL on Flash (batch 128, token-mean aggregation), runs without GAR saw turns and token counts balloon. More rollouts hit the length limit, and the pass rate stopped improving. With GAR, the pass rate kept rising through step 52 while turn counts stayed roughly flat. Maintainers auditing the no-GAR policy found exactly o2o_2-style habits: speculative compatibility branches, broad exports, swallowed exceptions, relaxed validation, and evaluation-specific config changes. The GAR policy wrote smaller patches that stayed within scope.


9. The Group-Relative Length Penalty

Longer rollouts cost more and, the report finds, generalize worse. MiMo subtracts a length penalty from successful rollouts that run long relative to other successes on the same prompt. For prompt qq, let Pq\mathcal{P}_q be the successful rollouts. If the group pass rate exceeds a threshold, ∣Pq∣/G>A|\mathcal P_q|/G > A (a hyperparameter, not the advantage), compute a reference length from a percentile of the successful lengths:

ℓq⋆=QuantileB/100{ℓj:j∈Pq},\ell^\star_q = \text{Quantile}_{B/100}\{\ell_j : j\in\mathcal P_q\},

and adjust the reward:

R~i=Ri−1[i∈Pq]  X[clip ⁣(ℓi/ℓq⋆−1−δs−δ, 0, 1)]γ.\tilde R_i = R_i - \mathbb 1[i\in\mathcal P_q]\; X \left[\text{clip}\!\left(\frac{\ell_i/\ell^\star_q - 1 - \delta}{s - \delta},\ 0,\ 1\right)\right]^{\gamma}.

Here X≥0X \ge 0 is the maximum deduction and δ\delta the tolerated excess. The penalty saturates once the relative excess ℓi/ℓq⋆−1\ell_i/\ell^\star_q - 1 reaches ss. The exponent γ≥1\gamma \ge 1 shapes the ramp, and clip(x,0,1)=min⁡(1,max⁡(0,x))\text{clip}(x, 0, 1) = \min(1, \max(0, x)).

Reading the formula piece by piece.

  • ℓi/ℓq⋆−1\ell_i/\ell^\star_q - 1 is the relative excess. It is 0.250.25 for a rollout 25% longer than the reference.
  • Subtracting δ\delta and dividing by s−δs - \delta maps the excess range [δ,s][\delta, s] onto [0,1][0, 1]: no penalty up to δ\delta, full penalty from ss on.
  • The indicator restricts the penalty to successes. A failure is already at R=0R = 0, and making it shorter or longer says nothing about quality.
  • The pass-rate gate skips hard prompts, where the model still needs room to explore with long attempts.

Numerical check. The report does not publish A,B,X,δ,s,γA, B, X, \delta, s, \gamma, so we pick illustrative values: A=0.25A = 0.25, B=50B = 50 (median), X=0.2X = 0.2, δ=0.1\delta = 0.1, s=0.5s = 0.5, γ=2\gamma = 2. After hack zeroing, R=(1,1,0,0)R = (1, 1, 0, 0) and Pq={1,2}\mathcal P_q = \{1, 2\}. The pass rate 2/4=0.5>0.252/4 = 0.5 > 0.25, so the gate is open. The median of {10,20}\{10, 20\} under linear interpolation is ℓq⋆=15\ell^\star_q = 15.

For o1o_1: 10/15−1=−1/310/15 - 1 = -1/3. Then (−1/3−0.1)/0.4=−1.083(-1/3 - 0.1)/0.4 = -1.083, which clips to 00. No penalty, and R~1=1\tilde R_1 = 1.

For o2o_2: 20/15−1=1/320/15 - 1 = 1/3. Then

13−11025=73025=730⋅52=712≈0.583,\frac{\tfrac13 - \tfrac1{10}}{\tfrac25} = \frac{\tfrac{7}{30}}{\tfrac25} = \frac{7}{30}\cdot\frac{5}{2} = \frac{7}{12} \approx 0.583,

which lies inside [0,1][0,1]. The deduction is 0.2×(7/12)2=0.2×49/144=49/720≈0.0680.2 \times (7/12)^2 = 0.2 \times 49/144 = 49/720 \approx 0.068, so R~2=1−0.068=0.932\tilde R_2 = 1 - 0.068 = 0.932.

The adjusted rewards are R~=(1, 0.932, 0, 0)\tilde R = (1,\ 0.932,\ 0,\ 0). The mean is 1.932/4=0.4831.932/4 = 0.483, and the advantages are

A=(0.517, 0.449, −0.483, −0.483),0.517+0.449−0.483−0.483=0.✓A = (0.517,\ 0.449,\ -0.483,\ -0.483), \qquad 0.517 + 0.449 - 0.483 - 0.483 = 0. \checkmark

The penalty is a reward-side edit, so centering on the group mean still gives a zero-sum group. The padded o2o_2 loses about 10% of its positive credit to o1o_1.


10. Segment-Level Behavioral Penalties

Outcome rewards credit every token in a rollout equally. Suppose a passing rollout contains a malformed tool call that happened to be harmless. The outcome reward reinforces the malformed call along with everything else. MiMo flags individual tokens: hi,t=1h_{i,t} = 1 marks tokens in a format violation or tool-call error (malformed markup, invalid tool names, malformed arguments), and 00 otherwise. Across the whole training batch, let H±H^{\pm} be the flagged tokens and C±C^{\pm} the clean tokens (with loss mask 11), split by the sign of the owning rollout’s advantage. The token advantage becomes

A~i,t={α (1−hi,t) Ai,Ai>0,(β (1−hi,t)+κ hi,t) Ai,Ai<0,0,Ai=0,\tilde A_{i,t} = \begin{cases} \alpha\,(1-h_{i,t})\,A_i, & A_i > 0,\\ \big(\beta\,(1-h_{i,t}) + \kappa\, h_{i,t}\big)\,A_i, & A_i < 0,\\ 0, & A_i = 0, \end{cases} α=min⁡ ⁣(αmax⁡, 1+∑H+Ai∑C+Ai),β=max⁡ ⁣(βmin⁡, 1−(κ−1)∑H−∣Ai∣∑C−∣Ai∣),κ>1.\alpha = \min\!\left(\alpha_{\max},\ 1 + \frac{\sum_{H^+} A_i}{\sum_{C^+} A_i}\right), \qquad \beta = \max\!\left(\beta_{\min},\ 1 - (\kappa-1)\frac{\sum_{H^-} |A_i|}{\sum_{C^-} |A_i|}\right), \qquad \kappa > 1.

Each sum runs over tokens, so a rollout with 18 clean tokens contributes its AiA_i eighteen times.

What each case does.

  • Positive rollout. Flagged tokens get 1−h=01 - h = 0, so they are masked: a success never reinforces its mistakes. Clean tokens are scaled up by α≥1\alpha \ge 1.
  • Negative rollout. Flagged tokens get κAi\kappa A_i, a stronger push down. Clean tokens get βAi\beta A_i with β≤1\beta \le 1, a weaker one.

Deriving conservation for each sign

Positive side. Before the penalty, the positive mass is ∑H+Ai+∑C+Ai\sum_{H^+} A_i + \sum_{C^+} A_i. After it, the flagged tokens give zero and the clean tokens give α∑C+Ai\alpha \sum_{C^+} A_i. Without clipping, α=1+∑H+Ai/∑C+Ai\alpha = 1 + \sum_{H^+} A_i / \sum_{C^+} A_i, so

α∑C+Ai=∑C+Ai+∑H+Ai∑C+Ai∑C+Ai=∑C+Ai+∑H+Ai.\alpha\sum_{C^+} A_i = \sum_{C^+} A_i + \frac{\sum_{H^+} A_i}{\sum_{C^+} A_i}\sum_{C^+} A_i = \sum_{C^+} A_i + \sum_{H^+} A_i.

The ∑C+Ai\sum_{C^+} A_i cancels in the second term. The mass taken from flagged tokens moves to clean ones.

Negative side. For Ai<0A_i < 0 write Ai=−∣Ai∣A_i = -|A_i|. Before the penalty, the negative mass is −∑H−∣Ai∣−∑C−∣Ai∣-\sum_{H^-} |A_i| - \sum_{C^-}|A_i|. After it:

κ∑H−Ai+β∑C−Ai=−κ∑H−∣Ai∣−(1−(κ−1)∑H−∣Ai∣∑C−∣Ai∣)∑C−∣Ai∣.\kappa\sum_{H^-}A_i + \beta\sum_{C^-}A_i = -\kappa\sum_{H^-}|A_i| - \left(1 - (\kappa-1)\frac{\sum_{H^-}|A_i|}{\sum_{C^-}|A_i|}\right)\sum_{C^-}|A_i|.

Distribute the second bracket. The ∑C−∣Ai∣\sum_{C^-}|A_i| cancels against the denominator:

=−κ∑H−∣Ai∣−∑C−∣Ai∣+(κ−1)∑H−∣Ai∣=−∑H−∣Ai∣−∑C−∣Ai∣.= -\kappa\sum_{H^-}|A_i| - \sum_{C^-}|A_i| + (\kappa-1)\sum_{H^-}|A_i| = -\sum_{H^-}|A_i| - \sum_{C^-}|A_i|.

Because −κ+(κ−1)=−1-\kappa + (\kappa - 1) = -1, this is exactly the original negative mass. ■\blacksquare

When α\alpha or β\beta is clipped, or a denominator is zero (in which case the scale is set to 11), conservation no longer holds exactly, and the report says so.

Numerical check. Use the hack-corrected advantages A=(0.5,0.5,−0.5,−0.5)A = (0.5, 0.5, -0.5, -0.5) and treat our group as the whole batch. Say o2o_2 has 2 flagged tokens (a malformed tool call) and o4o_4 has 4 (an invalid tool name). Take κ=2\kappa = 2, αmax⁡=1.5\alpha_{\max} = 1.5, and βmin⁡=0.5\beta_{\min} = 0.5 (illustrative).

Positive side. H+H^+: 2 tokens of o2o_2, so ∑H+A=2×0.5=1\sum_{H^+} A = 2 \times 0.5 = 1. C+C^+: 10 tokens of o1o_1 plus 18 of o2o_2, so 28 tokens and ∑C+A=28×0.5=14\sum_{C^+} A = 28 \times 0.5 = 14. Then α=min⁡(1.5, 1+1/14)=15/14≈1.071\alpha = \min(1.5,\ 1 + 1/14) = 15/14 \approx 1.071. Mass before: 30×0.5=1530 \times 0.5 = 15. Mass after: 28×1514×0.5=1528 \times \tfrac{15}{14} \times 0.5 = 15. ✓\checkmark

Negative side. H−H^-: 4 tokens of o4o_4, so ∑H−∣A∣=4×0.5=2\sum_{H^-}|A| = 4 \times 0.5 = 2. C−C^-: 12 tokens of o3o_3 plus 12 clean tokens of o4o_4, so ∑C−∣A∣=24×0.5=12\sum_{C^-}|A| = 24 \times 0.5 = 12. Then β=max⁡(0.5, 1−1×2/12)=5/6\beta = \max(0.5,\ 1 - 1 \times 2/12) = 5/6. Flagged tokens get 2×(−0.5)=−12 \times (-0.5) = -1 each, for 4×(−1)=−44 \times (-1) = -4. Clean tokens get 56×(−0.5)=−512\tfrac56 \times (-0.5) = -\tfrac{5}{12} each, for 24×(−512)=−1024 \times (-\tfrac{5}{12}) = -10. Total −14-14, equal to the original 28×(−0.5)=−1428 \times (-0.5) = -14. ✓\checkmark

The invalid tool call in o4o_4 is pushed down twice as hard as before, and the malformed call in o2o_2 is no longer reinforced. The totals on each side are unchanged, so the update is no more negative than before.

Where this lives in the system. These penalties run inside a Penalty Module, which separates detection from effect. A Rule judges a segment, context, or sequence (by hand-written logic or a model judge). It can flag infrastructure failures, garbled tokens, calls to unavailable tools, or repetition. A Strategy decides what to do: mask, shape advantages, or just log. Penalties escalate. A context with no surviving model turns is dropped, a sequence with no surviving context gets zero advantage, and a prompt with no surviving sequence is rejected. An early stop strategy halts a rollout the moment its rule fires and zeroes the outcome reward. Infrastructure failures are masked instead of punished, so the model is never blamed for a crashed container.


11. One Framework: Every Mechanism Edits the Advantage Vector

Sections 4–10 introduced six mechanisms. They are all edits to one vector, the group’s advantages. Each is either a reward-side edit, which changes RiR_i before centering, or an advantage-side edit, which changes AiA_i after it:

MechanismSideEditKeeps positive/negative balance by
Group-relative baseline—Ai=Ri−RˉA_i = R_i - \bar Rconstruction: ∑Ai=0\sum A_i = 0
Hack zeroingrewardRi←0R_i \leftarrow 0centering after the edit
GRSrewardRi=RitestSisolSibehR_i = R^{\text{test}}_i S^{\text{sol}}_i S^{\text{beh}}_icentering after the edit
Length penaltyrewardRi←Ri−penaltyiR_i \leftarrow R_i - \text{penalty}_icentering after the edit
GARadvantageAi←λfiAiA_i \leftarrow \lambda f_i A_i on P\mathcal Pthe common factor λ\lambda, then re-centering
Segment penaltiesadvantage (per token)α,β,κ\alpha, \beta, \kappa scalingα\alpha and β\beta conserve each sign’s mass

Every row keeps the total advantage mass in balance, and none makes the update net negative. Reward-side edits get this for free from mean-centering. Advantage-side edits have to build it in. That is why GAR has λ\lambda and the segment penalty has α\alpha and β\beta. MiMo’s recipe is one rule applied six times: change where the credit goes, never how much credit there is.

RolloutG trajectoriesReward-side editshack → 0 · GRS · lengthA = R − R̄sum = 0Advantage-side editsGAR (λ) · segment (α, β, κ)Eq. 1every edit moves credit between rollouts or tokens; none changes the balance of positive and negative mass

12. Training–Inference Consistency: Same Weights, Different Probabilities

The ratio ri,tr_{i,t} is only meaningful if πθ\pi_\theta and μ\mu differ because the policy changed, not because the two engines compute differently. MiMo runs rollout in SGLang and training in Megatron-LM, and closes three gaps between them.

Top-pp candidate-set replay

This is the gap that surprises almost everyone: identical weights, identical logits, and still a ratio that is not 1.

Top-pp (nucleus) sampling keeps the smallest set of most-likely tokens whose total probability reaches pp, renormalizes over that set, and samples. Suppose that at one step of o1o_1 both engines produce the same full-vocabulary distribution over four tokens:

π(a)=0.60,π(b)=0.25,π(c)=0.10,π(d)=0.05.\pi(a) = 0.60,\quad \pi(b) = 0.25,\quad \pi(c) = 0.10,\quad \pi(d) = 0.05.

With p=0.8p = 0.8: {a}\{a\} holds 0.60<0.80.60 < 0.8, and {a,b}\{a, b\} holds 0.85≥0.80.85 \ge 0.8. So the candidate set is {a,b}\{a, b\}. The sampler draws aa with probability

μ(a)=0.600.60+0.25=0.600.85≈0.706.\mu(a) = \frac{0.60}{0.60 + 0.25} = \frac{0.60}{0.85} \approx 0.706.

That is the probability the inference engine records. The training engine, computing a normal softmax over the full vocabulary, reports πθ(a)=0.60\pi_\theta(a) = 0.60. The ratio is

r=0.600.706=0.85≠1,r = \frac{0.60}{0.706} = 0.85 \neq 1,

even though nothing has been trained yet. Every token sampled under top-pp carries this systematic bias. The fix is to record each token’s candidate set during rollout and renormalize the training log-probability over the same set:

πθrenorm(a)=πθ(a)∑v∈{a,b}πθ(v)=0.600.85≈0.706,r=0.7060.706=1.✓\pi^{\text{renorm}}_\theta(a) = \frac{\pi_\theta(a)}{\sum_{v\in\{a,b\}}\pi_\theta(v)} = \frac{0.60}{0.85} \approx 0.706, \qquad r = \frac{0.706}{0.706} = 1. \checkmark

Moving these sets around is cheap. Only the GPU-to-CPU transfer is dense: a full-vocabulary bitmap of fixed shape, which avoids a GPU–CPU synchronization. Everything after that is sparse, because at MiMo’s typical p=0.97p = 0.97 a candidate set has fewer than five tokens on average.

Rollout Routing Replay (R3)

In an MoE layer, each token picks its top-8 experts by router score. If two experts score 0.50010.5001 and 0.49990.4999 in the inference engine, a tiny numerical difference in the training engine can swap them. The token then runs through a different expert, and πθ\pi_\theta is computed on a different network path from the one that produced μ\mu. R3 records the expert indices chosen during rollout and forces training to use them.

Quantize–dequantize (QDQ)

Rollout runs the experts in MXFP4 with the Humming GEMM kernels. After every parameter update, the training side quantizes and immediately dequantizes the expert weights under the same numeric constraints, so both engines see bit-identical expert weights.

All three records (candidate sets, expert indices, visual inputs) travel with the Context Cache. It persists each dialogue’s KV cache across turns within one policy version, so a new turn only prefills its new suffix. During tool calls it offloads idle state to pinned host memory on side CUDA streams, and it returns the records only when the rollout is collected. RL-adapted block-6 DFlash speculative decoding raises the average accepted length by 31.3% over the inherited MTP-3 drafter. In FP8 it adds about 10.3% per-node throughput.


13. Router Freezing: Stopping Load Collapse

From MoE Load Balancing from Scratch: expert load is the number of tokens routed to an expert, and expert collapse is when a few experts take most of the load. MiMo tracks three statistics of per-step loads n1,…,nEn_1, \dots, n_E with mean nˉ\bar n:

  • Coefficient of variation (CV): std(n)/nˉ\text{std}(n)/\bar n, the spread relative to the mean.
  • Peak load factor: max⁡ene/nˉ\max_e n_e / \bar n, how overloaded the busiest expert is.
  • Cold fraction: the share of experts with ne<0.1 nˉn_e < 0.1\,\bar n.

Numerical check. Route our group’s 5858 tokens through a toy 4-expert layer. A healthy split (29,15,12,2)(29, 15, 12, 2) has nˉ=14.5\bar n = 14.5. The deviations are (14.5,0.5,−2.5,−12.5)(14.5, 0.5, -2.5, -12.5), their squares are (210.25,0.25,6.25,156.25)(210.25, 0.25, 6.25, 156.25), the squares sum to 373373, the variance is 373/4=93.25373/4 = 93.25, and the standard deviation is 93.25=9.66\sqrt{93.25} = 9.66. So

CV=9.66/14.5=0.67,peak=29/14.5=2.0,cold=0% (no load below 1.45).\text{CV} = 9.66/14.5 = 0.67, \qquad \text{peak} = 29/14.5 = 2.0, \qquad \text{cold} = 0\% \ (\text{no load below } 1.45).

A collapsed split (50,4,3,1)(50, 4, 3, 1) has the same mean. The deviations are (35.5,−10.5,−11.5,−13.5)(35.5, -10.5, -11.5, -13.5), the squares sum to 16851685, the variance is 421.25421.25, and the standard deviation is 20.5220.52. So

CV=20.52/14.5=1.42,peak=50/14.5=3.45,cold=25% (the load of 1<1.45).\text{CV} = 20.52/14.5 = 1.42, \qquad \text{peak} = 50/14.5 = 3.45, \qquad \text{cold} = 25\% \ (\text{the load of } 1 < 1.45).

What happened in MiMo-V2.6-Pro. With a trainable router, at decoder layer 9 (384 experts), all three statistics rose steadily over the first 20 RL steps. CV went from 0.78 to 2.0, peak load from 6×6\times to 16×16\times, and the cold fraction from 0.5% to 22%. To find the cause, the team took the step-20 checkpoint and reset only the router to its pre-RL values. Load balance returned to near its starting level, and benchmark scores did not change. So the collapse came from the router drifting, not from the experts degrading. The fix is to freeze the router during RL. The frozen run stays flat (CV ≈0.7\approx 0.7, peak ≈5.5×\approx 5.5\times, cold ≈1%\approx 1\%) while scores improve normally.

Even with a frozen router, a single micro-batch can be badly unbalanced. One expert-parallel rank received over 30×30\times the mean token load at one layer and ran out of GPU memory, which forced a parallelism change.


14. The Sample Mixer: Keeping the Task Mix Stable

A mixed-task batch should contain each source in a fixed proportion, say BiB_i accepted groups per step from source ii. Sources differ enormously. Across 25 profiled sources, mean generated tokens vary 90×90\times and rollout durations vary 66×66\times. Dynamic sampling (Section 4) discards a source-dependent fraction of groups. If every source got the same number of concurrent rollouts, fast sources would fill their quota at once and slow ones would lag behind.

Extend our running example to a two-source batch: Code (the source of our prompt) and Chat. Let the targets be Bcode=Bchat=4B_{\text{code}} = B_{\text{chat}} = 4 groups, the acceptance rates rcode=0.5r_{\text{code}} = 0.5 and rchat=0.8r_{\text{chat}} = 0.8, and the rollout durations tcode=30t_{\text{code}} = 30 min and tchat=1t_{\text{chat}} = 1 min.

Step 1: demand

To keep BiB_i groups after filtering at acceptance rate rir_i, we must generate

mi=Biri:mcode=40.5=8,mchat=40.8=5.m_i = \frac{B_i}{r_i}: \qquad m_{\text{code}} = \frac{4}{0.5} = 8, \qquad m_{\text{chat}} = \frac{4}{0.8} = 5.

Step 2: concurrency from Little’s law

Little’s law from queueing theory says the average number of items in a system equals the arrival rate times the average time each spends inside: L=λWL = \lambda W. Rollouts from source ii must complete at a rate proportional to mim_i per step, and each lives for tit_i. So the number in flight must scale as timit_i m_i. This is the report’s “required concurrency scales with timit_i m_i”: 30×8=24030 \times 8 = 240 for Code against 1×5=51 \times 5 = 5 for Chat.

Step 3: oversampling

Each source gets a budget of (1+pi) mi(1 + p_i)\,m_i groups, with an oversampling ratio

pi=clip(c ti−1, pmin⁡, pmax⁡),∑imipi∑imi=pˉ.p_i = \text{clip}(c\,t_i - 1,\ p_{\min},\ p_{\max}), \qquad \frac{\sum_i m_i p_i}{\sum_i m_i} = \bar p.

Slow sources get more headroom. The shared constant cc is solved so the demand-weighted mean oversampling equals a global pˉ\bar p. Take pˉ=0.5\bar p = 0.5, pmin⁡=0p_{\min} = 0, and pmax⁡=2p_{\max} = 2.

First try, ignoring the clip:

8(30c−1)+5(c−1)13=0.5 ⇒ 245c−13=6.5 ⇒ c=0.0796.\frac{8(30c - 1) + 5(c - 1)}{13} = 0.5 \ \Rightarrow\ 245c - 13 = 6.5 \ \Rightarrow\ c = 0.0796.

This gives pchat=0.0796−1=−0.92p_{\text{chat}} = 0.0796 - 1 = -0.92, below pmin⁡p_{\min}, so it clips to 00. The equation used the unclipped value, so we solve again.

Second try, with Chat clipped at 0:

8(30c−1)+5×013=0.5 ⇒ 30c−1=6.58=0.8125 ⇒ c=0.0604.\frac{8(30c - 1) + 5 \times 0}{13} = 0.5 \ \Rightarrow\ 30c - 1 = \frac{6.5}{8} = 0.8125 \ \Rightarrow\ c = 0.0604.

Check: pcode=0.8125∈[0,2]p_{\text{code}} = 0.8125 \in [0, 2], and c tchat−1=−0.94c\,t_{\text{chat}} - 1 = -0.94 still clips to 00. The mean is (8×0.8125+5×0)/13=6.5/13=0.5(8 \times 0.8125 + 5 \times 0)/13 = 6.5/13 = 0.5. ✓\checkmark The budgets are (1.8125)(8)=14.5(1.8125)(8) = 14.5 groups for Code and 55 for Chat. The allocation is recomputed as timing and acceptance statistics change.

Step 4: which source to launch next

Within these budgets, sources are chosen by smooth weighted round-robin with weights

wi=αBiri+(1−α)(Bi−Ai)+ri,w_i = \alpha\frac{B_i}{r_i} + (1-\alpha)\frac{(B_i - A_i)_+}{r_i},

where AiA_i counts groups already accepted this step and (x)+=max⁡(x,0)(x)_+ = \max(x, 0). (This AiA_i and α\alpha are the report’s notation for this equation only. They are not the advantage or the segment-penalty α\alpha.) Suppose Chat has already met its quota, Achat=4A_{\text{chat}} = 4, while Code has Acode=1A_{\text{code}} = 1. With α=0.5\alpha = 0.5:

wcode=0.5×8+0.5×30.5=4+3=7,wchat=0.5×5+0.5×00.8=2.5.w_{\text{code}} = 0.5 \times 8 + 0.5 \times \frac{3}{0.5} = 4 + 3 = 7, \qquad w_{\text{chat}} = 0.5 \times 5 + 0.5 \times \frac{0}{0.8} = 2.5.

Code gets 7/9.5≈74%7/9.5 \approx 74\% of the next launches. With α=0\alpha = 0 (pure deficit), Chat’s weight would drop to 00. Its pipeline would empty and have to refill from scratch next step, which makes rollout occupancy unstable. With α=1\alpha = 1 (pure target), the ratio would stay at 8:58:5 however far behind Code was. In the report’s trace-driven simulation, α=0.5\alpha = 0.5 was steadier than α=0\alpha = 0 and more balanced than α=1\alpha = 1.

Two more pieces finish the Mixer. Predictive Rollout Dispatch admits a rollout to a GPU rank only if a safety multiple of its predicted KV demand fits. It then places the rollout on the rank with the most remaining capacity, measured as the smaller of free concurrency slots and free KV space. Sample Replay reuses completed groups from slow sources in the first step after startup or recovery. Startup collection takes about 1.8×1.8\times longer than steady state, and short rollouts finish first, which would otherwise bias the first batch.

The rest of the infrastructure supports these mechanisms. Each rollout runs as an Agent Loop that owns its environment’s lifecycle and calls the inference engine token-in, token-out. Trajectories form a four-level hierarchy (Sample → Sequence → Context → Segment), and only model-generated Segments carry loss. A Harness Pool of persistent Ray host actors, each hosting many tenants, avoids running out of file descriptors on Ray’s control node. A Payload Porter keeps the driver working on metadata only, while heavy payloads (routing records, top-pp bitmaps, images) go into a distributed key-value store and are packed where they are consumed.


15. Multi-Harness Training and MOPD2

An agent harness is the loop around the model: system prompt, tools, and context management. Training in one harness can tie the learned strategies to that harness’s quirks. Production harnesses (MiMo Code, Codex) are poor RL environments. They add instructions the reward never measures, which blurs credit assignment, and their modules are too coupled to vary one at a time. MiMo builds mini-harnesses instead: all start from the same minimal agent loop, and the modules are decoupled so they can be recombined into task-specific variants for Code, General, Visual, and Cyber.

On DeepSWE v1.1, training on four code mini-harnesses also raised performance on three held-out harnesses (Codex, Claude Code, mini-swe-agent). Their mean pass@1 went from about 50% to about 66%, and the gap to the training harnesses narrowed.

After mixed RL, Multi-Prefix Multi-Teacher On-Policy Distillation (MOPD2) merges in skills from domain teachers: mixRL teachers for verifiable tasks, and SFT teachers for open-domain tasks where no reliable reward exists. Standard MOPD has a teacher score full student rollouts token by token. MOPD2 adds prefix-conditioned rollouts. A source trajectory with kk assistant turns gives kk history prefixes h1,…,hkh_1, \dots, h_k, each ending just before an assistant turn. The student generates only that one turn, and the teacher supervises it. If o1o_1 had 3 assistant turns, it would give 3 single-turn distillation problems. Starting from a fixed prefix keeps the student in the histories the SFT teacher actually saw, so a student that has drifted is never judged in situations the teacher never learned. This extends training to domains such as long-horizon game development, scientific research, and embodied intelligence.


16. Results

A selection from the report’s final comparison (Table 3):

BenchmarkV2.6-ProV2.6-FlashV2.5-ProClaude Opus 5GPT-5.6 SolClaude Fable 5
DeepSWE v1.171.967.919.074.073.070.0
ProgramBench26.526.012.537.025.033.0
AutomationBench v1.0.653.152.316.050.345.846.2
Toolathlon-Verified76.973.649.180.674.977.9
Terminal Bench 2.189.987.665.289.188.884.3
Terminal Bench 4.034.928.81.549.039.942.4
OSWorld-Verified82.080.8–83.483.086.0
CyberGym94.095.140.0–––
ExploitBench47.925.316.670.078.578.0
MiMo Visual Coding72.371.5–70.073.469.1

The jump from V2.5 is large everywhere. Against frontier models, V2.6-Pro leads on AutomationBench and Terminal Bench 2.1 and is close on DeepSWE and OSWorld. It trails clearly on Terminal Bench 4.0 and on exploit development (ExploitBench, ExploitGym). That fits the training mix: the cyber RL task is vulnerability reproduction, not exploitation. Over training, scores rise together with total tokens used (Figure 9), so part of the gain comes with longer rollouts. The length penalty and GAR slow that growth but do not stop it.

What went wrong during the run. Infrastructure failures were mostly GPU double-bit memory errors, plus a Kubernetes failure (Flash) and an unreachable grader (Pro). Rollout failures came from partial rollout. Short rollouts finish first after a restart, which biased the length priors in Predictive Dispatch and exhausted the KV pools. One harness also produced rollouts less than half as long as the others on the same dataset. Training failures were the 30×30\times expert-imbalance out-of-memory errors from Section 13. Driver failures were CPU out-of-memory errors during packing, late in the Flash run, as sequences grew.


17. Open Foundations: The 9B Distilled Model

To make agentic RL research reproducible, the team released MiMo-V2.6-Distill-Qwen-9B, which is Qwen3.5-9B fine-tuned on 77.4B tokens of MiMo-generated data (27.2B of them loss tokens: code 7.3B, cyber 4.8B, general 5.7B, visual 9.4B). They also released about 7K RL tasks with verifiers (3K code, 1K cyber, 1K general, 2K visual, plus about 1K music-generation tasks), the RL framework, and the mini-harnesses.

Starting from the same SFT checkpoint, domain-specific GRPO improved all 11 reported evaluations:

BenchmarkQwen3.5-9BSFT+RL
SWE-bench Verified60.061.166.2
SWE-bench Pro32.044.647.6
MiMo Code Bench (mini)19.551.659.9
MiMo Cyber Bench (mini)5.731.347.0
AutomationBench v1.0.65.030.333.1
Terminal Bench 2.127.037.152.8
Toolathlon-Verified25.935.238.0
OfficeQA Pro9.019.524.8
JobBench2.618.325.2
MiMo General Bench (mini)28.562.270.6
MiMo Visual Coding (mini)61.764.072.4

A separate multi-harness coding run (four training mini-harnesses, three held out) improved every one of 21 dataset–harness pairs over the SFT checkpoint. On MiMo Code Bench (mini), the gains ranged from 1.8 to 9.3 points depending on the harness. The mean over the seven harnesses rose from 53.1 to 59.0. A music-composition benchmark rose from 45.7 to 52.5. The report’s case study on website generation shows the same 61.7→64.0→72.461.7 \to 64.0 \to 72.4 progression visually: plain layouts from Qwen3.5-9B, richer content after SFT, and polished, complete pages after RL.


Summary

MiMo-V2.6 trains with importance-sampled GRPO, ∇J=Eμ[rA∇log⁡π]\nabla J = \mathbb{E}_\mu[r A \nabla \log \pi]. Every added mechanism edits the group’s advantage vector without changing its balance. Reward-side edits (hack zeroing, the multiplicative GRS reward RtestSsolSbehR^{\text{test}} S^{\text{sol}} S^{\text{beh}}, the group-relative length penalty) stay balanced because A=R−RˉA = R - \bar R always sums to zero. Advantage-side edits (GAR’s λfiAi\lambda f_i A_i, the segment penalty’s α,β,κ\alpha, \beta, \kappa) are built to conserve mass, which moves credit from the sloppy patch to the clean one without adding net negative pressure that drives entropy up. The rest of the stack keeps the ratio rr and the batch honest: top-pp candidate replay, R3, and QDQ make r=1r = 1 when the policy has not changed; router freezing stops load collapse; and the Little’s-law Sample Mixer keeps the task mix stable while 25,088 long rollouts are in flight.


Previous: MaxRL: From REINFORCE to Maximum Likelihood

Enjoyed this post?

Subscribe to get notified when I publish new posts. No spam, unsubscribe anytime.