Illustration

Reading Open-Weight Recipes, Part 2:

What 2025–26 Model Reports Disclose About Midtraining

Written by Martin Ziqiao Ma

Notes on what the 2025–26 open-weight model reports say happens between the main pretraining run and fine-tuning: learning-rate decay and annealing, late data mixes, code and agent data, long-context extension, architecture retrofits, added vision and audio, mid-run changes to the optimizer and precision, and how labs check the result. Each chapter explains the method, works a real example, and gives the reasons the labs themselves stated.

Disclaimer: This blog is compiled and edited with help from LLMs. Every number links to the public document it came from, so please check the source before citing it.

This is Part 2 of Reading Open-Weight Recipes, a series where I review what open-weight model releases have written down about their training recipes between December 2024 and October 2026. The atlas indexes the disclosures lab by lab; these notes go through what happens between the main pretraining run and fine-tuning, one phase at a time, with the mechanism, a worked example using numbers from a released model, and the reasons the labs themselves gave.

The same caveats as the rest of the series apply. Everything here comes from the public reports of open-weight releases (plus Microsoft AI's reports, whose models are mostly closed-weight), so it describes what those labs chose to disclose. It is not a description of how frontier closed models are trained, and where a report is silent I don't fill the gap. These are personal notes, not written for, reviewed by, or endorsed by any lab covered here.

Before you start

After a base model has read trillions of tokens, what do labs still change before fine-tuning begins, and why has that late stretch of training become a stage of its own?

Between the main pretraining run and supervised fine-tuning sits a stage that labs call mid-training, annealing, cooldown, context extension or continued pre-training. In 2024 it was mostly a short patch to stretch the context window: DeepSeek-V3 spent under 1% of its tokens on it. By 2026, in the reports reviewed here, it had grown into the place where labs reshape a base model for what comes next:

  • Schedule and data. They decay the learning rate on their best data, add code and agent trajectories, and sometimes remove data on purpose.
  • Context. They train at 256K to 1M tokens of context.
  • The model itself. They retrofit sparse or linear attention, attach vision and audio, and continue a smaller base on a larger one's logits.
  • Optimizer and precision. They switch optimizers and start 4-bit training.

For DeepSeek V4.1-Flash, these notes count more than a third of all training tokens as midtraining.

These notes follow the same format as the pretraining notes and the posttraining notes. Each chapter opens with the question it answers, explains the method with a diagram, equations and short pseudocode, works a real example, quotes the labs' own reasons, and ends with trade-offs, three takeaways and two check-yourself questions. Underlined numbers link to their source; hover them for the exact quote.

The notes assume you know how a transformer is trained with next-token prediction and what a learning-rate schedule is. Rotary position embeddings, mixture-of-experts layers, sparse attention, vision encoders and the Muon optimizer are introduced in the pretraining notes; these notes link back to it and go further only where midtraining changes something. The core models and labs are those of the pretraining notes, whose roster lists each model's size and release date. Qwen, MiniMax, StepFun, Ant's Ling, NVIDIA's Nemotron and Mistral, which the atlas added later, come in where their reports change or sharpen a point.

Where pretraining ends and midtraining begins

Labs draw the line differently, so these notes use one rule for every release; chapter 00 explains it and sorts real phases with it. In short:

  • Pretraining is the from-scratch run on its main learning-rate schedule, including any decay inside that schedule, data re-weighting during it, and any growth in sequence length the lab does not name as a separate phase.
  • Midtraining is (1) any phase the lab names mid-training, annealing, cooldown, learning-rate decay stage, context extension or continued pre-training; (2) a distinct stage after the main decay that changes the data mix or the context length, such as MiMo-7B's stages 2 and 3; and (3) continued training of an earlier base, such as adding vision to a finished language model or retrofitting a new attention. The earlier base can be a released model or an intermediate checkpoint of an earlier run.
  • Posttraining is everything from supervised fine-tuning on.

When a lab's own label differs from this rule, the chapters say both.

Model families

The chapters follow a few model families through several releases. Sizes are total / active parameters per token.

FamilyReleasesHow they relate
DeepSeekV3 (Dec 2024, 671B / 37B); V3.1 and V3.1-Terminus (Aug–Sep 2025); V3.2-Exp and V3.2 (Sep–Dec 2025); V4-Pro and V4-Flash (Apr 2026, 1.6T / 49B and 284B / 13B); V4.1-Flash (Sep 2026, 552B plus 196B of lookup memory, 16B active)V3.1 continues V3 with longer context; V3.2 retrofits sparse attention onto V3.1-Terminus; V4 and V4.1-Flash are new models trained from scratch
Kimi (Moonshot)K2 (Jul 2025, 1.04T / 32B); K2.5 (Jan 2026); K3 (Jul 2026, 2.8T / 104B); K3.1 Pro (Oct 2026)K2.5 continues a near-final K2 checkpoint with vision; K3.1 Pro shares K3's training stages
GLM (Z.ai)GLM-4.5 (Jul 2025, 355B / 32B); GLM-5 (Feb 2026, 744B / 40B); GLM-5.2 (Jun 2026)GLM-5.2 keeps GLM-5's dimensions
MiMo (Xiaomi)MiMo-7B (Apr 2025, dense); MiMo-V2-Flash (Dec 2025, 309B / 15B); V2.5 and V2.5-Pro (Apr 2026, 310B / 15B and 1.02T / 42B); V2.6-Flash and V2.6-Pro (Sep 2026, same sizes as V2.5)V2.5 adds vision and audio; V2.6 adds an omni stage and agent-centric midtraining (whether its text backbone is a new run is not stated)
MAI (Microsoft AI)MAI-Thinking-1 (Jun 2026), built on the base model MAI-Base-1 (962B / 34.7B)the report covers pretraining, midtraining and posttraining of one model

Notation

SymbolMeaningSymbolMeaning
η, ηmax, ηminlearning rate; its peak and final valuesDtraining tokens
L, L′trained context length; target lengths = L′/Lcontext scale factor
bRoPE basedh, drhead dimension; rotated dimensions per head (dr = dh when the whole head rotates)
θi = b−2i/drrotary frequency of dimension pair iλi = 2π/θiits wavelength: tokens per full turn
wkmixture weight of data source kBbatch size, in tokens unless stated

Token counts use B for billion and T for trillion. Other symbols are local to the chapter that defines them. In stage figures, neutral grey marks pretraining and peach marks midtraining.

How to read these notes

Chapters 00 and 01 give the map: what midtraining is, how it grew, and why the low-learning-rate phase at the end of training matters so much. Chapters 02 and 03 cover what data goes in late: the mix, and the code and agent data that 2025-26 models added. Chapters 04 and 05 cover long context; the playground after chapter 04 shows what each RoPE scaling method does to every rotary dimension. Chapters 06 to 08 cover changes to the model itself: new attention, added vision and audio, and switching the optimizer or precision partway through. Chapter 09 covers how labs check a midtrained base and what they leave out, and chapter 10 follows three labs end to end. For which lab adopted what and when, see the midtraining section of the atlas.

00 What midtraining is and why it grew

What happens between the main pretraining run and fine-tuning, and why did it grow from a 126B-token context patch in DeepSeek-V3 (0.8% of its tokens) to 17T in DeepSeek V4.1-Flash (38%) and about half of Kimi K2.5's training?

A language model is built in three stages. Pretraining starts from random weights and trains next-token prediction on a large general corpus of web text, code, books and papers. Posttraining comes last: supervised fine-tuning (SFT, training on example responses) and reinforcement learning (RL, training on rewards for the model's own outputs) teach the model how to answer, reason and use tools. Midtraining sits between them. The loss is still next-token prediction on documents, but the recipe changes: smaller, targeted data, longer sequences, a low learning rate η (the factor that scales each weight update), and sometimes new modules such as a vision encoder.

The report on GLM-4.5, Z.ai's 355B-parameter mixture-of-experts (MoE) model, states the idea plainly: after pre-training it adds stages that use "medium-size domain-specific datasets, including instruction data", and it names them mid-training.

Where the boundaries sit

Labs use different words for these phases: mid-training (GLM, MAI, Meta, MiMo, DeepSeek V4), annealing (Kimi K2), cooldown (Moonlight, Kimi K3), learning-rate decay stage (DeepSeek V4.1-Flash), context extension (DeepSeek-V3) and continued pre-training (DeepSeek V3.2-Exp). To compare releases, these notes apply one rule to every lab. The idea behind it: midtraining is a deliberate change of recipe after the main run, not just the tail of a learning-rate schedule. A phase shows that intent in one of three ways: the lab names it as a phase, it changes the data or the context after the main decay, or it continues training a model that was already trained. In full:

  • Pretraining is the from-scratch run on its main learning-rate schedule, including any decay inside that schedule, data re-weighting during it, and sequence-length growth the lab does not name as a separate phase.
  • Midtraining is (1) any phase a lab names mid-training, annealing, cooldown, learning-rate decay stage, context extension or continued pre-training; (2) a distinct stage after the main decay that changes the data mix or the context length (MiMo-7B stages 2-3); (3) continued training of an earlier base, such as adding vision, a new attention or longer context. The earlier base can be a released model or an intermediate checkpoint of an earlier run.
  • Posttraining starts at SFT.

Figure 0.1 lays the rule out with an example under each entry.

The stage boundary rule Pretraining from random weights, main LR schedule also counted here LR decay inside that schedule (Kimi K2's last 5.5T tokens) data re-weighting during the run length growth the lab does not name (DeepSeek V4: 4K to 1M in one run) Midtraining phases named mid-training, annealing, cooldown, LR decay stage, context extension, continued pre-training also counted here stages after the main decay that change mix or context (MiMo-7B stages 2 and 3, called pre-training by Xiaomi) continued training of an earlier base (Kimi K2.5 vision-text stage, V3.2-Exp sparse attention) Posttraining starts at the first SFT step SFT, then RL schematic, not to scale
Figure 0.1. The boundary rule used throughout these notes, with midtraining in peach and the other stages neutral; the numbers (1)-(3) in the text match the three midtraining entries. Where a lab's own name for a phase disagrees with the rule, the text gives both.

The rule sometimes overrides the lab's own label. Four cases show how it sorts real phases:

  • Kimi K2, Moonshot AI's 1.04T-parameter MoE, decays η over its last 5.5T pretraining tokens. Kimi calls that pre-training and so does the rule, since the decay sits inside the main schedule; only the following 400B annealing and 60B long-context phases count.
  • MiMo-7B, Xiaomi's 7B model, calls all three of its stages pre-training, but stages 2 and 3 come after the main decay and raise math and code to about 70% of the mix, so clause (2) counts them as midtraining.
  • Kimi K2.5 and MiMo V2.6. Their labs call K2.5's vision-text stage and V2.6's omni stage pre-training. Clause (3) counts both as midtraining because they continue training an already pretrained text model (K2.5 starts from a near-end K2 checkpoint).
  • Step 3.5 Flash (Feb 2026). StepFun files a 3T-token annealing stage under pre-training and calls only the 750B tokens after it mid-training. Because StepFun names the stage annealing, clause (1) counts it, which raises the release's midtraining share from about 4% to about 20%.

Why not count every learning-rate decay? A literal "any decay" rule would add about 4.8T to DeepSeek-V3 and 5.5T to Kimi K2, but nothing to labs that run one cosine from the first step (GLM, MAI). The count would then measure the shape of a schedule rather than a deliberate change of recipe.

The rule as code
MID_NAMES = {"mid-training", "annealing", "cooldown", "learning-rate decay stage",
             "context extension", "continued pre-training"}

def stage(phase, main_decay_end):
    if phase.kind in ("SFT", "RL"):
        return "posttrain"
    if phase.lab_name in MID_NAMES:          # clause (1)
        return "midtrain"
    if phase.start >= main_decay_end and (phase.new_mix or phase.new_context):
        return "midtrain"                    # clause (2), e.g. MiMo-7B stages 2 and 3
    if phase.continues_earlier_base:         # clause (3): released model or earlier checkpoint
        return "midtrain"
    return "pretrain"                        # incl. in-schedule decay, unnamed length growth

def midtrain_share(phases, main_decay_end):
    lm = [p for p in phases if not p.encoder_only]          # tokens must pass through the LM
    pre = sum(p.tokens for p in lm if stage(p, main_decay_end) == "pretrain")
    own = sum(p.tokens for p in lm
              if stage(p, main_decay_end) == "midtrain" and not p.inherited)
    return own / (pre + own)   # inherited pretraining counts in pre; inherited midtraining does not

Seven kinds of phase

What do labs do in these phases? Labeling each phase by its main purpose gives seven kinds. A phase that does two things is counted once, under its main purpose: GLM-4.5's 128K stage with synthetic agent trajectories is a long-context phase. The counts come from a cross-lab grid that codes 68 releases from the labs these notes started with (the "coded releases"). Of them, 27 describe a midtraining recipe of their own; the rest are refreshes that reuse a parent's phases, releases that describe none, and a few where the question does not apply (the table in the disclosure section below lists them). Among the 27, the number of releases with each kind:

  • Long context (21): train on longer sequences, often with a changed position encoding; DeepSeek-V3's 4K to 32K to 128K phases (ch04, ch05).
  • Multimodal (9): attach a vision or audio encoder to a trained language model and train on mixed data, as Kimi K2.5 did (ch07).
  • Anneal (7): lower η, usually on upweighted high-quality data, like the cooldown of Moonlight, Moonshot's 16B MoE trained with the Muon optimizer, over 500B tokens (ch01).
  • Agentic (3): tool-use and agent trajectories, in DeepSeek V4, MiMo V2.6 and Muse Glimmer (ch03).
  • Code (2): code-centered stages, GLM-4.5's 500B repository-level stage (ch03) and MiMo V2-Flash's code-upsampled stage (ch02).
  • Reasoning (2): synthetic reasoning traces, in GLM-4.5 and Muse Glimmer (ch02).
  • Retrofit (2): change the architecture and keep training; DeepSeek V3.2-Exp and GLM-5 turned dense attention into sparse attention (ch06).

The six labs the atlas added later are not in these counts. Their reports mostly add cases to the same kinds, among them more retrofits (Qwen's sparse attention and Ling's hybrid linear attention, ch06) and more agentic stages (StepFun, NVIDIA, ch03). One kind is new: training an existing base on a larger model's logits, as NVIDIA does for both Nemotron 3.5 models; Mistral distills its Ministral 3 models from Mistral Small 3.1 the same way after pruning them from it (ch06).

How large it became

To compare releases of different sizes, these notes measure midtraining as a share of the tokens a release was trained on:

share = Dmidown midtraining / (Dprepretraining, incl. inherited + Dmidown midtraining)

A release that pretrains on 9T tokens and then midtrains on 1T has a share of 1 / (9 + 1) = 10%. Two details matter for real releases. Dpre includes pretraining inherited from a parent model, while Dmid counts only the release's own midtraining tokens. And only tokens that pass through the language model count, so a vision encoder trained on its own is left out. Figure 0.2 applies the measure to nine releases, in release order and to scale.

Midtraining tokens and share of total, nine releases, to scale pretraining (own run) pretraining inherited from the parent model midtraining (own) DeepSeek-V3Dec 2024 126B · 0.8% MiMo-7BApr 2025 6T · 25% GLM-4.5Jul 2025 1.1T · 4.8% DeepSeek-V3.1Aug 2025 839B · 5.4% Kimi K2.5Jan 2026 15.7T · 51% GLM-5Feb 2026 1.57T · 5.5% MAI-Thinking-1Jun 2026 3.55T · 10.6% DeepSeek V4.1-FlashSep 2026 17T · 38% MiMo V2.6-ProSep 2026 ≥3T · ≥10% (agent-centric phase not sized) 0T 10T 20T 30T 40T tokens through the language model, linear scale (V4.1-Flash total = 45T)
Figure 0.2. Own midtraining tokens (peach) after pretraining (neutral; dashed outline where inherited from a parent model), to scale; labels give midtraining tokens and share of the release's total. Rows are in release order. DeepSeek-V3's 126B is computed from steps × batch × sequence length (ch05); K2.5's inherited bar is the roughly 15T of K2 text pretraining before the near-end checkpoint it branches from (K2's full run was 15.5T), and its 15.7T sums the report's Table 3 without the 1T encoder-only ViT stage; MiMo-7B's denominator is the 23.8T implied by its schedule (the report rounds to 25T). The outline on each midtraining bar is drawn for visibility.

In tokens, the growth runs from billions to trillions:

  • 2024. DeepSeek-V3, DeepSeek's 671B MoE (37B parameters active per token), spent about 126B tokens on two context-extension phases.
  • 2025. DeepSeek-V3.1 re-ran both phases from the V3 base with 630B and 209B tokens. Outside the grid, MiniMax was already spending trillions: 7.5T continuing MiniMax-Text-01 into M1 (Jun 2025), and 9.3T, 32% of M2's tokens, in M2's named decay phase (Oct 2025).
  • 2026. Several releases spent trillions. MAI-Thinking-1, Microsoft AI's roughly 1T-total MoE (962B in its parameter table), spent 3.55T; MiMo V2.6-Pro, Xiaomi's 1.02T MoE, at least 3T (its agent-centric phase is not sized); DeepSeek V4.1-Flash, a 552B MoE, 17T in its named learning-rate decay stage and 1M-token context extension; and Kimi K2.5's vision-text continued pretraining 15.7T, more than the roughly 15T of K2 text pretraining it branches from (K2 itself ran 15.5T).

Part of this rise is labeling. The rule follows what a lab names as a phase, and three DeepSeek generations land on different sides of that line:

  • DeepSeek-V3 decays η inside its main schedule without naming a stage, so the rule keeps that decay in pretraining. The worked example below shows how much that matters, and ch10 returns to it.
  • DeepSeek V4 (April 2026) grows its sequence length from 4K to 1M inside its single run, which the rule counts as pretraining, and names an agentic mid-training phase of unstated size (ch03).
  • DeepSeek V4.1-Flash (September 2026) is a new model trained from scratch at 64K, not a continuation of DeepSeek V4 (the roster maps the family). It names its learning-rate decay stage and its context extension, which these notes place at 28T to 34T and 34T to 45T (η keeps falling until 40T and is then held, ch01), so all 17T count. Besides a falling η, those 17T change two things: the context grows from 64K to 1M at 34T, and the vision encoder, frozen until the decay starts at 28T, trains from then on.

Growth is not monotone. MiMo-7B already put a quarter of its tokens into stages 2 and 3 in April 2025, while GLM-5, Z.ai's 744B MoE, spent 5.5% in February 2026.

Worked example: shares from stage token counts

DeepSeek V4.1-Flash. One run of 45T tokens: pretraining at a constant η to 28T, the named learning-rate decay stage from 28T to 34T, then the 1M extension from 34T to 45T.

Dpre = 28T; Dmid = (34 − 28) + (45 − 34) = 6 + 11 = 17T; share = 17 / (28 + 17) = 17 / 45 = 37.8%.

MAI-Thinking-1. Main pretraining 30T; mid-training phase 1 3.4T at 65,536 context; phase 2 150B at 262,144.

Dmid = 3,400 + 150 = 3,550B; share = 3,550 / (30,000 + 3,550) = 3,550 / 33,550 = 10.6%.

The labeling effect. DeepSeek-V3's two context phases total about 125.8B tokens (ch05 derives the count), so its share is 125.8 / (14,800 + 125.8) = 0.84%. V3 also decayed η over 4.3T tokens and held it low for 500B more, but inside its main schedule and without naming a stage. Counted the way V4.1-Flash's named stage is, those 4.8T would give (4,800 + 125.8) / 14,925.8 = 33%.

Why labs make changes late

Why did so much work move into this late stretch, rather than into pretraining or a new run? The reports and papers give four reasons.

The last data have an outsized effect. When η decays, the loss falls fastest: MiniCPM saw it drop sharply as soon as the decay began. Putting data there also beats saving it for SFT: mixing high-quality and SFT data into a 2.4B model's decay raised MMLU from 44.6 to 50.9 after identical SFT. Chapter 01 shows why.

It costs a fraction of a new run. A change made late needs only the late tokens. DeepSeek gave a V3.1-Terminus checkpoint sparse attention (creating V3.2-Exp) with 945.8B tokens of continued training instead of a new 14.8T run.

Long sequences are cheapest at the end. A token in a long sequence costs more than one in a short sequence, because standard attention compares it with every earlier token: DeepSeek-V3's context extension used several times more GPU-hours per token than its pretraining (ch05 works out the numbers). Llama 3's report gives this as the reason to train on them only at the end: "the compute in self-attention layers grows quadratically in the sequence length". Kimi says of K3's context curriculum, which reaches 256K and 1M only in its cooldown, that "concentrating the costly long-sequence computation within a small fraction of the overall training budget keeps the curriculum economical".

It prepares the base for RL. MiMo V2.6 switched its optimizer from AdamW to Muown, a Muon variant, during mid-training "to prepare the model for subsequent large-batch RL", and started quantization-aware training there, training with the forward pass in the low-precision number format the model will later run in, so it adapts to it (ch08).

Who uses it and why

"In mid-training we further emphasize STEM, math, and coding abilities to build a strong foundation for reasoning RL climbs."

"We further introduce an agent-centric mid-training phase that expands the exploration space for agentic tasks, enabling the model to discover more effective task-solving trajectories during post-training."

Meta gives similar reasons: the first phase of Muse Glimmer, Meta's 30B on-device model, adds synthetic and domain data "to improve the starting point for post-training", and Llama 4's mid-training aimed "to improve core capabilities", including long context. Some labs state what they did without saying why. Kimi K2's report says only that "towards the end of pre-training, we conducted an annealing phase", with no reason and no description of its data.

The disclosure gap

The 68 coded releases fall into four groups:

GroupCountReleases
Own midtraining recipe27DeepSeek-V3, Prover-V2 (its 7B model's 4K → 32K extension), V3.1, V3.2-Exp, V4, V4-Flash-Vision-Exp, V4.1-Flash; Moonlight, Kimi-VL, Kimi K2, Kimi Linear, K2.5, K3; GLM-4.1V-Thinking, GLM-4.5, GLM-4.5V, GLM-4.6V, GLM-5, GLM-5.2; MiMo-7B, MiMo-VL-7B, MiMo-V2-Flash, V2.5, V2.6; MAI-Thinking-1; Llama 4, Muse Glimmer
Refresh that reuses a parent's phases13DeepSeek R1, V3-0324, R1-0528 (V3's phases); V3.1-Terminus (V3.1); Math-V2, V3.2 (V3.2-Exp); V4-DSpark, V4-Flash-0731, V4-Pro-0813 (V4); V4.1-Flash-1017 (V4.1-Flash); Kimi K3.1 Pro (K3); GLM-5.3 (GLM-5.2); MiMo V2.6-MOPD (V2.6)
Describe no midtraining25Kimi K2-0905, K2 Thinking, K2.6, K2.7 Code; GLM-4-0414, GLM-Z1-0414, GLM-4.6, GLM-4.7, GLM-4.7-Flash, GLM-5.1, GLM-5.3-Flash; MiMo V2.5-Pro; Gemma 3 (its 32K → 128K step is pretraining under the rule), Gemma 3n, Gemma 3 270M, Gemma 4, Gemma 4 12B; MAI-1-preview, MAI-Base-2; Inkling, Inkling-Small; gpt-oss, gpt-oss-safeguard; Llama 4 Behemoth, Muse Spark Open
Not applicable3MAI-DS-R1 (posttrains DeepSeek-R1), the Gemma 4 assistant drafters, MiMo V2.6-Distill-Qwen-9B (a distilled student)

So 40 releases describe some midtraining (27 recipes plus 13 refreshes), 25 describe none and 3 have none of their own to describe. Among the 25 are recent major releases such as Gemma 4, Inkling, MAI-Base-2, gpt-oss and Muse Spark Open. All six labs added to the atlas later describe some midtraining, so 11 of the atlas's 13 labs do; Gemma and Thinking Machines are the two that do not.

What is described is often thin:

  • A name only. Some of the six later labs say little: Mistral's Leanstral 1.5 names a mid-training stage and nothing more about it.
  • A result without the method. Some releases that describe no midtraining still raised the context window: Kimi K2-Instruct-0905 went from 128K to 256K and GLM-4.6 from 128K to 200K.
  • Data in words, not shares. Where phases are described, the data is usually described in words; MAI-Thinking-1 (35% STEM and math, 55% code) and MiMo-7B are among the few that give shares (ch02; ch09 counts how many give token counts and mix shares).

Trade-offs

  • Shares depend on where the line is drawn and on what labs choose to name: the worked example puts DeepSeek-V3 at 0.84% under the rule and 33% if its unnamed decay counted.
  • Skills learned late can be lost later. MAI found that "the model can forget long-context behavior learned from mid-training" during self-distillation in posttraining, and mixed mid-training data back in. NVIDIA saw it between two midtraining stages: after Nemotron 3.5 Super's 256K agentic stage it needed a 9B-token recovery stage at 1M to restore long-context scores.
  • Repeating a small high-quality set risks memorization. MAI caps epochs per source "to avoid overfitting sources that appear highly memorized".
  • Thin disclosure makes results hard to compare or reproduce: a third of releases say nothing, and most of the rest give no mixture weights.

Takeaways

  • Midtraining is next-token training with a changed recipe (data, context, η, modules) between pretraining and SFT; one boundary rule is needed because labs label the same phase differently.
  • It grew from DeepSeek-V3's 126B tokens (0.8%) to trillions by 2025-26, up to half of the run (Kimi K2.5, 51%; DeepSeek V4.1-Flash, 38%). Part of that rise is labeling, and some 2026 releases still spend about 5%.
  • Labs use it because late data has outsized effect, late changes avoid a new run, and the base can be prepared for RL; a third of releases do not describe it.
Check yourself: does Kimi K2's 5.5T cosine decay count as midtraining under the boundary rule?

No. It is the decay inside K2's main learning-rate schedule, and Kimi itself calls it pre-training. Only the named 400B annealing phase and the 60B long-context phase that follow count as midtraining.

Check yourself: GLM-4.5 pretrained on 22T tokens and then ran mid-training stages of 500B, 500B and 100B. What share is midtraining?

Dmid = 500 + 500 + 100 = 1,100B; share = 1,100 / (22,000 + 1,100) = 1,100 / 23,100 ≈ 4.8%, the value in Figure 0.2.

  1. DeepSeek-AI. DeepSeek-V3 Technical Report (2024), §4.1-4.3 and Table 1
  2. DeepSeek-V3.1 model card
  3. DeepSeek-V3.2-Exp report, §2.1
  4. DeepSeek-V4.1-Flash Technical Report, §4.2.2
  5. Kimi Team. Kimi K2: Open Agentic Intelligence (2025), §2.5
  6. Kimi Team. Kimi K2.5 technical report (2026), §4.1-4.3, Table 3
  7. Kimi K3 technical report, §3.4
  8. Liu et al. Muon is Scalable for LLM Training (Moonlight, 2025), §3.3
  9. GLM-4.5 Team. GLM-4.5 technical report (2025), §2.2-2.4
  10. GLM-5 technical report (2026), §2
  11. Xiaomi LLM-Core. MiMo: Unlocking the Reasoning Potential of Language Model (2025), §2.1-2.3
  12. MiMo-V2.6 technical report, §1, §3
  13. Microsoft AI. MAI-Thinking-1 technical report (2026), §2.5-2.6
  14. Meta. Muse Glimmer report (2026), §4.2
  15. Meta. The Llama 4 herd (blog, 2025)
  16. Llama Team, Meta. The Llama 3 Herd of Models (2024), §3.4.2
  17. Hu et al. MiniCPM: Unveiling the Potential of Small Language Models with Scalable Training Strategies (2024), §4.3, §5
  18. Kimi-K2-Instruct-0905 model card; GLM-4.6 model card
  19. Atlas, midtraining section

01 Learning-rate decay and annealing

Why do labs put their best data in the final, low-learning-rate stretch of training, and how do short anneals tell them which data deserves to be there?

The decay phase is the end of a learning-rate schedule, where the learning rate η falls from its peak ηmax toward a floor ηmin. Labs also call it annealing or cooldown, and often change the data at the same time. The pretraining notes cover warmup, cosine and warmup-stable-decay (WSD) schedules in more detail (pretraining notes, ch 09).

Schedule shapes

Every schedule warms up briefly to ηmax and ends low; what differs is when the fall happens (Figure 1.1):

  • Cosine starts falling right after warmup and follows half a cosine down to ηmin, so the whole run is one long decay with no clear start to a decay phase.
  • WSD holds η at its peak for most of the run, then decays it over a short final stretch: a natural slot for chosen data, and the checkpoint just before it can be kept and decayed again later.
Schedule shapes: cosine and warmup-stable-decay learning rate as a fraction of its peak decay phase 1 0 pre-decay checkpoint: a WSD run can keep it 0 80% 100% share of training steps (schematic; warmup drawn as the first 3%) cosine: falls from the end of warmup to the floor warmup, then WSD's stable phase at the peak WSD, linear decay WSD, 1−sqrt decay
Figure 1.1. Illustrative shapes, not from any lab; floors drawn at zero. Cosine decays over the whole run; WSD holds the peak and decays over the last 20% (shaded), linearly or with the 1−sqrt shape described below.

What the decay does to the loss

Two observations seem to clash. Each optimizer step moves the weights by an amount that scales with η: MiniCPM measured the largest element-wise weight change between checkpoints of a 2.4B model and found that "the updates exhibit a robust correlation with the learning rate's magnitude". Yet the loss barely moves while the steps are large and drops fast once they shrink. MiniCPM saw large updates with little loss reduction before the decay, and an accelerated decrease during it; Hägele et al. found the drop "aligns closely with the decay in LR".

Wen et al. explain this with a river valley picture of the loss surface: a few steep directions (the valley walls) and a flat direction along the valley floor (the river). At high η the weights "undergo large oscillations" across the walls while moving quickly along the river, so the loss stays high even as the weights make progress. Decay calms the oscillation, "revealing true optimization progress".

Why the last data count most

The river valley explains why the loss drops during the decay, not which data the final weights remember. A simple picture does: each step pulls the weights part of the way toward what its batch prefers, and every later step pulls again, partly erasing the earlier pulls. A batch's say in the final weights therefore depends on two things:

  • How hard it pulled, which scales with its own η;
  • How much pulling came after it, which grows with the sum of η over all later steps, the learning-rate area still to come.

With easy numbers: if every step pulls 5% of the way, then 100 steps later 0.95100 ≈ 0.6% of a batch's pull is left; at 0.2% per step, 0.998100 ≈ 82% is left. Big pulls are forgotten quickly, small ones remembered for long.

A one-parameter toy model makes this precise. Take one weight p and a quadratic loss per batch, ℓt(p) = ½ h (p − mt)², where mt is the value batch t prefers and h is the curvature: a large h is a steep valley wall, a small h the flat floor. After N gradient steps, p is a weighted average of the batches' preferred values, and batch t gets the weight

ct ≈ ηt hhow hard batch t pulls × exp(−h At)share of the pull that survives,    At = ∑u>t ηulearning-rate area still to come
Where does ct come from?

A gradient step on ℓt gives

pt+1 = pt − ηt h (pt − mt) = (1 − αt) pt + αt mt,    αt = ηt h

so SGD here is a moving average of the batches' preferred values with rate αt. Unrolling it over N steps:

pN = ∏t(1 − αt) · p0 + ∑t ct mt,    ct = αt ∏u>t(1 − αu) ≈ ηt h · exp(−h At)

The approximation uses 1 − α ≈ e−α for small α, so a product of (1 − αu) becomes e to the minus their sum; Figure 1.2 and the code use the exact product. The weights ct sum, with the leftover on p0, to 1.

In a steep direction (large h) only the last stretch survives, and after a decay that stretch is the decay data. In a flat direction the average spans the whole run. Figure 1.2 runs it on a WSD schedule with the same two pull sizes at peak η: the decay supplies 99.4% of the final value in the steep direction and 18% in the flat one.

Which batches set the final weights: toy SGD model on a WSD schedule decay phase A · learning rate as a fraction of its peak 10 stable at peak η (80% of steps) B · weight of each step's batch in the final weights steep direction, h × peak η = 0.05: 99.4% of the weight comes from decay-phase batches flat direction, h × peak η = 0.002: 18% from decay, 65% from the stable phase, 16% still from the starting value 0 200 400 600 800 1000 training step (illustrative run of 1,000 steps; linear decay over the last 200)
Figure 1.2. Illustrative, not from any lab. A: a WSD schedule with a linear decay over the last 20% of steps. B: the weight ct each step's batch gets in the final value of one parameter, from the toy model; each curve is scaled to its own peak. In the steep direction the decay data decide almost everything. The very last batches get little weight because the linear decay takes η to zero, so their own step ηt h is tiny; the weight peaks late in the decay.
The toy model in code
def final_weights(etas, h):
    """Weight c[t] of batch t's preferred value in the final parameter (toy SGD)."""
    c, keep = [0.0] * len(etas), 1.0
    for t in reversed(range(len(etas))):
        a = etas[t] * h
        c[t] = a * keep              # its pull, shrunk by every later step
        keep *= 1 - a
    return c, keep                   # sum(c) + keep == 1; keep stays on p_0

etas = [1.0] * 800 + [1 - k / 200 for k in range(200)]       # WSD, peak 1
for h in (0.05, 0.002):
    c, keep = final_weights(etas, h)
    print(h, round(sum(c[800:]), 3))                         # 0.994, 0.182

The model is illustrative: it assumes a fixed quadratic loss and plain SGD. Adam rescales each coordinate's step, but MiniCPM trained with Adam, and its step sizes still tracked η.

Experiments show the same effect. MiniCPM mixed high-quality and SFT data into a 2.4B model's decay; after the same SFT, MMLU rose from 44.6 to 50.9 and GSM8K from 27.7 to 42.3, and the authors recommend that capability work "should start from the decay phase". OLMo 2 calls its final stage mid-training, at 5–10% of training FLOPs; for the 7B it raised the benchmark average from 53.0 to 62.9 and GSM8K from 24.1 to 67.5, though its mid-training mix includes the GSM8K training split.

Decay shapes and lengths

A decay has a shape and a length. For the shape, let x run from 0 at the start of the decay to 1 at its end; over a decay of Nd steps ending at step N:

x = (t − (N − Nd)) / Nd ∈ [0, 1];    linear: η(t) = ηmax · (1 − x);    1−sqrt: η(t) = ηmax · (1 − √x)

A quarter of the way through (x = 0.25), linear decay is at 0.75 ηmax and 1−sqrt already at 0.5 ηmax; halfway, they are at 0.5 and 0.29. So 1−sqrt drops η quickly at first and spends longer near zero (Figure 1.1). A linear decay to zero is common in short anneals (Llama 3, OLMo 2, Moonlight's cooldown). Hägele et al. found that the 1−sqrt shape "consistently performs better than linear decay".

On length, MiniCPM found 10% of tokens enough and 2.5% short; Hägele et al. saw gains plateau at around 20%, and a 5% (1−sqrt) decay nearly matched cosine on a 20B-token run.

Annealing as a cheap test of data

Because the decay phase reacts strongly to its data, a short anneal on a candidate dataset is a cheap way to judge it. The procedure:

  1. start from a partly trained checkpoint;
  2. mix the candidate into the default data at a fixed share;
  3. decay η to zero over a short run on that mix;
  4. compare with the same anneal on the default mix alone.

Llama 3 took a 50%-trained 8B model, annealed η linearly to 0 over 40B tokens, and gave the new dataset 30% of the mix, which it found "more efficient than performing scaling law experiments for every small dataset". The gains can shrink with scale: annealing on GSM8k and MATH training data raised Llama 3 8B's validation scores by 24.0% and 6.4%, but the 405B gain was negligible.

Llama 3's anneal test in code
def anneal_test(ckpt, candidate, default_mix, tokens=40e9, share=0.3):
    """Llama 3 recipe: 50%-trained 8B checkpoint, linear decay to 0 over 40B tokens."""
    mix = {candidate: share, default_mix: 1 - share}
    model, eta0 = copy(ckpt), ckpt.lr
    steps = int(tokens / ckpt.batch_tokens)
    for k in range(steps):
        model.lr = eta0 * (1 - k / steps)      # linear anneal to 0
        model.step(sample(mix))
    return evaluate(model)    # compare with the same anneal on default_mix alone

OLMo 2 made this cheaper still with microanneals: short anneals of one candidate source mixed with general web text, with η driven to zero as in a full anneal. Its default takes equal amounts of candidate and web data (50/50), and it also varied the ratio (ch02 gives that result). 19 of them cost 130B tokens, less than three full 50B anneals. MAI tuned MAI-Thinking-1's mid-training weights "according to single-source microanneals".

What the labs did

Figure 1.3 draws six published schedules to scale. They show three ways to place midtraining around the decay; a fourth, re-warming, restarts from a decayed model.

Learning-rate schedules to scale, with midtraining shaded midtraining under the boundary rule η as a fraction of the release's peak (row top = 1) DeepSeek-V3peak 2.2×10⁻⁴ two YaRN phases (126B) at 7.3×10⁻⁶, the final pretraining η MiMo-7Bpeak 1.07×10⁻⁴ stages 2–3 (6T): held at 3×10⁻⁵, then cosine to 1×10⁻⁵ Kimi K2peak 2×10⁻⁴ annealing 400B + 60B: 2×10⁻⁵ to 7×10⁻⁶ (shape not stated) GLM-4.5peak 2.5×10⁻⁴ one cosine runs to the end of mid-training (1.1T) MAI-Thinking-1peak 2×10⁻⁴ phase 1: 3.4T, 2→1×10⁻⁵; phase 2: 150B at 1×10⁻⁶ DeepSeek V4.1-Flashpeak 2.6×10⁻⁴ named decay stage 28–34T, then 1M extension 34–45T: 17T 0 5 10 15 20 25 30 35 40 45 training tokens (T), one linear axis for all rows; warmups omitted
Figure 1.3. Published schedules drawn to scale on one token axis; each row shows η as a fraction of that release's peak. Peach spans are midtraining under the boundary rule of ch00. Kimi K2's annealing segment is dashed because the report gives its endpoints, not its shape. The dashed line in the V4.1-Flash row marks 34T, where the named decay stage ends and the 1M extension begins.

Decay inside pretraining, then midtraining at a low η. DeepSeek-V3 ended pretraining at 7.3×10−6 and ran its two context phases at that rate, "matching the final learning rate from the pre-training stage". MiMo-7B held 3×10−5 through stage 2 and most of stage 3, then decayed to 1×10−5. Kimi K2's 5.5T cosine stays in pretraining under the rule; its annealing and long-context phases (400B + 60B) took η from 2×10−5 to 7×10−6, and the report describes neither the data nor a reason.

One cosine through midtraining. GLM-4.5 decays from 2.5×10−4 to 2.5×10−5 until the end of mid-training. MAI-Thinking-1's main cosine ends at 2×10−5; its mid-training phase 1 continues from 2×10−5 to 1×10−5 without warmup, and phase 2 runs at 1×10−6.

A named decay stage. DeepSeek V4.1-Flash holds η at 2.6×10−4 to 28T tokens. Its named learning-rate decay stage covers 28T to 34T; η keeps falling during the 1M extension (34T to 45T) until it reaches 2.6×10−5 at 40T and is then held. When the decay starts at 28T, the vision encoder is unfrozen. MiniMax named such a stage much earlier: MiniMax-Text-01 (Jan 2025) closed its main run with a 1T-token "fast decay phase" that took η exponentially to 3×10−5, and MiniMax M2 (Oct 2025) spent its last 9.3T tokens in a decay phase that also grew the context from 8K to 192K.

Re-warming a decayed model. Moonlight, after a full cosine, raised η to 1×10−4 in 100 steps, then decayed linearly to 0 over 500B tokens of "the highest quality data, focusing on math, code, and reasoning". Moonlight is not in the figure, and neither is Muse Glimmer, which runs both mid-training phases below the pretraining peak and gives no values.

Checkpoint averaging

Averaging is another way to calm the oscillation: at a constant high η, nearby checkpoints scatter around the valley floor and their average lands closer to it, since "averaging reduces noise". The uniform average of the last K checkpoints, spaced Δ steps apart and ending at step N, is

p̄ = (1/K) ∑k=0…K−1 pN−kΔ

With K = 4 and Δ = 600, that is steps N, N − 600, N − 1,200 and N − 1,800. Hägele et al. found weight averaging narrows the gap to a cooldown without closing it, and ByteDance found averages of constant-η checkpoints a "low-cost simulator for the annealed performance". Labs use averaging for four different jobs:

Worked example: how far MAI-Thinking-1's phases can move the weights

The toy model says a phase can rewrite a direction only if its learning-rate area is large next to 1/h. Area is steps × mean η (warmup ignored), and the mean of a cosine from ηa to ηb is (ηa + ηb)/2. All phases use a batch of 134M tokens.

Main pretraining: cosine 2×10−4 to 2×10−5 over 30T tokens, mean 1.1×10−4: 30×1012 / 134×106 = 223,881 steps × 1.1×10−4 = 24.6.

Phase 1: mean 1.5×10−5; 3.4T tokens = 25,373 steps × 1.5×10−5 = 0.381. Phase 2: 150B tokens = 1,119 steps × 1×10−6 = 0.0011.

Total 25.0. Midtraining is 3.55 / 33.55 = 10.6% of tokens but (0.381 + 0.0011) / 25.0 = 1.5% of the learning-rate area. In the toy model, phase 1 rewrites only directions with h × 0.381 well above 1, that is h ≫ 2.6; flatter directions keep what pretraining put there.

Who uses it and why

"decays along a cosine schedule from a peak of 2×10−4 to a minimum of 2×10−5—a final-to-peak ratio of 0.1× rather than the more common 0.01× as we found that decaying the LR less improved post-RL results."

"Our early experiments showed that models trained with the WSD schedule perform worse on general benchmarks (SimpleQA, MMLU), indicating underfitting in the stable stage."

"The learning rate we use for this phase is lower than the peak pre-training learning rate, so as to to balance gains on synthetic-data objectives against acceptable regression on organic perplexity benchmarks."

Trade-offs

  • A decayed model is settled. Continuing to train it means re-warming η, as Moonlight did, or going back to a pre-decay checkpoint, which WSD keeps.
  • A deep decay is not always best for what follows: MAI kept a 0.1× floor because a smaller decay helped after RL, and GLM-4.5 rejected WSD after it underfit.
  • Strong late data can cost general skill; Muse Glimmer lowered η to limit regression on organic perplexity.
  • Anneal tests on small or half-trained models can overstate a dataset's value at full scale (Llama 3 405B), and annealing on benchmark training sets blurs evaluation, which is why Llama 3 kept them out of its annealing data.

Takeaways

  • Steps scale with η, yet the loss falls fastest while η decays; in a steep direction the final weights are set almost entirely by the decay data.
  • Short linear anneals on a 30-50% candidate mix are a cheap way to rank datasets, though gains seen at 8B may vanish at 405B.
  • Labs place midtraining after an in-schedule decay at a low η (DeepSeek-V3, MiMo-7B, Kimi K2), at the tail of one cosine (GLM-4.5, MAI-Thinking-1), or as a named decay stage (MiniMax-Text-01 and M2, V4.1-Flash); some start it from an averaged checkpoint (Muse Glimmer), and Ling replaces the decay with checkpoint averaging.
Check yourself: in the toy model, why does a batch seen early in a long stable phase barely affect a steep direction of the final weights?

Its weight is about ηt h · exp(−h At). After an early batch, the learning-rate area At still to come is large, so for large h the exponential is near zero: later steps overwrite it. Batches in the decay face a small At and survive.

Check yourself: MAI-Thinking-1's mid-training is 10.6% of its tokens. Why is it only about 1.5% of the learning-rate area?

Its mean η is far lower: 1.5×10−5 in phase 1 and 1×10−6 in phase 2, against 1.1×10−4 for the 30T-token main cosine. Area is steps × mean η, so 0.38 of a total 25.0.

  1. Hu et al. MiniCPM: Unveiling the Potential of Small Language Models with Scalable Training Strategies (2024), §4.3-4.4, §5
  2. Hägele et al. Scaling Laws and Compute-Optimal Training Beyond Fixed Training Durations (2024), §3-4
  3. Wen et al. Understanding Warmup-Stable-Decay Learning Rates: A River Valley Loss Landscape Perspective (2024)
  4. Llama Team, Meta. The Llama 3 Herd of Models (2024), §3.1.3, §3.4.3
  5. Team OLMo. 2 OLMo 2 Furious (2024), §2, §4
  6. ByteDance Seed. Model Merging in Pre-training of Large Language Models (2025)
  7. DeepSeek-AI. DeepSeek-V3 Technical Report (2024), §3.2, §4.2-4.3
  8. DeepSeek-V4.1-Flash Technical Report, §2.5, §4.2.2
  9. Kimi Team. Kimi K2: Open Agentic Intelligence (2025), §2.5
  10. Liu et al. Muon is Scalable for LLM Training (Moonlight, 2025), §3.3
  11. Xiaomi LLM-Core. MiMo: Unlocking the Reasoning Potential of Language Model (2025), §2.3
  12. GLM-4.5 Team. GLM-4.5 technical report (2025), §2.4
  13. Microsoft AI. MAI-Thinking-1 technical report (2026), §2.5.4, §2.6.2
  14. Meta. Muse Glimmer report (2026), §4.2

02 Choosing the midtraining data mix

When a lab starts a midtraining phase with a fixed token budget, which data does it raise in the mix, by how much, and how does it keep the model from losing what pretraining taught it?

A midtraining phase has a fixed token budget, so every token given to one source is taken from another. Raising the share of math or code is the point of the phase, but it pulls against two costs:

  • Repetition. The best sources are small, so a larger share means more passes over the same documents. Past about four passes, extra passes add little, and sources the model has memorized need caps.
  • Forgetting. The share comes out of general data, and a model that sees less general data drifts from what pretraining taught it.

The sections below work out the arithmetic of repetition, show what labs raise and by how much, and then turn to replay and to how the weights are chosen.

Mixture weights, tokens and epochs

A corpus is split into sources such as web text, code, math and books. The mixture weight wk is the fraction of a phase's tokens drawn from source k (∑k wk = 1). For a phase of Dphase tokens and a source with Uk unique tokens, three numbers follow from it:

Dk = wk · Dphasetokens taken from source k     ek = Dk / Ukpasses over it (epochs)     uk = wkmid / wkpreupweighting factor

Upweighting a source means raising wk above its pretraining value, so uk > 1. With easy numbers: a 1T-token phase that gives math 20% takes 200B math tokens; if the math source holds 100B unique tokens, that is 2 epochs, and if pretraining gave math 5%, math is upweighted 0.20 / 0.05 = 4 times. Good sources are small, so a large wk often means ek > 1: repetition.

Repetition has a limit. In runs up to 9B parameters, Muennighoff et al. found that up to 4 epochs of repeated data changed loss negligibly compared with unique data, while with more repetition the value of extra compute eventually decays to zero. MAI caps every dataset at 8 repetitions in its pretraining mix search, and its ~300B tokens of high-quality math were already seen 5.28 times on average before midtraining. Xiaomi reports one exception: in its preliminary experiments, synthetic reasoning data could be trained for an extremely high number of epochs without overfitting.

What labs upweight

The simplest recipe is a cooldown: decay the learning rate (chapter 01) on the best data. Moonlight, Kimi's 16B-total, 3B-active mixture-of-experts (MoE) model, re-warmed its learning rate and decayed it to zero over a 500B-token cooldown on "the highest quality data, focusing on math, code, and reasoning", without percentages.

Xiaomi's MiMo-7B, a 7B dense reasoning model, gave numbers. Xiaomi calls its stages 2 and 3 pre-training; these notes count them as midtraining because they follow the main learning-rate decay and change the mix. Stage 2 (4T tokens) raised math and code to about 70%. Stage 3 (about 2T) added about 10% synthetic reasoning responses. MiMo-V2-Flash, Xiaomi's 309B-total, 15B-active MoE, upsampled code-centric data in its 4T-token "Mid-training" stage and added about 5% synthetic reasoning data; the code share is not given.

Microsoft AI's MAI-Thinking-1 gives the fullest numbers. Its base model, MAI-Base-1, is a 962B-total, 34.7B-active MoE. MAI-Thinking-1's first midtraining phase, 3.4T tokens at 65,536 context, sets STEM and math to 35%, keeps code at 55% and leaves 10% for background sources, all drawn from the pretraining corpus: "no new or synthetic sources are introduced". Meta's Muse Glimmer, a ~29.6B dense model built for on-device agents, adds synthetic reasoning traces and structured problem-solving demonstrations to organic data in its midtraining Phase 1, without shares.

Moonlight, GLM-4.5, Kimi K2.5, DeepSeek V4, MiMo V2.6 and Muse Glimmer say what they upweighted but not by how much. Figure 2.1 collects the phases that state percentages. Among the labs added to the atlas later, MiniMax states a share close to MiMo-7B's: M1's 7.5T-token continued pretraining of MiniMax-Text-01 raised STEM, code, book and reasoning data to 70% (not drawn in the figure).

Stated data mixes of midtraining phases, to scale share of the phase's tokens (bar = 100%) 0% 50% 100% MAI-Base-1 pretraining MAI-Thinking-1's base · 30T code 54.6% 21.2% 24.3% MAI-Thinking-1 midtraining 1 3.4T code 55% STEM/math 35% 10% DeepSeek-Coder-V2 (2024) 6T continued pretraining code 60% 10% 30% (replay) MiMo-7B stage 2 4T math + code ~70% (not split) rest not described MiMo-7B stage 3 ~2T ~10% rest not broken down MiMo-V2-Flash stage 2 4T ~5% · rest: code-centric data upsampled, shares not given code STEM / math math + code combined synthetic reasoning general / background not stated
Figure 2.1. Phases whose labs state shares of code, math, synthetic reasoning or general data, drawn to scale (bar = 100% of the phase's tokens). Colours mark data source, not training stage. Top row: the pretraining mix of MAI-Base-1, MAI-Thinking-1's base, from MAI's Table 5 (STEM 15.8% + math 5.4%) for comparison; its categories may not map one-to-one onto the midtraining ones. DeepSeek-Coder-V2 (2024) is DeepSeek's named "continued pre-training" of an intermediate DeepSeek-V2 checkpoint, so clause (1) of the boundary rule (chapter 00) counts it as midtraining. Dashed: no breakdown given.

Read the top two rows together. Taking the categories as roughly comparable, MAI-Thinking-1's first phase raises STEM and math from 21.2% of MAI-Base-1's pretraining mix to 35% and holds code near 55%, so the extra share comes out of the rest, which falls from 24.3% to 10%. That is the forgetting side of the trade-off, and the replay section below asks how much general data is enough.

Synthetic reasoning traces

A reasoning trace is the step-by-step text a model writes before its answer (a chain of thought). A synthetic trace is written by another model, usually a strong reasoning model, for a question the lab collected. GLM-4.5, Z.ai's 355B-total, 32B-active MoE, gathered math, science and coding-competition questions from web pages and books and had a reasoning model write the reasoning, in a 500B-token stage. MiMo-VL-7B, Xiaomi's vision-language model, regenerated answers with long chains of thought and kept them only after rejection sampling (drawing several answers and keeping those that pass a quality check).

The reports give reasons, measured effects and some abstentions:

Replay: keeping general data in the mix

A network trained on a new distribution tends to lose what it learned on the old one: the same weights serve both, and nothing in the new batches pulls them back. This is catastrophic forgetting. In Ibrahim et al.'s continued pretraining of a 405M model, validation loss on the original Pile data rose from 2.17 to 3.56 after 200B tokens of German. The standard fix is replay, keeping a share of the old distribution in the new phase. With 25% replay the Pile loss ended at 2.33, while German loss moved only from 1.11 to 1.16. The authors find that even the lowest replay they tested, 1%, significantly reduces forgetting, while 50% slows learning of the new data.

Labs' replay shares vary widely with the stage:

  • DeepSeek-Coder-V2, DeepSeek's 2024 code model, comes from what DeepSeek calls continued pre-training of an intermediate DeepSeek-V2 checkpoint, a phase name the boundary rule counts as midtraining. That phase ran 6T tokens, with 30% natural language sampled from DeepSeek-V2's corpus, and MiMo-7B cites it for its 70% math-and-code stage.
  • MAI-Thinking-1 keeps 10% background data.
  • Kimi-VL, Moonshot's vision-language model, replays 75% shorter data in its long-context stages (chapter 05).
  • Step 3.5 Flash. StepFun gives replay in tokens: 81B of the 386B in its first mid-training stage (21%) and 10.5B of the 364B in its second (2.9%).
  • Nemotron 3.5 Super. NVIDIA keeps 20% pretraining replay in its agentic stage and 90% in its Indic stage.

Muse Glimmer works through the learning rate instead: Phase 1 runs below the pretraining peak to balance synthetic-data gains "against acceptable regression on organic perplexity benchmarks".

Selecting documents and setting weights

A quality classifier is a small model that scores each document, for example for educational value or reasoning depth, so a lab can keep, drop or upweight it. Most labs describe such classifiers only for pretraining data. For midtraining, MAI is the most explicit: it keeps documents, mainly from its PDF corpus, that the Essential-Web taxonomy labels technically correct, at least intermediate in reasoning depth and at Bloom level "Analyze" or above (the fourth of six levels from Remember to Create). A fine-tuned 0.5B-parameter model produces those labels.

Weights come from small experiments. MAI tunes weights within each category with single-source microanneals, the short test anneals described in chapter 01. One OLMo 2 microanneal result bears on "how much": a 10/90 math-to-web mix lifted its GSM8K-subset score from 28.5 to 61, near the 63.5 of a 35/65 mix, so presence mattered more than share. MAI also caps each source's epochs in midtraining, more strictly for sources the model already seems to have memorized (chapter 09).

Put together, planning a phase is a loop over sources: turn each weight into tokens and epochs, and check the epochs against the source's cap.

Planning a phase in code
# Plan one midtraining phase: tokens and epochs per source, with epoch caps.
def plan_phase(D_phase, w, U, seen, cap):
    # w[k]: mixture weight (sums to 1); U[k]: unique tokens in source k
    # seen[k]: epochs already used in pretraining; cap[k]: max total epochs
    assert abs(sum(w.values()) - 1.0) < 1e-6
    plan = {}
    for k in w:
        D_k = w[k] * D_phase              # tokens drawn from source k
        e_k = D_k / U[k]                  # passes over source k in this phase
        if seen[k] + e_k > cap[k]:
            raise ValueError(f"{k}: {seen[k] + e_k:.2f} epochs exceeds cap {cap[k]}")
        plan[k] = (D_k, e_k)
    return plan

def next_document(sources, w, rng):
    # each document is drawn from source k with probability w[k], then packed
    names = list(w)
    k = rng.choice(names, p=[w[n] for n in names])
    return sources[k].next_document()

Worked example: tokens and epochs from a stated mix

DeepSeek-Coder-V2 states both the mix and the source sizes: Dphase = 6,000B with w = 0.60 code, 0.10 math, 0.30 natural language. The code corpus holds 1,170B tokens and the math corpus 221B.

Code: 0.60 × 6,000B = 3,600B, so e = 3,600 / 1,170 = 3.08 epochs. Math: 0.10 × 6,000B = 600B, so e = 600 / 221 = 2.71 epochs. Natural language: 0.30 × 6,000B = 1,800B of replay. Both specialized sources stay under Muennighoff's 4 epochs.

MAI-Thinking-1, midtraining phase 1: Dphase = 3,400B gives STEM/math 0.35 × 3,400B = 1,190B, code 0.55 × 3,400B = 1,870B and background 0.10 × 3,400B = 340B. Against the pretraining shares in MAI's Table 5 (code 54.6%, STEM 15.8% + math 5.4% = 21.2%, the rest 24.3%): u = 35 / 21.2 = 1.65 for STEM/math, 55 / 54.6 = 1.01 for code and 10 / 24.3 = 0.41 for the rest.

The 1,190B STEM/math share cannot be turned into epochs: it draws on math (300B unique), STEM (2.2T) and Bloom-filtered PDFs, and MAI does not give the size of the filtered pool. The math numbers give a rough bound: if the pretraining cap of 8 repetitions also applied to the math family's average in midtraining, math could supply at most (8 − 5.28) × 300B ≈ 816B, so at least 1,190B − 816B ≈ 374B of the share would come from the other STEM sources. Illustrative only: a 0.6T filtered STEM/math pool would be passed 1,190 / 600 ≈ 2.0 times in phase 1 alone.

"Overall, we further bias the mixture towards STEM, math, and code to build a strong foundation for reasoning RL climbs"

"This approach is expected to enhance specialized skills without compromising general language abilities"

Trade-offs

  • Upweighting a small source means repeating it; past about 4 epochs extra passes add little, and memorized sources need caps.
  • Weight given to math or code is taken from general data: too little replay brings forgetting, too much slows learning.
  • Synthetic traces carry the generator's style and errors; long chains of thought can make answers verbose and RL unstable.
  • Mix experiments cost compute (chapter 01 gives OLMo 2's bill), and unpublished mixes cannot be reproduced.

Takeaways

  • A weight becomes tokens (wk · Dphase) and, over the source's unique size, epochs; upweighting a small source is a decision about repetition.
  • Since 2025 the upweighted data is mostly math, code and synthetic reasoning: about 70% math and code (MiMo-7B stage 2), 35% STEM/math with 55% code (MAI-Thinking-1), 5-10% synthetic traces (MiMo).
  • General data stays in (30% in DeepSeek-Coder-V2, 10% in MAI) or the learning rate stays low to limit forgetting; most labs describe the mix only in words.
Check yourself: a 4T-token phase puts 70% on math and code drawn from a pool of 1.4T unique tokens. How many epochs is that?

0.70 × 4T = 2.8T tokens, and 2.8 / 1.4 = 2 epochs: under the 4 epochs Muennighoff et al. found nearly as good as unique data, before adding pretraining passes.

Check yourself: in Ibrahim et al.'s English-to-German run, what did 25% replay buy and what did it cost?

Pile loss ended at 2.33 instead of 3.56, avoiding most of the forgetting. The cost: German loss 1.16 instead of 1.11, and a quarter of the budget spent on old data.

  1. Xiaomi, MiMo: Unlocking the Reasoning Potential of Language Model (MiMo-7B), 2025
  2. Xiaomi, MiMo-V2-Flash technical report
  3. Xiaomi, MiMo-VL technical report, 2025
  4. Microsoft AI, MAI-Thinking-1 technical report, 2026
  5. Moonshot AI, Muon is Scalable for LLM Training (Moonlight), 2025
  6. Moonshot AI, Kimi-VL technical report, 2025
  7. Z.ai, GLM-4.5 technical report, 2025
  8. Meta, Muse Glimmer 30B: An On-Device Agentic Model, 2026
  9. DeepSeek-AI, DeepSeek-Coder-V2, 2024
  10. Muennighoff et al., Scaling Data-Constrained Language Models, 2023
  11. Ibrahim et al., Simple and Scalable Strategies to Continually Pre-train Large Language Models, 2024
  12. Team OLMo, 2 OLMo 2 Furious (microanneals), 2025
  13. Essential AI, Essential-Web v1.0: 24T tokens of organized web data, 2025
  14. Wang et al., OctoThinker: Mid-training Incentivizes Reinforcement Learning Scaling, 2025

03 Code and agent data

Why did 2025-26 midtraining start feeding models whole repositories, GitHub issue-and-fix histories and agent trajectories, and what does one such training sample look like?

This chapter asks two questions: what the data looks like, and why labs add it in midtraining rather than in pretraining or post-training. The data comes in three sample formats, each closer to the work a coding agent does:

  • Repository-level code: a repository's related files in one sample, each definition before its use.
  • Issue-PR bundles: a bug report, the relevant files and the fix, in one context.
  • Agent trajectories: a model's reasoning, tool calls and tool outputs while it solves a task.

From files to repositories

Code corpora used to treat each source file as its own document, yet a function is often called in one file and defined in another, so the model rarely saw a definition next to its use. DeepSeek-Coder (2024) introduced repository-level samples, built in four steps:

  1. parse which files import which, using regular expressions for import in Python, using in C# and include in C;
  2. order the files so that each file's dependencies come before it;
  3. put a comment with the file path at the top of each file;
  4. concatenate each connected group of files into one training sample.

The format matters: training DeepSeek-Coder on file-level code only lowered cross-file completion in Java, TypeScript and C#.

Code: a simplified version of DeepSeek-Coder's construction
import re
# Simplified from DeepSeek-Coder's Algorithm 1 (Python imports only; one sample
# per repository, where the original makes one per connected group of files).
IMPORT = re.compile(r"^\s*(?:from|import)\s+([\w.]+)", re.M)

def repo_sample(files):                       # files: {path: source text}
    module = {p[:-3].replace("/", "."): p for p in files if p.endswith(".py")}
    deps = {p: {module[m] for m in IMPORT.findall(src)
                if m in module and module[m] != p}
            for p, src in files.items()}      # files that p imports
    indeg = {p: len(deps[p]) for p in files}  # imported files not yet placed
    order, left = [], set(files)
    while left:
        p = min(left, key=lambda q: (indeg[q], q))  # minimal in-degree: cycles still finish
        order.append(p)
        left.remove(p)
        for q in left:
            if p in deps[q]:
                indeg[q] -= 1
    return "".join(f"# {p}\n{files[p]}\n" for p in order)  # path comment, then file

GLM-4.5, Z.ai's 355B-total, 32B-active mixture-of-experts (MoE) model, made this a named midtraining stage: 500B tokens of concatenated files from the same repository "to learn cross-file dependency". Kimi K2.5 (Moonshot's 1.04T-total, 32B-active MoE) has a joint vision-text stage, which Moonshot calls pre-training and these notes count as midtraining; it also upweighted repository-level code. MAI-Thinking-1 adds file-level documents alongside its repository format, treating the two as complementary tasks.

Issues, pull requests and commits

On GitHub an issue is a bug report or feature request, a pull request (PR) is the proposed change that resolves it, and a commit is one recorded change, shown as a diff of removed and added lines. SWE-bench (2023) turned that pairing into a benchmark: given a codebase and an issue, the model writes a patch that is evaluated against real tests. It has 2,294 problems from 12 Python repositories. An issue-PR pair is a worked instance of exactly that task.

GLM-4.5 put model-filtered issues, PRs and commits into its repository stage, with related ones concatenated into one context and commits in diff form. GLM-5 (744B total, 40B active) relaxed the repository filters, tightened filtering of individual issues and retrieved more relevant files per pair, reaching about 10 million issue-PR pairs and about 160B unique tokens. Kimi K2.5 upweighted issues, code reviews and commit histories to improve "agentic coding subtasks such as patch generation and unit test writing".

Figure 3.1 compares the three code formats on one made-up repository.

Three code sample formats File-level one file = one document Repository-level DeepSeek-Coder construction Issue + pull request GLM-4.5, GLM-5 app/views.py calls parse_date(), defined elsewhere utils/dates.py defines parse_date() tests/test_dates.py tests parse_date() three separate samples: the model never sees a definition next to its use # utils/dates.py def parse_date(s, tz): ... # app/views.py from utils.dates import parse_date # tests/test_dates.py from utils.dates import parse_date one sample; files sorted so each import precedes its use; path comment per file Issue #412 parse_date() fails when tz is None relevant source files utils/dates.py, app/views.py commit (diff) + if tz is None: return d pull request "Fix #412: handle naive dates" one context: issue, files, diffs, PR; GLM does not state the order (illustrative) File names and contents are illustrative.
Figure 3.1. Three ways to turn code into training text; colours mark the kind of content (source file, issue, diff, pull request), not training stage. The repository sample follows DeepSeek-Coder (dependency order, a path comment per file); GLM-4.5 concatenates a repository's files without stating an order. The issue-PR sample follows GLM-4.5 and GLM-5.

Agent trajectories

An agent trajectory is the record of a model working on a task with tools. GLM-5's report writes one as (q, r1, a1, o1, …, rn, an, on): the question, then for each round the model's reasoning ri, its action ai (a tool call such as a shell command or a file edit) and the observation oi that the environment returns. ReAct (2022) introduced this interleaving of reasoning and actions. Written out with role markers, a trajectory is ordinary text and can be trained with next-token loss.

These labs describe such data in midtraining:

  • Z.ai. GLM-4.5 added "large-scale synthetic agent trajectories" to its 100B-token 128K stage (filed under long context in chapter 00, since that is the stage's main purpose), and GLM-5 up-sampled them in its later, longer-context stages. GLM-5.2 "substantially expanded 1M-context training for coding-agent scenarios" but does not say whether that is mid- or post-training.
  • DeepSeek. V4 (1.6T total, 49B active for Pro) grows its sequence length inside pretraining, but it also names an agentic mid-training phase of unstated size and says only that the agentic data strengthens coding (quoted below).
  • Xiaomi. MiMo V2.6 (1.02T total, 42B active for Pro) builds its midtraining around realistic agent trajectories from coding, general, visual and research tasks, mixed with text, repository code, images, video and audio, first at 256K context (most of the compute) and then at 1M. It also adds self-correction data: Xiaomi took cases where MiMo had reward-hacked (earned reward by exploiting the environment or grader instead of doing the task) and had MiMo reflect on the faulty reasoning, rewrite the turn and continue properly. Xiaomi says these examples "improved the model's alignment".
  • Meta. Muse Glimmer, a ~29.6B dense model for on-device agents, adds in its midtraining Phase 2 tool-use trajectories and demonstrations from a synthetic pipeline whose agent works in Docker containers that mimic email, calendar, messaging and code tools.
  • StepFun and NVIDIA, among the labs added to the atlas later, describe agentic stages in detail. StepFun's first mid-training stage for Step 3.5 Flash (Feb 2026) emphasizes software-engineering and tool-use mixtures at 32K. NVIDIA's stage for Nemotron 3.5 Super (Oct 2026) runs 65.4B tokens at 256K and states its whole mix: 41% issue-PR pairs, 20% whole repositories, 20% pretraining replay, 10% agent traces, 5% long-context data, 3% commits and 1% build and CI logs.

Which tokens carry loss? A trajectory mixes text the model wrote with text the tools returned, so there are two conventions:

Most labs here do not say which they use in midtraining. NVIDIA does: the agent traces are the only SFT-style data in its blend, and their tool responses are masked from the loss. Meta's synthetic pipeline, which feeds Muse Glimmer's midtraining Phase 2 and SFT alike, disables training on trajectory parts judged undesirable, such as bad tool calls. Figure 3.2 writes out one short coding trajectory and marks which rows each convention trains on.

One agent trajectory as training text step written by text (illustrative coding task) SFT-style loss all-token loss quser Issue: parse_date() raises AttributeError when tz=None. Fix it. r1model Find where parse_date is defined, then read it. a1model bash: grep -rn "def parse_date" src/ o1environment src/utils/dates.py:41: def parse_date(s, tz): r2model tz.localize() runs with no None check; return d unchanged when tz is None. a2model edit src/utils/dates.py + if tz is None: return d o2environment pytest tests/test_dates.py: 5 passed r3model Done: parse_date now returns naive dates unchanged. task from the user written by the model returned by tools token gets loss masked, no loss Rows follow GLM-5's notation: q, then reasoning r, action a, observation o per round.
Figure 3.2. An illustrative coding trajectory as one training sequence; row colours mark who wrote the text (user, model, tools), not training stage. SFT-style loss covers only model-written tokens (AgentTuning); all-token loss is plain next-token training. Most labs here do not say whether tool output gets loss in midtraining; NVIDIA masks it in Nemotron 3.5 Super's agent traces.

Why midtraining: long samples need long sequences

The first reason is length. Repository and issue-PR samples are long, and GLM-4.5 and GLM-5 pretrain at 4K tokens. GLM-4.5 raised the sequence length from 4K to 32K to fit large repositories and used best-fit packing (placing whole documents into sequences instead of cutting them; chapter 05) to avoid truncating repo-level code. In GLM-5 an average issue-PR pair is about 16,000 tokens, four times the pretraining window, and every midtraining stage runs at 32K or longer (worked example below). In both releases midtraining is the first stage where such a sample fits whole.

Why midtraining: RL needs a model that sometimes succeeds

The second reason is the reinforcement learning (RL) that comes later. RL samples several attempts at a task and raises the probability of those that did better than the rest. If the model never solves a task, every attempt gets the same zero reward and nothing stands out.

GRPO, the group method GLM-5 says its RL builds on, makes this exact. It scores attempt i within a group of attempts at the same task by the advantage (ri − mean r) / std r, where ri is that attempt's reward. In a group of four where one attempt succeeds (rewards 1, 0, 0, 0), the mean is 0.25 and the standard deviation over the four is 0.43, so the success gets advantage +1.73 and each failure −0.58, and the update moves toward the success. When all rewards are equal, the numerator is zero for every attempt and std r is zero as well; the DAPO authors treat such a group's advantage as zero, giving zero policy gradient, and their method filters out groups whose accuracy is 0 or 1. Either way, RL learns from a task only once the model sometimes solves it.

pass@k measures "sometimes": the probability that at least one of k samples is correct. Small rates matter. With per-attempt success p and a group of 16 independent attempts (illustrative numbers), the chance of at least one success is 1 − (1 − p)16: 1 − 0.99916 = 1.6% at p = 0.001 and 1 − 0.9816 = 27.6% at p = 0.02. Only groups with mixed outcomes give GRPO a gradient, so raising p in midtraining multiplies the tasks RL can learn from.

How is pass@k estimated from n samples?

Chen et al. draw n ≥ k samples per task, c of them correct, and average over tasks:

pass@k = Etasks [ 1 − C(n − c, k) / C(n, k) ]

where C(a, b) counts ways to choose b items from a. The fraction is the probability that k samples drawn without replacement from the n are all wrong, so one minus it is the chance that at least one is right. Chen et al. use this instead of 1 − (1 − p̂)k with p̂ = c/n, which they show is biased.

Three papers support the argument. Yue et al. compared RL-trained models with their bases on math, code and visual reasoning. RL won at k = 1, but the base models scored higher at large k, and the RL models' reasoning paths were already in the base models' sampling distribution. Gandhi et al. traced what the base needs to habits such as checking work and backtracking: under identical RL on the Countdown arithmetic game, Qwen-2.5-3B reached about 60% and Llama-3.2-3B about 30%, and continued pretraining on OpenWebMath filtered for those habits let Llama match Qwen's improvement. OctoThinker reached a similar result with midtraining on math data.

The labs give shorter reasons:

  • Xiaomi states the argument most directly (quoted below): agent midtraining "expands the exploration space" for RL.
  • DeepSeek gives a narrower aim, to "enhance the coding capabilities".
  • NVIDIA argues from placement: pretraining runs at short context and sees almost no agent interactions, while very long SFT can reduce what the model later gains from RL, so Nemotron 3.5 Super's agentic mid-training goes between them.

Where midtraining meets SFT

Midtraining used to mean more documents, and supervised fine-tuning (SFT) meant prompt-response pairs. The line is fading. GLM-4.5 already describes its midtraining data as medium-size, domain-specific and partly instruction data (chapter 00). Muse Glimmer feeds demonstrations from the same synthetic pipeline into midtraining Phase 2 and into SFT. MiMo-VL-7B, Xiaomi's vision-language model, lists "long-context Supervised Fine-Tuning (SFT)" as the fourth stage of its pre-training phase. What mostly separates the two is scale, since midtraining stages run hundreds of billions of tokens (500B in each of GLM-4.5's first two stages), yet MiMo-VL's "SFT" stage is 550B tokens, so even that line is blurring.

Worked example: GLM-5's issue-PR data in its midtraining budget

GLM-5 reports about 10 million issue-PR pairs and 160B unique tokens. Average sample: 160 × 109 / 107 = 16,000 tokens per pair, including its files and diffs.

Fit: GLM-5's first midtraining stage trains at 32K (32,768 tokens), so an average pair fills 16,000 / 32,768 = 0.49 of a sequence. GLM-5's own 4K pretraining window would hold only 4,096 / 16,000 = 26% of an average pair, which is why repository data arrives together with longer context.

Share: GLM-5's three midtraining stages total 1,000B + 500B + 50B = 1,550B tokens (1,572.8B with the two sparse-attention retrofit stages counted in ch00). One pass over the issue-PR data would be 160 / 1,550 = 10.3% of the three stages (160 / 1,572.8 = 10.2% of all midtraining), or 160 / 1,000 = 16% of the 32K stage. GLM-5 gives neither the epochs nor the stage that holds this data, so these shares are illustrative.

"an agent-centric mid-training phase that expands the exploration space for agentic tasks, enabling the model to discover more effective task-solving trajectories during post-training."

"we further enhance the coding capabilities of DeepSeek-V4 series by incorporating agentic data during the mid-training phase."

Trade-offs

  • Repository and issue-PR samples are long (about 16,000 tokens on average in GLM-5), so they need 32K-plus sequences and truncation-free packing (chapter 05).
  • Synthetic trajectories carry the generator's mistakes, including reward hacks; MiMo wrote correction data, and Meta drops trajectories with failed goals, hallucinations or false successes.
  • Narrow agent data can hurt general skills. AgentTuning found agent-only training worse on unseen tasks than a mix and settled on 20% agent data.
  • Benchmarks such as SWE-bench are built from GitHub issues and PRs, so issue-PR training data must be decontaminated against them (chapter 09).

Takeaways

  • Code data moved from single files to dependency-ordered repositories and then to issue-PR-commit bundles shaped like the SWE-bench task (GLM-5: about 10M pairs, 160B tokens).
  • Agent trajectories (reasoning, tool call, observation, repeated) entered midtraining in these notes with GLM-4.5 and now appear in GLM-5, DeepSeek V4, MiMo V2.6, Muse Glimmer, Step 3.5 Flash and Nemotron 3.5 Super; of these, only NVIDIA says whether tool output carries loss (it masks it).
  • RL mostly raises pass@1 within what the base already samples, so labs put the behaviors in first; the papers make that argument, and MiMo V2.6 states it as expanding the exploration space.
Check yourself: why does a task the base model never solves give GRPO nothing to learn from, and which metric measures whether the base "sometimes" solves it?

All attempts get the same reward, so the numerator ri − mean r is zero for every attempt; the advantage is taken as zero (or DAPO drops the group) and no gradient flows. pass@k at large k measures whether at least one of k samples succeeds, which is the pool RL can draw on.

Check yourself: GLM-5's issue-PR data is about 160B tokens in about 10M pairs. Would an average pair fit a 4K pretraining window?

No. The average pair is 16,000 tokens; a 4,096-token window holds about a quarter of it. All of GLM-5's midtraining stages run at 32K or longer, so whichever stage holds this data fits an average pair whole (GLM-4.5 made the same move, extending to 32K for repository code).

  1. Guo et al., DeepSeek-Coder: When the Large Language Model Meets Programming, 2024
  2. Z.ai, GLM-4.5 technical report, 2025
  3. Z.ai, GLM-5 technical report, 2026
  4. Z.ai, GLM-5.2 blog post
  5. Moonshot AI, Kimi K2.5 technical report, 2026
  6. Microsoft AI, MAI-Thinking-1 technical report, 2026
  7. DeepSeek-AI, DeepSeek-V4 technical report, 2026
  8. Xiaomi, MiMo-V2.6 technical report, 2026
  9. Meta, Muse Glimmer 30B: An On-Device Agentic Model, 2026
  10. Xiaomi, MiMo-VL technical report, 2025
  11. Jimenez et al., SWE-bench: Can Language Models Resolve Real-World GitHub Issues?, 2023
  12. Yao et al., ReAct: Synergizing Reasoning and Acting in Language Models, 2022
  13. Zeng et al., AgentTuning: Enabling Generalized Agent Abilities for LLMs, 2023
  14. Chen et al., Evaluating Large Language Models Trained on Code (pass@k), 2021
  15. Yue et al., Does Reinforcement Learning Really Incentivize Reasoning Capacity in LLMs Beyond the Base Model?, 2025
  16. Yu et al., DAPO: An Open-Source LLM Reinforcement Learning System at Scale, 2025
  17. Gandhi et al., Cognitive Behaviors that Enable Self-Improving Reasoners, 2025
  18. Wang et al., OctoThinker: Mid-training Incentivizes Reinforcement Learning Scaling, 2025

04 Stretching position encodings

A RoPE model trained on 4K-token sequences fails on a 128K-token input: which rotary dimensions break, and how do interpolation, a larger base, YaRN and position-free global layers each repair them?

What RoPE does to a query and a key

Rotary position embedding (RoPE; pretraining chapter 04 defines it) splits each query and key into pairs of numbers, treats each pair as an arrow in a plane, and turns pair i of the token at position m by the angle m·θi. In the dot product of a query at m and a key at n, position enters only through the difference (m − n)·θi, so attention sees how far apart the tokens are.

Each pair turns at its own speed θi, in radians per token; its wavelength λi counts the tokens per full turn. Fast pairs tell neighbouring tokens apart; slow pairs barely move over thousands of tokens. The speeds fall geometrically from a base b, counted over the dr rotated dimensions of a head's dh (many models rotate only part of the head; dr = dh when the whole head rotates):

θiradians per token = b−2i/dr,   λitokens per turn = 2π/θi = 2π·b2i/dr,   i = 0 … dr/2 − 1

A toy head with dr = 4 and b = 10,000 has two pairs: pair 0 turns 1 radian (57°) per token, a full turn every 6.3 tokens, and pair 1 turns 10,000−1/2 = 0.01 radian, a full turn every 628 tokens. A model trained at length L must later work at L′ = s·L. This chapter covers the position side; chapter 05 covers the data, stages and systems.

Why a model fails past its trained length

Train the toy head at L = 500. Pair 0 makes about 80 turns, so training shows it every angle; pair 1 reaches at most 5 radians (286°) and never completes a turn. At 2,000 tokens pair 1 reaches 20 radians, passing through angles from 286° to 360° that training never produced.

A real head splits the same way: fast pairs (λi ≪ L) have seen every angle, while slow pairs (λi > L) never finish a turn, so the network can read absolute position from them (the YaRN authors' argument) and past L they produce angles it never saw. LLaMA 7B, trained at 2,048 tokens, reached perplexity above 103 at 4,096 (Chen et al.), and fine-tuning at the new length alone grew its effective window only from 2,048 to 2,560 tokens in more than 10,000 batches.

So every fix must keep the slow pairs within the trained angles without blurring the fast ones. On the toy head stretched to 2,000 tokens (s = 4):

methodpair 0 (80 turns within L)pair 1 (0.8 turn within L)
position interpolation0.25 rad per token: neighbours 4× closer0.0025 rad per token, reaches 5 rad
base 10,000 → 160,0001 rad per token, unchanged0.0025 rad per token, reaches 5 rad
YaRN (α = 1, β = 32)over 32 turns: unchangedunder 1 turn: ÷ 4, reaches 5 rad
no position encodingno angles, so nothing leaves the trained range

Position interpolation: squeeze the positions

Position interpolation (PI; Chen et al., 2023) divides every position by s:

m ↦ m/s,   so for m < L′ the angle is m·θi/s < (L′/s)·θi = L·θi, an angle seen in training

Chen et al. extended the context of LLaMA models from 7B to 65B parameters within 1,000 steps, the 7B and 13B to 32,768 tokens. The cost falls on the fast pairs: neighbouring tokens are now only θi/s apart on every pair, which removes RoPE's high-frequency detail, and the YaRN authors report that PI fine-tunes degraded beyond roughly s = 8 (Chen et al. themselves report usable 7B and 13B models at s = 16). Gemma 3 still uses PI, from 32K to 128K with a factor of 8, twice the length ratio.

Raising the base: ABF and NTK-aware scaling

A larger base b′ leaves pair 0 alone (θ0 = 1 for any base) and stretches each pair more the slower it is:

λ′inew wavelength = 2π·b′2i/dr = λiold wavelength·(b′/b)2i/drstretch, 1 for pair 0

Meta's Llama 2 Long work (Xiong et al., 2023) called this adjusted base frequency (ABF). It raised b from 10,000 to 500,000 for 400B tokens of continued pretraining. Without it the model could not attend beyond 4,000 to 6,000 tokens; with it, ABF alone held up across a 32,768-token retrieval probe.

The "NTK-aware" rule, written up in the YaRN paper, picks b′ so that the slowest pair (i = dr/2 − 1) stretches exactly s times, as under PI:

b′(dr−2)/dr = s·b(dr−2)/dr  ⇒  b′ = b·sdr/(dr−2)

For the toy head that is 10,000 × 42 = 160,000; for dr = 128 and s = 32, b′ ≈ 338,000. Pair i is then stretched by λ′i/λi = s2i/(dr−2), less than s for every pair but the slowest. Middle pairs whose wavelength is a little above L can therefore still meet new angles: the rule leaves some dimensions "slightly extrapolated", so s must be set above the length ratio.

Worked example: which pairs finish a turn, at base 10,000 and 1,000,000

Take dr = dh = 128 (64 pairs; the whole head rotates), as in LLaMA 7B (4096/32 = 128). At any base λ0 = 2π ≈ 6.28 tokens. The slowest pair has λ63 = 2π·b126/128: 2π × 8,660 ≈ 54,400 at b = 10,000 and 2π × 805,800 ≈ 5,063,000 at b = 1,000,000. Pair i finishes less than one turn within L when λi > L, that is when i > (dr/2)·ln(L/2π)/ln b:

base bλ0λ63pairs with λi > 4,096pairs with λi > 131,072
10,0006.2854,41018 (i ≥ 46; 64 × 6.48/9.21 = 45.0)0 (64 × 9.95/9.21 = 69.1 > 63)
1,000,0006.285,063,25633 (i ≥ 31; 64 × 6.48/13.82 = 30.0)17 (i ≥ 47; 64 × 9.95/13.82 = 46.1)
  • Base 10,000. At 4K, 18 pairs (36 dimensions) see only part of a turn. The slowest sweeps 27° (4,096/54,410 of a turn), then 867° at 128K.
  • Base 1,000,000. The slowest pair sweeps only 9.3° over all of 128K, while pair 0 is untouched. Raising the base adds slow pairs (18 → 33 at 4K), but only the slowest few turn so little that a longer context adds small angles: pairs 59 to 63 sweep less than 27°, what the old slowest pair swept in 4K training, even over all of 128K. The other 28 slow pairs still meet angles at 128K they did not see at 4K (pairs 31 to 46 finish at least one turn); labs then train at the new length so the model adapts to them.

The 131,072 column counts pairs that still never finish a turn even when training at 128K. The setting is illustrative; GLM-4.5 made this base switch when moving from 4K to 32K.

YaRN: treat each pair by its wavelength

YaRN (Peng et al., 2023) decides per pair, by the number of turns ri = L/λi that pair i makes within L. Pairs that turn many times keep their frequency, so nearby tokens stay distinct; pairs that never finish a turn are interpolated as in PI; a ramp γ mixes the two in between:

γ(r) = 0 if r < α;   1 if r > β;   (r − α)/(β − α) otherwise      θ′i = (1 − γ(ri))·θi/sas in PI + γ(ri)·θiunchanged

For LLaMA, α = 1 and β = 32 worked well. YaRN also divides the logits by a temperature t, which the authors link to attention entropy rising with length. For one head's query qm ∈ ℝdh at position m and key kn ∈ ℝdh at n:

softmax over n of qm⊤kn / (t·√dh),     √(1/t) = 0.1·ln s + 1

The rule was fitted for lowest perplexity on LLaMA 7B to 65B. It multiplies every logit by (0.1 ln s + 1)2, 1.30 at s = 4. Scaling q and k by √(1/t) inside the rotary embedding applies it without touching attention code.

Code: YaRN's frequencies and the scaled rotary embedding
def yarn_frequencies(d_r, b, L, s, alpha=1.0, beta=32.0):
    i = arange(d_r // 2)              # pair index, fast first
    theta = b ** (-2 * i / d_r)       # [d_r/2] frequencies
    r = L * theta / (2 * pi)          # r_i = L / lambda_i
    gamma = clip((r - alpha) / (beta - alpha), 0, 1)   # paper's ramp
    theta_new = (1 - gamma) * theta / s + gamma * theta
    scale = 0.1 * log(s) + 1          # sqrt(1/t)
    return theta_new, scale

def rope_yarn(x, pos, theta_new, scale):
    # x: [n, d_r] rotated part of queries or keys; pos: [n] positions m
    ang = pos[:, None] * theta_new[None, :]   # [n, d_r/2]
    x1, x2 = x[:, 0::2], x[:, 1::2]
    out = empty_like(x)
    out[:, 0::2] = x1 * cos(ang) - x2 * sin(ang)
    out[:, 1::2] = x1 * sin(ang) + x2 * cos(ang)
    return scale * out                # q.k gains scale**2 = 1/t

DeepSeek-V3 applies YaRN only to its 64-dimension decoupled rotary key (MLA, pretraining chapter 03), as DeepSeek-V2 did, during two 1,000-step stages at 32K and 128K. Of its 32 pairs, 11 are unchanged, 12 sit on the ramp and 9 are stretched 40× (Figure 4.1). The released code multiplies every logit by (0.1 ln 40 + 1)2 ≈ 1.874, YaRN's 1/t. s = 40 over 4,096 positions covers 163,840, a margin over 128K.

YaRN on DeepSeek-V3's rotated key: wavelength of each of the 32 rotary pairs before and after YaRN, and the ramp functionDeepSeek-V3 decoupled key under YaRN: b = 10,000, d_r = 64 (32 pairs), L = 4,096, s = 40, α = 1, β = 32r > 32: unchanged (11 pairs)ramp: partly stretched (12)r < 1: θ ÷ 40 (9 pairs)101001K10K100K1Mwavelength λ in tokens (log scale)051015202531rotary pair i (fast → slow)L = 4,096: trained lengthL′ = s·L = 163,840: config max_position_embeddingsoriginal wavelengthunchangedstretchedunseen angles at L′ (none)ramp γ(r), r = L / λ01γ0.11101001000r: turns pair i makes within 4,096 tokensα = 1β = 32θ/sθ keptdots: the 32 pairs of the left panel
Figure 4.1. YaRN on DeepSeek-V3's rotated key, to scale. Left: the dashed line is each rotary pair's original wavelength; dots show it after YaRN, unchanged (green) or stretched (blue). None reaches angles unseen in training within L′ = 163,840 (peach in the demo after this chapter, which uses the same colour key). Right: the ramp γ(r) on a log axis, with the same pairs. The figure follows the paper's γ(r); DeepSeek's released code ramps linearly in the pair index between pairs 10 and 23, so it stretches the middle pairs less.

What the labs chose

Labs pick b′ by hand and none says how; the table's last column gives the NTK-aware rule for comparison. Their choices range from about the rule (Kimi-VL, MiMo-V2-Flash) to 16 times above it (MiMo-7B).

ModeldrLengthMethod and settingNTK-aware b′ (computed)
Gemma 3 (4B, 12B, 27B)not used by PI32K → 128KPI: factor 8; global-layer base 1M, local 10kn/a
GLM-4.564 of 1284K → 32K → 128Kbase raise at the 32K step: 10,000 → 1,000,00085,500 at the 32K step; 358,000 at 128K (chosen: 2.8×)
MiMo-7B128 (all)8,192 → 32,768base raise in stage 3: 10,000 → 640,00040,900 (chosen: 16×)
Kimi-VL648K → 32K → 128Kbase raise: 50,000 → 800,000875,000 (chosen: 0.9×)
MiMo-V2-Flash64 of 19232,768 → 262,144base raise, global layers only: 640,000 → 5,000,000; window layers keep 10,0005,475,000 (chosen: 0.9×)
GLM-5.264200K → 1Mbase raise (from configs; procedure not described): 1,000,000 (GLM-5) → 8,000,000n/a
DeepSeek-V364 (decoupled key)4K → 32K → 128KYaRN on the decoupled key: s = 40, α = 1, β = 32, b = 10,000n/a
gpt-oss64 (all)4,096 → 131,072YaRN on the dense layers: factor 32, b = 150,000n/a
Kimi K2.56432,768 → 262,144YaRN: factor 64 from 4,096, b = 50,000n/a

MiMo-7B and Kimi-VL call these stages the end of pretraining. These notes count them as midtraining (chapter 00): each is a distinct stage after the main decay that changes the context length (clause 2 of the rule), and Kimi-VL's also continues training an earlier base, an intermediate Moonlight checkpoint (clause 3). Gemma 3 also extends its context at the end of pre-training, but its report names no separate phase and gives no learning-rate schedule, so the rule counts the extension as pretraining, like DeepSeek V4's growth inside its run.

2025-26: global layers without RoPE

Each fix above retunes RoPE whenever the context grows. Several 2025-26 models avoid that: they drop position encoding (NoPE) from global layers and keep RoPE, if at all, where offsets stay short. A window layer never sees an offset beyond its window, and a NoPE layer has no angles at all. Two designs appear:

Llama 4 also adds temperature scaling at inference, its counterpart to YaRN's temperature. With its attn_temperature_tuning flag on (off by default), Meta's reference code scales a NoPE layer's query at position m:

qm ← qm·(1 + 0.1·ln(⌊(m + 1)/8,192⌋ + 1))

The factor is 1 while m + 1 < 8,192 and 1 + 0.1·ln 129 ≈ 1.49 at m + 1 = 1,048,576. The constants are the code's defaults, and the code cites Scalable-Softmax, which argues that softmax attention flattens as the number of keys grows. Llama 4's RoPE layers are still rescaled in one model: the code notes "Only Llama-4-Scout uses scaled rope", which divides the frequency of every pair with a wavelength above 8,192 tokens by 16.

Who uses it and why

"When extending the sequence length to 32K, we also adjusted RoPE’s base frequency from 10,000 to 1,000,000 for better long-context modeling ability."

"Second, it simplifies long-context training, as it obviates the need for RoPE parameter adjustments, such as frequency base tuning or methods like YaRN"

"Rotary position embeddings (RoPE) with θ [the base b] = 500,000 are applied exclusively to the local attention layers; the global layers rely on the accumulated positional signal from surrounding local layers, making the model extendable."

Trade-offs

  • PI makes nearby tokens harder to tell apart: at the original 2,048 tokens, Proof-pile perplexity rose by 0.01 to 0.05, and fine-tunes degraded past about s = 8 (YaRN authors).
  • Raising the base adds a hand-tuned number per stage; the labs' choices differ from the NTK-aware rule by up to 16×.
  • YaRN's settings were fitted on LLaMA, and a fixed s costs a little quality below L and fails abruptly past L′ (YaRN authors). DeepSeek-V2, whose YaRN settings V3 reuses, set a 160K target so the model would respond well at 128K.
  • In every model here, NoPE global layers were chosen before pretraining; none of these labs added them to an existing model. Attention over many more keys also flattens, which Llama 4 offsets at inference.
  • NoPE can have a hidden cost: Qwen kept partial RoPE in Qwen3.8-Flash-Next's global layers because a NoPE variant that differed little from RoPE in pretraining showed a much higher rate of endless generation after post-training.

Takeaways

  • RoPE breaks past the trained length because slow pairs, with wavelength above L, meet angles they never saw; fast pairs have seen every angle.
  • PI, a larger base and YaRN all slow the slow pairs. PI also slows the fast ones, a larger base barely does, and YaRN leaves them exactly alone and adds a logit temperature.
  • Llama 4, Kimi Linear, Kimi K3, MAI-Thinking-1 and Muse Glimmer drop position encoding from global layers, so those layers need no rescaling as context grows (Llama 4 Scout still rescales its RoPE layers); NVIDIA's Nemotron hybrids use none in any layer, while Qwen tried NoPE and kept RoPE.
Check yourself: why does position interpolation keep every angle inside the trained range, and what does it cost?

It rotates by m/s, so for m < L′ the angle mθi/s stays below Lθi. The cost: neighbouring tokens differ by only θi/s on every pair, including the fast pairs that carry local order.

Check yourself: with DeepSeek-V3's YaRN settings (L = 4,096, s = 40, α = 1, β = 32), what happens to pairs with wavelengths of 100 and 10,000 tokens?

The first turns r = 4,096/100 ≈ 41 times within L, more than β, so γ = 1: unchanged. The second turns r ≈ 0.41 times, fewer than α, so γ = 0: its frequency is divided by 40 and its wavelength becomes 400,000 tokens.

  1. Chen et al., Extending Context Window of Large Language Models via Positional Interpolation (2023)
  2. Xiong et al., Effective Long-Context Scaling of Foundation Models (ABF, 2023)
  3. Peng et al., YaRN: Efficient Context Window Extension of Large Language Models (2023; also covers NTK-aware scaling)
  4. Nakanishi, Scalable-Softmax Is Superior for Attention (2025)
  5. DeepSeek-AI, DeepSeek-V2 Technical Report (YaRN target length)
  6. DeepSeek-AI, DeepSeek-V3 Technical Report, config.json and modeling_deepseek.py
  7. Z.ai, GLM-4.5 Technical Report, GLM-4.5 config.json, GLM-5 config.json, GLM-5.2 config.json, GLM-5.2 blog
  8. Xiaomi, MiMo-7B Technical Report, MiMo-7B-Base config.json and MiMo-V2-Flash Technical Report
  9. Kimi Team, Kimi-VL Technical Report and config.json; Kimi K2.5 Technical Report and config.json
  10. Kimi Team, Kimi Linear Technical Report and Kimi K3 Technical Report
  11. Gemma Team, Gemma 3 Technical Report
  12. OpenAI, gpt-oss Model Card, config.json and reference model.py
  13. Meta, The Llama 4 herd (blog), reference model.py and args.py
  14. Meta, Muse Glimmer 30B technical report
  15. Microsoft AI, MAI-Thinking-1 Technical Report

Lab RoPE scaling playground

When a model trained at length L is stretched to L′, which rotary dimensions see angles they never saw in training, and what does each method do about it?

This demo goes with chapter 04. RoPE rotates each pair of query and key dimensions at its own frequency θi = b−2i/dr (dr: rotated dimensions per head), so pair i makes one full turn every λi = 2π/θi tokens. Each dot is one pair, placed at its wavelength after the method is applied; the dashed curve is the original wavelength, and the two horizontal lines mark L and L′. A pair whose wavelength is longer than L never completed a full turn in training, so at longer contexts it can reach angles the model has not seen. Pick a real model's settings or change them yourself. Three things to try:

  1. Choose the DeepSeek-V3 preset, set the method to "none" and count the orange pairs; then switch back to YaRN.
  2. Choose position interpolation with s = 32 and see how far even the fastest pair (pair 0) moves.
  3. Compare the NTK-aware change and YaRN at s = 8: find the middle pairs that still reach unseen angles under NTK.

Wavelength of each rotary dimension pair before and after scaling
unchanged stretched reaches angles not seen in training original wavelength

A pair counts as reaching unseen angles when, at L′, its angle can go further around the circle than it ever did within L in training. Every method here is followed by some training at the longer length; the demo shows the situation at the start of that training. YaRN uses α = 1 and β = 32 (the configs' beta_slow and beta_fast, in DeepSeek-V3 and gpt-oss) and the paper's ramp, which is linear in the number of turns L/λi; DeepSeek's released code ramps linearly over the dimension index between the same two end points, so the pairs in between differ slightly.

05 Long-context data, stages and systems

Why do labs reach 128K to 1M tokens of context in a few stages instead of training long from the start, and what data and parallelism does each long stage need?

Chapter 04 fixed the positions. Here a stage is a stretch of training at one sequence length L. A long stage raises three separate questions, taken in turn below: when and in how many steps the length grows (staging), what fills a sequence of 128K tokens or more (data), and how to train a sequence that outgrows one GPU (systems).

Staging: why grow the length in steps

Three pressures push long sequences late, and a fourth argues for small steps:

A late stage costs little quality. In Xiong et al.'s 7B runs, switching from 4K to 32K at 80% of training used 2.27 × 1022 FLOPs against 3.78 × 1022 for 32K throughout. The long-document QA scores were mixed: NarrativeQA unchanged at 18.5 and QuALITY 38.3 against 37.9, but Qasper 25.0 against 28.6 and QMSum 11.0 against 11.5; the authors summarize it as "almost no loss on performance". In MAI's ablations, 1T tokens at 32K then about 100B at 256K matched the code loss at 128K of a full 1T-token run at 128K, and most of the gain came within the first 1–10% of the extension.

Worked example: DeepSeek-V3's batches and attention cost from 4K to 128K

stageLsequences per batchtokens per steptokens
pretraining4,09615,3604,096 × 15,360 = 62,914,56014.8T
extension 132,7681,92032,768 × 1,920 = 62,914,5601,000 steps: 62.9B
extension 2131,072480131,072 × 480 = 62,914,5601,000 steps: 62.9B

From the table and the model's config:

  1. Tokens per step stay fixed at 62.9M while sequences per batch fall 32× (the token totals assume fully packed sequences, so they are upper bounds).
  2. Attention per step grows with L, not L2. One layer's attention costs 81,920·L2 FLOPs per sequence, 1.37 × 1012 at 4,096 and 1.41 × 1015 at 131,072: 1,024× per sequence. Per step, 15,360 × 1.37 × 1012 = 2.1 × 1016 against 480 × 1.41 × 1015 = 6.8 × 1017 is 32×, the length ratio.
  3. A 128K token costs about 4.8× a 4K token. The weights cost about 2 × 37B = 74 GFLOPs per token at any length (Kaplan et al.'s 2N); causal attention over 61 layers adds about 10 GFLOPs at 4K, 82 at 32K and 330 at 128K. So a 32K token costs 1.9× a 4K token, and the two equal-sized stages average (1.9 + 4.8)/2 ≈ 3.3×.

DeepSeek reports 180K GPU hours per trillion pretraining tokens and 119K for the roughly 126B extension tokens: 5.3× per token, above the FLOP estimate of 3.3×. DeepSeek gives no breakdown; lower utilization at long lengths would explain the gap.

Where 81,920·L2 and the per-token costs come from

Attention scores and the weighted sum of values cost 2·L2·(dqk + dv) FLOPs per head per sequence (forward, full matrix). With 128 heads, dqk = 192 and dv = 128, one layer costs 128 × 2 × 320·L2 = 81,920·L2. The causal mask keeps half the matrix, so per token one layer adds 40,960·L and 61 layers about 2.5 × 106·L.

Staging: how the schedules changed

The reports show three patterns (Figure 5.1 draws eight schedules to scale):

Training context length against training tokens for eight releases, to scaleContext length through training, to scale: x = training tokens, bar height ∝ log₂(length / 2K)bar height key:4K32K128K256K1Mpretrainingmidtraining (rule of these notes)inherited (Kimi K2)? size or place not givenextension stages after the main runDeepSeek-V34K (14.8T) → 32K (63B)→ 128K (63B)GLM-4.54K (22T) → 32K (1T)→ 128K (100B)GLM-54K (27T) → 32K (1T)→ 128K (500B) → 200K (50B)Kimi K2.54K (15T K2 + 15T vision-text)→ 32K (500B) → 256K (200B)MAI-Thinking-116K (30T) → 64K (3.4T)→ 256K (150B)MiMo-V2-Flash32K (26T) → 256K (1T)length grown inside one runDeepSeek V4-Prostarts at 4K; growth points not given?4K → 16K → 64K → 1M; ? = agenticmid-training of unstated sizeDeepSeek V4.1-Flash64K (34T) → 1M (11T)0T10T20T30T40T45Ttraining tokens (trillions), from the start of pretraining to the start of SFT
Figure 5.1. Context length through training, to scale: width is tokens, height grows with log2 of the length. Grey is pretraining and peach is midtraining under the rule of these notes; dashed outlines mark a phase inherited from Kimi K2 and DeepSeek V4's agentic mid-training phase, whose size and place are not given. DeepSeek-V3's two extension stages are under a pixel wide. Kimi K3 and MiMo V2.6 give no tokens per stage and are left out; GLM-5's 23B sparse-attention retrofit is omitted.

Data: what fills a long sequence

The reports give three answers to what a long sequence should hold:

Both GLM releases also add agent trajectories at long lengths (chapter 03).

Data: packing documents into sequences

Concatenating documents and cutting every L tokens splits any document that straddles a cut. Best-fit packing (Ding et al., 2024) avoids most cuts with the Best-Fit-Decreasing heuristic:

  1. cut documents longer than L into pieces of at most L;
  2. sort the pieces, longest first;
  3. put each piece into the sequence with the least room that still fits it, or into a new one;
  4. pad what is left.

Take L = 10 and documents of 6, 5, 4 and 3 tokens. Concatenate-and-cut gives [6 + 4 tokens of the 5] and [its last token + 4 + 3], splitting one document. Best-fit puts 6 and 5 in two sequences, then 4 into the first (the tightest fit) and 3 into the second: [6 + 4] and [5 + 3 + 2 padding], nothing cut.

Code: best-fit packing
def best_fit_pack(doc_lengths, L):
    chunks = []                    # 1. cut only docs longer than L
    for n in doc_lengths:
        while n > L:
            chunks.append(L); n -= L
        if n > 0:
            chunks.append(n)
    chunks.sort(reverse=True)      # 2. longest chunk first
    space, seqs = [], []           # free tokens per sequence
    for c in chunks:
        fits = [j for j, r in enumerate(space) if r >= c]
        if fits:                   # tightest sequence that fits
            j = min(fits, key=lambda j: space[j])
        else:                      # open a new sequence
            space.append(L); seqs.append([])
            j = len(space) - 1
        space[j] -= c
        seqs[j].append(c)
    return seqs                    # leftover space is padding
# Ding et al. find the tightest fit with a segment tree

GLM-4.5 skipped it in pretraining, where "random truncation is a good data-augmentation strategy", and used it in midtraining; DeepSeek V4.1-Flash reports a padding rate of at most 10−4. Packed documents can attend to each other unless the mask blocks it; DeepSeek-V3 packs but does "not incorporate cross-sample attention masking", and the other sources here do not say.

Systems: one sequence across many GPUs

At 256K to 1M tokens one sequence's activations outgrow a GPU, so context parallelism (CP) splits the sequence itself over P GPUs. Most of a layer treats each token alone and runs on each GPU's own tokens; attention is the exception, since every query needs keys and values held on other GPUs. Two designs move that data (Figure 5.2):

  • Ring attention (Liu et al., 2023) keeps the queries in place and sends key-value blocks around a ring of GPUs, overlapping transfer with compute, so sequences can be "up to device count times longer".
  • DeepSpeed-Ulysses (Jacobs et al., 2023) re-shards from tokens to heads with an all-to-all, so each GPU attends over the whole sequence for a subset of heads, and then shards back.

MAI-Thinking-1 used Ulysses-style CP only for long-context midtraining, adding ZeRO-3 (FSDP: parameters sharded and gathered just in time) for its 256K phase on 4,096 GB200 GPUs. Kimi K3 notes that softmax attention "requires ranks to exchange key–value blocks whose size grows with the sequence length", while its KDA layers (Kimi Delta Attention, linear attention with a fixed-size state; chapter 04) pass that state with one all-gather.

Two ways to split one long sequence over four GPUs: ring attention and Ulysses all-to-allRing attention: queries stay, key-value blocks travelKV1KV2KV3KV4GPU 1: Q1step 1GPU 2: Q2step 2step 1GPU 3: Q3step 3step 2step 1GPU 4: Q4step 4step 3step 2step 1grey: masked by the causal mask (key after query)GPU 1GPU 2GPU 3GPU 4each step: attend to the KV block in hand, send it onUlysses: all-to-all from token shards to head shardsprojections, MLP: GPU i has tokens Tih1h2h3h4T1T2T3T4attention: GPU j has heads hjh1h2h3h4T1T2T3T4all-to-allall-to-all backrows T1–T4: four quarters of one sequence;columns h1–h4: four groups of attention heads;colour: which GPU holds that blocktraffic per link per layer: 4Nh/P (N tokens, hidden size h, P GPUs),constant when N and P grow together; P cannot exceed the head count
Figure 5.2. Splitting one sequence over P = 4 GPUs (illustrative). Left: in ring attention GPU i keeps query block Qi while key-value blocks move one GPU per step. Right: Ulysses turns "a quarter of the tokens, all heads" into "all tokens, a quarter of the heads". Traffic formula from Jacobs et al.

How labs check long context

Who uses it and why

"Rather than training at the full 256K context length throughout pre-training or mid-training—which would be impractical due to the low MFU at long sequence lengths—we adopt a staged approach"

"Length alone, however, does not confer long-range capability."

"For datasets in mid-training, we applied best-fit packing to avoid truncating the reasoning process or repo-level code."

Trade-offs

  • A short final stage may leave long-range skills undertrained; GLM-5 found an extra 200K stage helped even at 128K, and Kimi K3 adds synthetic long-range tasks.
  • Upsampling long documents tilts the mix toward books, papers and long videos; MAI kept its mix and only re-packed it, "to minimize distribution shift".
  • Growing length inside the run spends far more tokens at long length (V4.1-Flash: 11T at 1M), which stays affordable only if long tokens are cheap; V4.1-Flash trains with sparse attention from scratch.
  • Training on MRCR-like data, as GLM-5 does, makes MRCR a weaker independent check of the result.

Takeaways

  • Length grows in stages because attention cost rises with L, long data is scarce and short-context quality must survive; ablations show a late extension matches training long throughout at much lower cost.
  • Through 2025 and in several 2026 releases the extension came after the main run (under 1% of tokens for DeepSeek-V3); DeepSeek V4, Kimi K3 and MiMo V2.6 grow length inside the run, and DeepSeek V4.1-Flash spends 11T tokens, a quarter of its run, at 1M.
  • A long stage needs long, untruncated documents (upsampled or re-packed), often synthetic tasks that force long-range attention, and context parallelism to spread one sequence over many GPUs.
Check yourself: DeepSeek-V3 kept 62.9M tokens per step from 4K to 128K. By how much did attention FLOPs per step grow, and why not 1,024×?

By 32×. Per sequence, attention grows with L2, 322 = 1,024×, but a fixed token budget holds 32× fewer sequences (15,360 → 480), so per step the growth is 1,024/32 = 32×, the length ratio.

Check yourself: why does best-fit packing cut fewer documents than concatenate-and-split, and when does it still cut one?

Concatenation cuts wherever a sequence boundary falls, splitting any document that straddles it. Best-fit packing cuts only documents longer than L, into pieces of at most L, and places whole pieces into the sequence with the least space that fits them; the small leftover gaps become padding.

  1. Xiong et al., Effective Long-Context Scaling of Foundation Models (2023)
  2. Ding et al., Fewer Truncations Improve Language Modeling (best-fit packing, 2024)
  3. Liu et al., Ring Attention with Blockwise Transformers for Near-Infinite Context (2023)
  4. Jacobs et al., DeepSpeed Ulysses: System Optimizations for Enabling Training of Extreme Long Sequence Transformer Models (2023)
  5. Hsieh et al., RULER: What's the Real Context Size of Your Long-Context Language Models? (2024)
  6. Vodrahalli et al., Michelangelo: Long Context Evaluations Beyond Haystacks via Latent Structure Queries (MRCR, 2024)
  7. Kaplan et al., Scaling Laws for Neural Language Models (2020)
  8. DeepSeek-AI, DeepSeek-V3 Technical Report and config.json; DeepSeek-V4 Technical Report; DeepSeek-V4.1-Flash Technical Report
  9. Z.ai, GLM-4.5 Technical Report and GLM-5 Technical Report
  10. Kimi Team, Kimi-VL Technical Report, Kimi K2.5 Technical Report and Kimi K3 Technical Report
  11. Microsoft AI, MAI-Thinking-1 Technical Report
  12. Xiaomi, MiMo-V2.6 Technical Report and MiMo-V2-Flash Technical Report
  13. Gemma Team, Gemma 3 Technical Report

06 Retrofitting architecture by continued training

How did DeepSeek and Z.ai give a trained dense-attention model sparse attention with at most 6.4% of its original pretraining tokens, and why did both train the new part alone first?

Why retrofit instead of retraining

Architecture ideas often arrive after a base model is finished, and retraining to adopt one repeats the whole run: 14.8T tokens for DeepSeek-V3, DeepSeek's 671B-total mixture-of-experts (MoE) model. A retrofit loads the trained weights, adds or changes a component, and keeps training until the network adapts. The labs call this continued pre-training; these notes count continued training that adds a new attention to an earlier base as midtraining (Chapter 00).

The sparse-attention retrofits in this chapter follow one sequence:

  1. Swap. Load the trained base and add the new part with fresh weights.
  2. Train the new part alone. Keep the old computation path, freeze the rest, and teach the new part to imitate what the trained model already does. This is short: 1,000 steps and 2 to 3 billion tokens. (GLM-5 does not say what it froze.)
  3. Train together. Switch the new path on and train all the weights so the network adapts to it. This is the long part: 20B to 944B tokens.
  4. Compare with the parent. Score both models on the same benchmarks, as bases or after identical post-training.

The main case is dense to sparse attention. Dense attention compares each query with every earlier token, so a sequence's attention cost grows with the square of its length. DeepSeek Sparse Attention (DSA), introduced in pretraining notes Chapter 03, lets each query read only a few thousand earlier tokens. The next sections walk DSA through the four steps; later ones show how other labs varied them.

The swap: what DSA adds to a trained layer

DSA leaves the trained attention weights in place and adds two things to every attention layer:

  • A lightning indexer, a small scorer with its own projections, gives every earlier token a score for the current query.
  • A top-k selector keeps the k highest-scoring tokens, and the existing multi-head latent attention (MLA, which caches one compressed latent per token) runs only over those.

With k = 2,048, a query at position 131,072, the end of a 128K sequence, has main attention read 2,048 latents instead of 131,072, one in 64; the indexer still scores all 131,072, at a much lower cost per pair. Up to position 2,048, top-2048 keeps every token, so selection only matters deeper into a sequence.

The indexer's score for query position t and earlier key position j sums over HI indexer heads g. Each head matches a query vector computed from the query's hidden state xt against a key vector computed from xj, and a weight, also computed from xt, scales the match:

It,j = ∑g=1…HI wIt,ghead weight · ReLU(qIt,g · kIjquery–key match),    qIt,g, kIj ∈ ℝdI,   wIt,g ∈ ℝ

DeepSeek-V3.2-Exp uses HI = 64, dI = 128 and k = 2048; GLM-5 uses 32 heads of 128. Per query–key pair the V3.2-Exp indexer does 64 × 128 = 8,192 multiply-adds in FP8, a ninth of the 73,728 that MLA spends scoring the same pair.

Where do MLA's 73,728 multiply-adds per pair come from?

DSA runs MLA in its weight-absorbed form, which DeepSeek calls the MQA mode: the key up-projection is folded into the query, so each of the 128 heads compares its query with the shared latent plus the rotary key, 512 + 64 = 576 dimensions, 128 × 576 = 73,728 multiply-adds before reading values. V3.1-Terminus trained in the expanded form, with 192-dimensional query–key heads (128 + 64) and 128-dimensional values; that is the form Chapter 05 counts. Both compute the same attention.

One fact shapes the rest of the recipe: top-k is a discrete choice. The language-modeling (LM) loss flows through attention over the selected tokens, but no gradient flows back through which tokens were selected. The indexer needs a loss of its own. Figure 6.1 shows the layer before and after the swap, and what trains in each of the two stages that follow.

Attention path before and after the DSA retrofit, and the two training stagesBEFORE: V3.1-TERMINUS, DENSE MLAhidden state xtMLA core attentionreads all t earlier latentsoutput utattention work per query grows with tAFTER: V3.2-EXP, DSA ADDED BY CONTINUED TRAININGhidden state xtinput detachedLightning indexer (new)64 heads × d_I 128, ReLU, FP8scores I_t,:Top-k selector, k = 2048indicesMLA core attentionreads only the k selected latentsoutput utKL target p_t from main attention(stage 1: all tokens; stage 2: selected set)per query: k latents read; the indexer scans all tStage 1 · dense warm-up (midtraining)attention stays dense; all weights frozen except the indexersindexers learn the KL loss toward dense attentionV3.2-Exp: 2.1B tokens, LR 1e-3Stage 2 · sparse training (midtraining)top-k on; main model trains on the LM loss onlyindexers keep the KL loss on the selected set S_tV3.2-Exp: 943.7B tokens, LR 7.3e-6, k = 2048
Figure 6.1. Before and after the DSA retrofit. Left: V3.1-Terminus reads every earlier latent. Right: V3.2-Exp adds a lightning indexer whose top-k choice decides which latents MLA reads; the dashed arrow is the training target, not a forward path. Bottom: what trains in each stage; both stages are midtraining (peach), with the warm-up dashed. Indexer sizes from the V3.2-Exp config.

The indexer's target: dense attention

A trained dense model already knows which tokens matter: its attention weights. For query t, DeepSeek sums the main attention weights at,h,j over heads h and normalizes over j. Each head's weights sum to 1, so the sum is H, the number of main heads, and the target is the head average. A Kullback–Leibler (KL) divergence pulls the softmax of the index scores toward it:

pt,j = (1/H) ∑h at,h,jtarget: head-averaged dense attention    qt,j = softmaxj(It,:)the indexer's distribution
ℒI = ∑t DKL(pt,: ‖ qt,:) = ∑t ∑j≤t pt,j log(pt,j / qt,j)

The loss is zero when the indexer's distribution matches the dense attention. Since top-k keeps the highest scores, an indexer trained this way keeps the tokens dense attention weighted most.

Shapes, and the gradient the indexer receives
per layer, for a sequence of L tokens: a ∈ ℝH×L×L;   p, I, q ∈ ℝL×L (causal, j ≤ t);    ∂ℒI/∂It,j = qt,j − pt,j

The gradient is the usual softmax cross-entropy result, since p does not depend on the indexer: a score rises where dense attention puts more mass than the indexer does and falls where it puts less.

Training alone: the dense warm-up (stage 1)

The first stage keeps dense attention and freezes every parameter except the indexers, so the model's outputs do not change while the indexers learn ℒI from attention the model already computes. DeepSeek started from the DeepSeek-V3.1-Terminus base, already extended to 128K, and trained the indexers at learning rate 10−3 for 1,000 steps of 16 sequences of 128K tokens, 2.1B tokens.

DeepSeek gives the stage's purpose only as "to initialize the lightning indexer". Arithmetic shows what skipping it would mean. A new indexer ranks tokens almost at random, and if k of t earlier tokens are picked at random, each is kept with probability k/t, so the expected attention mass kept is k/t whatever the attention pattern: 2,048 / 131,072 = 1.6% at the end of a 128K sequence. The LM loss would then have to adapt the whole network to near-random selections.

Z.ai measured how far a warm-up alone gets. GLM-4.7-Flash, a 30B-total MLA model, scores 79.21 on RULER at 128K with dense attention. Switching to sparse attention after only a 1,000-step indexer warm-up gives 71.35, with shorter contexts "virtually unaffected", and 150B tokens of joint training recover 78.86. That recovery is the next stage's job.

Training together: sparse training (stage 2)

Then selection turns on and every parameter trains, with two losses on disjoint parameters:

  • The main model trains on the LM loss alone.
  • The indexer keeps ℒI, now restricted to the selected set St, which is all the main attention still scores. Its input is detached from the graph, so ℒI never reaches the main model.

This stage takes nearly all the tokens. DeepSeek used learning rate 7.3 × 10−6 and 15,000 steps of 480 sequences of 128K tokens, 943.7B tokens, on the data distribution of V3.1-Terminus's 128K extension. That learning rate is the one DeepSeek-V3 ended pretraining with (Chapter 08).

Compared with its parent after identical post-training, V3.2-Exp matched V3.1-Terminus on MMLU-Pro (85.0), scored 67.8 vs 68.4 on SWE-bench Verified, and scored four points higher on the independent AA-LCR long-context test in reasoning mode.

The two stages in code
def indexer_kl(attn, scores):
    # attn:   [H, L, n] main attention weights over n candidates (n = L dense, k sparse)
    # scores: [L, n]    index scores I for the same candidates (masked entries = -inf)
    p = attn.mean(0)                          # [L, n] head average = normalized head sum
    q = softmax(scores, dim=-1)               # [L, n] indexer distribution
    return (xlogy(p, p) - xlogy(p, q)).sum()  # sum over t of KL(p_t || q_t)

# Stage 1, dense warm-up (V3.2-Exp: 1,000 steps x 16 sequences x 128K, LR 1e-3)
freeze(all_params_except_indexers)
for batch in data_128k:
    out = model(batch, sparse=False)          # dense attention: outputs unchanged
    loss = sum(indexer_kl(l.attn.detach(), l.scores) for l in out.layers)
    loss.backward(); opt.step()

# Stage 2, sparse training (15,000 steps x 480 sequences x 128K, LR 7.3e-6)
unfreeze(all_params)
for batch in data_128k:
    out = model(batch, sparse=True, k=2048)   # per layer: idx = topk(scores, k)
    loss_lm = cross_entropy(out.logits, batch.targets)   # reaches main model only
    loss_i = sum(indexer_kl(l.attn.detach(), l.scores.gather(-1, l.idx))
                 for l in out.layers)          # reaches indexers only (input detached)
    (loss_lm + loss_i).backward(); opt.step()

GLM-5 and Qwen: the same steps, other lengths

GLM-5, Z.ai's 744B-total MoE, pretrained with MLA on 27T tokens and mid-trained up to 200K context. Its DSA training "begins from the base model at the end of mid-training":

  • Training alone. The warm-up ran 1,000 steps of 14 sequences of 202,752 tokens, the learning rate falling from 5 × 10−3 to 2 × 10−4.
  • Training together. Sparse adaptation reused mid-training's data and hyperparameters for 20B tokens at a constant 1 × 10−5, where mid-training's linear decay ended.
  • Comparing with the parent. Z.ai found this "enough to adapt the DSA model to match the performance of the original MLA model": at 128K the DSA base scored 86.0 vs 79.7 on SQuAD but 63.0 vs 66.3 on HotpotQA, and after the same SFT the two models "tie in training loss and evaluation benchmarks".

GLM-5's sparse stage is 47 times smaller than DeepSeek's, and neither lab explains the difference. Qwen ran the same two stages for Qwen3.8-Flash-Next (Aug 2026), a Gated DeltaNet hybrid with one full-attention layer in every four, to replace that full attention with Qwen Sparse Attention (QSA) during continued pretraining at 256K:

  • Training alone. At first only the indexer trained, learning the dense attention by KL for 1,000 steps at η = 10−3 (about 2B tokens).
  • Training together. Backbone and indexer then trained together for 8,000 steps at 2.5 × 10−5, about 200B tokens, between GLM-5's 20B and DeepSeek's 943.7B.

One indexer for four layers: GLM-5.2 IndexShare

The indexer still scores every earlier token, so its own cost grows with the context. For GLM-5.2's 1M context, Z.ai shares it: "every 4 transformer layers share a lightweight indexer", which sits in the first of the four, and the next three reuse its top-k indices. The released config gives 21 of 78 layers their own indexer, not 78 / 4 ≈ 20: the first two layers keep their own, and the other 76 form 19 groups of four, each led by one indexer, so 2 + 19 = 21. GLM-5.2 "is trained with IndexShare from mid-training with 128K sequence length"; the blog gives no token count, does not name the pretrained base, and does not say how the shared indexers were initialized.

The model card links Z.ai's IndexCache paper for IndexShare. Its training-aware variant trains each shared indexer to pick tokens that suit every layer reusing its choice: it distills the indexer of layer ℓ against itself and the m layers ℓ+1 … ℓ+m that reuse its indices, ℒ = (1/(m+1)) ∑ℓ′=ℓ…ℓ+m ∑t DKL(p(ℓ′)t ‖ q(ℓ)t), which has the same gradient as one KL toward the average of their attention distributions. The blog does not say whether GLM-5.2 used this loss.

Other retrofits

The same steps recur when labs swap other parts:

  • Cheaper attention, tested small. On GLM-9B, Z.ai tried cheaper swaps (sliding-window layers, Gated DeltaNet linear attention, and SimpleGDN, which reuses the pretrained query, key and value weights), each continued for 190B tokens with half the layers kept at full attention. All lost between 5.69 and 30.35 points on RULER at 128K.
  • Cheaper attention at full scale. Ant's Ring-linear-2.0 (Sep 2025) converted Ling 2.0 bases to hybrid linear attention and continued them for 600B and 1T tokens. Ling 2.5 and 2.6 (Feb and Apr 2026) then turned the 20T-token Ling-2.0-1T into a 7:1 mix of Lightning linear-attention and MLA layers rather than retrain it (Ant's reason is quoted below). Ling 2.6's migration ran swap and warm-up twice in about 400B tokens (convert to Lightning, warm up the linear layers, convert the remaining layers to MLA, warm up MLA), followed by 8T tokens of continued pretraining, where switching straight to new high-quality data beat first replaying 2T tokens of the original corpus.
  • A new objective. Muse Glimmer, Meta's ~29.6B dense on-device model, was pretrained on Muse Spark's top-256 logits with a KL-only loss for 95% of pretraining and cross-entropy for the rest. Mid-training starts from an averaged ("souped") checkpoint, the mean of the last four (Chapter 01), and Phase 2 uses cross-entropy for the reason quoted below. The report gives no token counts and does not state Phase 1's loss.
  • A larger model's outputs. NVIDIA built both Nemotron 3.5 bases by continuing an existing Nemotron 3 base: each first trains a new MTP head for 100B tokens with the backbone frozen, much as the warm-ups above train the new indexer alone, and then trains the whole model for 1T tokens on the logits of the next larger Nemotron 3 base (Ultra for Super, Super for Lightning). Mistral's Ministral 3 models come from pruning Mistral Small 3.1 step by step and distilling each smaller model from it for 1 to 3T tokens, which Mistral calls pretraining and clause (3) counts as midtraining.

Later models made the switch earlier. DeepSeek moved it into pretraining: DeepSeek-V4-Flash used dense attention for its first 1T tokens, then warmed up the indexer and went sparse, and DeepSeek-V4.1-Flash trained sparse attention from scratch. Figure 6.2 puts the three DSA retrofits on one token axis, to scale.

Token budgets of the DSA retrofits, drawn to scaleDeepSeek-V3.2-Expsparse training 943.7B · all parameters · LR 7.3e-6 · k = 2048dense warm-up 2.1B (indexers only, LR 1e-3)GLM-4.7-Flash (test)joint training 150B after a 1,000-step indexer warm-up (warm-up tokens not stated)GLM-5warm-up 2.84B (LR 5e-3 → 2e-4) + sparse adaptation 20B (LR 1e-5)0250B500B750B1,000Bcontinued-training tokens, drawn to scaleoff scale: V3 pretraining 14,800B; GLM-5 pretraining 27,000B
Figure 6.2. Continued-training tokens of the DSA retrofits on one axis, to scale; all are midtraining (peach), warm-ups dashed. The warm-ups (2.1B and 2.84B) are slivers at the left edge; GLM-5's whole retrofit is 22.84B. For comparison the original pretraining runs would be 14.8 and 27 axis widths long.

Worked example: what the retrofits cost in tokens

Figure 6.2 draws these budgets. DeepSeek-V3.2-Exp: warm-up 1,000 × 16 × 131,072 = 2.10B; sparse stage 15,000 × 480 × 131,072 = 943.7B; total 945.8B. Against V3's 14.8T pretraining tokens: 945.8 / 14,800 = 6.4%. Against the 630B + 209B = 839B of V3.1's context extension that the base inherits: 945.8 / 839 = 1.13.

GLM-5: warm-up 1,000 × 14 × 202,752 = 2.84B; sparse stage 20B; total 22.84B. Against 27T: 22.84 / 27,000 = 0.085%.

Per step, DeepSeek's warm-up used 16 × 131,072 = 2.1M tokens and its sparse stage 480 × 131,072 = 62.9M, a 30× larger batch. The sparse stages differ by 943.7 / 20 = 47×.

Token shares understate compute: DeepSeek's retrofit tokens and GLM-5's warm-up tokens run at 131,072 or 202,752 context, where the indexer and dense attention cost more per token than at the 4K both models started pretraining with.

Who uses it and why

"What makes DSA particularly interesting from a researcher’s perspective is how it was introduced via Continued Pre-Training from a dense base model. This avoided the “astronomical” cost of training from scratch."

"For the consideration of continued training from DeepSeek-V3.1-Terminus, we instantiate DSA based on MLA (DeepSeek-AI, 2024) for DeepSeek-V3.2-Exp."

"For this phase we have used a cross-entropy loss, as the distributional shift introduced by long-context and agentic data makes teacher logits less reliable at this stage."

"training a trillion-parameter replacement from scratch discards the 20T-token investment in Ling-2.0-1T."

Trade-offs

  • A retrofit inherits the parent's design: DeepSeek built DSA on MLA because the base used MLA.
  • The indexer keeps a quadratic scan; GLM-5 reports DSA cuts long-sequence attention computation by "roughly 1.5-2×", and GLM-5.2 added IndexShare to cut the indexer's cost at 1M.
  • Parity is close, not exact: GLM-5's DSA base lost 3.3 points on HotpotQA at 128K.
  • The new part adds failure modes later: in RL, GLM-5 freezes the indexer by default "to accelerate training and prevent unstable learning in the indexer".

Takeaways

  • Top-k selection passes no gradient to the indexer, so DSA retrofits train it with its own KL loss toward the dense model's head-averaged attention.
  • DeepSeek, Z.ai and Qwen all first warm up the indexer with dense attention on (2.1B, 2.84B or about 2B tokens), then switch selection on and train everything (DeepSeek and Qwen state that only the indexer trained during warm-up; GLM states it only for its GLM-4.7-Flash test); a random indexer would keep only k/t of the attention mass.
  • The retrofit cost 6.4% of V3's pretraining tokens and 0.085% of GLM-5's; later models made such changes earlier, with GLM-5.2 training IndexShare from the start of mid-training and DeepSeek-V4 going sparse inside pretraining.
Check yourself: why can't the LM loss train the lightning indexer during sparse training?

The indexer's scores affect the output only through which tokens top-k selects, a discrete choice that passes no gradient. The indexer instead trains on its own KL loss toward the main attention over the selected set, with its input detached so that loss does not reach the main model.

Check yourself: a query sits at position 65,536 of a 128K training sequence. If its 2,048 tokens were picked at random, what share of its dense attention mass would main attention see, and how does the warm-up avoid this?

Each token is kept with probability 2,048 / 65,536, so about 3.1% of the mass. The dense warm-up first trains the indexer, with everything else frozen, to match the head-averaged dense attention, so selection keeps the high-mass tokens from the first sparse step.

  1. DeepSeek-AI. DeepSeek-V3.2-Exp: Boosting Long-Context Efficiency with DeepSeek Sparse Attention (2025), §1-2.
  2. DeepSeek-AI. DeepSeek-V3.2 technical report (2025), §2.1-2.2.
  3. DeepSeek-AI. DeepSeek-V3 Technical Report (2024), §4.
  4. DeepSeek-AI. DeepSeek-V3.1 model card; DeepSeek-V3.2-Exp config.json.
  5. DeepSeek-AI. DeepSeek-V4 technical report (2026), §4.2.2; DeepSeek-V4.1-Flash technical report (2026), §4.2.2.
  6. Z.ai. GLM-5 technical report (2026), §2.1.1-2.1.2, §3.2, App. A; GLM-4.7-Flash model card.
  7. Z.ai. GLM-5.2 blog, model card and config.json (2026).
  8. Bai et al. IndexCache: Accelerating Sparse Attention via Cross-Layer Index Reuse (2026), §3.2.
  9. Meta. Muse Glimmer: a 30B on-device agentic model (2026), §4.2.

07 Adding vision and audio to a language model

When a lab adds images and audio to a text model it has already trained, which parts does it train in which order, how many tokens does each stage take, and how does it check that the text skills survive?

Three parts and one risk

A vision-language model joins three parts:

  • Encoder. A vision encoder, usually a ViT (a transformer over image patches), turns an image into feature vectors.
  • Projector. Usually a two-layer MLP, it maps each feature vector to the language model's width d.
  • Language model. The LM reads the projected vectors as soft tokens beside text.

Patches and token counts are in pretraining notes, ch 07; this chapter covers the stages that join the parts to an existing LM. Those stages all train on next-token loss over the text, so what tells them apart is which parts receive gradients and which stay frozen.

The risk sits in the projector. A new projector emits vectors the LM has never seen, and if the LM trains then, the updates land on weights that took trillions of tokens to learn. LLaVA (2023) set the order that avoids this: stage 1 trains only the projection on 595K image-caption pairs with encoder and LM frozen, "a compatible visual tokenizer for the frozen LLM"; stage 2 also updates the LM. Later labs grew this into a procedure of up to five stages:

  1. Pretrain the encoder beside a small stand-in LM; the production LM is not attached.
  2. Warm up the projector with encoder and LM frozen.
  3. Align encoder and projector with the LM still frozen.
  4. Train everything jointly, with text-only data mixed in.
  5. Train everything at long context.
The stages in symbols

With encoder weights ψ, projector weights φ and LM weights W:

Hv = Pφ(Eψ(Xv)),   Eψ(Xv) ∈ ℝNp×dv,   Hv ∈ ℝN×d
J(S) = −∑i ∈ text log pW(xi | Hv, x<i),   gradients reach only the trainable set S ⊆ {ψ, φ, W}

Xv is the image, Np its patch count, N the soft tokens the LM reads (Np/4 after a 2×2 merge such as Kimi-VL's pixel shuffle), dv the encoder width. J is next-token loss on text positions. A stage is defined by which weights are in S: {φ} in stage 1, {ψ, φ} in stage 2, all three in stages 3 and 4.

Labs skip or merge stages. Figure 7.1 shows which part trains in each stage and which releases report it.

What each stage trains STAGE ENCODER PROJECTOR LANGUAGE MODEL EXAMPLES 0 · Encoder pretraining against a small stand-in LM trained — not attached Kimi-VL: 2T, contrastive + caption loss K2.5: about 1T against Moonlight-16B-A3B DeepSeek-ViT: 47B pairs, then 236B tokens 1 · Projector warm-up encoder and LM frozen frozen trained frozen LLaVA stage 1: 595K image-caption pairs MiMo-VL S1: 300B tokens, η = 1e-3 K2.5: "very short", projector only 2 · Encoder + projector alignment, LM frozen trained trained frozen Kimi-VL: 0.1T MiMo-VL S2: 167B tokens, interleaved data 3 · Joint training all parts, text mixed in trained trained trained Kimi-VL: 1.4T, then 0.6T joint cooldown MiMo-VL S3: 1.4T, η = 1e-5 · K2.5: 15T MiMo-V2.6 omni stage: Pro 3T, Flash 22T 4 · Long-context joint longer sequences, all parts trained trained trained Kimi-VL: 0.3T, 8K → 128K MiMo-VL S4: 550B tokens at 32K K2.5: 500B → 200B tokens, 32K → 256K NATIVE VARIANT · DEEPSEEK V4.1-FLASH, IMAGES FROM THE FIRST TOKEN 0 → 28T pretraining, constant η frozen* trained trained *its final normalization layer still trains corpus: 7:1 text-only to multimodal tokens 28T → 45T decay stage + 1M extension trained trained trained encoder at a smaller η than the LM counted as midtraining in these notes (17T) trained (receives gradients) frozen not part of this stage
Figure 7.1. Which parts receive gradients in each stage (colour marks trained parts, not stage type). Kimi-VL skips row 1, K2.5 row 2; GLM-V and MiMo-V2.5 do not say what is frozen.

Stage 0: train the encoder against a small LM

Kimi, DeepSeek and Xiaomi first train the encoder beside a small stand-in LM. Kimi-VL turned SigLIP-SO-400M (a contrastively trained image encoder) into its 400M MoonViT over 2T tokens; K2.5 trained MoonViT-3D for about 1T tokens against Moonlight-16B-A3B "with very few training FLOPs". DeepSeek's ViT saw about 47B image-text pairs, then 236B tokens through a 4B mixture-of-experts (MoE) LM that is then discarded. MiMo-ViT trained on more than 4T image tokens beside a small LM. These tokens never reach the production LM, so midtraining token counts leave them out.

Stages 1-2: align the projector, then the encoder, while the LM is frozen

MiMo-VL-7B (Xiaomi, on MiMo-7B-Base) runs both steps in full:

  • Stage 1 freezes the Qwen2.5-ViT and the LM and trains only the randomly initialized projector on captions: 300B tokens at learning rate η = 1e-3.
  • Stage 2 unfreezes the ViT and trains it with the projector, adding interleaved image-text pages to the captions, for 167B tokens, LM still frozen.

Other labs shorten or drop these steps:

  • Qwen3-Omni (Sep 2025) dropped stage 2: it no longer trains encoder and adapter jointly on a frozen LLM, because the encoder may then compensate for the frozen LLM's limits and perceive worse, and trains each adapter before its encoder instead.
  • Kimi-VL has no projector-only stage and uses one 0.1T stage that updates only MoonViT and the projector.
  • K2.5 uses a "very short" projector-only stage to bridge to its 1T-parameter LM.
  • MiMo-V2.5 (Xiaomi's April 2026 310B omni model, built on the text-only MiMo-V2-Flash backbone, with a 729M ViT and a 261M audio encoder) describes only a short-duration warm-up of its projectors.

Stage 3: joint training on mixed data

Then all parts train together, and text-only data stays in the mix. Three releases show the earlier size of this stage, 1.4T to 2T tokens:

  • Kimi-VL loaded Moonlight (Moonshot's 16B-total MoE) after 5.2T text tokens, before its cooldown, and trained 1.4T more tokens, starting text-only and raising the multimodal share to at most 40%, then a 0.6T joint cooldown.
  • MiMo-VL's stage 3 trains everything for 1.4T tokens at η = 1e-5, a hundredth of stage 1's rate, keeping "a limited amount of text-only data".
  • GLM-V (GLM-4.1V-Thinking on GLM-4-9B-0414; GLM-4.5V and 4.6V on the 106B GLM-4.5-Air) runs 120,000 steps × 1,536 × 8,192, at most 1.51T tokens, without saying which parts train.

These stages have grown to pretraining size. K2.5 continues "from a near-end Kimi K2 checkpoint over additional 15T vision-text tokens at 4K sequence length". MiMo-V2.6 (September 2026, a 310B Flash and a 1.02T Pro; whether Flash reuses V2.5's base is not stated) trains its backbone on text, then attaches its ViT and audio encoder and trains "the full model on omni-modal data": 3T tokens for Pro, 22T for Flash. Both labs call this pre-training; the rule of chapter 00 counts continued training of an earlier base as midtraining. DeepSeek's V4-Flash-Vision-Exp card says only that visual modules were added to V4-Flash before continued training.

Stage 4: long multimodal context

The last stage extends the context with all parts training:

  • Kimi-VL goes 8K → 32K → 128K over 0.3T tokens, raises the RoPE base b from 50,000 to 800,000, and mixes 25% long data with 75% replay of shorter data so the model can "learn long-context understanding while maintaining short-context ability".
  • MiMo-VL's stage 4 runs 550B tokens at 32K and raises η to 2.5e-5 because "long-context packing significantly increases the effective batch size".
  • K2.5 extends from 32K to 262,144 with YaRN, a RoPE rescaling (chapter 04, chapter 05).
MiMo-VL-7B's four stages in code
STAGES = [  # MiMo-VL-7B, Table 1: (name, trainable parts, tokens, seq_len, lr)
    ("S1 projector warm-up", {"projector"},               300e9,  8192,  1e-3),
    ("S2 ViT + projector",   {"vit", "projector"},        167e9,  8192,  1e-4),  # table: "1e-4, 1e-5"
    ("S3 all parameters",    {"vit", "projector", "llm"}, 1.4e12, 8192,  1e-5),
    ("S4 long context",      {"vit", "projector", "llm"}, 550e9,  32768, 2.5e-5),
]

def run(model, data):
    for name, trainable, tokens, seq_len, lr in STAGES:
        for part in ("vit", "projector", "llm"):
            getattr(model, part).requires_grad_(part in trainable)  # frozen: no gradient
        opt = make_optimizer([p for p in model.parameters() if p.requires_grad], lr)
        seen = 0
        while seen < tokens:
            batch = data.sample(stage=name, seq_len=seq_len)      # mix changes per stage
            h_img = model.projector(model.vit(batch.images))      # (N, d) soft tokens
            loss = model.llm.next_token_loss(batch.text, h_img)   # loss on text positions
            loss.backward(); opt.step(); opt.zero_grad()
            seen += batch.num_tokens

Early or late, and how much vision

For K2.5, Kimi tested timing at a fixed vision-text budget: vision from 0% of training at 10:90 vision:text, from 50% at 20:80, or from 80% at 50:50. Early fusion scored best on text knowledge (45.5 against 43.9 and 43.1); with later injection, text scores dipped when vision arrived, then recovered (table in pretraining notes, ch 07). Starting from a near-end K2 checkpoint ruled out vision from 0%, so K2.5 took the other half of the lesson: a constant, moderate ratio (not given) from the start of its joint stage, rather than "aggressive vision-heavy training concentrated at the end". That stage begins after about 15T text-only tokens, so over K2 plus K2.5 vision arrives about halfway.

DeepSeek V4.1-Flash, a 552B-backbone MoE, has images in its data from the first of 45T tokens, at a 7:1 text-only to multimodal ratio. The encoder stays frozen (its final norm layer and the projector train) until the learning-rate decay stage at 28T, then trains with the LM "with a smaller learning rate". The stage rule counts that decay stage as midtraining. DeepSeek gives no reason for the timing.

Figure 7.2 puts these schedules on one axis: the tokens that pass through the LM before and during the multimodal stages.

Multimodal token budgets to scale TOKENS THROUGH THE LANGUAGE MODEL, TO SCALE (12 PX = 1T) Kimi-VL 5.2T text (Moonlight checkpoint) + 2.4T in four stages through the LM MiMo-VL-7B 25T text (MiMo-7B-Base) + 2.4T in four stages Kimi K2.5 15T text (K2) + 15T joint + 0.5T + 0.2T long-context MiMo-V2.6-Pro ? 27T text + 3T omni + agentic mid-training (?: size not given) MiMo-V2.6-Flash ? 26T text + 22T omni + agentic mid-training (?) DeepSeek V4.1-Flash 45T, images in 1/8 of tokens from the start; from 28T: decay + 1M extension, encoder unfrozen 0 10T 20T 30T 40T 48T pretraining (inherited or own) midtraining midtraining of unstated size
Figure 7.2. Tokens through the LM, to scale, coloured by stage as in the legend. Encoder-only stages and GLM-V (base size not restated) are left out. K2.5's bar is 15.7T (the report's own totals differ). MiMo-7B-Base is drawn at its stated 25T (chapter 00 uses the 23.8T its schedule sums to).

Checking that text survives

Most labs report this in words. MiMo-VL says its models "maintain decent performance on text-only benchmarks" against MiMo-7B but prints no MiMo-7B column; GLM-V trains on pure text "to preserve its language capabilities" and shows no comparison. Two releases give numbers: K2.5's ablation, and the V4-Flash-Vision-Exp card, which beats V4-Flash-0731 on 6 of 7 text-agent benchmarks and trails on Cybergym, 75.3 to 76.7. Both models are post-trained, so this does not isolate the vision stage.

Worked example: how big is the multimodal part of MiMo-V2.6?

Tokens: Flash trains 26T text and 22T omni tokens, Pro 27T and 3T.

  • Flash: 22 / (26 + 22) = 22 / 48 = 45.8% omni.
  • Pro: 3 / (27 + 3) = 3 / 30 = 10.0% omni. Flash's omni stage is 7.3 times Pro's (22 / 3); the report gives no reason.

Both leave out the unsized agent-centric stage that follows; adding it to top and bottom raises a fraction below 1, so as midtraining shares these are lower bounds (Pro ≥ 10%, as in Figure 0.2 of chapter 00).

Parameters (Table 1; encoders include input embeddings, exclude projectors): MiMo-ViT 681M + audio tokenizer encoder 308M + audio patch encoder 127M = 1,116M.

  • Flash (310B total, 15B active): 1.116 / 310 = 0.36% of total, 1.116 / 15 = 7.4% of active.
  • Pro (1.02T, 42B active): 1.116 / 1,020 = 0.11%, 1.116 / 42 = 2.7%.

The encoders are tiny next to a large MoE; the stage's size comes from its tokens.

Who uses it and why

"This ensures the projector learns to map visual concepts to the language model's representation space effectively, providing informative gradient signals for subsequent training stages rather than noisy updates from a poorly aligned projector."

"To preserve text abilities, all stages that update the language model are joint training stages."

Trade-offs

  • Alignment stages leave the LM unchanged: MiMo-VL's stages 1-2 are (300 + 167) / 2,417 = 19% of its multimodal tokens.
  • Late vision shifts the LM's inputs and text scores dip, so labs keep text in every joint stage.
  • Joint stages now cost as much as pretraining: K2.5's 15.7T matches the 15T of text behind it.

Takeaways

  • The usual order: encoder pretraining on a small LM, projector warm-up with the LM frozen, joint training with text mixed in, long-context joint training.
  • Staging keeps a random projector from pushing noisy updates into a trained LM; text stays in every stage that updates the LM.
  • Joint stages grew from about 2T tokens (Kimi-VL, MiMo-VL, GLM-V) to 15-22T (K2.5, MiMo-V2.6-Flash); DeepSeek V4.1-Flash mixes images in from the first token.
Check yourself: in MiMo-VL-7B's stage 1, which weights get gradients, and why train them first?

Only the randomly initialized projector; ViT and LM are frozen. It first learns to map visual features into the LM's space, so later stages get informative gradients, not noisy updates.

Check yourself: is MiMo-V2.6-Flash's omni stage large because of its encoders?

No: the encoders total about 1.12B parameters, 0.36% of Flash's 310B; the stage is large because of its 22T tokens, 45.8% of 48T.

  1. Liu et al., Visual Instruction Tuning (LLaVA), 2023
  2. Kimi Team, Kimi-VL Technical Report
  3. Kimi Team, Kimi K2.5 Technical Report
  4. GLM-V Team, GLM-4.1V-Thinking and GLM-4.5V (also GLM-4.6V)
  5. Xiaomi MiMo, MiMo-VL Technical Report
  6. Xiaomi MiMo, MiMo-V2.5 model card
  7. Xiaomi MiMo, MiMo-V2.6 Technical Report
  8. DeepSeek-AI, DeepSeek-V4.1-Flash Technical Report
  9. DeepSeek-AI, DeepSeek-V4-Flash-Vision-Exp model card
  10. Pretraining notes, chapter 07: multimodal input

08 Changing optimizer, precision and hyperparameters mid-run

When a lab switches optimizer, turns on 4-bit training or changes a loss weight partway through a run, what state has to carry over, and what goes wrong if it restarts from zero?

What a checkpoint carries

A checkpoint holds more than the weights the model runs with. Labs change three kinds of state at stage boundaries, and each is risky to change mid-run for its own reason:

  • Optimizer state. DeepSeek-V3 keeps FP32 master weights and gradients and stores AdamW's two moment estimates per parameter in BF16. These running averages took many steps to build; a new optimizer, or a restart, begins them at zero, and the first steps come out the wrong size or in a noisier direction.
  • Number format. The precision the forward pass computes in. Rounding to fewer bits changes what the trained weights compute, and every later stage must keep the new format in its kernels.
  • Schedule settings. The learning rate η, the batch size, loss weights, and the update rate of a mixture-of-experts (MoE) router's per-expert bias. A change takes effect at the next step for every weight it touches.

The sections below take the three in that order. Only the changes made for what follows midtraining (RL, serving in 4 bits, a hardware number format) come with stated reasons. Of the schedule changes, one keeps each step the same size when the context grows; the rest turn settings down as the run settles, at schedule boundaries. Some changes fall at token counts these notes count as main pretraining (in-schedule decay, Chapter 00); each is labeled. Figure 8.1 places several on a token axis.

Optimizer: why its state matters

AdamW, Adam with decoupled weight decay (pretraining notes Chapter 08), does not step by the raw gradient g. It keeps two running averages per weight, of g and of g2, corrects them for starting at zero, and steps by their ratio:

W ← W − ηlearning rate · m̂taverage gradient / (√v̂ttypical gradient size + ε)
The averages in full
mt = β1mt−1 + (1−β1)gt,   vt = β2vt−1 + (1−β2)gt2
m̂t = mt/(1−β1t),   v̂t = vt/(1−β2t)
W ← W − η · m̂t / (√v̂t + ε)
(elementwise; g, m, v have the shape of W)

The ratio is what makes warm Adam gentle: averaging noisy batches shrinks m̂ more than √v̂. For a weight whose gradient flips sign from batch to batch, m̂ nearly cancels while √v̂ does not, so the weight barely moves. Kimi's Moonlight report measured AdamW update RMS "usually around 0.2 to 0.4" (in units of η).

Restart m and v at zero and the averaging is gone. The first step has m̂1 = g1 and v̂1 = g12, so every weight moves by η · sign(g1) and the update's root-mean-square (RMS) is η. A cold restart at an unchanged learning rate therefore takes first steps 2.5 to 5 times their usual size until the averages refill, over roughly 1/(1−β2) = 20 steps for β2 = 0.95.

Muon sets its step size by construction instead. It keeps one momentum matrix per weight matrix and replaces it with the nearest semi-orthogonal matrix, whose singular values are all 1 (computed by Newton–Schulz iteration, NS):

Mt = μMt−1 + Gt,   Ot = NS(Mt) ≈ UV⊤,   W ← W − η · 0.2√max(dout, din) · Ot
W, G, M, O ∈ ℝdout×din

The step size comes from the orthogonalization, not from the state: a cold buffer (M0 = 0) gives O1 = NS(G1), a normal-size step in a noisier single-batch direction, until momentum μ = 0.95 has averaged about 20 steps. Muon has no counterpart to Adam's v; its M plays the role of Adam's m.

Optimizer: switching AdamW to Muown before RL (MiMo-V2.6)

MiMo-V2.6-Pro, Xiaomi's 1.02T-total omni-modal MoE, was pretrained with AdamW on 27T text tokens and then 3T omni-modal tokens; the lab calls both pre-training, and these notes count the omni stage as midtraining. Its agent-centric mid-training, at 256K and then 1M context, switched the hidden weight matrices to Muown, a Muon variant, while embeddings, the LM head and the MoE router stayed on AdamW. The reason is the RL stage that follows: AdamW showed "diminishing optimization efficiency as the batch size increased in mixed-task RL", while Muon "retains stronger data efficiency beyond the critical-batch-size regime". The critical batch size is the point past which larger batches give diminishing returns (McCandlish et al.).

The switch is risky in two ways. The new optimizer's state starts cold, as above, and the new optimizer may not suit weights shaped by the old one: Qu et al. report that "naively switching to Muon for fine-tuning leads to degraded performance due to an optimizer mismatch", with damage that grows with update strength, and Moonlight found Muon SFT of an AdamW-pretrained Qwen2.5-7B only "on par" with AdamW. MiMo cites the risk and reports "no loss spike throughout the training process".

Muown targets a drift that Muon leaves unchecked. Its authors split a weight matrix's spectral norm (its largest singular value) into a row-magnitude factor and a row-coherence factor, and found that under Muon without weight decay the largest row norm grows and pulls the spectral norm up with it. Muown therefore gives the row magnitudes their own parameter, which MiMo describes as "explicit row-norm control, mitigating spectral-norm drift and reducing sensitivity to weight decay":

W = Diag(ρ / ‖R‖row) R,   ρ ∈ ℝdout, R ∈ ℝdout×din
R takes a Muon step scaled by 0.2√max(dout, din), ρ takes an Adam step, both at learning rate η

Here ρ holds the row magnitudes and ‖R‖row the row lengths of the direction matrix R. What a switch carries over follows from the Muown paper's initialization; MiMo does not say how it initialized Muown or what learning rate mid-training used.

  • The weights stay put. The paper starts from R = W and ρ = the row norms of W, so the weights do not move.
  • The new state starts at zero. Muown keeps Muon momentum for R, ρ with a cached copy of ‖R‖row, and Adam moments for ρ. R itself is rebuilt from W each step, so Muown adds no full-size state to Muon.
  • AdamW's m and v for these matrices are dropped, since nothing in Muown uses them.

The paper scales the R step "to match the RMS norm of a typical Adam update", so one learning rate serves both parts. A switch can therefore start from AdamW-trained weights; the sketch below follows the paper's rule.

The switch in code (illustrative)
def switch_to_muown(ckpt, hidden):          # illustrative, per the Muown paper
    state = {}
    for name, W in ckpt.master_weights.items():  # FP32 weights W, unchanged
        if name in hidden:                      # attention, MLP and expert matrices
            rho = W.norm(dim=1)                 # ρ: [d_out] row magnitudes of W
            state[name] = dict(
                rho=rho,                        # ρ, updated by Adam
                R_rownorm=rho.clone(),          # cached ‖R‖_row (R = W here)
                M=zeros_like(W),                # Muon momentum for R, starts cold
                m_rho=zeros_like(rho),          # Adam first moment for ρ, starts cold
                v_rho=zeros_like(rho))          # Adam second moment for ρ, starts cold
            # each step rebuilds R = diag(R_rownorm / rho) W, so R = W at the switch;
            # AdamW's m and v for W are dropped: nothing in Muown uses them
        else:                                   # embeddings, LM head, MoE router
            state[name] = ckpt.adamw_state[name]  # stays on AdamW (carry-over assumed)
    return state

At the start of RL, MiMo carries over "the FP32 master weights and Muown's row state from the SFT checkpoint", to "stabilize MXFP4 training" (MXFP4 is the 4-bit format of the next section).

Precision: when 4-bit training starts

A model served in 4 bits computes with rounded weights, which is not quite the function it was trained as. Quantization-aware training (QAT) lets training see the rounding. It runs the forward pass on quantized weights while gradients update an FP32 master copy, passing through the rounding as if it were the identity (the straight-through estimator):

forward: Ŵ = δ · round(W / δ),   backward: ∂ℒ/∂W ≈ ∂ℒ/∂Ŵ
W stays in FP32; δ = the block's scale; round = nearest representable 4-bit value

In MXFP4, blocks of 32 four-bit values share one power-of-two scale (pretraining notes Chapter 11). Each value is 0, ±0.5, ±1, ±1.5, ±2, ±3, ±4 or ±6 times the scale, so the grid is coarse: with δ = 0.25, a weight of 0.37 is 1.48δ and rounds to 1.5δ = 0.375, while 0.90 is 3.6δ and rounds to 4δ = 1.0, 11% too large. Turning QAT on changes every forward pass at once, and labs turn it on at different points:

  • In mid-training. MiMo-V2.6 starts MXFP4 QAT in mid-training, "allowing the model to adapt to low-precision computation while preserving model quality", and its RL rollouts then run MXFP4 experts.
  • From SFT through RL. Kimi K3 runs MXFP4-weight, MXFP8-activation QAT through all of post-training, SFT and RL alike.
  • In post-training. DeepSeek-V4 adds MXFP4 QAT for expert weights and the indexer's query–key path in post-training, for "inference acceleration and reducing memory traffic".
  • In SFT. GLM-5 applies INT4 QAT in SFT "to provide better accuracy at low-precision".

No lab compares start points. Starting earlier gives the model more tokens to adapt; every later stage must then keep the quantization in its training kernels.

Precision: hardware number formats

Low-precision formats store each block of numbers with a shared scale, so changing the scale format changes how every block is rounded, and the change has to reach every layer. DeepSeek-V3 trained in FP8 with one scale per 1×128 activation tile and per 128×128 weight block, and rounded only some scales to powers of 2. DeepSeek-V3.1 "is trained using the UE8M0 FP8 scale data format on both model weights and activations to ensure compatibility with microscaling data formats". UE8M0 is an unsigned, exponent-only 8-bit scale, the E8M0 scale format of the Microscaling (MX) standard, so every scale is a power of two. The card does not say which stage used it. V3.1's only training before SFT is its 839B-token context extension, so these notes count it as midtraining, an inference. One layer missed the change: the V3.1-Terminus card says the self_attn.o_proj parameters "do not conform to the UE8M0 FP8 scale data format".

NVIDIA tested a precision switch before the anneal, inside main pretraining under these notes' rule. Nemotron 3 Super trains most linear layers in 4-bit NVFP4 for all 25T pretraining tokens; promoting every tensor to MXFP8 1T tokens before the anneal improved the loss curve but not downstream accuracy, so NVIDIA kept NVFP4 to the end.

Hyperparameters: batch size when the context grows

A longer sequence holds more tokens, so a batch of a fixed number of sequences grows in tokens, and each step averages its gradient over more of them. DeepSeek-V3 and MiMo-V2-Flash both cut the batch, counted in sequences, by the factor the context grew, which keeps tokens per step fixed: 62.9M for DeepSeek-V3 at 4K, 32K and 128K (Chapter 05 works through these numbers and their GPU-hour cost) and 67.1M for MiMo-V2-Flash at 32K and 256K (worked example below). DeepSeek-V3 also kept its learning rate at the value pretraining ended on instead of restarting the schedule (quoted below), while MiMo-V2-Flash kept decaying it. Neither report gives the batch unit or a reason. MiMo-VL went the other way at its 32K stage and raised the learning rate because packing grew its effective batch (Chapter 07).

Hyperparameters: loss weights, balancing and frozen parts

Multi-token prediction (MTP) adds a head that predicts one further token, with its loss scaled by a weight (pretraining notes Chapter 06). Every report below lowers that weight from 0.3 to 0.1 late in the run:

Auxiliary-loss-free balancing keeps experts evenly loaded with a per-expert routing bias ce (for expert e) that is added to routing scores only when choosing experts. After each step, an overloaded expert's bias falls and an underloaded one's rises, by a fixed rate γ:

ce ← ce + γ · sign(n̄ − ne),   ne = tokens routed to expert e in the batch,   n̄ = mean over experts

Setting γ = 0 freezes the biases at their learned values. The loss-free balancing paper found that a high fixed rate "deteriorates load balance in the later stage" of training, and the reports slow or stop balancing late:

A frozen part can join training mid-run. DeepSeek-V4.1-Flash kept its vision encoder frozen until its learning-rate decay stage (midtraining in these notes) began at 28T of 45T tokens, then trained it jointly "with a smaller learning rate" (Chapter 07).

No lab gives a reason for these changes. What they share is timing: each sits on a schedule boundary, either the start of the learning-rate decay (DeepSeek-V3's and DeepSeek-V4's MTP weight, V4.1-Flash's vision encoder), the final low-learning-rate tail (DeepSeek-V3's bias rate), or a named stage (GLM-4.5 at 15T, Moonlight's cooldown, MiMo-V2-Flash's Stages 2 and 3).

Worked example: what changes at MiMo-V2-Flash's Stage 3 boundary

At 26T of its 27T tokens, MiMo-V2-Flash moves from Stage 2 to Stage 3, its context extension, and changes several settings at once. The report gives the batch without a unit; reading it as sequences:

before: 2,048 × 32,768 = 67,108,864 tokens per step
after: 256 × 262,144 = 67,108,864

The context grows by s = 262,144 / 32,768 = 8 and the batch shrinks 8×, so tokens per step stay at 67.1M. Stage 3's 1T tokens are then 1012 / 67,108,864 ≈ 14,900 steps.

The learning rate continues its cosine decay from 3 × 10−5 to 1 × 10−5: from 3 / 32 = 9.4% to 1 / 32 = 3.1% of the 3.2 × 10−4 peak.

The bias update rate drops 100×, from γ = 0.001 to 1 × 10−5. Each step moves a bias by exactly ±γ, so over the whole stage one expert's bias can move by at most 14,900 × 10−5 ≈ 0.15.

The RoPE base of the global-attention layers rises from 640,000 to 5,000,000 (Chapter 04), and the MTP weight has been 0.1 since 22T. The report gives no reason for any of these values.

Timeline of setting changes in DeepSeek-V3 and MiMo-V2-Flash, drawn to scale in tokensDeepSeek-V314.8T + 126Bη 2.2e-4 constantcosine, low tail0.47T: batch ramp 3,072 → 15,360 ends14.8T: 32K then 128K, batch 1,920 then 480, η 7.3e-610T: MTP weight 0.3 → 0.1; LR decay starts14.3T: bias update rate 0.001 → 0MiMo-V2-Flash27Tη 3.2e-4 constantcosine → 1e-4Stage 2S30.5T: batch warm-up to 2,048 ends22T, Stage 2 (mid-training): MTP weight 0.3 → 0.1, code-centric mix, η 1e-4 → 3e-526T, Stage 3 (context extension): 32K → 262,144, batch 2,048 → 256,bias update rate 0.001 → 1e-5, GA RoPE base 640K → 5M, η 3e-5 → 1e-505T10T15T20T25Ttraining tokens, drawn to scalepretraining, peak LRpretraining, LR decay and tailmidtrainingnext midtraining phase
Figure 8.1. Two runs on one token axis, to scale. Bars show the learning-rate phases: pretraining in neutral grey (decay dashed), midtraining in peach (a second midtraining phase dashed). Ticks mark when a setting changed. DeepSeek-V3's 126B-token context extension and MiMo-V2-Flash's Stages 2 and 3 (4T + 1T) are midtraining under these notes' rule; DeepSeek-V3's MTP-weight and bias-update-rate changes fall inside main pretraining. Batch sizes are as printed in the reports, whose unit is not stated; Chapter 05 works through DeepSeek-V3's.

Who uses it and why

"We therefore switch to a variant of Muon optimizer, Muown, for the hidden weight matrices during mid-training to prepare the model for subsequent large-batch RL."

"We perform quantization-aware training (QAT) [50] throughout the entire post-training stage, covering both SFT and RL, so that the model adapts to quantization-induced precision loss."

"The learning rate for both phases is set to 7.3× 10−6, matching the final learning rate from the pre-training stage."

Trade-offs

  • Carrying optimizer state costs checkpoint space (two values per parameter for Adam, one momentum for Muon, plus Muown's per-row state); dropping it gives Adam oversized first steps.
  • An optimizer switch risks the mismatch Qu et al. measured. MiMo reports no loss spike but publishes no comparison with staying on AdamW.
  • Earlier QAT means more tokens to adapt and quantized kernels in every later stage; no lab compares start points.
  • With the bias update rate at 0, routing biases cannot respond if late data shifts expert load; MiMo-V2-Flash kept a small 1 × 10−5 instead.

Takeaways

  • Optimizer state is part of the model: a cold Adam restart takes first steps 2.5 to 5 times their warm size, while Muon's step size is set by orthogonalization, and MiMo-V2.6 switched AdamW to Muown in mid-training, then carried Muown's row state into RL.
  • Low precision enters at different stages: MXFP4 QAT from mid-training (MiMo-V2.6), from SFT (Kimi K3, GLM-5's INT4) or in post-training (DeepSeek-V4), and UE8M0 scales in DeepSeek-V3.1 (stage not stated); NVIDIA pretrains Nemotron 3 Super in NVFP4 throughout, having found that a switch to MXFP8 before the anneal did not help downstream.
  • The other late changes sit on schedule boundaries and come without stated reasons: MTP weight 0.3 to 0.1, bias update rate to 0 or 1 × 10−5, a frozen encoder released at the decay, and a batch cut in sequences so tokens per step stay constant when the context grows.
Check yourself: a run restarts AdamW with m = v = 0 at its previous learning rate. How large is the first update compared with a typical warm one?

With m̂1 = g1 and v̂1 = g12, each weight moves by η · sign(g1), an update RMS of η. Warm AdamW updates have RMS around 0.2 to 0.4 η, so the first cold steps are 2.5 to 5 times larger until the averages refill.

Check yourself: if MiMo-V2-Flash had kept γ = 0.001 through its roughly 14,900 Stage 3 steps, how far could one expert's routing bias have moved, and what does the actual setting allow?

Each step moves a bias by exactly ±γ, so at γ = 0.001 it could move up to 14,900 × 0.001 ≈ 14.9; at the actual 1 × 10−5, at most about 0.15, 100 times less. With γ = 0, as in Moonlight's cooldown, it cannot move at all.

  1. Kingma and Ba. Adam: A Method for Stochastic Optimization (2014), §2-3.
  2. Lion et al. Muown: Row-Norm Control for Muon Optimization (2026), §1, §3, §5.
  3. McCandlish et al. An Empirical Model of Large-Batch Training (2018), §5.
  4. Qu, Huang and Horvath. Can Muon Fine-tune Adam-Pretrained Models? (2026).
  5. Liu et al. (Moonshot AI). Muon is Scalable for LLM Training (Moonlight) (2025), §2.2, §3.3, §3.5.
  6. Jacob et al. Quantization and Training of Neural Networks for Efficient Integer-Arithmetic-Only Inference (2017), §3; Bengio, Léonard and Courville. Estimating or Propagating Gradients Through Stochastic Neurons (2013).
  7. Wang et al. Auxiliary-Loss-Free Load Balancing Strategy for Mixture-of-Experts (2024).
  8. Xiaomi. MiMo-V2.6 technical report (2026), §3, §5.1; MiMo-V2-Flash technical report (2025), §3.
  9. DeepSeek-AI. DeepSeek-V3 Technical Report (2024), §3.3, §4.2-4.3; DeepSeek-V3.1 and V3.1-Terminus model cards.
  10. DeepSeek-AI. DeepSeek-V4 technical report (2026), §4.2.2, §5.2.1; DeepSeek-V4.1-Flash technical report (2026), p.15, §4.2.2.
  11. Kimi Team. Kimi K3 technical report (2026), §4.1.4.
  12. Z.ai. GLM-4.5 technical report (2025), §2.4; GLM-5 technical report (2026), §2.4.3.

09 Measuring a midtrained base and deciding what to leave out

How do labs tell whether midtraining made the base model better, and which data do they deliberately keep out of it?

The chapter takes the two halves of that question in turn:

  • Did the phase help? Labs score the base with few-shot prompts, with its loss on held-out text (per token or per byte), with pass@k, and before and after a single phase.
  • What stays out? Benchmark text, sources the model has already memorized, and data a lab judges risky.

Few-shot scores on the base model

A base model, the checkpoint before supervised fine-tuning, does not follow instructions, so labs prompt it with a few solved examples and a new question to continue. DeepSeek compares V4.1-Flash-Base with its two V4 bases on 20 benchmarks in one setting (16 scored for all three; the 4 multimodal ones only for V4.1-Flash), each with a fixed number of examples (5 for MMLU-Pro, 0 for HumanEval). The answer is then scored in one of two ways:

  • By likelihood. Multiple-choice tests are often scored by which option the model finds most likely, which MAI describes as "an NLL-based scoring scheme over logits for A, B, C, and D".
  • By sampling. Other tests sample an answer and check it.

Small gaps are noise: DeepSeek treats scores within 0.3 "at the same level", and K2 averages GPQA-Diamond over eight runs "to mitigate the high variance".

Loss on held-out text

The MAI-Thinking-1 report (Microsoft AI; base model MAI-Base-1) argues against accuracy for pretraining work. It tracks nearly 40 benchmarks scored by negative log-likelihood (NLL): the model reads held-out text, such as vendor-written worked solutions or private code, and the score is its mean loss. NLL needs no sampling or judge, and teacher forcing (conditioning on the true prefix) keeps one formatting slip from compounding. Multiple-choice skill, MAI notes, "typically emerges only at surprisingly large scale". Five category scores are weighted into one target, with code at 0.5. NLL per token compares models only when they share a tokenizer, as MAI's ablations do.

Bits per byte

Tokenizers cut the same text into different numbers of tokens, so per-token losses measure differently sized pieces. Bits per byte (BPB) fixes the denominator. The Pile paper defines it from the mean loss ℓ in nats per token:

BPB = (NT / NB)tokens per byte · ℓnats per token / ln 2nats per bit

NT is the number of tokens and NB the number of UTF-8 bytes in the evaluation text (LT, LB in the paper); all are scalars. NT·ℓ is the total loss in nats, dividing by ln 2 turns nats into bits, and dividing by NB spreads the bits over bytes. Same text, same bytes: BPB puts models with different tokenizers on one scale.

DeepSeek-V3 reported BPB on the Pile test set. V4.1-Flash-Base "achieves lowest BPB on all tasks" against V4-Flash-Base and V4-Pro-Base on held-out internal documentation, code and academic material. MAI compares MAI-Base-1 with DeepSeek, Kimi and Gemma bases on four held-out tasks: lower BPB than models of similar active size, with DeepSeek V4 Pro best. Both note that APIs do not return log-likelihoods, so only open-weight models qualify.

Figure 9.1 shows why the denominator matters on one toy string: the tokenizer with the lower loss per token is not the better model of the text.

Per-token loss versus bits per byte ILLUSTRATIVE: ONE 14-BYTE STRING, TWO TOKENIZERS, MADE-UP LOSSES IN NATS tokenizer A4 tokens def1.2 ␣add(1.8 a,␣b2.1 ):0.9 UTF-8 BYTES d e f ␣ a d d ( a , ␣ b ) : tokenizer B7 tokens def1.2 ␣add1.4 (0.3 a1.1 ,0.4 ␣b1.6 ):0.3 6.0 nats in total1.50 nats per token0.62 bits per byte 6.3 nats in total0.90 nats per token0.65 bits per byte A: 6.0 / ln 2 = 8.66 bits; 8.66 / 14 bytes = 0.62 BPB B: 6.3 / ln 2 = 9.09 bits; 9.09 / 14 bytes = 0.65 BPB B looks better per token; per byte, A encodes the same text in fewer bits, so A is the better model of it.
Figure 9.1. Per-token loss misleads across tokenizers (illustrative numbers; ␣ marks a space).

Worked example: from nats per token to bits per byte

The Pile paper measured the GPT-2 tokenizer at NT/NB = 0.29335 tokens per byte across the Pile. Take an illustrative loss ℓ = 2.0 nats per token.

  1. Bits per token: 2.0 / ln 2 = 2.0 / 0.6931 = 2.885.
  2. Bits per byte: 2.885 × 0.29335 = 0.846.
  3. A tokenizer with longer pieces, say 0.25 tokens per byte (illustrative), ties at ℓ = 0.846 × 0.6931 / 0.25 = 2.35 nats per token: a higher per-token loss, the same quality.
  4. Domains differ too: GPT-2 needs 0.4412 tokens per byte on GitHub code and 0.8137 on DeepMind Mathematics, so ℓ = 2.0 means 2.885 × 0.4412 = 1.27 and 2.885 × 0.8137 = 2.35 BPB there; compare models on one held-out set.

pass@k: what reinforcement learning can reach

Chapter 03 defines pass@k, the chance that at least one of k sampled answers is correct, and its unbiased estimator. Because reinforcement learning (RL) learns only from answers the model sometimes produces, labs use pass@k on the base as a ceiling for RL. Yue et al. (2025) found that RL-trained models beat their bases at small k while the bases win at large k, and they treat the base as an upper bound on what current RL elicits. MiMo-7B adopts the metric from Yue et al.; its base's lead over other bases, a 32B one included, widens as k grows. The GLM-V report plots pass@k on the non-multiple-choice part of MathVista and says base performance "arguably sets the upper bound for the final results after reinforcement learning".

Before and after one phase

To judge one phase, labs score checkpoints before and after it on the same held-out set, checking what the phase targets and what it should leave alone. MAI's small-scale ablations of context extension do this with code NLL: the last 16K tokens of a repository chunk are scored after 16K to 256K tokens of context. After extension the loss falls steadily as context grows, while models mid-trained at shorter lengths get worse beyond twice their training length. At 16K and 32K all five configurations reach about the same NLL: no short-context cost (chapter 05; OLMo 2's few-shot before/after is in chapter 01).

Keeping benchmarks out

Decontamination removes test items from training data. The labs here mostly match n-grams, runs of n consecutive words, between benchmarks and training text; they differ in n and in what they do with a hit:

  • GPT-3 searched for 13-gram overlaps (13 consecutive lowercase words) between benchmarks and training data; a bug left some in, so OpenAI also scored clean subsets to measure the effect.
  • DeepSeek dropped pretraining text containing any 10-gram from evaluation questions or solutions, about six million math texts alone, and warns that "the n-gram based decontamination method cannot prevent the paraphrase of testset".
  • MAI removes huggingface.co and its mirrors, runs a 20-gram fuzzy deduplication at 80% similarity, calls its methods "imperfect" and builds private benchmarks.
  • Xiaomi drops SFT queries with 16-gram overlap (MiMo-7B) and removes benchmark images by perceptual hash (MiMo-VL).
A 10-gram filter in code
import re

def grams(text, g):                  # GPT-3: lowercase words, punctuation stripped
    words = re.sub(r"[^\w\s]", "", text.lower()).split()
    return {tuple(words[i:i + g]) for i in range(len(words) - g + 1)}

def build_index(benchmarks, g=10):   # DeepSeek: 10-grams of questions and solutions
    index = set()
    for item in benchmarks:
        index |= grams(item.question, g) | grams(item.solution, g)
    return index

def is_clean(doc, index, g=10):      # sketch: drop the whole document on one hit
    return not (grams(doc, g) & index)

index = build_index(benchmarks)
corpus = [d for d in corpus if is_clean(d, index)]

Capping what the model already memorized

MAI also limits how often midtraining repeats a source. Between two pretraining checkpoints, it measures what fraction of a source's validation-loss improvement comes from tokens predicted with near certainty (NLL below 0.01). The intuition: a token the model already predicts almost perfectly has little left to teach, so if most of a source's loss gain comes from such tokens, the model is learning to recite that source rather than to generalize. MAI reads a high fraction as "memorization or highly repeated structure" and gives such sources stricter epoch caps. In the notation here (the report gives it in words; I assume near-certainty at the later checkpoint):

mj = ∑t ∈ Vj, ℓt(2) < 0.01 (ℓt(1) − ℓt(2)) / ∑t ∈ Vj (ℓt(1) − ℓt(2))

Here Vj is the validation tokens of source j and ℓt(1), ℓt(2) the losses of token t at the earlier and later checkpoint. For example (illustrative numbers), if a source's validation loss falls by 100 nats in total and 70 of them come from tokens now below 0.01, mj = 0.7 and the source is capped harder than one at 0.1. The report gives no cap values.

Removing data on purpose

Kimi K3.1 Pro, Moonshot's 3T-class open-weight model, removed data for safety. As post-training scaled, its vulnerability-research scores rose; Kimi traced this to cyber content in the general midtraining corpus and cyber tasks in the RL mix. For the open-weight release it removed both and kept general coding tasks. On its xdev-bench-hard exploit tasks, a checkpoint without the removal solves 90.5% at pass@3 and the released model 81.0%. Kimi does not say how the data was found. The blog calls K3.1 Pro "a post-trained version of Kimi K3" yet edits its midtraining corpus, so these notes count it as having midtraining. MAI leaves out synthetic data: in its midtraining "no new or synthetic sources are introduced".

What the reports leave out

Chapter 00 counts which releases describe midtraining at all and finds 27 distinct recipes. Of those 27, 12 state their token count, 5 allow only an estimate and 10 give no total size. Four give a mix share as a number, and only MAI gives its whole mix by domain: 35% STEM and math, 55% code, 10% other. Outside the grid, NVIDIA gives the whole mix of Nemotron 3.5 Super's agentic stage (chapter 03), and Ant gives Ling-2.6-1T's final mid-training phase at 256K as 43% general, 42% reasoning and 15% agentic data.

What reports disclose about midtraining RECIPES, TO SCALE (9 PX = 1 RECIPE) The 27 recipestoken count given? 12 stated 5 10 no size 5 = estimates (steps × batch × length, or an unclear table) The same 27mix given as numbers? 4 23 give no share 4: Kimi-VL, MiMo-7B, MiMo-V2-Flash, MAI-Thinking-1 0 27
Figure 9.2. Disclosure across the 27 distinct midtraining recipes of chapter 00, to scale; colours mark disclosure status.

Who uses it and why

"use Bits-Per-Byte (BPB) as the metric to guarantee fair comparison among models using different tokenizers."

"we cap data source exposure during mid-training to avoid overfitting sources that appear highly memorized by the end of pre-training."

"For the open-weight release of K3.1 Pro, we identified and removed cyber-related data from both training stages, while retaining the general-purpose coding tasks needed for model usefulness."

Trade-offs

  • Few-shot scores are noisy; labs treat small gaps as ties or average runs.
  • BPB needs log-likelihoods, so closed models are out, and it is only as good as the held-out set.
  • pass@k at large k needs many samples per problem; Codex drew n = 200.
  • n-gram filters miss paraphrases (DeepSeek); MAI calls its filters imperfect.
  • Removal costs capability by design: 90.5% to 81.0% on Kimi's exploit benchmark.

Takeaways

  • Labs judge a midtrained base by few-shot scores in one fixed setting, by held-out loss before and after a phase, and by pass@k as a ceiling for RL.
  • Bits per byte divides total bits by a byte count all tokenizers share, so DeepSeek and MAI use it to compare bases across labs.
  • Labs also choose what stays out: benchmark n-grams, over-memorized sources (MAI) and cyber data (Kimi K3.1 Pro); most reports give no mix numbers.
Check yourself: why does DeepSeek report bits per byte rather than per-token loss when comparing base models?

The models use different tokenizers, so their tokens cover different numbers of bytes. Total bits over the shared byte count puts every model on one scale.

Check yourself: what did removing cyber data from K3.1 Pro's midtraining and RL cost on Kimi's exploit benchmark?

Without the removal a checkpoint solved 90.5% of xdev-bench-hard at pass@3; the released model solves 81.0%.

  1. Gao et al., The Pile: An 800GB Dataset of Diverse Text for Language Modeling, 2020
  2. Chen et al., Evaluating Large Language Models Trained on Code (Codex, pass@k), 2021
  3. Yue et al., Does Reinforcement Learning Really Incentivize Reasoning Capacity in LLMs Beyond the Base Model?, 2025
  4. Brown et al., Language Models are Few-Shot Learners (GPT-3), 2020
  5. DeepSeek-AI, DeepSeek-V3 Technical Report
  6. DeepSeek-AI, DeepSeek-R1 (decontamination appendix)
  7. DeepSeek-AI, DeepSeek-V4.1-Flash Technical Report
  8. Microsoft AI, MAI-Thinking-1 Technical Report
  9. Kimi Team, Kimi K2 Technical Report
  10. Kimi Team, Kimi K2.5 Technical Report
  11. Kimi, Introducing Kimi K3.1 Pro
  12. Xiaomi MiMo, MiMo-7B Technical Report
  13. Xiaomi MiMo, MiMo-VL Technical Report
  14. GLM-V Team, GLM-4.1V-Thinking and GLM-4.5V
  15. Kimi Team, Kimi-VL Technical Report

10 Putting it together: three midtraining recipes

When a lab rebuilds its midtraining from one release to the next, what changes, and how much of the run does it take?

Chapters 00 to 09 took one midtraining decision at a time. This chapter follows three labs across releases and reads each release the same way: which phases followed the main run, in what order, how many tokens they took, and what changed besides the data.

  • DeepSeek kept midtraining small for most of 2025 and then folded it into one long run.
  • Z.ai's GLM named a midtraining stage early and kept its share near 5%.
  • Xiaomi's MiMo already spent a fifth to a quarter of its tokens late in training with MiMo-7B and V2-Flash.

Figure 10.1 draws each release's midtraining tokens on one scale, colored by what each phase was for.

Midtraining tokens per release, by phase purpose, to scaleDeepSeekV3 · Dec 2024126B · 0.8% of 14.9TV3.2-Exp · Sep 2025946B retrofit on a 15.6T baseV4.1-Flash · Sep 202617T · 38% of 45TGLMGLM-4.5 · Jul 20251.1T · 4.8% of 23TGLM-5 · Feb 20261.57T · 5.5%, including a 23B retrofitMiMoMiMo-7B · Apr 20256T · about 25% of the runV2-Flash · Dec 20255T · 19% of 27TV2.6-Pro · Sep 2026?3T omni stage (10% of 30T) + agentic stage (size not given)0T5T10T15Tanneal / decaycodereasoninglong contextvision and audiosparse-attention retrofit
Figure 10.1. Midtraining tokens per release, drawn to scale. Colors mark each phase's main purpose as coded in chapter 00, not the stage key of other figures, so MiMo-7B's stage 2 (math and code raised at a held, already-decayed learning rate) is an anneal while V2-Flash's code-upsampled stage is code. Only each release's own phases are shown; inherited phases are left out. The label gives the total and its share of the release's training tokens. MiMo-V2.6's agent-centric stage got "the majority of compute" in midtraining, but its size is not given, so its bar is a lower bound. DeepSeek V4 and GLM-5.2 are left out because neither gives a size.

DeepSeek: from a context patch to over a third of the run

  1. V3: a context patch. Two short YaRN phases stretched the context from 4K to 128K (chapter 04) at the learning rate pretraining ended on (chapter 08): 126B tokens, 0.8% of the run.
  2. V3.2-Exp: a retrofit. On the V3.1-Terminus base, DeepSeek Sparse Attention went in by the steps of chapter 06, the indexer trained alone and then everything together, in about 946B tokens.
  3. V4: length inside the run. Length growth moved into the main run, so under the rule in these notes V4 has almost no separate midtraining, only a phase of agentic coding data whose size and place are not given (chapter 03 quotes DeepSeek on it).
  4. V4.1-Flash: named late phases again. A learning-rate decay stage from 28T to 34T and a 1M-token context extension from 34T to 45T, during which the learning rate keeps falling until 40T and is then held; the vision encoder joins at the decay (chapter 07). Counted as midtraining, that is 17T of 45T.

That is the largest share of any DeepSeek release (Kimi K2.5's 51% in chapter 00 is larger). Part of the jump is labeling: DeepSeek-V3 also held its learning rate constant for most of its run and decayed it over the last 4.8T, but inside its main schedule, so the rule counts that as pretraining (chapter 00 puts V3 at 33% if it were counted). The long-context work did grow: 11T at 1M against V3's 126B.

ChoiceV3 · Dec 2024V3.2-Exp · Sep 2025V4 · Apr 2026V4.1-Flash · Sep 2026
Phases after the main runtwo YaRN context phasessparse-attention retrofit: indexer warm-up, then sparse trainingnone named besides an agentic mid-training phase of unstated size and place; length grows inside the runa learning-rate decay stage, then context extension, inside one 45T run
Tokens126B (0.8%)2.1B + 943.7Bagentic phase size not given6T + 11T (38%)
Context4K → 32K → 128K128K, unchanged4K → 16K → 64K → 1M during pretraining64K → 1M
Other changeslearning rate held at its final pretraining valueDeepSeek Sparse Attention addedagentic data for codingvision encoder unfrozen at the start of the decay, at a smaller learning rate

GLM: a named stage that grew longer, then sparse

  1. GLM-4.5: three named phases. Repo-level code, then synthetic reasoning, then long context and agent data, 1.1T tokens up to 128K. Z.ai named the stage mid-training because it trains on medium-size, domain-specific datasets, including instruction data, rather than large general corpora (chapter 00 quotes its definition).
  2. GLM-5: the same shape, longer, then a retrofit. GLM-5 aimed the stage at reasoning, long context and agentic ability and stretched it to 200K. Its mix keeps repository-level code with issues and pull requests, and upsamples long documents and synthetic agent trajectories in the later stages. It then added DeepSeek Sparse Attention to the finished base by the steps of chapter 06, with far fewer tokens than DeepSeek had used.
  3. GLM-5.2: sparse from the start. A shared sparse-attention indexer trains from the start of 128K midtraining.
ChoiceGLM-4.5 · Jul 2025GLM-5 · Feb 2026GLM-5.2 · Jun 2026
Phasesrepo-level code (500B, 32K) → synthetic reasoning (500B, 32K) → long context and agent data (100B, 128K)32K (1T) → 128K (500B) → 200K (50B), then a sparse-attention retrofit (2.84B warm-up + 20B)128K midtraining with a shared sparse-attention indexer from the start; 1M coding-agent training (stage not stated)
Tokens1.1T (4.8% of 23T)1.55T + 23B retrofit (5.5% of about 28.6T)not given
Context and RoPE4K → 32K → 128K; base 10,000 → 1,000,000 at 32K4K → 32K → 128K → 200K1M; config base 8M (GLM-5's config: 1M)
Data focusrepo-level code with issues, PRs and commits; synthetic reasoning; long documents; synthetic agent trajectories; some instruction datarepo-level software-engineering data, long documents and synthetic agent trajectories upsampled; a small share of MRCR-like data at 200K1M-context coding-agent data

On GLM-5's retrofit, Z.ai reported that this was enough:

"Although the training budget is much smaller than that of DeepSeek-V3.2 (943.7B tokens), we find that it is enough to adapt the DSA model to match the performance of the original MLA model."

MiMo: a late-heavy schedule from the start

  1. MiMo-7B: math and code, then reasoning. Stage 2 raised math and code to about 70% (chapter 02); stage 3 added synthetic reasoning at 32K. The report's schedule sums to 23.8T and its text says "approximately 25 trillion tokens", so the 6T are about a quarter either way.
  2. V2-Flash: code, then context. A code-centric "Mid-training" stage at 32K, then a "Context Extension" to 256K at whose boundary batch, RoPE base and balancing rate changed together (worked example in chapter 08).
  3. V2.6: the setup changes too. An omni stage added vision and audio (chapter 07); agent-centric midtraining, at 256K and then 1M, switched the optimizer and began 4-bit training (chapter 08).
ChoiceMiMo-7B · Apr 2025V2-Flash · Dec 2025V2.6 · Sep 2026
Phasesstage 2: math and code raised to about 70% (4T, 8K); stage 3: about 10% synthetic reasoning responses, 32K (2T)"Mid-training": code-centric data and about 5% synthetic reasoning (4T, 32K); "Context Extension" (1T, 256K)omni stage adding vision and audio; agent-centric midtraining at 256K; a final 1M stage
Tokens6T (about 25%)5T (19% of 27T)omni stage 3T (Pro), 22T (Flash); agent stage not given
Context and RoPE8K → 32K; base 10,000 → 640,00032K → 256K; global-layer base 640,000 → 5,000,00032K → 256K during pretraining, then 1M at the end of midtraining
Setup changesbatch 2,560 → 640; learning rate held, then decayed to 1e-5learning rate 1e-4 → 3e-5 → 1e-5AdamW → Muown for hidden matrices; MXFP4 quantization-aware training

MiMo-7B's two late stages already followed the pattern GLM and DeepSeek reached later: shift the mix toward math and code, then add synthetic reasoning and longer context at a low learning rate. V2.6 widened the purpose of the stage from data to the whole training setup:

"Mid-training bridges this general foundation and subsequent large-scale RL by further developing the model's agentic abilities, extending long-context support, and adapting the optimization setup for large-batch training."

The optimizer switch is the clearest example. Xiaomi pretrained V2.6 with AdamW, found that its efficiency fell as RL batches grew, and switched to a Muon variant in midtraining so that the model would already be adapted when RL began (chapter 08).

What midtraining is for

Across the three labs, the choices of chapters 01 to 09 sort into five purposes (Figure 10.2).

Midtraining choices grouped by the purpose they serve Use the best data lastlow learning rate Prepare for RLskills RL can amplify Long context128K to 1M Change the modelwithout retraining Check and removewhat goes out decay and annealing (01)more math and code (02)quality filtering (02)replay of general data (02) synthetic reasoning (02)repo code, issues, PRs (03)agent trajectories (03)large-batch optimizer (08) PI, base raise, YaRN (04)NoPE global layers (04)staged lengths, packing (05)long-range data (05) sparse-attention retrofit (06)vision, audio encoders (07)4-bit training starts (08)settings changed (08) base-model evaluation (09)decontamination (09)removing risky data (09)memorization caps (02, 09)
Figure 10.2. Midtraining choices from chapters 01 to 09, grouped by what they are for. Numbers in parentheses are chapters.

Exercise: how much of each run is trained at long context?

Using the tables above, compute for each release the share of all its training tokens that were trained at a context of 128K or longer: DeepSeek-V3 (its 128K phase was 62.9B tokens), GLM-4.5, GLM-5, MiMo-V2-Flash and DeepSeek V4.1-Flash. What changed between late 2024 and late 2026?

Show the solution

DeepSeek-V3: 62.9B of 14,926B ≈ 0.42%. GLM-4.5: its 100B long-context phase of 23.1T ≈ 0.43%. GLM-5: 500B at 128K plus 50B at 200K, 550B of about 28.6T ≈ 1.9%. MiMo-V2-Flash: 1T at 256K of 27T ≈ 3.7%. DeepSeek V4.1-Flash: 11T at 1M of 45T ≈ 24%, and the other 34T were already trained at 64K. Long-context training went from under half a percent of the run to about a quarter. Two changes made that affordable: attention whose cost grows slowly with length (DeepSeek says its hybrid of compressed sparse attention and heavily compressed attention makes one-million-token context "feasible in practice"; see the pretraining notes' chapter 03), and growing length inside the main run instead of in a short stage at the end (chapter 05).

Trade-offs

  • A long late stage makes the end of training count for more, but it also means more of the run happens after the main data mix is fixed, so mistakes there are costly to undo.
  • Growing context inside the main run avoids a separate extension stage but makes every long-context step part of the main training cost.
  • Changing the model in midtraining (new attention, new modalities, a new optimizer) is far cheaper than retraining, but each change needs its own warm-up and checks that earlier abilities survive.

Takeaways

  • How large midtraining looks depends on how a lab schedules its run: DeepSeek's share went from under 1% to 38%, while GLM stayed near 5% and MiMo-7B and V2-Flash spent a fifth to a quarter.
  • The purpose moved from context length alone to code, reasoning and agent data meant to prepare the model for RL.
  • Midtraining is also where labs change the model itself: sparse attention, vision and audio, and the optimizer and precision RL will use.
Check yourself: under the rule in these notes, DeepSeek V4 has almost no midtraining while V4.1-Flash has 17T. Did DeepSeek really spend far more on late training in V4.1-Flash?

Not necessarily. V4 grows context and decays its learning rate inside its single pretraining run without naming those phases, so the rule counts them as pretraining. V4.1-Flash names a learning-rate decay stage and a context extension, so the rule counts them as midtraining. Part of the difference is how the reports describe the run, which is why these notes always state the rule and the denominator alongside a share.

Check yourself: why did MiMo switch optimizers in midtraining instead of at the start of RL?

Xiaomi found that AdamW's efficiency fell as RL batch sizes grew, and switched its hidden matrices to a Muon variant during midtraining "to prepare the model for subsequent large-batch RL". Xiaomi does not say why it switched in midtraining rather than when RL began. Chapter 08 shows what a switch disturbs, the optimizer state, which suggests a reason to do it on ordinary training data first, but that reasoning is ours, not Xiaomi's.

  1. DeepSeek-V3 report
  2. DeepSeek-V3.2-Exp report
  3. DeepSeek-V4 report
  4. DeepSeek-V4.1 report
  5. GLM-4.5 report
  6. GLM-5 report
  7. MiMo-7B report
  8. MiMo-V2-Flash report
  9. MiMo-V2.6 report

A Glossary

Short definitions of the terms used in these notes, with the chapter that explains each one.

ABF (adjusted base frequency)
Extending context by raising the RoPE base b, which stretches the wavelength of every rotary pair except the fastest, and then training at the longer length. GLM-4.5 raised its base from 10,000 to 1,000,000 at its 32K step. ch 04
Agent trajectory
The record of a model working on a task with tools: the task, the model's reasoning and tool calls, and the tool outputs it saw, written out as one training text. ch 03
Annealing
Training at a learning rate that decays toward zero, usually on upweighted high-quality data. Also used for short decay runs that test whether a dataset helps. ch 01
Best-fit packing
Placing whole documents into fixed-length training sequences so that as few as possible are cut, instead of concatenating everything and splitting at fixed points. ch 03, ch 05
Bits per byte
A model's loss converted from nats per token to bits per byte of raw text, so models with different tokenizers can be compared on the same text. ch 09
Catastrophic forgetting
A model losing skills it had when training moves to a narrower data distribution. Midtraining guards against it with replay. ch 02
Checkpoint averaging (souping)
Averaging the weights of several checkpoints from the end of a run to get a smoother starting point; Muse Glimmer starts its midtraining from such an average, and Ling uses one in place of a learning-rate decay (WSM). ch 01
Coded releases
The 68 releases, from the labs these notes started with, in the cross-lab table behind the atlas's midtraining section (the six labs the atlas added later are not coded), each coded for its phases, tokens, context and data under one boundary rule. Releases that reuse a parent's phases count once as a recipe, giving 27 distinct midtraining recipes. ch 00
Context parallelism
Splitting one long sequence across several GPUs so its activations fit; ring attention passes key-value blocks between the GPUs while they compute. ch 05
Cooldown
Another lab name for the final phase in which the learning rate decays (Moonlight, Kimi K3). ch 00
Decontamination
Removing training documents that overlap with benchmark questions, usually by matching long n-grams, so evaluation scores are not inflated by memorization. ch 09
Dense warm-up
The first stage of a sparse-attention retrofit: the rest of the model is frozen and only the new indexer trains, to match the dense attention pattern with a KL loss. ch 06
DSA (DeepSeek Sparse Attention)
Attention in which a small lightning indexer scores earlier tokens and each query attends only to the top-scoring ones (2,048 in DeepSeek V3.2). DeepSeek and GLM added it to trained models by continued training. ch 06
Epoch
One full pass over a data source. Upweighting a small source in a long phase means repeating it several times. ch 02
Few-shot evaluation
Scoring a base model on a benchmark by putting a few solved examples in the prompt; labs keep the setting fixed so base models can be compared. ch 09
GRPO
Group relative policy optimization: RL that scores each of several attempts at the same task against the group's mean reward, so a task gives no signal until the model sometimes solves it. ch 03, posttraining ch 03
Held-out loss
The model's next-token loss on text it was not trained on, by domain; MAI prefers it to benchmark accuracy for judging pretraining and midtraining changes. ch 09
IndexShare
GLM-5.2's change to DSA: one indexer is shared by every four attention layers, trained from the start of midtraining. ch 06
Issue–PR data
Training samples built from a GitHub issue and the pull request that fixed it, showing a problem description followed by a code change. GLM-5 used about 10 million such pairs. ch 03
KDA (Kimi Delta Attention)
The linear-attention layer in Kimi Linear and Kimi K3, which keeps a fixed-size state instead of a growing cache and carries word order in place of RoPE. ch 04, pretraining ch 03
Learning-rate area
The sum of the learning rate over a stretch of steps. In the one-parameter model of chapter 01, a batch's influence on the final weights shrinks with the learning-rate area still to come after it, so the last data count most. ch 01
Lightning indexer
The scorer DSA adds to each attention layer, with its own small projections and scoring heads (64 heads of 128 dimensions in DeepSeek V3.2-Exp, computed in FP8), that picks which earlier tokens each query attends to. ch 06
MFU (model FLOPs utilization)
The share of a chip's peak arithmetic a training run actually uses; it falls at long context, which MAI cites as one cost of long stages. ch 05
Microanneal
A short annealing run on a candidate data source mixed with general data, used to test the source cheaply (OLMo 2). ch 01
Midtraining
In these notes: (1) any phase a lab names mid-training, annealing, cooldown, learning-rate decay stage, context extension or continued pre-training; (2) a distinct stage after the main decay that changes the data mix or the context length; (3) continued training of an earlier base (a released model or an intermediate checkpoint). It ends where supervised fine-tuning begins. ch 00
Mixture weight (wk)
The share of a phase's tokens drawn from data source k. ch 02
MLA (multi-head latent attention)
DeepSeek's attention, also used by Kimi and GLM-5, which caches one compressed latent vector per token plus a small rotary key instead of full keys and values. ch 06, pretraining ch 03
Moonlight
Moonshot's 16B-total mixture-of-experts model from February 2025, trained with Muon, whose final phase the lab calls a cooldown. ch 00
MRCR, RULER, needle in a haystack
Long-context tests: find a planted fact in a long input (needle), harder retrieval, tracing and aggregation tasks (RULER), and recall of one of several similar earlier requests (MRCR). ch 05
Multi-token prediction (MTP) weight
The factor that scales the loss of the extra heads predicting later tokens; several labs lower it late in training, for example from 0.3 to 0.1. ch 08
Muon, Muown
Muon is an optimizer that orthogonalizes each weight matrix's update (pretraining notes chapter 08). Muown is a Muon variant by Lion et al. (2026) with explicit control of row norms; MiMo V2.6 switched to it from AdamW in midtraining to prepare for large-batch RL. ch 08
MXFP4
A 4-bit floating-point format in which each block of 32 values shares one power-of-two scale. MiMo V2.6 began MXFP4 quantization-aware training in midtraining. ch 08, pretraining ch 11
NoPE
No position encoding: attention layers without RoPE. Using it in global layers (Llama 4, Kimi Linear, Kimi K3, MAI-Thinking-1) avoids rescaling RoPE when context grows. ch 04
NTK-aware scaling
Raising the RoPE base by sdr/(dr−2) so the fastest pairs stay almost unchanged and the slowest is stretched by exactly s. ch 04
Omni stage
MiMo V2.6's stage that attaches vision and audio encoders to the text model and trains everything on mixed-modality data: 3T tokens for Pro, 22T for Flash. ch 07
Optimizer state
What the optimizer keeps between steps besides the weights: Adam's running averages of the gradient and its square, Muon's momentum. Switching optimizer mid-run means starting this state again. ch 08
pass@k
The probability that at least one of k samples solves a task. Used as a rough ceiling for what RL can reach from a base model. ch 03, ch 09
Position interpolation (PI)
Dividing every position by the scale factor s before applying RoPE, so a longer input uses only angles seen in training; nearby tokens become harder to tell apart. ch 04
Projector
The small network, usually an MLP, that maps a vision or audio encoder's outputs into the language model's embedding space. Labs often train it alone first. ch 07
QAT (quantization-aware training)
Training with the rounding of the low-precision serving format applied in the forward pass. MiMo V2.6 starts MXFP4 QAT in midtraining; other labs start it at SFT or in posttraining. ch 08
Replay
Keeping a share of the earlier, general data in a specialized phase so the model does not forget it. ch 02
Repository-level code
Training samples that concatenate files from one repository, so the model learns how code depends on other files. ch 03
Retrofit
Changing a trained model's architecture, such as replacing dense attention with sparse attention, by continued training instead of training a new model. ch 06
River valley
A picture of the loss surface with steep walls and a flat floor: at a high learning rate the weights bounce between the walls, and decaying it lets them settle onto the floor, which is why loss drops quickly during decay. ch 01
RoPE wavelength (λi)
The number of tokens over which rotary pair i makes one full turn, 2πb2i/dr, where dr is the number of rotated dimensions per head. Pairs whose wavelength exceeds the trained length never completed a turn in training. ch 04
Synthetic reasoning traces
Step-by-step solutions generated by a model, filtered for correctness, and mixed into late training to prepare the base for reasoning RL. ch 02
UE8M0
An 8-bit scale format that stores only an exponent (a power of two) for each block of FP8 values; DeepSeek-V3.1 trained with it for compatibility with microscaling formats. ch 08
Ulysses (sequence parallelism)
A way to split one long sequence across GPUs: an all-to-all exchange moves each GPU from holding some tokens for all heads to all tokens for some heads, and back. MAI-Thinking-1 used it for long-context midtraining. ch 05
Upweighting factor (uk)
How many times larger a source's share is in a midtraining phase than in pretraining: uk = wkmid / wkpre. ch 02
Warmup-stable-decay (WSD)
A learning-rate schedule held constant for most of training and decayed only at the end, which makes a separate decay phase on chosen data possible. ch 01
YaRN
A RoPE extension that leaves fast pairs unchanged, interpolates slow pairs by s, blends the pairs in between, and slightly sharpens attention with a temperature. DeepSeek-V3 used it with s = 40. ch 04

B Citation

To give credit if you find this work useful, please cite:

@misc{ma2026openrecipesmidtrain,
  title={Reading Open-Weight Recipes, Part 2: What 2025--26 Model Reports Disclose About Midtraining},
  author={Ma, Ziqiao},
  howpublished={\url{https://mars-tin.github.io/blogs/posts/open_recipes_midtraining}},
  note={Blog post},
  year={2026}
}