Introduction

DeepSeek-V3.2 pairs architectural changes with a large-scale reinforcement learning and environment synthesis pipeline to make long-context reasoning and multi-turn tool use affordable at scale. It modifies how attention reads a long conversation history, stabilizes off-policy reinforcement learning across a massive mixture-of-experts network, and trains on thousands of synthetic agent environments where actions can be verified automatically.

This book builds that technical story from the ground up. Each chapter introduces the required mathematical and systems context, walks through one subsystem in detail, and connects its design choices to the rest of the stack. You can read the chapters sequentially or jump directly to a specific subsystem.

Our primary source is DeepSeek-V3.2: Pushing the Frontier of Open Large Language Models (arXiv:2512.02556v1, submitted 2 December 2025), supplemented by revision-pinned configuration, inference, and encoding files from the official open-weights release. Where the paper leaves training hyperparameters or systems numbers unstated, we note those gaps directly and derive what we can from the published equations and checkpoint specifications.

Contents

Chapter Question it answers
1. The problem and the model family What changed, and why do efficiency, reasoning, and agents belong together?
2. The foundations the report assumes What are tokens, attention, caches, language modeling, and reinforcement learning?
3. Inside the inherited backbone How do the transformer, experts, and parameter counts fit together?
4. Multi-head latent attention How can many attention heads read one compressed cache?
5. The lightning indexer and sparse selection How does DSA decide which 2,048 tokens to read?
6. Converting a dense model to sparse attention How is the selector trained without breaking the existing model?
7. Computation, memory, and inference cost Which costs shrink, and why is the whole model still not asymptotically linear?
8. Specialists, distillation, and mixed learning How does the base model become a general assistant?
9. GRPO from first principles What exactly does learning from groups of answers optimize?
10. The corrected KL estimator Why does the sampling distribution matter for regularization and its gradient?
11. Keeping off-policy learning stable What do sequence masking, routing replay, and sampling masks fix?
12. Rewards, length, and reasoning behavior What does the model learn when success, helpfulness, and brevity compete?
13. Reasoning with tools and conversation state Why do message roles and retained reasoning change agent behavior?
14. Synthesizing general agent environments How are hard but verifiable tasks created at scale?
15. Coding agents and code interpreters What makes an executable training environment credible?
16. Search agents and difficult questions How are long-tail search tasks constructed and rewarded?
17. What the synthesis experiments establish Do synthetic tasks transfer to unfamiliar tools and environments?
18. Context management and test-time scaling What happens when an agent fills the 128K window?
19. Reading the reasoning benchmarks What do the math, science, knowledge, and coding scores actually mean?
20. Reading the agent benchmarks How much of an agent score belongs to the model, framework, or environment?
21. Speciale and competition-level reasoning What buys higher reasoning scores, and what does a gold-medal result measure?
22. Understanding the released implementation How do configuration, precision, encoding, and kernels affect deployment?
23. One request through the whole system How do attention, experts, learning, tools, and context cooperate?
24. Limits, practical choices, and research questions What should a reader conclude, and what evidence is still missing?
25. Glossary, equations, and source atlas Where can a reader check terminology, numbers, and original sources?

Reading paths

If you are focused on model architecture, read Chapters 2–7 and 22. For reinforcement learning, read Chapters 8–12 and 21. For agent training and tool use, read Chapters 13–18, 20, and 23. For benchmarks and deployment trade-offs, read Chapters 1, 7, 19–21, and 24. Chapter 25 serves as a technical glossary, equation index, and file atlas.

Whichever path you take, start with Chapter 1 to keep the four model variants in the paper straight: DeepSeek-V3.1-Terminus, DeepSeek-V3.2-Exp, the final DeepSeek-V3.2, and DeepSeek-V3.2-Speciale represent distinct training stages and capability trade-offs.

Source and numerical conventions

Chapter source notes cite the corresponding report sections, TeX files, and official repository artifacts preserved under ../_sources/. The TeX source archive is stored at ../2512.02556v1-source.tar.gz with ../main.tex as its entry point, and original figures are retained under ../figures/ alongside rasterized versions in assets/.

Unless noted otherwise, K, M, and B denote powers of 1,000. In the continued-training token calculations, however, the paper's sequence counts and token totals only reconcile if 128K denotes 131,072 tokens (128×1024128 \times 1024). We retain the paper's 128K shorthand when discussing the context window and note where the configuration files specify different limits (examined in Chapters 3 and 22). Memory capacities use GB for 10910^9 bytes and GiB for 2302^{30} bytes. Differences between percentage scores are stated in percentage points, while Codeforces comparisons use rating points.

1. The Problem and the Model Family

A language model that answers short prompts fluently can still fall apart on multi-step engineering or research problems. Fixing a software bug requires inspecting source files, writing a patch, running the test suite, and recovering when an initial hypothesis fails. Answering an open-ended research question requires issuing multiple searches, cross-checking sources, and reconciling conflicting claims. Proving a competition math theorem often takes thousands of tokens of Scratchpad exploration before a viable proof strategy emerges.

Tasks like these strain three parts of the stack simultaneously: the model needs strong multi-step reasoning habits, a large reinforcement-learning budget to practice them, and an attention mechanism that can read a long, growing context without blowing up inference cost. DeepSeek-V3.2 tackles all three together, treating sparse attention, RL optimization stability, and synthetic agent environments as mutually reinforcing pieces of a single design.

Why long reasoning changes the economics

Because an autoregressive transformer generates one token at a time conditioned on the entire preceding sequence, a 20,000-token reasoning trace requires forty times as many decode passes as a 500-token reply—and each pass attends over a longer history than the last. Tool use compounds this growth: every file dump, compiler trace, or search snippet returned by an external environment is appended directly to the context window. Even if the model writes terse action calls, verbose tool outputs rapidly fill a 128K window.

Under dense causal attention, every query token compares against every preceding key token. Prefilling a long prompt scales quadratically with sequence length LL, while decoding each new token requires scanning a cache whose length grows linearly with every step. That cost hits twice: once when serving long-horizon user requests in production, and again during reinforcement learning, when the training cluster must sample thousands of long rollouts per update.

To cut the cost of reading long histories, the paper introduces DeepSeek Sparse Attention (DSA). A lightweight module called the lightning indexer scores all past positions, and the main Multi-head Latent Attention (MLA) kernel loads only the top 2,048 token entries per query. The indexer itself still scans the full prefix—a crucial systems nuance we analyze in Chapter 7—but the heavy main-attention read drops from O(L2)O(L^2) to O(Lk)O(Lk) during prefill.

Why architecture alone cannot produce an agent

Making long contexts cheaper to read does not automatically teach a model how to use them. Given a fast 128K context window, a poorly trained assistant will still hallucinate tool arguments, drop constraints halfway through a task, or declare victory without verifying its output.

The authors trace the gap between open-weights models and frontier proprietary systems to two bottlenecks: insufficient post-training RL compute and a shortage of diverse, verifiable agent environments. In DeepSeek-V3.2, the post-training RL budget exceeds 10% of the total pre-training cost (the report states this as a relative share without disclosing raw GPU-hours or dollar figures). Lowering attention cost makes long-horizon rollouts cheaper to sample, while stabilizing off-policy GRPO updates lets the model absorb a much larger RL compute budget across synthetic coding, search, and tool-use environments.

Keeping the four model variants straight

The report tracks four distinct checkpoints across its experiments:

Name Role in the story What the report uses it for
DeepSeek-V3.1-Terminus Preceding dense-attention checkpoint Baseline backbone for architectural parity and speed comparisons
DeepSeek-V3.2-Exp Intermediate checkpoint with DSA Isolating whether converting dense attention to DSA hurts quality
DeepSeek-V3.2 Final general-purpose release Main model trained for reasoning, tool use, coding, search, and chat
DeepSeek-V3.2-Speciale Long-horizon reasoning specialist Pushing math, coding, and Olympiad scores with relaxed length penalties

Separating these checkpoints prevents a common misreading of the benchmark tables. The architectural ablation compares DeepSeek-V3.1-Terminus against DeepSeek-V3.2-Exp, which shares the Terminus training style after continued training to install DSA. The jump in reasoning and agent scores between V3.2-Exp and the final DeepSeek-V3.2 comes from the expanded post-training pipeline—specialist distillation, mixed RL, and synthetic agent environments—not from sparse attention itself.

DeepSeek-V3.2-Speciale branches off the same post-training pipeline but trains exclusively on reasoning data with a weaker length penalty, plus the dataset and proof-verification reward system from DeepSeekMath-V2. According to the official model card, Speciale omits tool-calling support altogether; it is built to maximize competition reasoning performance at the cost of much longer token trajectories, not to serve as a drop-in replacement for the general model.

Three distinct forms of sparsity and truncation

Because DeepSeek-V3.2 uses selection mechanisms at three completely different stages of computation, it helps to separate their scopes upfront:

  1. Expert sparsity (MoE): Each token routes through 8 out of 256 routed feed-forward experts per layer (plus 1 shared expert), bounding the active FFN parameter count per token.
  2. Attention sparsity (DSA): Each query token reads 2,048 historical key-value entries out of a prefix of up to 128K tokens, bounding the main attention cost.
  3. Sampling truncation (top-pp / top-kk): During rollout generation, the sampler zeros out low-probability vocabulary tokens before drawing the next token, which shapes rollout diversity and must be preserved via sampling masks during off-policy RL updates.

Although the paper discusses masks and top-kk selection in all three contexts, they operate on different axes: feed-forward modules, sequence positions, and vocabulary logits.

What the open release includes

The weights and inference code for DeepSeek-V3.2 are released under the MIT license, allowing direct inspection of the layer definitions, quantization formats, and chat templates, as well as local deployment. As with most open-weights frontier releases, however, the full pre-training corpus, distributed RL orchestration code, reward models, and synthetic task generators remain internal. Throughout this book, we cross-check the paper's equations against the released model.py and config.json artifacts so you can see exactly where the paper's high-level description meets the production tensor shapes.

Reading the paper's headline claims

When evaluating the report's three headline claims—frontier parity, Olympiad gold-medal performance, and reduced attention complexity—it pays to look closely at the underlying unit of measurement:

Sources: Report §1 and §3 (sections/01-0-intro.tex, sections/02-post.tex); official model card at the preserved revision. Continue with the foundations.

2. The Foundations the Report Assumes

Before diving into DeepSeek-V3.2's specific modifications, this chapter establishes the core notation and mechanics the report takes for granted: autoregressive tokenization, pre-norm transformer blocks, causal attention and KV caching, and policy-gradient reinforcement learning over multi-turn agent trajectories.

Tokens and next-token probabilities

A tokenizer maps raw text into a sequence of integer IDs drawn from a fixed vocabulary V\mathcal V. Depending on the byte-pair or subword vocabulary, a single token might represent a full word, a subword stem, punctuation, whitespace, or a reserved control symbol such as <|tool▁call▁begin|>. Token counts therefore vary across languages and formatting styles for the exact same semantic content.

At the input layer, each token ID is mapped to a learned embedding vector. A stack of transformer layers refines these vectors into contextual representations, and a final linear head projects the top-layer hidden state into one logit zvz_v per vocabulary item. Applying a softmax yields the next-token probability distribution conditioned on the prefix x≤tx_{\le t}:

p(v∣x≤t)=exp⁡(zv)∑u∈Vexp⁡(zu).p(v\mid x_{\le t})=\frac{\exp(z_v)}{\sum_{u\in\mathcal V}\exp(z_u)}.

During generation, a sampler selects the next token according to a decoding rule (such as temperature scaling followed by top-pp truncation), appends it to the prefix, and runs the next step. Whether the emitted tokens form a natural-language paragraph or a JSON tool invocation makes no difference to the underlying probability model; an external runtime parser watches the output stream and intercepts structured tool calls when a stop sequence appears.

Transformer blocks: communication vs. local computation

Each transformer layer alternates between two operations wrapped in residual connections and root-mean-square normalization (RMSNorm):

h′=h+Attention⁡(Norm⁡(h)),hnext=h′+FFN⁡(Norm⁡(h′)).h'=h+\operatorname{Attention}(\operatorname{Norm}(h)), \qquad h^{\mathrm{next}}=h'+\operatorname{FFN}(\operatorname{Norm}(h')).

Attention moves information across sequence positions, letting token tt read states from tokens s≤ts \le t. The feed-forward network (FFN) transforms features within each position independently, operating on a single token's residual vector after attention has mixed in contextual signals. In a Mixture-of-Experts (MoE) layer, that single dense FFN is replaced by a bank of parallel expert FFNs controlled by a learned router.

Queries, keys, and values

Inside a single attention head, position tt projects its normalized hidden state into a query vector qt∈Rdkq_t \in \mathbb R^{d_k}, while every historical position s≤ts \le t projects its state into a key vector ks∈Rdkk_s \in \mathbb R^{d_k} and a value vector vs∈Rdvv_s \in \mathbb R^{d_v}. The scaled dot product between qtq_t and ksk_s scores their compatibility, and a softmax converts those scores into convex combination weights over the value vectors:

at,s=exp⁡(qt⋅ks/dk)∑r≤texp⁡(qt⋅kr/dk),ot=∑s≤tat,svs.a_{t,s}=\frac{\exp(q_t\cdot k_s/\sqrt{d_k})}{\sum_{r\le t}\exp(q_t\cdot k_r/\sqrt{d_k})}, \qquad o_t=\sum_{s\le t}a_{t,s}v_s.

In short, the query specifies what the current position is looking for, the keys determine where to attend, and the values supply what gets read. Multi-head attention runs dozens of these heads in parallel with distinct learned projections so a token can simultaneously attend to different positions and subspaces, then concatenates and projects the head outputs back into the residual stream.

Causal masking and the quadratic triangle

Because an autoregressive model cannot peek at future tokens when predicting token t+1t+1, a causal mask sets attention logits for all positions s>ts > t to −∞-\infty, driving their softmax weights to zero. Over a prompt of length LL, the number of valid query-key pairs (t,s)(t, s) with 1≤s≤t≤L1 \le s \le t \le L is the lower triangular sum:

1+2+⋯+L=L(L+1)2.1+2+\cdots+L=\frac{L(L+1)}2.

Thus, causal masking cuts the work in half relative to bidirectional attention, but the pair count still scales as Θ(L2)\Theta(L^2).

Prefill, decode, and the KV cache

Inference splits into two distinct execution regimes:

To avoid recomputing keys and values for every historical token at every decode step, inference engines maintain a KV cache in GPU memory. Standard multi-head attention caches explicit ksk_s and vsv_s tensors for every head, which quickly consumes tens of gigabytes on long sequences. DeepSeek's Multi-head Latent Attention (MLA) compresses that cache into a shared low-rank latent vector per token, while DeepSeek Sparse Attention (DSA) reduces how many cached tokens each query actually reads. MLA shrinks the storage footprint of the history; DSA shrinks the read volume per step.

From next-token cross-entropy to post-training

Pre-training minimizes the standard cross-entropy loss over a massive text corpus:

LLM=−∑tlog⁡pθ(xt+1∣x≤t).\mathcal L_{\mathrm{LM}}=-\sum_t\log p_\theta(x_{t+1}\mid x_{\le t}).

Predicting the next token over trillions of words teaches the base model syntax, world knowledge, code idioms, and reasoning patterns, but it does not align the model to follow multi-constraint user instructions or recover from runtime errors in an interactive environment. Post-training bridges that gap through three mechanisms:

  1. Supervised fine-tuning (SFT) trains on curated prompt-response demonstrations.
  2. Knowledge distillation transfers behavior from specialized domain teacher checkpoints into a single general student checkpoint.
  3. Reinforcement learning (RL) samples candidate trajectories from the model, scores them with rule-based verifiers or reward models, and updates the weights to increase the probability of high-scoring trajectories.

Policies, agent trajectories, and advantages

In RL terminology, the language model is a stochastic policy πθ\pi_\theta parameterized by weights θ\theta. For a single-turn prompt qq, the probability of generating an output sequence o=(o1,…,o∣o∣)o = (o_1, \dots, o_{|o|}) factors autoregressively over its tokens:

πθ(o∣q)=∏t=1∣o∣πθ(ot∣q,o<t).\pi_\theta(o\mid q)=\prod_{t=1}^{|o|}\pi_\theta(o_t\mid q,o_{<t}).

In a multi-turn agent environment, a trajectory interleaves model-generated tokens (internal reasoning and tool calls) with environment observations (command outputs, search results, or error traces). Although the model conditions on the entire interleaved transcript when generating its next action, only the tokens actually sampled from πθ\pi_\theta are actions of the policy; environment observations must be masked out when computing policy gradients.

A verifier or reward function assigns a scalar reward to the completed trajectory, and Group Relative Policy Optimization (GRPO, detailed in Chapter 9) converts a group of rewards for the same prompt into a baseline-subtracted advantage. If four sampled rollouts receive binary rewards [1,1,0,0][1, 1, 0, 0], their group mean is 0.50.5, yielding mean-centered advantages [0.5,0.5,−0.5,−0.5][0.5, 0.5, -0.5, -0.5] that push probability mass toward the successful rollouts and away from the failures.

Because a verifier only needs to check a final answer or run a unit test suite rather than grade every intermediate step, tasks that are hard to solve but cheap to verify—such as software patches, math proofs, and constraint-satisfaction puzzles—form the backbone of scalable RL training. Even so, an RL policy is only as good as its verifier: if a test suite has gaps or a constraint checker has a bug, the optimizer will happily exploit it.

Sources: Transformer and RL policy formulation in Report §§2–3; released model.py (MLA, Block, and Transformer classes) in the pinned official implementation. Continue with the backbone and experts.

3. Inside the Inherited Backbone

DeepSeek-V3.2 builds directly on the Mixture-of-Experts (MoE) transformer backbone introduced in DeepSeek-V3 and refined through V3.1-Terminus. While sparse attention is the headline architectural addition in V3.2, attention is only one piece of the forward pass: every token still flows through embeddings, RMSNorm layers, query/key/value projections, routed feed-forward experts, and a 129,280-entry vocabulary head.

Inspecting the revision-pinned config.json and model.py files in the official repository anchors the paper's equations in concrete tensor dimensions.

Architectural dimensions in the released checkpoint

Component Preserved release value Role in the network
Vocabulary (vocab_size) 129,280 Total token identifiers in the embedding and LM head
Hidden width (dim) 7,168 Residual stream dimension across all layers
Main transformer layers (n_layers) 61 Total stacked attention + FFN blocks
Initial dense FFN layers (n_dense_layers) 3 Leading layers that use a standard dense FFN instead of MoE
Main attention heads (n_heads) 128 Parallel query/output heads per MLA layer
Query latent rank (q_lora_rank) 1,536 Bottleneck dimension for low-rank query compression
KV latent rank (kv_lora_rank) 512 Compressed latent width stored in the MLA cache
Non-RoPE query/key head width (qk_nope_head_dim) 128 Content-addressing head dimension without positional rotation
RoPE head width (qk_rope_head_dim) 64 Decoupled rotary-position head dimension
Value head width (v_head_dim) 128 Per-head value dimension before output projection
Routed experts per MoE layer (n_routed_experts) 256 Conditional FFN experts available in Layers 3–60
Activated routed experts (n_activated_experts) 8 Routed experts evaluated per token in each MoE layer
Shared experts (n_shared_experts) 1 Always-on expert evaluated for every token in each MoE layer
Expert intermediate width (moe_inter_dim) 2,048 Hidden dimension inside each routed and shared expert
Indexer heads / width (index_n_heads / index_head_dim) 64 / 128 Head count and dimension for the DSA lightning indexer
Attention selection budget (index_topk) 2,048 Number of historical tokens selected per query by DSA

The Hugging Face config.json also lists num_nextn_predict_layers: 1, which carries over the auxiliary Multi-Token Prediction (MTP) head from DeepSeek-V3. During standard autoregressive inference in model.py, the model executes the 61 main layers; using the MTP head for speculative decoding requires dedicated runtime support outside the minimal reference script.

Why 128 heads do not mean a 128-head KV cache

A glance at num_key_value_heads: 128 in config.json can mislead off-the-shelf memory calculators designed for standard Grouped-Query Attention (GQA). In a conventional transformer with 128 KV heads, caching per-head keys and values for every token would require storing 128×(192+128)=40,960128 \times (192 + 128) = 40{,}960 elements per token per layer.

DeepSeek-V3.2 uses Multi-head Latent Attention (MLA), which never materializes per-head key and value caches in memory. Instead, each layer caches a single shared 512-dimensional latent vector alongside a 64-dimensional rotary positional key—just 576 elements per token per layer—and folds the per-head expansion matrices into the query and output projections at runtime. Chapter 4 walks through this matrix absorption step by step.

Inside an MoE layer: SwiGLU experts and group-limited routing

After the first three layers (which use standard dense SwiGLU feed-forward networks with intermediate dimension 18,432), the remaining 58 layers replace the dense FFN with an MoE module. Each individual expert ee is a gated SwiGLU network mapping R7168→R7168\mathbb R^{7168} \to \mathbb R^{7168} through a 2,048-dimensional bottleneck:

Ee(x)=W2,e[SiLU⁡(W1,ex)⊙(W3,ex)].E_e(x)=W_{2,e}\left[\operatorname{SiLU}(W_{1,e}x)\odot(W_{3,e}x)\right].

For each token tt, a learned router selects a subset Et\mathcal E_t of 8 routed experts out of 256, scales their outputs by gating weights gt,eg_{t,e}, and adds the result to an always-active shared expert:

yt=Eshared(xt)+∑e∈Etgt,eEe(xt).y_t=E_{\mathrm{shared}}(x_t)+\sum_{e\in\mathcal E_t}g_{t,e}E_e(x_t).

In the reference implementation (Gate in model.py), routing follows a two-stage group-limited procedure:

  1. Unbiased affinity scoring: The router computes a linear projection followed by a sigmoid activation, producing raw affinity scores st,e∈(0,1)s_{t,e} \in (0, 1) across all 256 experts.
  2. Biased group and top-kk selection: A learned load-balancing bias beb_e is added to form selection scores st,e′=st,e+bes'_{t,e} = s_{t,e} + b_e. The 256 experts are partitioned into 8 groups of 32; each group is scored by summing its top 2 biased expert scores, the top 4 groups are retained, and the top 8 experts overall are picked from those 4 groups.
  3. Unbiased weight normalization: Once the 8 expert IDs Et\mathcal E_t are chosen, their combination weights gt,eg_{t,e} are computed by normalizing the original unbiased sigmoid scores st,es_{t,e} across the 8 selected experts and multiplying by route_scale = 2.5.

Separating biased discrete selection from unbiased continuous weighting keeps load balancing from distorting the magnitude of expert contributions. At the same time, because top-kk selection is a discrete argmax operation, tiny floating-point shifts between rollout generation and training replay can flip which experts cross the threshold—the exact instability that motivates the Keep Routing replay mechanism covered in Chapter 11.

Parameter accounting: 671B total vs. 37B active

The DeepSeek-V3 backbone is cited at roughly 671B total parameters with 37B activated per token (adding the V3.2 lightning indexer changes the total by less than 0.2%). We can verify how the MoE layers dominate that budget directly from the tensor shapes.

Ignoring normalization vectors and router biases, a single expert contains three matrices of shape 7168×20487168 \times 2048:

3×7168×2048=44,040,192 parameters.3\times7168\times2048=44{,}040{,}192\text{ parameters.}

Across the 58 MoE layers, the 256 routed experts per layer account for:

58×256×44,040,192≈653.9B parameters.58\times256\times44{,}040{,}192\approx653.9\text{B parameters.}

When processing a single token, however, each MoE layer evaluates only 8 routed experts plus 1 shared expert, activating:

58×9×44,040,192≈23.0B expert parameters.58\times9\times44{,}040{,}192\approx23.0\text{B expert parameters.}

Adding the 3 initial dense FFN layers, the 61 MLA blocks, the embedding matrix, the LM output head, and the MTP module brings the per-token active count to roughly 37B parameters and the stored total to roughly 671B.

While a single token only pays the FLOP cost of 37B parameters, a serving cluster cannot fit the model into the VRAM of a 37B dense checkpoint: across a batch of tokens, almost all 256 experts in every layer will be touched, so the full 671B weight footprint must stay resident in high-bandwidth memory across the GPU cluster.

MoE layer experts vs. post-training domain specialists

The paper uses the word "specialist" for two completely unrelated mechanisms at different scales:

Term Granularity How it works
MoE routed expert A single 7168→2048→71687168 \to 2048 \to 7168 SwiGLU module inside one layer Dynamically selected per token during the forward pass by the layer's router
Post-training domain specialist A full 671B checkpoint fine-tuned with RL on a single domain (e.g., math, code, or search) Used offline to generate synthetic distillation trajectories for training the unified V3.2 checkpoint

Domain specialists exist only during the post-training pipeline (Chapter 8); at inference time, a single unified checkpoint serves all tasks, and its internal MoE routers pick combinations of FFN submodules token by token without any explicit notion of task labels.

Reconciling the three context-length numbers in the release

If you inspect the paper alongside the repository files, you will encounter three different sequence-length constants:

Throughout our analysis, we use 128K when discussing the paper's training and evaluation regime, and write out explicit token counts (131,072131{,}072 vs. 128,000128{,}000) whenever we compute exact FLOPs or memory footprints.

Sources: Report §2 (sections/01-method.tex); released config.json; pinned inference/config_671B_v3.2.json and inference/model.py (Gate, MoE, and Block classes). Continue with Multi-head Latent Attention.

4. Multi-Head Latent Attention

Multi-Head Latent Attention (MLA) compresses the per-token attention state stored in the KV cache. DeepSeek-V3.2 inherits MLA directly from the V3 backbone and wraps sparse token selection around it. Understanding how MLA structures its cache explains both what DeepSeek Sparse Attention (DSA) actually selects and why sharing each selected token entry across all 128 query heads maps so cleanly onto GPU memory hierarchies.

The core algebraic insight of MLA is straightforward: instead of caching explicit per-head key and value vectors for every past token, the layer caches a single low-rank latent vector and reconstructs per-head keys and values through linear projections. Because those reconstructions are linear, the up-projection matrices can be absorbed directly into the query and output projections during decoding.

Compressing keys and values into a shared latent

Let hs∈Rdh_s \in \mathbb R^d (d=7168d = 7168) be the hidden state at historical position ss. MLA projects hsh_s down into a compressed key-value latent vector csKV∈Rdcc_s^{KV} \in \mathbb R^{d_c} (dc=512d_c = 512) and applies RMSNorm:

csKV=Norm⁡(WDKVhs).c_s^{KV}=\operatorname{Norm}(W^{DKV}h_s).

For each attention head i∈{1,…,128}i \in \{1, \dots, 128\}, learned up-projection matrices WiK∈R128×512W_i^K \in \mathbb R^{128 \times 512} and WiV∈R128×512W_i^V \in \mathbb R^{128 \times 512} map that shared 512-dimensional latent into head-specific content keys and values:

ks,iC=WiKcsKV,vs,i=WiVcsKV.k_{s,i}^{C}=W_i^Kc_s^{KV},\qquad v_{s,i}=W_i^Vc_s^{KV}.

Even though all 128 heads read from the same compressed latent csKVc_s^{KV}, each head applies its own learned subspace projection WiKW_i^K and WiVW_i^V, preserving distinct per-head attention patterns. Queries undergo a similar low-rank bottleneck (7168→1536→128 heads7168 \to 1536 \to 128 \text{ heads}) to save parameter and activation memory, though only the key-value latent csKVc_s^{KV} persists in the historical cache across decoding steps.

Absorbing the key up-projection into the query

During decoding, explicitly multiplying WiKcsKVW_i^K c_s^{KV} for every historical token ss and every head ii would defeat the bandwidth savings of caching a compact latent. Instead, look at the content compatibility score between query head ii at current position tt and historical position ss:

(qt,iC)⊤ks,iC=(qt,iC)⊤WiKcsKV.(q_{t,i}^C)^\top k_{s,i}^C = (q_{t,i}^C)^\top W_i^Kc_s^{KV}.

By associativity of matrix multiplication, we can group WiKW_i^K with the current query vector instead of the historical latent:

((WiK)⊤qt,iC)⏟qt,iA⊤csKV.\underbrace{\left((W_i^K)^\top q_{t,i}^C\right)}_{q_{t,i}^{A}}{}^\top c_s^{KV}.

For a single new decode token tt, the model multiplies qt,iC∈R128q_{t,i}^C \in \mathbb R^{128} by (WiK)⊤(W_i^K)^\top once to form an absorbed query qt,iA∈R512q_{t,i}^A \in \mathbb R^{512} in latent space. All 128 absorbed query heads then compute dot products against the exact same cached vector csKV∈R512c_s^{KV} \in \mathbb R^{512}, eliminating per-head key materialization across the historical sequence.

Absorbing the value up-projection into the output

The same associativity trick eliminates per-head value reconstruction. Given softmax attention weights at,s,ia_{t,s,i} for head ii, the head output is:

ot,i=∑sat,s,ivs,i=∑sat,s,iWiVcsKV.o_{t,i}=\sum_sa_{t,s,i}v_{s,i}=\sum_sa_{t,s,i}W_i^Vc_s^{KV}.

Factoring the position-independent matrix WiVW_i^V outside the sum over ss gives:

ot,i=WiV(∑sat,s,icsKV).o_{t,i}=W_i^V\left(\sum_sa_{t,s,i}c_s^{KV}\right).

Instead of expanding csKVc_s^{KV} into 128 distinct value vectors at every historical position ss, the attention kernel accumulates a weighted sum of the shared 512-dimensional latents csKVc_s^{KV} for each head, and only multiplies by WiVW_i^V once per head after the sequence reduction is complete (or fuses WiVW_i^V directly into the final output projection WOW^O).

Why rotary position embeddings require a separate 64-dim path

Relative positional encoding via Rotary Position Embedding (RoPE) applies a position-dependent rotation matrix RtR_t to queries and RsR_s to keys so that their inner product depends on the relative offset t−st - s. If we tried to apply RoPE inside the compressed latent before multiplying by WiKW_i^K, the position-dependent matrix RsR_s would sit between WiKW_i^K and csKVc_s^{KV}, preventing us from absorbing (WiK)⊤(W_i^K)^\top into the query vector at step tt.

MLA solves this by decoupling content addressing from positional addressing. Alongside the 512-dimensional content latent csKVc_s^{KV}, each token produces a single shared 64-dimensional positional key ksR∈R64k_s^R \in \mathbb R^{64} rotated by RsR_s, while each query head produces a 64-dimensional positional query qt,iR∈R64q_{t,i}^R \in \mathbb R^{64} rotated by RtR_t. The full attention logit adds the two inner products:

ℓt,s,i=(qt,iA)⊤csKV+(qt,iR)⊤ksR,\ell_{t,s,i}=(q_{t,i}^{A})^\top c_s^{KV} +(q_{t,i}^{R})^\top k_s^{R},

followed by softmax scaling (1128+64\frac{1}{\sqrt{128 + 64}}) and causal masking. Each historical token therefore caches 512+64=576512 + 64 = 576 numbers per layer—shared across all 128 query heads. (Chapter 22 covers the exact runtime scale factors and RMSNorm placement in model.py.)

MHA mode vs. MQA mode execution

Appendix A of the report contrasts the two ways an engine can execute the exact same MLA layer:

Authors' diagram of MLA in MHA mode, with expanded per-head keys and values.

Authors' diagram of MLA in MQA mode, with shared latent history and absorbed projections.

Reproduced from Report Appendix A (Figure 7). Both diagrams compute the same mathematical function, arranged for different compute-to-memory-bandwidth regimes.

In DeepSeek-V3.1-Terminus, the engine runs MHA mode for training and prefill, and switches to MQA mode for decoding. In DeepSeek-V3.2, DSA is built specifically around MQA mode: when the lightning indexer selects 2,048 token indices for query tt, a sparse MQA kernel gathers each selected 576-element entry once from HBM and reuses it across all 128 query heads in SRAM. Only on short-sequence prefills—where dense matrix kernels outperform sparse gather kernels—does the engine fall back to a masked MHA kernel to simulate the sparse selection pattern.

Sizing the MLA cache at 128K

To see the memory footprint in concrete terms, consider a single sequence of L=131,072L = 131{,}072 tokens across all 61 layers. If both the 512-dimensional latent csKVc_s^{KV} and the 64-dimensional RoPE key ksRk_s^R are stored in BF16 (2 bytes per element), the MLA cache for one sequence requires:

61×131,072×(512+64)×2=9,210,691,584 bytes≈9.21 GB (8.58 GiB).61\times131{,}072\times(512+64)\times2 =9{,}210{,}691{,}584\ \text{bytes} \approx 9.21\text{ GB}\ (8.58\text{ GiB}).

By comparison, an un-compressed 128-head BF16 KV cache with head dimensions 192+128=320192 + 128 = 320 would require 61×131,072×128×320×2≈655 GB61 \times 131{,}072 \times 128 \times 320 \times 2 \approx 655\text{ GB} per sequence. Furthermore, as noted in the model.py source comments, production deployments quantize the KV cache to FP8, cutting the MLA footprint roughly in half again (though DSA adds a small separate cache for indexer keys, which we account for in Chapter 7).

Why MLA and DSA fit together

MLA compresses each token's feature vector along the channel axis without merging neighboring tokens along the time axis; every token position ss still has its own distinct cache slot csKVc_s^{KV}. That design gives DSA clean, fine-grained addressability—it can cherry-pick individual token positions rather than coarse multi-token blocks—while MLA's shared-latent MQA layout ensures that every irregular memory gather from the KV cache feeds all 128 query heads at once.

Sources: Report §2.1 and Appendix A (sections/01-method.tex, sections/appendix.tex); pinned inference/model.py (MLA class) in the official inference repository. Continue with the lightning indexer.

5. The Lightning Indexer and Sparse Selection

DeepSeek Sparse Attention (DSA) splits attention into a cheap candidate-ranking pass and an expressive latent-reading pass. First, the lightning indexer scans the prefix and scores every historical token position for the current query. Next, a top-kk selector picks the 2,048 highest-scoring positions, and Multi-head Latent Attention (MLA) runs only over those selected entries.

Because the ranking is computed freshly at every layer and every query position, token selection is fully dynamic and content-dependent rather than constrained to fixed stride patterns or local sliding windows.

DSA architecture overview

Authors' DSA architecture: a lightning indexer selects shared MLA latent entries for core attention.

Reproduced from Report Figure 1. Green modules denote the lightning indexer and top-kk selector; black paths denote the surrounding MLA computation.

As the diagram shows, the indexer runs alongside MLA inside every transformer block. In the released implementation, the indexer query branches off the same normalized low-rank query latent (qtlora∈R1536q_t^{\text{lora}} \in \mathbb R^{1536}) used by main attention, whereas the historical indexer key ksI∈R128k_s^I \in \mathbb R^{128} is projected directly from the layer's input hidden state hsh_s and stored in its own lightweight cache.

The lightning indexer scoring equation

For a query token at position tt and a candidate historical token at position s≤ts \le t, the lightning indexer computes a scalar relevance score It,sI_{t,s}:

It,s=∑j=1HIwt,jIReLU⁡(qt,jI⋅ksI).I_{t,s}=\sum_{j=1}^{H^I}w_{t,j}^I \operatorname{ReLU}\left(q_{t,j}^I\cdot k_s^I\right).

Each variable plays a specific role in keeping the scan fast:

Symbol Dimension in V3.2 Role
HIH^I 6464 Number of indexer query heads (half the 128 heads of main MLA)
qt,jIq_{t,j}^I R128\mathbb R^{128} Indexer query vector for head jj at current token tt
ksIk_s^I R128\mathbb R^{128} Single shared indexer key vector at historical token ss
wt,jIw_{t,j}^I R\mathbb R Query-dependent scalar weight combining head jj's contribution
It,sI_{t,s} R\mathbb R Final scalar ranking score for candidate token ss

Notice that ksIk_s^I has no head index jj: just as MLA in MQA mode shares one latent vector across all query heads, the indexer shares a single 128-dimensional key vector ksIk_s^I across all 64 indexer query heads. Replacing a softmax with ReLU⁡\operatorname{ReLU} avoids expensive row-wise exponentiation and normalization during the scan, and executing the inner products in FP8 keeps memory bandwidth and arithmetic cost small. Because the head weights wt,jIw_{t,j}^I come from an unconstrained linear projection of hth_t, individual weights wt,jIw_{t,j}^I can be positive or negative even though ReLU⁡(qt,jI⋅ksI)≥0\operatorname{ReLU}(q_{t,j}^I \cdot k_s^I) \ge 0.

How head weights shape candidate selection

To see how the query-dependent head weights wt,jIw_{t,j}^I steer selection, consider a two-head toy slice with weights wtI=(0.75,0.25)w_t^I = (0.75, 0.25) scoring four historical tokens:

Candidate ss Raw dot products (qt,1I⋅ksI,  qt,2I⋅ksI)(q_{t,1}^I\cdot k_s^I,\; q_{t,2}^I\cdot k_s^I) After ReLU⁡\operatorname{ReLU} Aggregate score It,sI_{t,s}
Position A (4,−2)(4, -2) (4,0)(4, 0) 0.75(4)+0.25(0)=3.000.75(4) + 0.25(0) = 3.00
Position B (1,8)(1, 8) (1,8)(1, 8) 0.75(1)+0.25(8)=2.750.75(1) + 0.25(8) = 2.75
Position C (3,2)(3, 2) (3,2)(3, 2) 0.75(3)+0.25(2)=2.750.75(3) + 0.25(2) = 2.75
Position D (−1,6)(-1, 6) (0,6)(0, 6) 0.75(0)+0.25(6)=1.500.75(0) + 0.25(6) = 1.50

With wtI=(0.75,0.25)w_t^I = (0.75, 0.25), a top-2 selector picks Position A and either B or C. If the next query token shifts its head weights to (0.20,0.80)(0.20, 0.80), Position B jumps to 6.606.60 and Position D rises to 4.804.80, completely changing which historical tokens get loaded into MLA.

Once the selector passes those top-kk indices to MLA, main attention computes its own softmax weights from scratch using the full 576-dimensional MLA latents; the indexer score It,sI_{t,s} only determines membership in the active set St\mathcal S_t, not the final attention weight inside MLA.

Shared token-level top-kk selection

During sparse training and inference, each query tt selects at most k=2,048k = 2{,}048 historical positions:

St=TopK⁡s≤t(It,s),ut=Attn⁡(ht,{cs:s∈St}).\mathcal S_t=\operatorname{TopK}_{s\le t}(I_{t,s}), \qquad u_t=\operatorname{Attn}\left(h_t,\{c_s:s\in\mathcal S_t\}\right).

If t≤2,048t \le 2{,}048, the prefix has no more than kk tokens and DSA reads the entire history identically to dense MLA. Once t>2,048t > 2{,}048, St\mathcal S_t contains the 2,048 indices with the highest It,sI_{t,s} scores.

Three structural properties of St\mathcal S_t stand out:

  1. Shared across main query heads: At a given layer and token tt, all 128 MLA heads attend over the same 2,048 selected positions St\mathcal S_t (though each head computes its own independent softmax distribution over those 2,048 entries). Sharing St\mathcal S_t across heads is what allows the sparse MQA kernel to load each selected latent csKVc_s^{KV} once and reuse it 128 times.
  2. Token-level granularity: Selection picks individual token indices rather than coarse 64-token or 128-token page blocks, avoiding wasted budget on irrelevant tokens that happen to sit next to a single critical keyword.
  3. No hardcoded local window: Unlike sliding-window + sink-token architectures, the V3.2 DSA prototype does not reserve fixed slots for initial sink tokens or a mandatory local window; any recency bias or anchor-token retention is learned directly by the indexer (which has its own RoPE dimensions).

Enforcing causality across both stages

To prevent information leakage from future tokens s>ts > t, causal masking must hold in both the indexer and main attention. During prefill, model.py adds an upper-triangular −∞-\infty mask to It,sI_{t,s} before calling torch.topk.

A subtle boundary case arises during prefill for early tokens where t<2,048t < 2{,}048: when a fixed-width topk(2048) kernel runs on row tt of a rectangular score matrix, the remaining 2,048−t2{,}048 - t slots in the returned index tensor will be filled with −∞-\infty-scored future indices s>ts > t. Consequently, the main MLA stage must still apply its own causal mask (or filter out indices s>ts > t) so those padding slots receive zero probability in the softmax. During single-token decoding, the cache slice only contains positions s≤ts \le t, so future tokens are absent by construction.

Hadamard rotation and FP8 quantization in model.py

Inspecting the Indexer class in inference/model.py reveals several engineering refinements beyond Equation (1) of the paper:

The retrieval bottleneck

Why not simply use main attention's own query-key dot products to pick the top 2,048 entries? Because evaluating 128 heads of 576-dimensional dot products across all s≤ts \le t is already half the cost of dense MLA. The indexer cuts that scanning cost by reducing the head count from 128 to 64, shrinking the head dimension from 576 to 128, sharing a single 128-byte FP8 key across heads, and using ReLU⁡\operatorname{ReLU} instead of softmax.

The trade-off is a hard retrieval bottleneck: if the lightning indexer fails to rank a critical historical token inside the top 2,048 at layer ℓ\ell, main attention at layer ℓ\ell gets zero signal from that token and cannot send gradients back through the discrete topk operator to fix the miss. Training the indexer to track main attention accurately before switching on sparsity is therefore essential—and is the subject of Chapter 6.

Sources: Report §2.1 (sections/01-method.tex); pinned inference/model.py (Indexer class) in the official repository. Continue with continued training.

6. Converting a Dense Model to Sparse Attention

DeepSeek-V3.2 does not train a 671B sparse-attention model from random initialization. Instead, it starts from the dense DeepSeek-V3.1-Terminus base checkpoint—already extended to a 128K context window—and converts it to DeepSeek Sparse Attention (DSA) through a two-stage continued pre-training curriculum totaling roughly 945.8B tokens.

Retrofitting sparse selection onto a pre-trained dense model poses an obvious bootstrap problem: if you turn on top-2,048 truncation while the lightning indexer weights are still random, every attention layer suddenly loses access to 98% of a 128K context window, corrupting hidden states and destabilizing gradients across the backbone. DeepSeek avoids this shock by warming up the indexer against the frozen dense model before switching on sparse selection.

Stage 1: Dense warm-up (freezing the backbone to train the selector)

In the dense warm-up stage, all inherited backbone parameters remain frozen and main attention continues to run densely over the full causal prefix. Only the newly initialized lightning indexer parameters are updated.

To give the indexer a dense supervision target without hand-labeled retrieval annotations, the authors extract the actual softmax attention distributions at,s,ia_{t,s,i} computed by the 128 main MLA heads at query tt, sum them across all heads ii, and L1-normalize the result across historical positions s≤ts \le t:

p~t,s=∑i=1Hat,s,i,pt,s=p~t,s∑r≤tp~t,r.\widetilde p_{t,s}=\sum_{i=1}^{H} a_{t,s,i}, \qquad p_{t,s}=\frac{\widetilde p_{t,s}}{\sum_{r\le t}\widetilde p_{t,r}}.

Because each head's causal attention distribution already sums to 11 over s≤ts \le t, normalizing their sum simply averages the 128 head distributions into a single consensus distribution pt,:p_{t,:} over the prefix. That consensus target matches the structural constraint of DSA, which picks one shared set of 2,048 token positions for all 128 MLA heads.

The indexer scores It,:I_{t,:} are passed through a softmax over s≤ts \le t, and the indexer is trained to minimize the forward Kullback-Leibler (KL) divergence from the teacher distribution pt,:p_{t,:}:

LI=∑tDKL(pt,:  ∥  Softmax⁡(It,:)).\mathcal L^I=\sum_t D_{\mathrm{KL}} \left(p_{t,:}\;\middle\|\;\operatorname{Softmax}(I_{t,:})\right).

Using the forward KL divergence DKL(p∥q)=∑spslog⁡(ps/qs)D_{\mathrm{KL}}(p \| q) = \sum_s p_s \log(p_s / q_s) is a deliberate choice: forward KL is mean-seeking (zero-avoiding), meaning it heavily penalizes the student distribution q=Softmax⁡(It,:)q = \operatorname{Softmax}(I_{t,:}) whenever qt,sq_{t,s} assigns near-zero probability to a position ss where any group of main attention heads placed substantial mass pt,sp_{t,s}.

For example, if four historical positions receive consensus attention mass p=(0.60,0.25,0.10,0.05)p = (0.60, 0.25, 0.10, 0.05) and an untrained indexer initially assigns q=(0.05,0.10,0.25,0.60)q = (0.05, 0.10, 0.25, 0.60), a top-2 selector would drop the token carrying 60% of the teacher's attention weight. Minimizing DKL(p∥q)D_{\mathrm{KL}}(p \| q) rapidly pulls the indexer's top logits into alignment with the high-mass positions of the frozen dense model.

Warm-up compute budget

The dense warm-up stage is short and uses a relatively high learning rate of 10−310^{-3} (safe because the pre-trained backbone is frozen). Training runs for 1,000 steps with a batch size of 16 sequences of 128K tokens, which with 128K=131,072128\text{K} = 131{,}072 tokens gives:

1,000×16×131,072=2,097,152,000 tokens (≈2.1B tokens).1{,}000\times16\times131{,}072=2{,}097{,}152{,}000\text{ tokens}\ (\approx 2.1\text{B tokens}).

Stage 2: Sparse training (co-adapting the backbone and selector)

Once the indexer can reliably identify the tokens that dense MLA attends to, Stage 2 turns on top-kk sparse selection (k=2,048k = 2{,}048) and unfreezes all backbone parameters so the model can adapt its representations to sparse reading.

During this stage, main MLA only computes attention over the selected index set St=TopK⁡s≤t(It,s)\mathcal S_t = \operatorname{TopK}_{s \le t}(I_{t,s}). Consequently, the teacher distribution pt,Stp_{t,\mathcal S_t} is only available on the selected subset St\mathcal S_t, and the indexer's KL loss is restricted to that same active support:

LI=∑tDKL(pt,St  ∥  Softmax⁡(It,St)).\mathcal L^I=\sum_t D_{\mathrm{KL}} \left(p_{t,\mathcal S_t}\;\middle\|\; \operatorname{Softmax}(I_{t,\mathcal S_t})\right).

Here, the main attention weights at,s,ia_{t,s,i} are already softmax-normalized over s∈Sts \in \mathcal S_t, and the indexer softmax is likewise taken over the 2,048 logits in St\mathcal S_t. As the un-frozen backbone adjusts its attention heads to work within a 2,048-token budget, this within-set KL loss keeps the indexer's relative ranking calibrated to the evolving main attention heads.

Detached gradients: why LLM\mathcal L_{\mathrm{LM}} and LI\mathcal L^I are decoupled

A crucial implementation detail in Stage 2 is that the indexer inputs are detached from the computation graph (stop_gradient), separating the backward pass into two independent optimization paths:

  1. Backbone update: The standard next-token cross-entropy loss LLM\mathcal L_{\mathrm{LM}} backpropagates through the sparse MLA layers, MoE routers, and experts, updating the main model weights without sending any gradients into the indexer.
  2. Indexer update: The KL alignment loss LI\mathcal L^I backpropagates only into the lightning indexer parameters; because its hidden-state and query-latent inputs are detached, LI\mathcal L^I never perturbs the backbone's residual stream or query projections to make the indexer's job artificially easy.

Because the discrete TopK⁡\operatorname{TopK} operator has zero gradient almost everywhere, DeepSeek does not attempt to differentiate LLM\mathcal L_{\mathrm{LM}} through token selection via straight-through estimators or Gumbel-Softmax relaxations. Instead, language modeling adapts the reader to whatever 2,048 tokens are selected, while KL distillation keeps the selector tracking the reader's preferences.

Sparse adaptation compute budget

Stage 2 drops the learning rate to 7.3×10−67.3 \times 10^{-6} and runs for 15,000 steps at a batch size of 480 sequences of 128K tokens:

15,000×480×131,072=943,718,400,000 tokens (≈943.7B tokens).15{,}000\times480\times131{,}072=943{,}718{,}400{,}000\text{ tokens}\ (\approx 943.7\text{B tokens}).

At nearly a trillion tokens—roughly 450 times the warm-up budget—Stage 2 is a major continued pre-training run in its own right. Both stages sample from the exact same 128K long-context extension corpus used for DeepSeek-V3.1-Terminus, ensuring that comparisons between Terminus and the resulting DeepSeek-V3.2-Exp checkpoint isolate the transition from dense MLA to DSA rather than a shift in data mixture.

Trade-offs of attention-matching supervision

Using summed attention weights as the retrieval target is pragmatic, though it comes with two theoretical approximations worth noting:

Even with those approximations, the benchmark comparison between V3.1-Terminus and V3.2-Exp (examined in Chapter 19) shows that two-stage distillation plus 943.7B tokens of sparse adaptation preserves short- and long-context quality across standard evaluations, setting the stage for the systems cost analysis in Chapter 7.

Sources: Report §2.1.1 and §2.2 (sections/01-method.tex). Continue with computation, memory, and inference cost.

7. Computation, Memory, and Inference Cost

DeepSeek Sparse Attention (DSA) makes the heavy MLA reader sparse, but it does not eliminate the lightning indexer's prefix scan, shrink the total KV cache footprint, or reduce the FLOPs spent in MoE feed-forward layers. Building an accurate mental model of V3.2's performance requires separating the pieces that scale with the sparse budget k=2,048k = 2{,}048 from the pieces that still scale with the full sequence length LL.

Counting query-key pairs in main attention

Over a prompt of length LL, dense causal attention evaluates all lower-triangular pairs (t,s)(t, s) with 1≤s≤t≤L1 \le s \le t \le L, totaling L(L+1)/2L(L+1)/2 interactions per layer. Under DSA, each query tt attends to at most kk historical tokens, capping the total main-attention pairs during prefill at:

∑t=1Lmin⁡(t,k).\sum_{t=1}^{L}\min(t,k).

When L≥kL \ge k, the first kk tokens attend densely to their short prefixes while the remaining L−kL - k tokens each attend to exactly kk entries:

k(k+1)2+(L−k)k=Lk−k(k−1)2.\frac{k(k+1)}2+(L-k)k =Lk-\frac{k(k-1)}2.

Plugging in the paper's full context window L=131,072L = 131{,}072 and sparse budget k=2,048k = 2{,}048 illustrates the gap between prefill and final-token decode:

The prefill ratio (32.25×32.25\times) is roughly half the final-token decode ratio (64×64\times) because the average prefix length across a prompt of length LL is L/2L/2, not LL.

Why full-sequence complexity is still asymptotically Θ(L2)\Theta(L^2)

Although main attention drops from Θ(L2)\Theta(L^2) to Θ(Lk)\Theta(Lk) during prefill, the lightning indexer must still score every valid candidate pair (t,s)(t, s) with s≤ts \le t to determine which kk indices win. Writing out the total prefill cost of a transformer block as a function of LL gives three scaling regimes:

CDSA(L)=aIL2+aALk+bL+Ctopk(L).C_{\mathrm{DSA}}(L)=a_I L^2+a_A Lk+bL+C_{\mathrm{topk}}(L).

Here, aIL2a_I L^2 captures the quadratic prefix scan inside the lightning indexer, aALka_A Lk captures the sparse MLA read over kk tokens, bLbL aggregates token-wise linear work (QKV/output projections and the 9 active MoE experts per token), and Ctopk(L)C_{\mathrm{topk}}(L) represents the top-kk selection kernel.

Because aI>0a_I > 0, the asymptotic complexity as L→∞L \to \infty for fixed kk remains Θ(L2)\Theta(L^2). What makes DSA fast at L=128KL = 128\text{K} is the ratio of the leading constants aI≪aAa_I \ll a_A:

  1. Fewer heads and narrower vectors: The indexer computes 64 heads of width 128 (64×128=8,19264 \times 128 = 8{,}192 multiply-adds per pair, with No-RoPE/RoPE fused and no value aggregation), whereas main MLA in MQA mode computes 128 heads of 576-dim score inner products plus 128 heads of 512-dim value accumulations (128×(576+512)=139,264128 \times (576 + 512) = 139{,}264 multiply-adds per pair)—more than a 17×17\times reduction in raw arithmetic per pair.
  2. FP8 execution and ReLU⁡\operatorname{ReLU}: Running the indexer dot products in FP8 with a cheap ReLU⁡\operatorname{ReLU} activation instead of BF16/FP16 with row-wise softmax synchronization cuts both memory bandwidth and tensor-core cycles further.

During single-token decoding at prefix length LL, the per-token cost scales linearly with LL in the indexer and stays constant in kk for main attention:

cdecode(L)=αIL+αAk+clocal+cselection(L).c_{\mathrm{decode}}(L)=\alpha_I L+\alpha_A k+c_{\mathrm{local}}+c_{\mathrm{selection}}(L).

Thus, decoding a 20,000-token reasoning chain still pays a linear αIL\alpha_I L scan in the indexer at every step, plus the fixed αAk\alpha_A k sparse MLA read and clocalc_{\mathrm{local}} MoE expert execution.

Sparse reads do not shrink the KV cache footprint

A common misconception is that attending to 2,048 tokens means the engine only needs to keep 2,048 tokens in GPU memory. Because token selection is dynamic, a token ignored at step tt may be selected at step t+50t + 50. The serving engine must therefore retain the entire historical sequence in HBM—both the MLA cache and the new indexer key cache.

In Chapter 4, we calculated that a 131,072-token MLA cache (512 latent + 64 RoPE dimensions) takes ~9.21 GB in BF16 (or ~4.61 GB in FP8). On top of that, DSA must cache one 128-dimensional FP8 indexer key ksIk_s^I plus one 4-byte FP32 quantization scale per token per layer (k_cache and k_scale_cache in model.py):

61×131,072×(128+4)=1,055,391,744 bytes≈1.06 GB (0.98 GiB).61\times131{,}072\times(128+4) =1{,}055{,}391{,}744\ \text{bytes} \approx 1.06\text{ GB}\ (0.98\text{ GiB}).

So DSA actually increases total KV cache storage per sequence by roughly 1 GB at 128K context in exchange for cutting the memory bandwidth read per token during decoding by an order of magnitude.

Kernel engineering vs. the reference model.py script

Achieving wall-clock speedups from token-level sparsity on modern GPUs requires specialized kernels (fp8_index and sparse FlashMLA). Naive sparse gather operations over individual tokens suffer from uncoalesced HBM reads unless each fetched cache line performs enough compute to hide memory latency. Because DSA shares the same 2,048 selected token indices across all 128 MLA query heads in MQA mode, a single 576-element gather from the MLA cache feeds all 128 query heads simultaneously inside shared memory/registers, restoring high arithmetic intensity.

If you benchmark the reference inference/model.py script shipped in the repository, be careful not to confuse it with the production kernels: in model.py, the MLA.forward method computes the full dense L×LL \times L (or 1×L1 \times L) attention score matrix scores first and then overwrites unselected indices with -inf via index_Mask. That reference code is written to verify mathematical equivalence and checkpoint loading; actual FLOP and bandwidth savings require replacing the dense matmul + mask with a fused sparse gather-and-attend kernel such as TileLang/FlashMLA.

Production H800 cost curves

To show how these systems trade-offs play out on real hardware, the authors benchmark end-to-end serving throughput for DeepSeek-V3.1-Terminus and DeepSeek-V3.2 on a cluster of NVIDIA H800 GPUs, converting throughput into dollar cost per million tokens at a reference rental rate of US$2 per H800 GPU-hour:

Authors' prefilling cost curve: Terminus grows much faster than V3.2 as token position increases.

Authors' decoding cost curve: the V3.2 curve remains much lower at long token positions.

Reproduced from Report Figure 2 (figures/cost_prefilling.pdf and figures/cost_decoding.pdf). Vertical axes show estimated serving cost (USD per 1M tokens) as a function of token position inside a 128K context window, priced at $2/GPU-hour on H800 hardware.

Several practical behaviors stand out in Figure 2:

Speedup⁡=1(1−f)+f/S,\operatorname{Speedup}=\frac1{(1-f)+f/S},

the non-attention portion of the forward pass (1−f1 - f)—communicating tokens via all-to-all dispatch/combine, executing 9 SwiGLU experts per layer, running MLA projections, and scanning the FP8 indexer cache—places a hard floor on per-token cost.

That per-token savings is what makes the next part of the paper feasible: scaling post-training reinforcement learning to long-horizon reasoning and multi-turn agent trajectories.

Sources: Report §2.3 (sections/01-method.tex); Report Figure 2 (figures/cost_prefilling.pdf, figures/cost_decoding.pdf); pinned inference/model.py (Indexer and MLA classes). Continue with post-training: specialists, distillation, and mixed RL.

8. Specialists, Distillation, and Mixed Learning

Converting DeepSeek-V3.1-Terminus into the sparse-attention base checkpoint (DeepSeek-V3.2-Exp base) only solves the pre-training half of the problem. Turning that base checkpoint into a general assistant that can prove theorems, debug repositories, orchestrate search tools, and hold normal conversations requires a three-stage post-training pipeline: training dedicated domain specialists via large-scale RL, distilling their trajectories into a unified student checkpoint, and running a final mixed-domain GRPO stage.

Throughout all three post-training stages, the model retains the exact same DeepSeek Sparse Attention (DSA) architecture introduced during continued pre-training.

Stage 1: Training six domain specialists

Instead of jumping straight from the base model into a single multi-task RL run, the authors first branch off six specialized models, each initialized from the same pre-trained V3.2 base checkpoint and trained with large-scale reinforcement learning on a single domain:

  1. Mathematics
  2. Programming
  3. General logical reasoning
  4. General agent tasks
  5. Agentic coding
  6. Agentic search

Alongside these six technical domains, the pipeline maintains specialized teachers for writing and open-ended question answering.

Training separate domain specialists first solves a practical reward-engineering and curriculum problem. A math or competitive-programming specialist benefits from binary outcome verifiers, long rollout limits, and near-zero KL penalties, whereas an agentic search or general chat model requires rubric-based reward models, formatting checks, and stricter style regularization. Decoupling the domains during the initial RL push lets each specialist saturate its domain benchmark without cross-domain gradient interference or reward-scale tuning headaches.

Stage 2: Distilling Thinking and Non-Thinking trajectories

Because deploying six separate 671B checkpoints behind a routing classifier is operationally unwieldy, the specialist models are used as data generators to train a single unified checkpoint. Each specialist generates both thinking mode trajectories (with explicit <think>...</think> scratchpad blocks and interleaved reasoning across tool turns) and non-thinking mode trajectories (direct answers and immediate tool calls).

Training a student policy πθ\pi_\theta on filtered specialist trajectories (q,o)∈Dteachers(q, o) \in \mathcal D_{\text{teachers}} via standard supervised cross-entropy minimizes:

Ldistill=−∑(q,o)∈Dteachers∑tlog⁡πθ(ot∣q,o<t).\mathcal L_{\mathrm{distill}}=-\sum_{(q,o)\in\mathcal D_{\mathrm{teachers}}} \sum_t\log\pi_\theta(o_t\mid q,o_{<t}).

(While the paper describes generating domain-specific data from the specialists to train the merged checkpoint, it does not publish the exact rejection-sampling filters, dataset sizes, or whether token-level logit distillation supplements sequence-level SFT.)

According to the report, the unified checkpoint resulting from specialist distillation lands only slightly below the individual domain specialists on their respective benchmarks—and the subsequent mixed RL stage closes that remaining gap completely.

Supporting both thinking and non-thinking modes inside the same weights gives downstream applications a clean latency-versus-accuracy knob. Both modes execute the exact same 61-layer sparse MoE transformer; the difference is purely behavioral, triggered by the chat template (covered in Chapter 13). On straightforward queries or latency-sensitive agent loops, non-thinking mode skips the multi-thousand-token scratchpad while retaining strong tool-calling accuracy (for instance, scoring 67.6% vs. 73.1% on SWE-bench Verified, examined in Chapter 20).

Stage 3: Unified mixed-domain GRPO

Imitation learning on teacher trajectories has a well-known limitation: once the student model makes a slight mistake at test time, it enters states the teacher never visited. To make the unified model robust on its own rollout distribution—and to erase the small gap left by distillation—DeepSeek-V3.2 runs a consolidated mixed RL stage using Group Relative Policy Optimization (GRPO) that blends reasoning, agent, and human-alignment prompts into a single training loop.

Sequential multi-stage RL (for example, running math RL first, then coding agent RL, then chat RL) notoriously suffers from catastrophic forgetting: optimizing for concise chat responses degrades long-chain math reasoning, while aggressive math exploration degrades instruction formatting. By mixing all domains in every update step, the policy must satisfy all reward signals simultaneously:

Scaling RL compute and branching DeepSeek-V3.2-Speciale

Across specialist training and unified mixed RL, the post-training RL compute budget exceeds 10% of the total pre-training cost. In an agentic RL loop, compute goes not just to forward and backward passes on the 671B policy, but also to autoregressive rollout decoding over 64K–128K contexts, container execution for coding environments, search API queries, and generative reward-model grading.

From this pipeline, the authors produce two distinct final checkpoints:

Why doesn't cranking RL compute above 10% of pre-training cause the 671B MoE policy to collapse? As the authors detail in Section 3.1 of the report, naive GRPO breaks down at this scale unless you fix three subtle mismatches between rollout generation and gradient updates—the focus of Chapters 9, 10, and 11.

Sources: Report §3 opening and §4.1 (sections/02-post.tex). Continue with GRPO from first principles.

9. GRPO from First Principles

Group Relative Policy Optimization (GRPO) eliminates the separate value-network critic of Proximal Policy Optimization (PPO) by sampling a group of GG candidate outputs for each prompt, scoring them with a verifier or reward model, and using the group's average reward as the baseline. For a 671B-parameter MoE model, dropping the critic cuts memory and compute overhead nearly in half while avoiding value-estimation errors over 64K-token reasoning chains.

The three policies in a GRPO update

Every GRPO step involves three distinct probability distributions over next tokens:

Policy Notation Role in training
Rollout (behavior) policy πold\pi_{\mathrm{old}} The inference snapshot that actually sampled the rollout trajectories
Current (trainable) policy πθ\pi_\theta The active model weights being updated by gradient ascent
Reference policy πref\pi_{\mathrm{ref}} A frozen anchor checkpoint used to penalize excessive policy drift via KL divergence

Why distinguish πold\pi_{\mathrm{old}} from πθ\pi_\theta? First, to amortize the cost of generating long reasoning and agent trajectories, a single batch of rollouts from πold\pi_{\mathrm{old}} is typically split into multiple mini-batches for several gradient updates, so πθ\pi_\theta drifts away from πold\pi_{\mathrm{old}} after the first step. Second, even before a single weight update occurs, the high-throughput inference engine running πold\pi_{\mathrm{old}} (using FP8 kernels and custom paging) and the distributed training engine running πθ\pi_\theta produce slightly different token probabilities due to floating-point and kernel differences.

Group mean-centered advantages

Given a prompt qq, the rollout worker samples a group of GG outputs {o1,…,oG}\{o_1, \dots, o_G\} from πold(⋅∣q)\pi_{\mathrm{old}}(\cdot \mid q) and evaluates their scalar rewards {R1,…,RG}\{R_1, \dots, R_G\}. In DeepSeek-V3.2, the advantage assigned to token tt of output oio_i is the group mean-centered reward:

A^i,t=Ri−1G∑j=1GRj.\widehat A_{i,t}=R_i-\frac1G\sum_{j=1}^G R_j.

Notice two specific details in Equation (5) of the report:

  1. Sequence-level credit assignment: Every token t∈{1,…,∣oi∣}t \in \{1, \dots, |o_i|\} generated in trajectory oio_i receives the exact same outcome advantage A^i,t=A^i\widehat A_{i,t} = \widehat A_i.
  2. No standard-deviation division: Unlike earlier GRPO formulations that divide by std⁡(R1,…,RG)\operatorname{std}(R_1, \dots, R_G), DeepSeek-V3.2's displayed equation subtracts the group mean without dividing by the group standard deviation. Avoiding division by std⁡(R)\operatorname{std}(R) prevents exploding advantages when all GG samples in a group receive nearly identical rewards (for instance, when only one sample incurs a tiny length or formatting penalty).

Consider a group of G=4G = 4 rollouts with binary verification rewards [1,0,0,1][1, 0, 0, 1]. Their mean is 0.50.5, yielding advantages [+0.5,−0.5,−0.5,+0.5][+0.5, -0.5, -0.5, +0.5]. If a prompt is so easy that all GG rollouts pass ([1,1,1,1][1, 1, 1, 1]) or so hard that all GG fail ([0,0,0,0][0, 0, 0, 0]), all outcome advantages become 00, contributing zero policy-gradient signal from the outcome verifier. Maintaining a task curriculum where prompts sit at intermediate pass rates is therefore critical for sample efficiency.

Token-level importance ratios and the clipped surrogate

Because the tokens oi,to_{i,t} were drawn from πold\pi_{\mathrm{old}} rather than πθ\pi_\theta, the update reweights each token by its conditional likelihood ratio:

ri,t(θ)=πθ(oi,t∣q,oi,<t)πold(oi,t∣q,oi,<t).r_{i,t}(\theta)= \frac{\pi_\theta(o_{i,t}\mid q,o_{i,<t})} {\pi_{\mathrm{old}}(o_{i,t}\mid q,o_{i,<t})}.

Notice that ri,t(θ)r_{i,t}(\theta) is the ratio of single-token conditional probabilities at prefix (q,oi,<t)(q, o_{i,<t}), not the product of ratios across the whole sequence ∏s≤tri,s(θ)\prod_{s \le t} r_{i,s}(\theta) (which would explode or vanish exponentially over thousands of tokens).

Putting the clipped PPO surrogate, per-response length averaging, and token-level KL penalty together gives the complete GRPO objective maximized by DeepSeek-V3.2:

JGRPO(θ)=Eq∼P(Q), {oi}i=1G∼πold(⋅∣q)[1G∑i=1G1∣oi∣∑t=1∣oi∣{min⁡(ri,t(θ)A^i,t,  clip⁡(ri,t(θ),1−ε,1+ε)A^i,t)−βDKL(πθ(oi,t) ∥ πref(oi,t))}].\mathcal J_{\mathrm{GRPO}}(\theta)=\mathbb E_{q\sim\mathcal P(Q),\,\{o_i\}_{i=1}^G\sim\pi_{\mathrm{old}}(\cdot\mid q)}\left[ \frac1G\sum_{i=1}^G\frac1{|o_i|}\sum_{t=1}^{|o_i|} \left\{ \min\left(r_{i,t}(\theta)\widehat A_{i,t},\; \operatorname{clip}(r_{i,t}(\theta),1-\varepsilon,1+\varepsilon)\widehat A_{i,t}\right) -\beta D_{\mathrm{KL}}\left(\pi_\theta(o_{i,t})\,\|\,\pi_{\mathrm{ref}}(o_{i,t})\right) \right\}\right].

How length normalization and clipping behave

Two structural terms inside JGRPO(θ)\mathcal J_{\mathrm{GRPO}}(\theta) govern how long trajectories are weighted and bounded:

Credit assignment and action masking in multi-turn trajectories

Assigning a single sequence-level advantage A^i\widehat A_i to every token t∈{1,…,∣oi∣}t \in \{1, \dots, |o_i|\} means GRPO relies on statistical averaging across batches to separate productive reasoning steps from dead-end detours inside a winning trajectory. If a 10,000-token proof meanders for 3,000 tokens before finding the right lemma and succeeding, all 10,000 tokens receive a positive update on that step; only across many groups—especially when paired with a length penalty that gives higher reward RiR_i to shorter proofs—do redundant detours get washed out.

In multi-turn agent trajectories, the transcript oio_i alternates between model-generated tokens (thoughts and tool calls) and environment observations (tool outputs). Because environment observations are injected by the runtime rather than sampled from πold\pi_{\mathrm{old}}, the training loop masks environment tokens out of the inner sum over tt, conditioning on them in the prefix (q,oi,<t)(q, o_{i,<t}) while computing gradients only on tokens emitted by the model.

Finally, look closely at the two places where πold\pi_{\mathrm{old}}, πθ\pi_\theta, and πref\pi_{\mathrm{ref}} interact in JGRPO(θ)\mathcal J_{\mathrm{GRPO}}(\theta): the KL penalty DKL(πθ∥πref)D_{\mathrm{KL}}(\pi_\theta \| \pi_{\mathrm{ref}}) and the importance ratio ri,t(θ)=πθ/πoldr_{i,t}(\theta) = \pi_\theta / \pi_{\mathrm{old}}. In standard RL codebases, subtle bugs in both terms routinely destabilize large MoE runs. Chapters 10 and 11 examine how DeepSeek-V3.2 fixes them.

Sources: Report §3.1 (sections/02-post.tex, Equations 4–5). Continue with the corrected KL estimator.

10. The Corrected KL Estimator

To keep the trainable policy πθ\pi_\theta from drifting too far from the reference checkpoint πref\pi_{\mathrm{ref}} during GRPO, the objective subtracts a KL penalty βDKL(πθ∥πref)\beta D_{\mathrm{KL}}(\pi_\theta \| \pi_{\mathrm{ref}}) at every generated token position tt. Rather than materializing full 129,280-vocabulary softmax distributions for both πθ\pi_\theta and πref\pi_{\mathrm{ref}} at every token to compute the exact sum, RL implementations typically estimate the KL divergence from the single sampled rollout token oi,to_{i,t} using Schulman's nonnegative K3 estimator.

There is a catch: the K3 estimator is only an unbiased estimator of DKL(πθ∥πref)D_{\mathrm{KL}}(\pi_\theta \| \pi_{\mathrm{ref}}) when the token is sampled from πθ\pi_\theta. In off-policy GRPO, however, the rollout token oi,to_{i,t} was sampled from πold\pi_{\mathrm{old}}, not πθ\pi_\theta. DeepSeek-V3.2 corrects this mismatch by multiplying the K3 estimator by the importance ratio πθ/πold\pi_\theta / \pi_{\mathrm{old}}.

Why the standard K3 estimator works on-policy

Fix a single prefix (q,oi,<t)(q, o_{i,<t}) and abbreviate the next-token probability distributions over the vocabulary v∈Vv \in \mathcal V as:

p(v)=πold(v∣q,oi,<t),q(v)=πθ(v∣q,oi,<t),r(v)=πref(v∣q,oi,<t).p(v)=\pi_{\mathrm{old}}(v\mid q,o_{i,<t}),\qquad q(v)=\pi_\theta(v\mid q,o_{i,<t}),\qquad r(v)=\pi_{\mathrm{ref}}(v\mid q,o_{i,<t}).

Assume all three distributions have full support on V\mathcal V (so ∑v∈Vp(v)=∑v∈Vq(v)=∑v∈Vr(v)=1\sum_{v \in \mathcal V} p(v) = \sum_{v \in \mathcal V} q(v) = \sum_{v \in \mathcal V} r(v) = 1). We want to estimate the forward KL divergence from the reference rr to the current policy qq:

DKL(q∥r)=∑v∈Vq(v)log⁡q(v)r(v).D_{\mathrm{KL}}(q\|r)=\sum_{v\in\mathcal V} q(v)\log\frac{q(v)}{r(v)}.

The standard single-sample K3 function is:

f(v)=r(v)q(v)−log⁡r(v)q(v)−1.f(v)=\frac{r(v)}{q(v)}-\log\frac{r(v)}{q(v)}-1.

Because x−log⁡x−1≥0x - \log x - 1 \ge 0 for all x>0x > 0 (with equality if and only if x=1x = 1), f(v)f(v) is guaranteed to be nonnegative for every token vv, reducing variance compared to the naive log-ratio log⁡(q(v)/r(v))\log(q(v)/r(v)). If we draw v∼qv \sim q, its expectation is:

Ev∼q[f(v)]=∑v∈Vq(v)[r(v)q(v)+log⁡q(v)r(v)−1]=∑v∈Vr(v)−∑v∈Vq(v)+∑v∈Vq(v)log⁡q(v)r(v)=1−1+DKL(q∥r)=DKL(q∥r).\begin{aligned} \mathbb E_{v\sim q}[f(v)] &=\sum_{v\in\mathcal V} q(v)\left[\frac{r(v)}{q(v)}+\log\frac{q(v)}{r(v)}-1\right]\\ &=\sum_{v\in\mathcal V} r(v)-\sum_{v\in\mathcal V} q(v)+\sum_{v\in\mathcal V} q(v)\log\frac{q(v)}{r(v)}\\ &=1 - 1 + D_{\mathrm{KL}}(q\|r) = D_{\mathrm{KL}}(q\|r). \end{aligned}

What goes wrong when sampling from πold\pi_{\mathrm{old}}

During an off-policy GRPO step, the token v=oi,tv = o_{i,t} was actually drawn from p=πoldp = \pi_{\mathrm{old}}, not q=πθq = \pi_\theta. Taking the expectation of the uncorrected K3 term f(v)f(v) under v∼pv \sim p yields:

Ev∼p[f(v)]=∑v∈Vp(v)[r(v)q(v)−log⁡r(v)q(v)−1]≠DKL(q∥r).\mathbb E_{v\sim p}[f(v)]=\sum_{v\in\mathcal V} p(v)\left[\frac{r(v)}{q(v)}-\log\frac{r(v)}{q(v)}-1\right] \neq D_{\mathrm{KL}}(q\|r).

To see the numerical bias on a two-token vocabulary, take:

p=(0.8,0.2),q=(0.5,0.5),r=(0.2,0.8).p=(0.8, 0.2),\qquad q=(0.5, 0.5),\qquad r=(0.2, 0.8).

The true KL divergence between qq and rr is:

DKL(q∥r)=0.5log⁡(0.50.2)+0.5log⁡(0.50.8)≈0.22314.D_{\mathrm{KL}}(q\|r)=0.5\log\left(\frac{0.5}{0.2}\right)+0.5\log\left(\frac{0.5}{0.8}\right)\approx 0.22314.

Evaluating the uncorrected K3 function f(v)f(v) on the two tokens gives f(1)≈0.31629f(1) \approx 0.31629 and f(2)≈0.13000f(2) \approx 0.13000. Because the rollout policy p=(0.8,0.2)p = (0.8, 0.2) samples token 1 four times as often as token 2, the uncorrected expectation under pp is 0.8(0.31629)+0.2(0.13000)≈0.279030.8(0.31629) + 0.2(0.13000) \approx \mathbf{0.27903}, overestimating the true KL divergence by 25%.

Even worse than the value bias is the gradient pathology when q(v)≪r(v)q(v) \ll r(v). Differentiating the uncorrected K3 term f(v)f(v) with respect to θ\theta gives:

∇θf(v)=−(r(v)q(v)−1)∇θlog⁡q(v).\nabla_\theta f(v) = -\left(\frac{r(v)}{q(v)} - 1\right)\nabla_\theta \log q(v).

When the current policy πθ\pi_\theta assigns very small probability q(v)q(v) to a token vv that was sampled by πold\pi_{\mathrm{old}} and favored by πref\pi_{\mathrm{ref}}, the coefficient r(v)/q(v)r(v)/q(v) explodes. In uncorrected K3 implementations, those rare off-policy tokens hit πθ\pi_\theta with massive, unclipped gradient spikes that push probability mass violently back toward πref\pi_{\mathrm{ref}} and destabilize training.

DeepSeek-V3.2's importance-weighted K3 estimator

Equation (6) of the report fixes both the expectation mismatch and the r(v)/q(v)r(v)/q(v) gradient spike by multiplying the K3 term by the importance weight q(v)p(v)=πθ(oi,t∣q,oi,<t)πold(oi,t∣q,oi,<t)\frac{q(v)}{p(v)} = \frac{\pi_\theta(o_{i,t}\mid q,o_{i,<t})}{\pi_{\mathrm{old}}(o_{i,t}\mid q,o_{i,<t})}:

D^(v)=q(v)p(v)[r(v)q(v)−log⁡r(v)q(v)−1].\widehat D(v)=\frac{q(v)}{p(v)} \left[\frac{r(v)}{q(v)}-\log\frac{r(v)}{q(v)}-1\right].

Taking the expectation over v∼pv \sim p at the fixed prefix (q,oi,<t)(q, o_{i,<t}) cancels p(v)p(v) cleanly:

Ev∼p[D^(v)]=∑v∈Vp(v)q(v)p(v)f(v)=∑v∈Vq(v)f(v)=DKL(q∥r).\mathbb E_{v\sim p}[\widehat D(v)] =\sum_{v\in\mathcal V} p(v)\frac{q(v)}{p(v)}f(v) =\sum_{v\in\mathcal V} q(v)f(v) =D_{\mathrm{KL}}(q\|r).

In our two-token example, the importance-weighted values become D^(1)=0.50.8(0.31629)≈0.19768\widehat D(1) = \frac{0.5}{0.8}(0.31629) \approx 0.19768 and D^(2)=0.50.2(0.13000)=0.32500\widehat D(2) = \frac{0.5}{0.2}(0.13000) = 0.32500, whose expectation under p=(0.8,0.2)p = (0.8, 0.2) is 0.8(0.19768)+0.2(0.32500)=0.223140.8(0.19768) + 0.2(0.32500) = \mathbf{0.22314}—recovering DKL(q∥r)D_{\mathrm{KL}}(q\|r) exactly.

Why the importance ratio must stay inside the autodiff graph

If you implement Equation (6) in PyTorch, there is a critical implementation detail: do not wrap the leading ratio q(v)p(v)\frac{q(v)}{p(v)} in torch.no_grad() or .detach(). To get an unbiased estimator of the gradient ∇θDKL(q∥r)\nabla_\theta D_{\mathrm{KL}}(q\|r), the numerator q(v)q(v) in the importance weight must be differentiated alongside the inner K3 bracket.

We can verify this directly by multiplying q(v)q(v) through the bracket before differentiating:

D^(v)=r(v)+q(v)log⁡q(v)r(v)−q(v)p(v).\widehat D(v)=\frac{r(v)+q(v)\log\frac{q(v)}{r(v)}-q(v)}{p(v)}.

Since p(v)p(v) and r(v)r(v) do not depend on θ\theta, differentiating D^(v)\widehat D(v) with respect to θ\theta via the product rule cancels the +1+1 and −1-1 terms:

∇θD^(v)=1p(v)[0+∇θq(v)log⁡q(v)r(v)+q(v)∇θq(v)q(v)−∇θq(v)]=∇θq(v)p(v)log⁡q(v)r(v)=q(v)p(v)log⁡q(v)r(v)∇θlog⁡q(v).\begin{aligned} \nabla_\theta\widehat D(v) &=\frac{1}{p(v)}\left[0 + \nabla_\theta q(v)\log\frac{q(v)}{r(v)} + q(v)\frac{\nabla_\theta q(v)}{q(v)} - \nabla_\theta q(v)\right]\\ &=\frac{\nabla_\theta q(v)}{p(v)}\log\frac{q(v)}{r(v)} =\frac{q(v)}{p(v)}\log\frac{q(v)}{r(v)}\nabla_\theta\log q(v). \end{aligned}

Taking the expectation of this gradient under v∼pv \sim p yields the exact gradient of DKL(q∥r)D_{\mathrm{KL}}(q\|r):

Ev∼p[∇θD^(v)]=∑v∈Vp(v)∇θq(v)p(v)log⁡q(v)r(v)=∑v∈V∇θq(v)log⁡q(v)r(v)=∇θDKL(q∥r),\mathbb E_{v\sim p}\left[\nabla_\theta\widehat D(v)\right] =\sum_{v\in\mathcal V} p(v)\frac{\nabla_\theta q(v)}{p(v)}\log\frac{q(v)}{r(v)} =\sum_{v\in\mathcal V} \nabla_\theta q(v)\log\frac{q(v)}{r(v)} =\nabla_\theta D_{\mathrm{KL}}(q\|r),

where the final equality uses ∑v∈V∇θq(v)=∇θ∑v∈Vq(v)=∇θ(1)=0\sum_{v \in \mathcal V} \nabla_\theta q(v) = \nabla_\theta \sum_{v \in \mathcal V} q(v) = \nabla_\theta(1) = 0.

Look at what happened to the gradient magnitude: multiplying q(v)q(v) through the bracket before differentiating completely eliminated the explosive r(v)q(v)\frac{r(v)}{q(v)} term, leaving a logarithmic factor q(v)p(v)log⁡q(v)r(v)∇θlog⁡q(v)\frac{q(v)}{p(v)} \log \frac{q(v)}{r(v)} \nabla_\theta \log q(v) that stays well-behaved even when q(v)≪r(v)q(v) \ll r(v). If an engineer mistakenly detaches q(v)p(v)\frac{q(v)}{p(v)} as a stop-gradient weight, the r(v)q(v)\frac{r(v)}{q(v)} term survives in the backward pass and the gradient becomes biased again.

Domain-specific β\beta tuning and remaining off-policy limits

Fixing the KL estimator gives the hyperparameter β\beta clean semantics across domains. As the authors note in Section 3.1, different domains benefit from very different regularization strengths: complex competition mathematics often performs best with a very weak KL penalty—or β=0\beta = 0 altogether—so the policy is free to depart from its initial token distribution and discover much longer reasoning chains, whereas general alignment tasks keep a stronger β\beta to preserve fluency and formatting.

Note two boundaries of this derivation:

  1. Conditional vs. prefix unbiasedness: The importance weight q(v)p(v)\frac{q(v)}{p(v)} makes D^(v)\widehat D(v) unbiased conditioned on the visited prefix (q,oi,<t)(q, o_{i,<t}), not across the entire marginal distribution of prefixes (which are still visited according to πold\pi_{\mathrm{old}}).
  2. Truncated sampling supports: Our derivation used ∑v∈Vr(v)=1\sum_{v \in \mathcal V} r(v) = 1. When top-pp or top-kk sampling truncates the active vocabulary support of pp and qq to a subset S⊂VS \subset \mathcal V (as discussed in the next chapter), ∑v∈Sr(v)\sum_{v \in S} r(v) is slightly less than 11 unless rr is also renormalized on SS.

What if the rollout batch is so stale that p(v)≪q(v)p(v) \ll q(v) or a negative-advantage trajectory has drifted far away from πθ\pi_\theta? That is where DeepSeek-V3.2's three off-policy stabilization mechanisms step in.

Sources: Report §3.1, "Unbiased KL Estimate" (sections/02-post.tex, Equation 6). Continue with off-policy stability.

11. Keeping Off-Policy Learning Stable

In a large-scale RL system, rollout generation and gradient optimization run on decoupled software stacks. High-throughput inference servers (such as SGLang or vLLM) generate large batches of trajectories using FP8/INT8 quantization and paged attention kernels, while distributed training clusters (such as Megatron/DeepSpeed) consume those trajectories across multiple mini-batch gradient steps in BF16/FP32.

That architecture introduces two distinct sources of off-policy divergence between πold\pi_{\mathrm{old}} and πθ\pi_\theta:

  1. Temporal staleness: As πθ\pi_\theta takes multiple gradient steps on a large rollout batch, its parameters drift away from the checkpoint that generated the rollouts.
  2. Execution mismatch: Even at step zero—before a single weight update is applied—the inference engine's quantized kernels, reduction orders, MoE routing decisions, and top-pp truncation masks produce slightly different probabilities than a standard training forward pass.

To prevent this off-policy gap from destabilizing the 671B MoE model, DeepSeek-V3.2 sets πold\pi_{\mathrm{old}} directly to the token probabilities returned by the inference engine and introduces three targeted interventions: Off-Policy Sequence Masking, Keep Routing, and Keep Sampling Mask.

1. Off-Policy Sequence Masking

When a sampled trajectory oio_i has a negative advantage (A^i,t<0\widehat A_{i,t} < 0), the policy gradient pushes down the probability of its tokens. If πθ\pi_\theta has already drifted far away from πold\pi_{\mathrm{old}} on that trajectory, continuing to push down on a stale failure modes can overshoot and destabilize the policy—especially because PPO's lower clip (1−ε)(1 - \varepsilon) only bounds the per-token ratio, not the cumulative drift across thousands of tokens or the unclipped branch when ri,t>1−εr_{i,t} > 1 - \varepsilon.

DeepSeek-V3.2 measures how far πθ\pi_\theta has drifted from πold\pi_{\mathrm{old}} on trajectory oio_i using the length-averaged log probability ratio across its tokens:

di=1∣oi∣∑t=1∣oi∣log⁡πold(oi,t∣q,oi,<t)πθ(oi,t∣q,oi,<t).d_i=\frac1{|o_i|}\sum_{t=1}^{|o_i|} \log\frac{\pi_{\mathrm{old}}(o_{i,t}\mid q,o_{i,<t})} {\pi_\theta(o_{i,t}\mid q,o_{i,<t})}.

In expectation at each step, this empirical sample average approximates the token-average KL divergence DKL(πold∥πθ)D_{\mathrm{KL}}(\pi_{\mathrm{old}} \| \pi_\theta) along the trajectory. The algorithm then defines a binary mask Mi,tM_{i,t} (constant across all tokens tt in sequence ii) that zeros out the surrogate loss whenever a negative-advantage trajectory exceeds a divergence threshold δ\delta:

Mi,t={0,if A^i,t<0 and di>δ,1,otherwise.M_{i,t}= \begin{cases} 0,&\text{if }\widehat A_{i,t}<0\ \text{and}\ d_i>\delta,\\ 1,&\text{otherwise}. \end{cases}

Applying Mi,tM_{i,t} to the GRPO objective (Equations 7–8 of the report) gives:

JGRPO(θ)=E[1G∑i=1G1∣oi∣∑t=1∣oi∣{min⁡(ri,t(θ)A^i,t,  clip⁡(ri,t(θ),1−ε,1+ε)A^i,t)Mi,t−βDKL(πθ(oi,t) ∥ πref(oi,t))}].\mathcal J_{\mathrm{GRPO}}(\theta)=\mathbb E\left[ \frac1G\sum_{i=1}^G\frac1{|o_i|}\sum_{t=1}^{|o_i|} \left\{ \min\left(r_{i,t}(\theta)\widehat A_{i,t},\; \operatorname{clip}(r_{i,t}(\theta),1-\varepsilon,1+\varepsilon)\widehat A_{i,t}\right)M_{i,t} -\beta D_{\mathrm{KL}}\left(\pi_\theta(o_{i,t})\,\|\,\pi_{\mathrm{ref}}(o_{i,t})\right) \right\}\right].

Two asymmetries in this formula are worth highlighting:

2. Keep Routing: Replaying MoE expert assignments

In each of DeepSeek-V3.2's 58 MoE layers, a token routes through 8 out of 256 routed experts based on a discrete top-kk selection over sigmoid affinity scores. Because top-kk is a discontinuous step function, even a tiny numerical discrepancy between the FP8 inference engine and the BF16 training engine—or a single gradient step on the router weights—can flip the 8th-ranked and 9th-ranked experts for token oi,to_{i,t}.

When an expert flip occurs between rollout and training, the importance ratio ri,t(θ)=πθ(oi,t)πold(oi,t)r_{i,t}(\theta) = \frac{\pi_\theta(o_{i,t})}{\pi_{\mathrm{old}}(o_{i,t})} breaks down:

To eliminate this credit-assignment discontinuity, Keep Routing caches the exact indices of the 8 routed experts selected at every layer and every token by the inference engine during rollout generation, and forces the training forward pass to route through those exact same expert indices instead of recomputing top-kk selection. With the discrete computational graph held fixed between rollout and training, πθ\pi_\theta evaluates and updates the exact expert parameters that generated the trajectory. The authors note that Keep Routing has been a critical pillar of their MoE RL pipeline since DeepSeek-V3-0324.

3. Keep Sampling Mask: Aligning truncated vocabulary supports

During rollout generation, inference servers rarely sample from the raw 129,280-token softmax distribution; instead, they apply top-pp (nucleus) or top-kk truncation to zero out the low-probability tail and renormalize over the surviving candidate set Si,t⊂VS_{i,t} \subset \mathcal V:

π~old(v∣q,oi,<t)=πold(v∣q,oi,<t) 1[v∈Si,t]∑u∈Si,tπold(u∣q,oi,<t).\widetilde\pi_{\mathrm{old}}(v\mid q,o_{i,<t})= \frac{\pi_{\mathrm{old}}(v\mid q,o_{i,<t})\,\mathbf 1[v\in S_{i,t}]} {\sum_{u\in S_{i,t}}\pi_{\mathrm{old}}(u\mid q,o_{i,<t})}.

If the training pass computes πθ(v∣q,oi,<t)\pi_\theta(v \mid q, o_{i,<t}) over the untruncated vocabulary V\mathcal V (or recomputes a fresh top-pp mask Si,t′S'_{i,t} from πθ\pi_\theta's shifted logits), πold\pi_{\mathrm{old}} and πθ\pi_\theta no longer share the same probability space or normalization constant.

To see how inconsistent normalization distorts the importance ratio ri,t(θ)r_{i,t}(\theta), consider a three-token vocabulary where the raw probabilities are πold=(0.6,0.3,0.1)\pi_{\mathrm{old}} = (0.6, 0.3, 0.1) and top-pp (p=0.9p = 0.9) retains the first two tokens S={1,2}S = \{1, 2\}:

Even worse, if training recomputed a fresh top-pp mask from πθ\pi_\theta, the sampled token oi,to_{i,t} could fall just outside the new threshold pp, driving π~θ(oi,t)\widetilde\pi_\theta(o_{i,t}) to zero!

Keep Sampling Mask prevents both bugs by recording the truncation mask Si,tS_{i,t} produced by πold\pi_{\mathrm{old}} during rollout sampling and applying that identical mask Si,tS_{i,t} when normalizing πθ\pi_\theta during the training pass:

π~θ(v∣q,oi,<t)=πθ(v∣q,oi,<t) 1[v∈Si,t]∑u∈Si,tπθ(u∣q,oi,<t).\widetilde\pi_\theta(v\mid q,o_{i,<t})= \frac{\pi_\theta(v\mid q,o_{i,<t})\,\mathbf 1[v\in S_{i,t}]} {\sum_{u\in S_{i,t}}\pi_\theta(u\mid q,o_{i,<t})}.

Summary of the RL stability stack

Together with the importance-weighted K3 estimator from Chapter 10, these three mechanisms ensure that the mathematical objects in the GRPO objective match the actual system execution:

Mechanism Mismatch it fixes What the rollout worker must log
Unbiased K3 KL Off-policy sampling bias & r/qr/q gradient spikes in KL penalty Token probabilities π~old(oi,t)\widetilde\pi_{\mathrm{old}}(o_{i,t})
Off-Policy Sequence Masking Destructive updates from stale negative-advantage trajectories Sequence log-ratio drift did_i & advantage sign
Keep Routing Discontinuous MoE expert flips between inference and training Selected expert IDs (61 layers×8 IDs/token61\text{ layers}\times 8\text{ IDs/token})
Keep Sampling Mask Mismatched vocabulary support and normalization under top-pp/top-kk Retained vocabulary mask Si,tS_{i,t} (or truncation threshold)

With the optimizer stabilized against off-policy drift, the next design question is what reward signals actually drive the policy—and how outcome accuracy, length penalties, and rubric rewards interact.

Sources: Report §3.1, "Off-Policy Sequence Masking," "Keep Routing," and "Keep Sampling Mask" (sections/02-post.tex, Equations 7–8). Continue with rewards, length, and reasoning behavior.

12. Rewards, Length, and Reasoning Behavior

A reinforcement-learning policy optimizes whatever reward signal it is given. For a general-purpose assistant, that signal has to balance several competing goals at once: solving verifiable problems accurately, keeping reasoning chains concise enough to serve affordably, staying in the user's requested language, and writing helpful, well-structured responses on open-ended prompts.

DeepSeek-V3.2 combines four reward families across its specialist and mixed-RL stages: rule-based outcome rewards, length penalties, language-consistency rewards, and rubric-based generative reward models. (While the report specifies which reward types apply to each task family, it does not publish the exact mixing weights or functional forms for each penalty.)

Rule-based outcome rewards

On reasoning and agent tasks—mathematics, competitive programming, repository repair, constraint planning, and fact-seeking search—the primary signal comes from a rule-based verifier that checks the final outcome:

Evaluating only the final outcome gives the policy complete freedom over its intermediate reasoning steps: a 15,000-token scratchpad can explore dead ends, backtrack, and switch strategies without being penalized by a step-by-step process critic that might misjudge an unconventional approach.

The flip side is that outcome verifiers only guard what they explicitly test. If a repository test suite misses an edge case or a synthetic constraint checker omits a boundary condition, GRPO will happily reinforce patches that pass the verifier while failing the underlying specification.

Length penalties: pricing test-time compute during training

Left unconstrained under a binary outcome reward, RL-trained reasoning models rapidly inflate their output length: because generating an extra verification pass or re-deriving an identity slightly increases the probability of catching an arithmetic slip, the optimizer pushes trajectories toward the context limit.

To keep token consumption bounded in the main DeepSeek-V3.2 checkpoint, the reward combines outcome success with an explicit length penalty, alongside language-consistency and quality terms:

R=Routcome−λ Clength+Rlanguage+Rquality.R=R_{\mathrm{outcome}}-\lambda\,C_{\mathrm{length}}+R_{\mathrm{language}}+R_{\mathrm{quality}}.

To see how λ\lambda shifts the learned reasoning strategy, compare two candidate behaviors on a math benchmark:

If λ\lambda charges 0.0020.002 reward units per 1,000 tokens on a [0,1][0, 1] success scale, Strategy A nets an expected reward of 0.80−0.02=0.780.80 - 0.02 = 0.78, whereas Strategy B nets 0.85−0.05=0.800.85 - 0.05 = 0.80—so GRPO favors the longer Strategy B. Raise the length penalty to λ=0.005\lambda = 0.005 per 1,000 tokens, and Strategy A (0.80−0.05=0.750.80 - 0.05 = 0.75) overtakes Strategy B (0.85−0.125=0.7250.85 - 0.125 = 0.725).

Crucially, training with a different length penalty changes how the model reasons from the very first token, not just where it stops. You cannot turn the main DeepSeek-V3.2 checkpoint into DeepSeek-V3.2-Speciale simply by raising max_tokens at inference time: Speciale is trained with a substantially reduced length penalty during RL so that it learns to unpack long case analyses, test multiple proof strategies, and run iterative self-verification loops that the main model was trained to prune away.

Language-consistency rewards

Multilingual reasoning models trained with pure outcome RL frequently develop code-switching drift—for instance, receiving a prompt in Chinese or English, switching into the other language mid-thought when recalling a technical theorem, and bleeding that switch into tool arguments or the final user response.

DeepSeek-V3.2 includes an explicit language-consistency reward during RL to penalize unintended language mixing. As noted in Chapter 11, the authors also found that pairing top-pp sampling with Keep Sampling Mask plays a direct role here: without sampling-mask replay, off-policy updates on truncated tails often inject erratic low-probability tokens from other scripts that trigger mid-sentence language switches.

Rubric-based generative reward models for open-ended tasks

For open-ended writing, instruction following, and general chat where no deterministic verifier exists, DeepSeek-V3.2 uses a generative reward model guided by prompt-specific rubrics. Rather than mapping (q,o)(q, o) to a single opaque scalar through a linear value head, a generative reward model evaluates the candidate response against a checklist of criteria tailored to the prompt—such as factual accuracy, completeness, tone, formatting constraints, and absence of hallucinated citations—before producing its reward score.

Prompt-specific rubrics avoid the one-size-fits-all bias of traditional preference models (which often unconditionally favor longer, bulleted responses regardless of whether the user asked for a one-line shell command or an architectural essay). Even in agentic search, where training starts from hard, short-answer verifiable queries, the authors blend in helpfulness-oriented search prompts graded by multi-dimensional rubrics so the final assistant writes clear, well-cited synthesis reports rather than terse benchmark entity strings.

Emergent side effects: redundant self-verification in agents

Reward engineering also explains one of the main failure modes documented in the paper's agent evaluations. On complex coding and tool-use benchmarks, DeepSeek-V3.2 sometimes falls into redundant self-verification loops—repeatedly re-running test suites, re-reading files it just edited, or double-checking already-confirmed search facts until the transcript hits the 128K context ceiling.

When outcome correctness carries a high reward and a single broken edit ruins the entire trajectory, a risk-averse policy naturally learns to spend extra tool turns verifying its work before submitting. Teaching an agent to calibrate the marginal value of one more verification call against context-window exhaustion remains an active tension in agentic RL—and makes context management across tool turns (Chapters 13 and 18) a first-class systems concern.

Sources: Report §3, §4.1, and §4.2 (sections/02-post.tex, sections/06-high.tex). Continue with reasoning with tools and conversation state.

13. Reasoning with Tools and Conversation State

Early reasoning models such as DeepSeek-R1 were built around a single-turn loop: the user sends a prompt, the model emits a <think>...</think> block followed by a final answer, and when the user sends a follow-up prompt, the prior <think> block is stripped from the context window.

That single-turn rule breaks down catastrophically in multi-step tool use. If an agent calls 15 bash or search tools to solve a single request and its <think> blocks are deleted after every tool output, the model loses its working plan, hypotheses, and eliminated dead ends at every step—forcing it to re-read the entire transcript and reconstruct its reasoning from scratch on every turn. DeepSeek-V3.2 redesigns both its conversation-state retention policy and its cold-start RL curriculum around thinking with tools.

Retaining reasoning across tool turns vs. stripping on user turns

DeepSeek-V3.2 draws a sharp state-management boundary between a tool observation (role: "tool") and a new user turn (role: "user"):

Tracing a two-turn debugging session shows exactly what stays in context at each step:

Turn 1, Step 1:
  user: "Fix the failing date-parser test in tests/test_parser.py."
  assistant: <think>[Plan A: inspect test_parser.py]</think>
             <tool_call>read_file("tests/test_parser.py")</tool_call>
  tool: "[file contents...]"

Turn 1, Step 2 (Reasoning from Step 1 is RETAINED):
  assistant: <think>[Test expects ISO-8601 timezone offset; patch parser.py and run pytest]</think>
             <tool_call>run_bash("pytest tests/test_parser.py")</tool_call>
  tool: "1 passed in 0.12s"

Turn 1, Step 3 (Reasoning from Steps 1 & 2 is RETAINED):
  assistant: <think>[Test passes; summarize fix]</think>
             "I updated parse_tz() in parser.py to handle Z and ±HH:MM offsets."

Turn 2 (New user message arrives -> Turn 1 <think> blocks DROPPED, tool calls/outputs KEPT):
  user: "Now add a unit test for leap-second timestamps."

Keeping <think> blocks intact across tool turns saves massive amounts of tokens and latency: instead of re-deriving why test_parser.py failed after every shell command, each subsequent <think> block picks up directly where the previous one left off. Dropping <think> blocks once the user asks a new question reclaims context space while leaving the concrete record of executed tool calls and outputs visible for future turns.

Why agent frameworks that fake tool outputs as user messages break thinking mode

Because this retention rule triggers specifically on "user" messages, it exposes a critical integration trap in third-party agent harnesses. Several popular coding agents (the report specifically flags Roo Code and Terminus in its evaluation setups) do not use native "tool" role messages; instead, they serialize tool execution results into a "user" message and send it back to the model.

Under DeepSeek-V3.2's chat template, injecting a tool output as role: "user" tricks the encoder into thinking a brand-new user turn has started—wiping out all prior <think> blocks after every single tool call and forcing the model to re-reason from scratch at every step. For frameworks that encode tool outputs as user messages, the authors explicitly recommend running V3.2 in non-thinking mode until the harness is updated to emit proper "tool" messages.

Cold-start bootstrapping: teaching the model to interleave thinking and tools

Before launching full-scale agentic RL, the base model has to learn the syntax and control flow of interleaved <think> blocks and <tool_call> invocations. At the start of post-training, the authors already had strong non-agentic reasoning traces (single-turn math/code <think> data) and non-thinking agent traces (multi-turn tool calls without <think>), but no natural corpus combining the two.

Rather than manually annotating thousands of multi-turn thinking-with-tools demonstrations, DeepSeek-V3.2 uses prompt-driven cold-start bootstrapping (illustrated in Report Appendix B, Figures 8–10):

  1. The model is given explicit system instructions detailing how to interleave <think> tags with <|tool▁calls▁begin|>...<|tool▁calls▁end|> blocks, pause after emitting a tool call, wait for <|tool▁outputs▁begin|>...<|tool▁outputs▁end|>, and resume reasoning inside a fresh <think> block.
  2. In the Appendix B example prompts, the model is instructed to use a Python interpreter tool during problem solving (with per-prompt sandbox constraints such as a 3-second execution timeout and a 20-call cap) before emitting a \boxed{} final answer.
  3. Even though zero-shot adherence to this composite format is initially noisy and brittle, the model succeeds often enough to seed the initial RL rollout buffer. Once GRPO takes over, positive outcome rewards rapidly reinforce valid interleaved formatting and prune away malformed calls.

Verifying message encoding with encoding_dsv32.py

The official repository ships a standalone Python reference encoder (encoding/encoding_dsv32.py) rather than a Jinja2 chat template, because the state-dependent <think> stripping logic depends on scanning the index of the last "user" message in the conversation array.

Before benchmarking or deploying DeepSeek-V3.2 in a custom agent loop, run a quick four-message sanity test through encode_messages:

  1. Pass [user_1, assistant_think_tool_1, tool_output_1] with thinking_mode="thinking" and verify that assistant_think_tool_1's <think>...</think> substring is present in the rendered prompt string.
  2. Append [assistant_final_1, user_2] and verify that assistant_think_tool_1's <think>...</think> block is removed, while its <|tool▁calls▁begin|> and <|tool▁outputs▁begin|> blocks remain intact.

Also note a practical warning from the official model card: parse_message_from_completion_text in encoding_dsv32.py is a strict reference parser without defensive error recovery for truncated or malformed XML/special-token sequences. Production runtimes should wrap tool-call parsing in validation and retry handlers.

With the conversation format and cold-start mechanism in place, the next three chapters examine how DeepSeek-V3.2 builds the 85,267 training environments that turn this cold-start policy into a general, coding, and search agent.

Sources: Report §3.2.1–3.2.2 and Appendix B (sections/02-post.tex, sections/appendix.tex); official encoding_dsv32.py; pinned model card ("Chat Template" section). Continue with synthesizing general agent environments.

14. Synthesizing General Agent Environments

Training an agent to handle unfamiliar APIs and multi-step constraints requires thousands of interactive environments. While coding and web search have natural real-world substrates (GitHub repositories and the live web), general tool use—booking itineraries, managing enterprise databases, scheduling resources, or reconciling financial records—lacks a public corpus of interactive sandboxes with programmatic verifiers.

To fill that gap, DeepSeek-V3.2 builds an automated environment synthesis pipeline that generates self-contained sandboxes, custom toolsets, multi-constraint tasks, and deterministic Python verifiers from scratch. Every synthesized training instance is packaged as a four-part tuple:

⟨environment,  tools,  task,  verifier⟩.\langle\text{environment},\;\text{tools},\;\text{task},\;\text{verifier}\rangle.

Breaking down the 85,267 agent training prompts

Table 1 of the report summarizes the four environment families used in agentic RL:

Agent domain Environment source Prompt source Retained tasks
Code Agent Real (GitHub repos) Extracted (Issue–PR pairs) 24,667
Search Agent Real (Search APIs) Synthesized 50,275
General Agent Synthesized (1,827 sandboxes) Synthesized 4,417
Code Interpreter Real (Jupyter notebooks) Extracted 5,908
Total 85,267

Summing the four rows (24,667+50,275+4,417+5,908=85,26724{,}667 + 50{,}275 + 4{,}417 + 5{,}908 = 85{,}267) explains the paper's headline figure of "over 1,800 environments and 85,000 complex prompts": the 1,827 synthesized environments specifically house the 4,417 general-agent tasks, while the remaining 80,850 prompts execute against real software repositories, search APIs, and Jupyter kernels.

The four-stage synthesis loop for General Agent sandboxes

Generating a general-agent environment that is both nontrivial and guaranteed to be solvable follows a four-step agentic workflow powered by DeepSeek-V3.2 itself:

  1. Database construction: Given a seed task category (for example, multi-city itinerary planning), a synthesis agent uses bash and search tools inside a sandbox to gather or generate realistic domain tables—such as cities, hotels, restaurants, attractions, prices, ratings, and train schedules—and populates a local sandbox database.
  2. Toolset synthesis: The synthesis agent writes a suite of task-specific Python tool functions (e.g., list_hotels(city), get_restaurant_details(id), query_transport(origin, dest)) that query the underlying database. Crucially, the downstream policy being trained cannot read the raw database directly; it can only inspect state by invoking these documented tool interfaces.
  3. Iterative task, solution, and verifier co-generation: The synthesis agent proposes an initial simple task alongside two Python functions: a reference solution() function and a verify(candidate) function. To prevent the reference solution from cheating, solution() is strictly restricted to calling the exposed tool functions and performing in-memory logic—it is forbidden from reading the database files directly or importing privileged helpers. The pipeline executes solution() and checks whether its return value passes verify(). Once validated, the synthesis agent iteratively layers on harder constraints, updating solution(), verify(), and the toolset in lockstep whenever the current tools prove insufficient.
  4. Pass@100 reachability filtering: Finally, the pipeline runs 100 rollout attempts per task with DeepSeek-V3.2 and discards any task where pass@100 is zero—retaining only the 1,827 environments and 4,417 tasks where the model achieves at least one verified success out of 100 tries.

Requiring both a tool-restricted reference solution() and a nonzero pass@100 filters out impossible or contradictory prompts that would otherwise waste RL compute with all-zero reward groups.

Why constraint satisfaction is hard to search but cheap to verify

The core design principle of the synthesis pipeline is asymmetric complexity: finding a valid solution requires exploring a combinatorial state space across dozens of tool calls, whereas verifying a proposed solution takes a few lines of deterministic Python.

Consider the three-day travel itinerary task described in Section 3.2.3 of the report:

For the agent solving the task, discovering a valid Day 2 package requires querying hotels in candidate cities, branching on the hotel price tier, fetching restaurant menus and ratings, and backtracking whenever a city has luxury hotels with ≥4.0\ge 4.0-rated restaurants whose combined price exceeds 350 CNY.

For the verifier, grading the submitted three-day JSON plan is a simple O(1)O(1) lookup:

def verify_itinerary(plan, db):
    if len(plan) != 3 or not all_ids_unique(plan):
        return False
    for day in plan:
        if not all_located_in_city(day, db):
            return False
    day2 = plan[1]
    h_price = db.hotels[day2.hotel_id].price
    r1, r2 = db.restaurants[day2.lunch_id], db.restaurants[day2.dinner_id]
    t_price = db.attractions[day2.attraction_id].price
    if h_price >= 800:
        return (r1.price + r2.price <= 350) and (r1.rating >= 4.0 and r2.rating >= 4.0) and (t_price < 120)
    elif h_price >= 500:
        return (r1.price + r2.price <= 500) and max(r1.rating, r2.rating) >= 4.2
    else:
        return (r1.price + r2.price <= 600)

For example, if an agent proposes a Day 2 luxury hotel at 900 CNY, lunch at 160 CNY (rating 4.2), dinner at 180 CNY (rating 4.1), and an attraction at 100 CNY, the combined restaurant spend is 160+180=340≤350 CNY160 + 180 = 340 \le 350\text{ CNY} and every Branch A condition passes. If dinner instead costs 195 CNY, the combined restaurant bill hits 355 CNY and verify_itinerary returns False immediately.

Potential failure modes of synthetic environments

While co-generating solution() and verify() eliminates most broken tasks, two edge cases always warrant attention in synthetic data pipelines:

  1. Correlated specification bugs: If the synthesis agent misinterprets an ambiguous phrase in its own natural-language prompt (such as whether "500–800 CNY" includes 800.00 CNY) and writes the exact same off-by-one boundary into both solution() and verify(), the self-consistency check will pass even though the prompt text is ambiguous to the student model.
  2. Survivorship bias from pass@100 filtering: Discarding tasks with pass@100=0\text{pass@100} = 0 removes broken tasks, but also drops valid tasks that require more than 100 trials for the current checkpoint to stumble across a solution.

As we will see in Chapter 17, training on these 4,417 synthetic general-agent tasks transfers directly to held-out out-of-distribution tool benchmarks like MCP-Mark, Tau2Bench, and Toolathlon—confirming that the model learns generalizable tool-exploration and constraint-tracking habits rather than memorizing the 1,827 sandbox schemas.

Sources: Report §3.2.3, Table 1 and "General Agent" (sections/02-post.tex). Continue with coding agents and code interpreters.

15. Coding Agents and Code Interpreters

Software engineering provides one of the cleanest reward signals in reinforcement learning: compile the code and run the test suite. Turning raw GitHub history into a reliable RL training environment, however, requires far more than scraping pull-request diffs. Every candidate repository must build cleanly inside an isolated container, reproduce the exact bug before the fix is applied, and pass both the new bug-fix tests and the existing regression suite once the patch is applied.

DeepSeek-V3.2 splits its code-executing RL environments into two distinct categories (Table 1 of the report): 24,667 Code Agent tasks built from real multi-language GitHub repositories, and 5,908 Code Interpreter tasks executed inside stateful Jupyter notebooks.

Task family Retained count Execution environment Primary skill trained
Code Agent 24,667 Containerized multi-file software repositories Repository navigation, root-cause diagnosis, patch authoring, regression testing
Code Interpreter 5,908 Stateful Jupyter notebook kernels Translating mathematical, logical, and data-science problems into executable Python

Mining and filtering millions of GitHub Issue–PR pairs

To construct the 24,667 Code Agent environments, the pipeline starts from millions of historical GitHub Issue–Pull Request pairs across eight programming languages: Python, Java, JavaScript, TypeScript, C, C++, Go, and PHP. Heuristic rules and LLM filters narrow that raw pool down to candidate pairs that contain:

  1. A clear, self-contained issue description (which becomes the task prompt).
  2. A correlated gold code patch (the actual implementation diff that resolved the issue).
  3. A test patch (the unit or integration test diff added or updated in the PR to verify the fix).

Filtering out noisy PRs—such as sweeping refactors, dependency bumps, documentation edits, or issues whose reproduction steps live in external screenshots—is essential before spending compute on container builds.

Automated container building and JUnit normalization

Even a well-written GitHub PR is useless for RL if its dependencies fail to install or its test runner crashes. Rather than writing manual Dockerfiles for thousands of repositories, DeepSeek uses an automated environment-setup agent powered by DeepSeek-V3.2 to provision each candidate repository at its pre-PR commit:

The F2P and P2F differential acceptance test

Simply getting a test runner to exit without crashing does not prove an environment is a valid RL task. The pipeline validates every container using two transition metrics measured by applying the PR's test patch before and after the gold code patch:

A candidate environment is accepted into the training pool if and only if applying the gold patch yields:

F2P>0andP2F=0.\text{F2P} > 0 \qquad\text{and}\qquad \text{P2F} = 0.

Tracing three tests inside a candidate container illustrates how this rule filters out broken setups:

Test case Base commit + Test patch Base commit + Test patch + Gold patch Classification
test_issue_412_timezone_z FAIL PASS F2P (proves the test catches the bug and the gold patch fixes it)
test_standard_iso_dates PASS PASS Preserved regression test (must stay passing)
test_locale_formatting PASS FAIL P2F (disqualifies the environment: gold patch broke an existing test)

Requiring F2P>0\text{F2P} > 0 guarantees that the test patch actually reproduces the reported bug and is solvable by a known patch; requiring P2F=0\text{P2F} = 0 ensures the environment is deterministic and free of flaky tests that fail randomly between runs.

What the policy learns inside a repository sandbox

During RL rollouts, the gold patch is hidden; the agent receives only the issue description and bash/file-editing tools inside the pre-PR container. Because a repository may contain hundreds of thousands of lines of code, the agent cannot dump the entire codebase into its context window. Instead, it has to learn an interactive debugging loop:

  1. Search the directory tree (grep/find) to locate the modules implicated by the issue description.
  2. Read the relevant source and test files into context.
  3. Formulate a root-cause hypothesis inside its <think> block and apply a minimal edit.
  4. Run the local test suite to see whether its patch resolves the failure without breaking existing tests, using compiler errors or stack traces to iterate if the first attempt fails.

Code Interpreter environments: stateful Jupyter notebooks

The 5,908 Code Interpreter tasks target a different workflow: using an interactive Jupyter notebook kernel to solve competition math, logic puzzles, and data-analysis problems.

Unlike stateless one-shot script execution, a Jupyter kernel preserves variables, imports, and data structures in memory across cell executions. If Cell 1 loads a dataset or precomputes a prime sieve into variable primes, Cell 2 can inspect and slice primes directly without recomputing it. At the same time, stateful execution forces the agent to manage mutable state carefully: if an earlier cell mutates a list in place or times out mid-loop, subsequent cells inherit that mutated state.

Code interpreter tasks also train the model to combine symbolic reasoning with computational verification—for instance, deriving a closed-form combinatorial formula in <think>, writing a 10-line Python brute-force script to enumerate small N≤8N \le 8 cases, checking whether the formula matches the enumeration, and revising the derivation when a mismatch appears.

As with any test-driven environment, container hygiene is paramount: the sandbox must strictly isolate the git history and remote remotes so the agent cannot simply run git log --all or fetch the gold PR commit from GitHub during a rollout.

Sources: Report §3.2.3, "Code Agent," "Code Interpreter Agent," and Table 1 (sections/02-post.tex); Report Appendix B (cold-start interpreter prompts). Continue with search agents and difficult questions.

16. Search Agents and Difficult Questions

A capable search agent has to recognize when its parametric memory is insufficient, formulate targeted search queries, cross-check conflicting web snippets, and synthesize a grounded answer. If a training prompt can be answered directly from pre-training memorization—or solved with a single obvious keyword lookup—reinforcement learning will never pressure the model to plan multi-hop searches.

To train DeepSeek-V3.2 on genuinely demanding retrieval problems, the authors construct 50,275 search-agent tasks (the largest domain in Table 1) using an automated multi-agent synthesis and adversarial filtering pipeline executed against real commercial search APIs, supplemented by rubric-graded helpfulness tasks.

Step 1: Sampling long-tail entities

To prevent the policy from coasting on memorized facts about famous people, landmarks, or events, the pipeline starts by sampling informative long-tail entities across diverse domains from large-scale web corpora. Because obscure entities appear rarely in pre-training data, answering fine-grained questions about their attributes almost always requires live tool use.

Step 2: Configurable depth-and-breadth exploration

Next, a question-construction agent equipped with search tools explores each seed entity using configurable depth and breadth parameters:

Step 3: Adversarial filtering with heterogeneous answer agents

Not every synthesized multi-hop question is actually hard; a clever single query might still surface a Wikipedia summary table containing the answer on the first turn. To filter out easy or flawed questions, the pipeline subjects every candidate (q,a∗)(q, a^*) pair to a panel of heterogeneous answer-generation agents alongside a multi-pass search-enabled verifier:

  1. Heterogeneous candidate generation: Multiple answer agents—configured with different model checkpoints, system prompts, and sampling strategies—attempt to solve qq. Varying the checkpoints and prompts ensures that a question isn't kept merely because one specific prompt template stumbled on a formatting quirk.
  2. Multi-pass search verification: A dedicated verification agent with search access runs multiple verification passes on both the proposed ground-truth answer a∗a^* and all candidate answers produced by the heterogeneous panel.
  3. Strict retention rule: A sample (q,a∗)(q, a^*) is retained in the RL training set if and only if the ground truth a∗a^* is verified as correct and every candidate answer from the heterogeneous panel is verifiably incorrect.

Requiring all panel candidates to fail guarantees that the retained 50,275 prompts sit at the frontier of current capability, while multi-pass verification of a∗a^* filters out ambiguous questions, outdated web claims, or hallucinated ground truths.

To see why both filters are necessary, consider a question asking for the birthplace of the translator of a specific 1998 edition of a novel. Without entity-resolution care, an agent might confuse the 1998 translator with the better-known 1974 translator, confuse the translator with the foreword author, or trust an unsourced blog snippet. Only questions that defeat shallow single-hop retrieval while admitting an unambiguous, verifiable ground-truth entity survive into the RL training buffer.

Blending exact-match verification with helpfulness rubrics

Training exclusively on short-answer multi-hop trivia carries a well-known failure mode: the assistant learns to emit terse, one-word benchmark answers ("Kyoto") even when a real user asks an open-ended research question requiring context, citations, and trade-off analysis.

To make the search agent useful in production conversations, the authors augment the verifiable short-answer dataset with filtered helpfulness-oriented RL queries—prompts where live web search measurably improves response quality. During RL, these open-ended search trajectories are graded by a generative reward model using detailed multi-dimensional rubrics (covering factual grounding, coverage, organization, and citation accuracy) alongside the rule-based outcome rewards used for short-answer tasks.

Runtime dependencies in search evaluation

Unlike self-contained math or repository-container tasks, search-agent rollouts interact with a live external search engine (the report uses a standard commercial search API in its evaluations). That introduces two systems variables that any evaluation or reproduction must account for:

Sources: Report §3.2.3, "Search Agent" and Table 1 (sections/02-post.tex); Report §4.1 search evaluation notes. Continue with what the synthesis experiments establish.

17. What the Synthesis Experiments Establish

Synthesizing 1,827 sandbox environments and 4,417 general-agent tasks (Chapter 14) only pays off if two hypotheses hold:

  1. The synthesized tasks are genuinely difficult, challenging frontier models rather than testing trivial API calls.
  2. RL training on those synthetic sandboxes transfers out-of-distribution, improving performance on unfamiliar third-party agent benchmarks whose tool schemas and domains were never seen during training.

In Section 4.3 of the report, the authors test both hypotheses directly through a 50-task difficulty audit and a controlled RL ablation starting from the supervised fine-tuned checkpoint (DeepSeek-V3.2-SFT).

Experiment 1: Auditing task difficulty on 50 sampled instances

To measure how hard the synthesized general-agent tasks are, the authors draw a random sample of 50 task instances from the retained general-agent dataset and evaluate four models across Pass@1\text{Pass@1}, Pass@2\text{Pass@2}, and Pass@4\text{Pass@4}:

Metric DeepSeek-V3.2-Exp Claude-4.5-Sonnet Gemini-3.0-Pro GPT-5-Thinking
Pass@1 12% 34% 51% 62%
Pass@2 18% 47% 65% 75%
Pass@4 26% 62% 74% 82%

Notice first that the DeepSeek baseline in Column 1 is DeepSeek-V3.2-Exp (prior to the new synthetic general-agent RL pipeline), which solves only 12% of the sampled tasks on the first try and 26% within four tries. Even the strongest frontier baseline tested—GPT-5-Thinking—fails 38% of the tasks at Pass@1\text{Pass@1} and 18% at Pass@4\text{Pass@4}.

Why empirical Pass@k\text{Pass@}k scales sub-independently across tasks

Recall that Pass@k\text{Pass@}k measures the probability that at least one of kk sampled trajectories passes the environment verifier. If every task in the benchmark shared an identical, independent per-attempt success probability p=0.12p = 0.12, then drawing k=4k = 4 independent attempts would yield a theoretical success rate of:

1−(1−p)k=1−(0.88)4≈40.0%.1-(1-p)^k = 1 - (0.88)^4 \approx 40.0\%.

In Table 3, however, DeepSeek-V3.2-Exp's actual Pass@4\text{Pass@4} is 26%, well below 40%. That gap is a classic signature of heterogeneous task difficulty: when a benchmark contains a mix of moderate tasks (p∈[0.2,0.8]p \in [0.2, 0.8]) and very hard tasks (p≈0.01p \approx 0.01, which survived the Pass@100>0\text{Pass@100} > 0 filter in Chapter 14 by succeeding once or twice in 100 rollouts), the Jensen inequality guarantees that Ei[1−(1−pi)k]<1−(1−Ei[pi])k\mathbb E_i[1 - (1 - p_i)^k] < 1 - (1 - \mathbb E_i[p_i])^k. (When estimating Pass@k\text{Pass@}k from n≥kn \ge k rollouts containing cc successes per problem, standard evaluation harnesses use the unbiased combinatorial estimator 1−(n−ck)/(nk)1 - \binom{n - c}{k} / \binom{n}{k}.)

Also keep the sample size in mind when reading small percentage shifts: on a 50-problem sample (n=50n = 50), a single problem flips the score by 22 percentage points, and the binomial standard error p(1−p)/n\sqrt{p(1-p)/n} near p=0.5p = 0.5 is roughly ±7\pm 7 percentage points. Even with that sampling noise, the 50-point spread between V3.2-Exp (12%) and GPT-5-Thinking (62%) clearly establishes that the synthesis pipeline creates demanding multi-step constraint problems.

Experiment 2: Out-of-distribution transfer from synthetic-only RL

To isolate whether RL on the 4,417 synthetic general-agent tasks actually teaches transferable agent skills—rather than riding on the coattails of extended <think> scratchpads or coding/search RL—the authors run a clean ablation starting from DeepSeek-V3.2-SFT in non-thinking mode:

Authors' transfer curves: RL only on synthetic general-agent data improves several held-out agent benchmark categories.

Reproduced from Report Figure 5 (figures/synthesis-rl-plot.png). Training curves track non-thinking evaluation accuracy across RL steps on τ2\tau^2-bench (Airline, Retail, Telecom, Overall), MCP-Mark (Filesystem, Postgres, Overall), and MCP-Universe (Location Navigation, Repository Management, Financial Analysis, Browser Automation, Web Searching, Overall).

The twelve subplots in Figure 5 isolate two striking findings:

  1. Coding and search RL alone do not transfer to general tool use: Comparing the two horizontal dashed lines shows that V3.2-Exp (trained with RL on real GitHub repositories and search APIs) barely budges—and in several categories slightly trails—V3.2-SFT on τ2\tau^2-bench, MCP-Mark, and MCP-Universe. Mastering bash, pytest, and web search does not automatically teach an agent how to navigate stateful airline-reservation policies or MCP database schemas.
  2. Synthetic general-agent RL transfers across held-out domains: Even in non-thinking mode, running GRPO solely on the 1,827 synthetic sandboxes drives steady gains over both V3.2-SFT and V3.2-Exp across τ2\tau^2-bench (rising roughly 10+ points overall), MCP-Mark (Filesystem and Postgres), and MCP-Universe.

What skills transfer across unfamiliar tool schemas?

Because the tool definitions, database schemas, and domain rules of τ2\tau^2-bench, MCP-Mark, and MCP-Universe were never seen during synthetic sandbox generation, the improvements in Figure 5 cannot come from memorizing function names. Instead, RL on verifiable constraint-satisfaction sandboxes pressures the policy to internalize domain-agnostic operational habits:

While this ablation cleanly establishes that synthetic general-agent RL drives large out-of-distribution gains over SFT and code/search-only RL, note that once an agent scales up to dozens of tool turns in production, it eventually runs into the 128K context ceiling—the problem addressed in Chapter 18.

Sources: Report §4.3 (sections/05-thinking-with-tool.tex, Table 3, and figures/synthesis-rl-plot.png). Continue with context management and test-time scaling.

18. Context Management and Test-Time Scaling

Even with a 128K context window and DeepSeek Sparse Attention, multi-turn search agents routinely run out of context space. On BrowseComp—a demanding deep-search benchmark where each tool call fetches bulky web snippets and page dumps—the authors report that over 20% of trajectories exceed the 128K token limit before the agent can finalize an answer.

When an agent approaches the edge of its context window, the runtime has to decouple per-step context capacity (capped at 128K tokens) from total test-time task compute (which can span hundreds of tool steps and hundreds of thousands of cumulative tokens). In Section 4.4 of the report, the authors evaluate four test-time scaling strategies on BrowseComp: three serial context-management policies that free up space mid-trajectory, and one parallel trajectory baseline.

Triggering context management at the 80% watermark

Waiting until token 131,072 to intervene leaves zero room for the next tool response or final answer. Instead, DeepSeek-V3.2's serial context-management policies trigger whenever the active transcript crosses 80% of the context window (roughly 0.80×131,072≈104,8580.80 \times 131{,}072 \approx 104{,}858 tokens).

Once a trajectory crosses that 80% watermark, the runtime applies one of three serial compaction rules to the accumulated tool history:

  1. Summary: The model generates a natural-language summary of the overflowing trajectory—compressing the entities found, hypotheses tested, and remaining questions—and restarts the rollout seeded with that summary in place of the raw tool history.
  2. Discard-75%: The runtime drops the oldest 75% of the tool-call history in place, keeping the original user prompt and the most recent 25% of tool calls and observations so the agent can continue without paying the latency of a summarization call.
  3. Discard-all: The runtime wipes 100% of the previous tool-call history, resetting the context back to the initial prompt so the agent starts a fresh search trajectory from scratch inside the same serial run.

As a fourth comparison point, the authors evaluate a pure parallel-scaling baseline without serial context resets:

  1. Parallel-fewest-step: The runtime samples NN independent trajectories in parallel and selects the completed trajectory that finishes in the fewest steps.

Comparing accuracy vs. step efficiency on BrowseComp

Authors' BrowseComp scaling curves comparing summary, partial discard, full discard, and parallel sampling.

Reproduced from Report Figure 6 (figures/search.pdf). Curves plot BrowseComp accuracy against average real tool steps Executed under Summary, Discard-75%, Discard-all, and Parallel-fewest-step.

Comparing the trajectories in Figure 6 reveals several counterintuitive lessons about long-horizon search agents:

Why wiping the history (Discard-all) beats keeping a summary

At first glance, Discard-all looks paradoxical: if you throw away 100% of the previous tool calls when the context hits 80% capacity, how is that any different from simply failing and restarting?

First, in a stochastic policy (temperature 1.0), a trajectory that burns through 105,000 tokens of web searches without finding the answer is almost always trapped in a dead-end rabbit hole—chasing a mistaken entity disambiguation or issuing repetitive variations of a failing query. Keeping the last 25% of those dead-end tool outputs (Discard-75%) or summarizing them (Summary) keeps conditioning the model on the very distraction that caused the trajectory to stall. Wiping the tool history (Discard-all) breaks that path dependence immediately, giving the policy a clean slate to draw a fresh initial search plan.

Second, unlike Parallel-fewest-step—which blindly spawns NN trajectories upfront for every question, including the 80% of questions that succeed on the first try within a single 128K window—Discard-all allocates extra retry compute adaptively, spending a second or third 105K-token attempt only on the hard queries that actually overflow the 80% watermark.

Why Discard-all works for read-only search, not stateful coding

Before applying Discard-all to every agent workload, notice a crucial systems distinction between read-only environments (like web search) and state-mutating environments (like repository editing or database transactions):

As the authors note, combining adaptive serial context management with parallel candidate verification—so an agent can allocate both sequential depth and parallel breadth dynamically—is a natural next step for test-time scaling.

Sources: Report §4.4 (sections/03-seach-agent.tex, Figure 6 / figures/search.pdf); Report §4.1 and Table 2 (tables/eval_main.tex). Continue with reading the reasoning benchmarks.

19. Reading the Reasoning Benchmarks

In Section 4 of the report, DeepSeek-V3.2 is evaluated across general knowledge, graduate-level science, competition mathematics, and competitive programming. Before comparing headline numbers against GPT-5-High or Gemini-3.0-Pro, it helps to examine the exact evaluation protocol, prompt templates, and token budgets behind Table 2.

Evaluation protocol and prompt sensitivity

All reasoning benchmarks in Table 2 run at temperature 1.0 with a 128K context window. For mathematical and scientific reasoning benchmarks—specifically AIME 2025, HMMT (Feb & Nov 2025), IMOAnswerBench, and Humanity's Last Exam (HLE)—the evaluation harness appends a lightweight formatting instruction:

{question}\nPlease reason step by step, and put your final answer within \boxed{}.

Prompt formatting matters more than casual readers often realize. In a footnote to Section 4.1, the authors note that evaluating DeepSeek-V3.2-Thinking on text-only HLE with the benchmark's official default template yields 23.9%, whereas using the \boxed{} step-by-step instruction above yields 25.1%—a 1.2-percentage-point swing from a one-line prompt suffix on the exact same checkpoint.

Similarly, time-windowed benchmarks depend on their exact cutoff dates: the report's LiveCodeBench (2408–2504) column specifically evaluates problems released between August 2024 and April 2025 in Chain-of-Thought (CoT) mode.

Main reasoning and coding benchmark results

Table 2 of the report compares DeepSeek-V3.2 (Thinking) against leading closed- and open-weights reasoning models as of December 2025 (full table in the report also includes Claude-4.5-Sonnet and MiniMax-M2):

Benchmark Metric DeepSeek-V3.2 (Thinking) GPT-5-High Gemini-3.0-Pro Kimi-K2-Thinking
MMLU-Pro Exact Match (%) 85.0 87.5 90.1 84.6
GPQA Diamond Pass@1 (%) 82.4 85.7 91.9 84.5
HLE (Text-only, no tools) Pass@1 (%) 25.1 26.3 37.7 23.9
LiveCodeBench (2408–2504) Pass@1-CoT (%) 83.3 84.5 90.7 82.6
Codeforces Rating 2,386 2,537 2,708 —
AIME 2025 Pass@1 (%) 93.1 94.6 95.0 94.5
HMMT Feb 2025 Pass@1 (%) 92.5 88.3 97.5 89.4
HMMT Nov 2025 Pass@1 (%) 90.2 89.2 93.3 89.2
IMOAnswerBench Pass@1 (%) 78.3 76.0 83.3 78.6

Dissecting the capability profile: math vs. broad world knowledge

Looking across the rows of Table 2 reveals a clear split between deductive reasoning and parametric knowledge breadth:

Also keep the distinction between short-answer Olympiad benchmarks and full proof grading in mind: AIME, HMMT, and IMOAnswerBench verify a final numerical or algebraic expression inside \boxed{}. A model can guess a pattern from small cases and get full credit on IMOAnswerBench without writing a rigorous proof. Full proof verification on IMO 2025 and CMO 2025 requires the dedicated DeepSeek-V3.2-Speciale pipeline analyzed in Chapter 21.

Token efficiency: accuracy per thousand generated tokens

Benchmark accuracy alone hides how much test-time compute a model burns to get its answer. In Table 4 of the report (examined alongside Speciale in Chapter 21), the authors report both accuracy and average output length (in thousands of tokens) across reasoning benchmarks:

Benchmark DeepSeek-V3.2 (Thinking) Score / Tokens Kimi-K2-Thinking Score / Tokens Gemini-3.0-Pro Score / Tokens
AIME 2025 93.1% (16K) 94.5% (24K) 95.0% (15K)
HMMT Feb 2025 92.5% (19K) 89.4% (31K) 97.5% (16K)
LiveCodeBench 83.3% (16K) 82.6% (29K) 90.7% (13K)
Codeforces 2,386 (29K) — 2,708 (22K)

Compared to Kimi-K2-Thinking, DeepSeek-V3.2 achieves higher scores on HMMT Feb 2025 (+3.1 points) and LiveCodeBench (+0.7 points) while generating 39% to 45% fewer output tokens (19K vs. 31K on HMMT; 16K vs. 29K on LiveCodeBench). Compared to Gemini-3.0-Pro, however, V3.2 still uses slightly more tokens (16K–29K vs. 13K–22K) for lower accuracy—the exact token-efficiency gap that motivates branching DeepSeek-V3.2-Speciale to see what happens when V3.2's length penalty is relaxed.

Parity check: DeepSeek-V3.1-Terminus vs. DeepSeek-V3.2-Exp

Finally, remember the architectural baseline from Chapters 5–6: before running this new post-training pipeline, the authors validated that converting dense MLA (V3.1-Terminus) to sparse DSA (V3.2-Exp) under matched post-training recipes caused no degradation across short- and long-context evaluations (such as AA-LCR and Fiction.liveBench) or ChatbotArena Elo ratings. That parity check ensures that the capability profile in Table 2 reflects a genuine combination of lossless sparse attention and scaled post-training RL.

Sources: Report §2.2, §4.1, and §4.2 (sections/01-method.tex, sections/02-post.tex, sections/06-high.tex; tables/eval_main.tex). Continue with reading the agent benchmarks.

20. Reading the Agent Benchmarks

Evaluating an agent never measures a language model in a vacuum: every score reflects the coupled system of model checkpoint + chat encoder + agent scaffold + tool runtime + context-management policy. Change how the scaffold formats tool outputs, or swap out the context-reset policy, and the exact same model weights can swing by 10 to 16 percentage points.

In Section 4.1 and Appendix C of the report, the authors document the exact harness conditions behind DeepSeek-V3.2's coding, search, and general tool-use evaluations.

Main coding, search, and tool-use benchmark results

Table 2 of the report compares DeepSeek-V3.2 (Thinking) against closed- and open-weights baselines across eleven agent evaluations (the full table in the report also includes Claude-4.5-Sonnet, which reaches 77.2% on SWE-bench Verified and 38.6% on Tool-Decathlon, as well as MiniMax-M2):

Benchmark DeepSeek-V3.2 (Thinking) GPT-5-High Gemini-3.0-Pro Kimi-K2-Thinking
Terminal Bench 2.0 46.4 35.2 54.2 35.7
SWE-bench Verified 73.1 74.9 76.2 71.3
SWE-bench Multilingual 70.2 55.3 — 61.1
BrowseComp (no context mgmt) 51.4 54.9 — —
BrowseComp (with context mgmt) 67.6 — — 60.2
BrowseCompZh 65.0 63.0 — 62.3
HLE (with search & Python tools) 40.8 35.2 45.8 44.9
τ2\tau^2-bench 80.3 80.2 85.4 74.3
MCP-Universe 45.9 47.9 50.7 35.6
MCP-Mark 38.0 50.9 43.1 20.4
Tool-Decathlon (Toolathlon) 35.2 29.0 36.4 17.6

How agent scaffolds interact with Thinking Mode

The footnotes and Appendix C tables for Terminal Bench 2.0 and SWE-bench provide a textbook case study in why scaffold details matter:

Thinking mode Agent scaffold Terminal Bench 2.0 score
Thinking Claude Code 46.4%
Non-Thinking Claude Code 37.1%
Non-Thinking Terminus 39.3%

Comparing 46.4% vs. 37.1% (both inside Claude Code) isolates the true +9.3-percentage-point gain from retained <think> blocks on complex terminal tasks, whereas comparing 46.4% (Claude Code) directly against 39.3% (Terminus) confounds thinking mode with a scaffold change.

Thinking vs. Non-Thinking across agent benchmarks

Appendix C (tables/nonthink.tex) compares DeepSeek-V3.2 in Thinking versus Non-Thinking mode under matched scaffolds across seven agent benchmarks:

Benchmark Non-Thinking Thinking Gain from Thinking (percentage points)
Terminal Bench 2.0 (Claude Code) 37.1 46.4 +9.3
SWE-bench Verified 72.1 73.1 +1.0
SWE-bench Multilingual 68.9 70.2 +1.3
τ2\tau^2-bench 77.2 80.3 +3.1
MCP-Universe 38.6 45.9 +7.3
MCP-Mark 26.5 38.0 +11.5
Tool-Decathlon 25.6 35.2 +9.6

Look at where <think> blocks make the biggest difference: on SWE-bench Verified and Multilingual, non-thinking mode already captures ~98.5% of the full thinking performance (72.1% vs. 73.1%), making non-thinking mode an attractive low-latency option for standard repository repair. On unfamiliar, multi-constraint MCP tool suites (MCP-Mark +11.5 points, Tool-Decathlon +9.6 points, Terminal Bench +9.3 points, MCP-Universe +7.3 points), explicit multi-turn <think> planning drives nearly a 10-point jump in task resolution.

Environment details: τ2\tau^2-bench, MCP harnesses, and redundant verification

Three additional protocol details in Section 4.1 help put the general tool-use numbers in context:

  1. τ2\tau^2-bench category breakdown and user simulator: On τ2\tau^2-bench, the evaluation uses the tested model itself as the simulated user agent. DeepSeek-V3.2-Thinking scores 63.8% on Airline, 81.1% on Retail, and 96.2% on Telecom, whose unweighted average is 63.8+81.1+96.23=80.366…%\frac{63.8 + 81.1 + 96.2}{3} = 80.366\dots\% (reported as 80.3%).
  2. Internal MCP environment alignment: For MCP-Universe and MCP-Mark, all models in Table 2 are evaluated inside DeepSeek's internal sandbox environment (where search API and Playwright browser configurations differ slightly from the official upstream harnesses) with tool outputs strictly formatted in the "tool" role.
  3. Context exhaustion from redundant self-verification: While V3.2 narrows the gap with proprietary frontier models across tool benchmarks, it still trails GPT-5-High on MCP-Mark (38.0% vs. 50.9%) and Gemini-3.0-Pro on MCP-Universe (45.9% vs. 50.7%). Investigating the failure traces, the authors note that on complex stateful tasks—particularly MCP-Mark GitHub and Playwright—V3.2 frequently gets stuck in redundant self-verification steps, inflating trajectory lengths until the transcript overflows the 128K context window and fails the task.

That trade-off between giving a model room to verify its work and keeping token trajectories within bounds becomes even starker when we examine DeepSeek-V3.2-Speciale in Chapter 21.

Sources: Report §4.1 and Appendix C (sections/02-post.tex, tables/eval_main.tex, tables/nonthink.tex). Continue with Speciale and competition-level reasoning.

21. Speciale and Competition-Level Reasoning

What happens if you take the DeepSeek-V3.2 post-training pipeline, strip out general chat and tool-use constraints, relax the length penalty during GRPO, and fold in a dedicated mathematical proof-verification reward? The result is DeepSeek-V3.2-Speciale—a specialized reasoning checkpoint built to test how far extended test-time thinking can push Olympiad math and competitive programming.

Evaluating Speciale requires separating two things: how the checkpoint itself trades token volume for single-attempt accuracy on standard benchmarks, and how the multi-candidate competition harness (parallel sampling, sample-test filtering, and iterative self-verification) turns that checkpoint into a gold-medal system on IMO, CMO, IOI, and ICPC.

How Speciale's training recipe differs from the main model

DeepSeek-V3.2-Speciale shares the exact same 671B DSA architecture and base checkpoint as the main model, but diverges during post-training in three ways:

  1. Reasoning-only RL mixture: Speciale trains exclusively on reasoning data during its RL stage, omitting multi-turn agent tool use and general conversational alignment (and consequently does not support tool calling in the released weights).
  2. Relaxed length penalty: Lowering the length penalty coefficient λ\lambda allows GRPO to reinforce much longer exploratory chains, case analyses, and inline sanity checks.
  3. DeepSeekMath-V2 proof dataset and reward: To handle full natural-language mathematical proofs rather than just \boxed{} short answers, Speciale incorporates the theorem-proving dataset and self-verification reward method from DeepSeekMath-V2.

Accuracy vs. token consumption: Main V3.2, Speciale, and Gemini-3.0-Pro

Table 4 of the report pairs benchmark scores with average generated output length (in thousands of tokens) across eight reasoning benchmarks:

Benchmark DeepSeek-V3.2 (Main) Score / Tokens DeepSeek-V3.2-Speciale Score / Tokens Gemini-3.0-Pro Score / Tokens
AIME 2025 (Pass@1) 93.1 / 16K 96.0 / 23K 95.0 / 15K
HMMT Feb 2025 (Pass@1) 92.5 / 19K 99.2 / 27K 97.5 / 16K
HMMT Nov 2025 (Pass@1) 90.2 / 18K 94.4 / 25K 93.3 / 15K
IMOAnswerBench (Pass@1) 78.3 / 27K 84.5 / 45K 83.3 / 18K
LiveCodeBench (Pass@1-CoT) 83.3 / 16K 88.7 / 27K 90.7 / 13K
Codeforces (Rating) 2,386 / 42K 2,701 / 77K 2,708 / 22K
GPQA Diamond (Pass@1) 82.4 / 7K 85.7 / 16K 91.9 / 8K
HLE (Text-only Pass@1) 25.1 / 21K 30.6 / 35K 37.7 / 15K

Comparing the three columns highlights both the power and the cost of test-time length scaling:

Gold-medal Olympiad and World Finals results

In Table 5 and Appendix D, the authors evaluate DeepSeek-V3.2-Speciale on four premier 2025 human competitions in mathematics and informatics:

Competition Score / Solved Per-problem breakdown Equivalent medal / rank
IMO 2025 (Math) 35 / 42 points [7,7,7,7,7,0][7, 7, 7, 7, 7, 0] Gold Medal threshold
CMO 2025 (Math, English version) 102 / 126 points [18,18,9,21,18,18][18, 18, 9, 21, 18, 18] Gold Medal threshold
IOI 2025 (Informatics) 492 / 600 points [100,82,72,100,55,83][100, 82, 72, 100, 55, 83] Gold Medal (10th place overall)
ICPC World Finals 2025 10 / 12 problems 10 solved within submission limits Gold Medal (2nd place overall)

Notice that on IMO 2025, Speciale achieves a perfect 7/77/7 on the first five problems and 0/70/7 on Problem 6. Because these evaluations model full contest participation (up to 50 submissions per problem in IOI, multi-submission penalty rules in ICPC, and multi-hour proof drafting in IMO/CMO), Appendix D documents the exact test-time search and filtering harnesses used for each contest. (All generation runs at a 128K token limit without external tools or internet access during model inference.)

The IOI 2025 and ICPC World Finals 2025 selection harnesses

In competitive programming contests, the official grading environment allows multiple submissions per problem and provides public sample test cases. DeepSeek-V3.2-Speciale uses a three-stage sample–filter–rank funnel:

  1. Parallel candidate sampling: For each IOI 2025 problem, the system generates 500 independent candidate solutions in parallel (for ICPC World Finals 2025, it generates 32 candidates per problem).
  2. Sample-test and refusal filtering: The harness executes each candidate program against the problem's public sample tests, discarding any candidate that fails the sample tests or exceeds code-length limits. Next, DeepSeek-V3.2-Exp acts as an automated judge to filter out candidates whose text explicitly states an inability to solve the problem or refuses the task.
  3. Ranking by thinking-trace length: From the surviving valid candidates for each IOI problem, the harness selects the 50 candidates with the longest <think> traces and submits them under IOI's official 50-submission rule (where a contestant's score on each subtask is the maximum score achieved across their submissions).

Notice how clever Step 3 is: once broken code is filtered out by sample tests, longer <think> traces correlate with deeper edge-case analysis and more complete algorithmic derivations, making thinking-trace length a zero-cost proxy for solution quality among passing candidates.

In ICPC World Finals 2025, using the same filtering funnel on 32 candidates per problem, Speciale solves 10 out of 12 problems—solving 8 problems on the very first filtered submission, 1 problem on the 2nd submission, and 1 problem on the 4th submission.

The IMO 2025 and CMO 2025 self-verification loop

Unlike IOI and ICPC, mathematical Olympiads provide no executable sample tests to filter out flawed proofs. Instead, for IMO 2025 and CMO 2025, Speciale uses the generate–verify–refine loop developed in DeepSeekMath-V2:

  1. The model drafts a candidate proof for the problem.
  2. Using its trained proof-verification capability, the model critiques and scores its own proof for logical gaps, unproved lemmas, or invalid case reductions.
  3. The model iteratively revises the proof based on those self-verification critiques until the proof achieves a perfect self-evaluation score or reaches the maximum revision cap.

To allow independent inspection of the final mathematical proofs and competition code, the authors released the full text of Speciale's final IMO, CMO, IOI, and ICPC submissions in the official repository.

Sources: Report §3, §4.2, and Appendix D (sections/02-post.tex, sections/06-high.tex, sections/appendix.tex); official model card and competition submission archive. Continue with understanding the released implementation.

22. Understanding the Released Implementation

The open-weights release of DeepSeek-V3.2 ships with a clean, self-contained reference implementation (inference/model.py, inference/config_671B_v3.2.json, and encoding/encoding_dsv32.py). Reading those files alongside the paper bridges the gap between the compact mathematical notation in Section 2 and the exact tensor shapes, RoPE coordinate layouts, and mixed-precision quantization rules required to run the checkpoint faithfully.

Reconciling ModelArgs defaults with config_671B_v3.2.json

If you open inference/model.py and look only at the Python @dataclass class ModelArgs, you will see small placeholder defaults (dim = 2048, n_layers = 27, n_routed_experts = 64, max_seq_len = 4096 * 4) intended for unit testing on a single node. When loading the actual 671B checkpoint, those defaults are overwritten by inference/config_671B_v3.2.json (and the Hugging Face root config.json).

Parameter ModelArgs dataclass default config_671B_v3.2.json / config.json
dim / hidden_size 2,048 7,168
n_layers / num_hidden_layers 27 61
n_dense_layers / first_k_dense_replace 1 3
n_heads / num_attention_heads 16 128
n_routed_experts 64 256
n_activated_experts / num_experts_per_tok 6 8
index_n_heads 64 64
index_head_dim 128 128
index_topk 2,048 2,048

Always initialize memory calculators and kernel configurations from config_671B_v3.2.json or config.json, never from the bare ModelArgs defaults.

Code map of inference/model.py and encoding/encoding_dsv32.py

Class / Function File What to inspect
ModelArgs inference/model.py Runtime configuration fields, YaRN parameters, and FP8 block size (block_size = 128)
Linear / linear() inference/model.py Blockwise 128×128128 \times 128 FP8 weight storage with dynamic per-token activation quantization
apply_rotary_emb() inference/model.py interleaved=True (MLA) vs. interleaved=False (Indexer) RoPE coordinate pairing
rotate_activation() inference/model.py Fast Hadamard Transform (hadamard_transform(x, scale=dim**-0.5)) prior to FP8 quantization
Indexer inference/model.py Query/key projections, LayerNorm, Hadamard rotation, FP8 cache, fp8_index, and torch.topk
MLA inference/model.py Low-rank Q/KV compression, RoPE split, FP8 KV simulation, and top-kk masking
Gate & MoE inference/model.py Sigmoid affinity scoring, 8-group top-4 group selection, route_scale = 2.5, and all-to-all dispatch
Block & Transformer inference/model.py Pre-norm residual loop across 3 dense layers + 58 MoE layers, YaRN frequency precomputation
encode_messages() encoding/encoding_dsv32.py Rendering OpenAI-style message arrays into DeepSeek-V3.2 prompt strings
drop_thinking_messages() encoding/encoding_dsv32.py Stripping <think> blocks prior to last_user_idx while retaining tool history

Crucial numerical detail 1: Interleaved vs. non-interleaved RoPE

One of the easiest places to introduce a silent numerical bug when porting DeepSeek-V3.2 to a new inference engine is RoPE coordinate layout. Look at apply_rotary_emb(x, freqs_cis, interleaved) in inference/model.py:

In fact, the official DeepSeek-V3.2-Exp repository history includes a November 2025 commit specifically fixing a mismatch where the reference indexer script accidentally defaulted to interleaved RoPE. If an engine applies interleaved RoPE to the indexer keys, the dot products qt,jI⋅ksIq_{t,j}^I \cdot k_s^I scramble the learned positional bias and degrade top-2,048 token selection without raising any runtime shape errors.

Crucial numerical detail 2: Mixed precision and blockwise FP8

Calling DeepSeek-V3.2 an "FP8 checkpoint" is shorthand for a carefully partitioned mixed-precision execution graph configured in config.json (quantization_config):

Sizing multi-node GPU memory for deployment

Even with 1-byte FP8 weights, storing ~671B parameters requires roughly 671 GB of raw weight memory before adding block scales, BF16 embeddings/norms/gates, KV caches, and activation buffers. A standard production deployment therefore shards the model across at least 8×\times80 GB (640 GB, tight/offloaded) or 8×\times141 GB H200 / 16×\times80 GB H100/H800 GPUs using a combination of Tensor Parallelism (TP), Expert Parallelism (EP), and Data-Parallel Attention (DP-Attention):

Chat encoding and developer role constraints

When integrating encoding/encoding_dsv32.py into a serving gateway, keep three interface rules in mind:

  1. Recommended sampling parameters: Both the paper and the official model card recommend temperature 1.01.0 and top-p=0.95p = 0.95 for general and reasoning workloads.
  2. Search-only developer role: The encoder supports a special role: "developer" message branch designed specifically for internal search-agent prompts; the model card notes that developer is not accepted on standard general-purpose API endpoints and should not be treated as an alias for "system".
  3. Strict tool-output ordering: When the assistant emits MM parallel tool calls inside a single <|tool▁calls▁begin|> block, the next MM messages in the conversation list must be MM corresponding role: "tool" messages in exact order, which the encoder wraps inside a single <|tool▁outputs▁begin|>...<|tool▁outputs▁end|> block before appending the next <think> or answer prompt.

In the next chapter, we trace a single multi-turn agent request through every layer of this stack—from encode_messages through the lightning indexer, MLA, MoE routing, tool execution, and GRPO training replay.

Sources: Pinned official inference/model.py, config.json, inference/config_671B_v3.2.json, encoding/encoding_dsv32.py, and README.md; Report §2 and Appendix A; DeepSeek-V3.2-Exp repository commit history. Continue with one request through the whole system.

23. One Request Through the Whole System

The preceding chapters examined DeepSeek-V3.2's subsystems one at a time. To see how message encoding, sparse attention, Mixture-of-Experts routing, tool state, context management, and GRPO training fit together in practice, let us trace a single multi-turn repository-repair request from the initial user prompt all the way through inference and offline RL replay.

The task

Suppose a developer submits the following request inside an agentic coding session:

Repair the CSV parser bug where an empty quoted field ("") is silently dropped. Preserve existing behavior for escaped quotes and custom delimiters, add a regression test, and run the test suite.

The agent harness exposes three tools—read_file, edit_file, and run_bash—and the conversation already contains a lengthy repository architecture guide plus several prior tool outputs totaling 40,000 tokens.

Step 1: Message encoding and <think> boundary checks

Before a single GPU kernel runs, encode_messages in encoding/encoding_dsv32.py serializes the structured message list into a single prompt string:

The tokenizer converts the rendered string into L≈40,000L \approx 40{,}000 integer token IDs in {0,…,129,279}\{0, \dots, 129{,}279\}, and the input embedding table maps each ID to a 7,168-dimensional vector.

Step 2: Prefilling the 40K prompt through MLA and the Lightning Indexer

As the 40,000-token prompt flows through the 61 transformer blocks (Block), each layer builds two historical caches in GPU memory:

  1. The MLA cache: Each token s∈{1,…,40,000}s \in \{1, \dots, 40{,}000\} projects its normalized hidden state into a shared 512-dimensional content latent csKVc_s^{KV} and a 64-dimensional interleaved RoPE key ksRk_s^R (576 coordinates total per layer).
  2. The Indexer cache: Each token ss also projects its hidden state into a 128-dimensional indexer key ksIk_s^I (with 64 non-interleaved RoPE coordinates), applies a LayerNorm and a Fast Hadamard Transform (rotate_activation), quantizes the vector to 128 bytes of FP8 (float8_e4m3fn) plus one 4-byte float32 scale, and stores them in k_cache and k_scale_cache.

For every query position t>2,048t > 2{,}048, the lightning indexer computes 64 heads of ReLU-gated FP8 dot products against all s≤ts \le t, combines them with query-dependent head weights wt,jIw_{t,j}^I, and selects the top k=2,048k = 2{,}048 token positions St\mathcal S_t. Main MLA then gathers only those 2,048 shared latents {csKV,ksR}s∈St\{c_s^{KV}, k_s^R\}_{s \in \mathcal S_t} and evaluates 128 query heads over that 2,048-token subset.

After attention, Layers 0–2 pass each token through a dense SwiGLU FFN, while Layers 3–60 route each token through 1 shared expert plus 8 out of 256 routed experts chosen by the group-limited sigmoid router (Gate).

Step 3: Autoregressive decoding of <think> and the first tool call

Once prefill finishes, the model decodes one token at a time at temperature 1.01.0, top-p=0.95p = 0.95:

Step 4: Multi-turn tool loop with retained reasoning

When encode_messages runs for Step 2 of the turn, the newest message has role: "tool", not role: "user". Consequently:

Across the next few tool turns, the model:

  1. Reads src/csv_parser.py and spots a if field == "": continue bug that strips empty quoted tokens after unquoting.
  2. Calls edit_file to fix the condition and add test_empty_quoted_field() to tests/test_csv.py. (Note that this call mutates the container filesystem.)
  3. Calls run_bash("pytest tests/test_csv.py"). Suppose the first test run fails because a trailing comma at end-of-line now emits a spurious empty field.
  4. Because the previous <think> blocks and tool outputs are all retained in context, the model does not re-read src/csv_parser.py; its next <think> block immediately diagnoses the trailing-comma interaction, patches the state machine, re-runs pytest, observes all tests passing (F2P = 1, P2F = 0), and writes a concise summary of the fix.

If the debugging loop had dragged on past 80% of the 128K window (~105K tokens), a context-management policy would have had to intervene—and because Step 2 mutated src/csv_parser.py on disk, a coding runtime would need a state-aware summary or git diff inspection rather than a blind Discard-all reset.

Step 5: Replaying the trajectory during offline GRPO training

Now suppose this trajectory was one of G=8G = 8 rollouts generated for this repository issue during the mixed RL stage. How does the training cluster turn this rollout into a stable gradient update?

  1. Outcome verification and advantage calculation: Inside the container, the test harness runs the JUnit test suite. This trajectory passed both the new regression test and all existing tests, earning R1=1.0R_1 = 1.0 (minus its small length penalty). Subtracting the group mean 1G∑j=1GRj\frac{1}{G}\sum_{j=1}^G R_j gives a positive advantage A^1,t>0\widehat A_{1,t} > 0 for every model-generated token in the trajectory.
  2. Action masking: All prompt tokens and all <|tool▁outputs▁begin|>...<|tool▁outputs▁end|> environment observations are masked out of the GRPO loss sum; only the assistant's <think>, <tool_call>, and final-answer tokens receive gradients.
  3. Keep Routing replay: At every generated token tt and every MoE layer ℓ∈{3,…,60}\ell \in \{3, \dots, 60\}, the training forward pass loads the exact 8 expert IDs logged by the inference server during rollout decoding, preventing expert-flip discontinuities in πθ(o1,t)\pi_\theta(o_{1,t}).
  4. Keep Sampling Mask replay: The training pass applies the saved top-p=0.95p = 0.95 vocabulary mask S1,tS_{1,t} from the inference engine before normalizing πθ(o1,t)\pi_\theta(o_{1,t}), ensuring r1,t(θ)=π~θ/π~oldr_{1,t}(\theta) = \widetilde\pi_\theta / \widetilde\pi_{\mathrm{old}} is computed over the exact same vocabulary support.
  5. Unbiased K3 KL and Sequence Masking: The KL penalty is evaluated with the importance-weighted K3 estimator (keeping πθ/πold\pi_\theta / \pi_{\mathrm{old}} inside the autodiff graph), while any failed rollout ii in the group (A^i<0\widehat A_i < 0) whose sequence log-ratio drift did_i exceeds δ\delta has its surrogate loss zeroed out by Mi,t=0M_{i,t} = 0.

Subsystem summary across the lifecycle of a request

Subsystem What it does during this request
Chat Encoder (encoding_dsv32.py) Strips <think> from prior user turns, preserves <think> across tool turns, wraps tool calls/outputs
Lightning Indexer (Indexer) Scans 40K+ FP8 cached keys with 64 ReLU heads, selects top 2,048 token indices St\mathcal S_t per query
Multi-Head Latent Attention (MLA) Caches 576-dim shared latent + RoPE key per token; gathers only the 2,048 selected entries in MQA mode
MoE Router & Experts (Gate, MoE) Evaluates 1 shared + 8 routed SwiGLU experts (out of 256) per token using group-limited sigmoid routing
Container Runtime & Verifier Executes file edits and pytest, grading final container state via JUnit F2P>0,P2F=0\text{F2P} > 0, \text{P2F} = 0
GRPO Stabilization Stack Replays MoE routes and top-pp masks, masks stale negative trajectories, and applies importance-weighted K3 KL

Sources: Integrated walkthrough synthesized from Report §§2–4 and the pinned repository artifacts (inference/model.py, encoding/encoding_dsv32.py). Continue with limits, practical choices, and research questions.

24. Limits, Practical Choices, and Research Questions

In Section 5 of the report, the authors candidly lay out three areas where DeepSeek-V3.2 still trails frontier proprietary models like Gemini-3.0-Pro and GPT-5-High. Pairing those acknowledged limitations with our structural analysis of DSA, off-policy GRPO, and synthetic agent environments clarifies both how to deploy the released checkpoints today and what open research questions remain.

Three limitations highlighted by the authors

  1. Breadth of world knowledge vs. total pre-training FLOPs: On encyclopedic and long-tail factual benchmarks such as MMLU-Pro (85.0% vs. 90.1%) and text-only HLE (25.1% vs. 37.7%), DeepSeek-V3.2 lags Gemini-3.0-Pro. The authors attribute this gap to spending fewer total pre-training FLOPs than the largest proprietary frontier runs, and note plans to scale pre-training compute in future generations. (When paired with live search tools, V3.2's HLE score jumps from 25.1% to 40.8%, confirming that external retrieval compensates for much of the parametric knowledge gap.)
  2. Token efficiency in long-horizon reasoning: Achieving parity with Gemini-3.0-Pro on competition math and coding requires generating substantially more tokens. While DeepSeek-V3.2-Speciale overtakes Gemini-3.0-Pro on AIME, HMMT, and IMOAnswerBench, it burns 23K to 77K tokens per problem compared to Gemini-3.0-Pro's 15K to 22K tokens—meaning the model relies on longer serial search chains where a more token-efficient policy reaches the same deduction in half the steps.
  3. Complex multi-turn task execution and redundant verification: On long-tail agent suites like MCP-Mark (38.0% vs. GPT-5-High's 50.9%), V3.2 still falls short, frequently getting trapped in redundant self-verification loops that exhaust the 128K context window on GitHub and Playwright browser tasks.

Architectural boundaries of DeepSeek Sparse Attention

Beyond those empirical benchmark gaps, the mechanics of DSA impose three concrete systems boundaries:

Practical deployment guide: choosing between V3.2 variants and modes

When deploying the open-weights checkpoints in production, match the checkpoint and mode to your workload's tool requirements and latency budget:

Workload profile Recommended checkpoint & mode Why
Interactive multi-turn coding, search, or MCP agents (in frameworks with native tool roles) DeepSeek-V3.2 (Main) — Thinking mode Retains <think> state across tool calls; delivers +7 to +11.5 point gains on complex MCP and terminal benchmarks
Latency-sensitive repository repair or legacy agent scaffolds (e.g., Terminus / Roo Code that emit user messages for tool outputs) DeepSeek-V3.2 (Main) — Non-Thinking mode Avoids re-reasoning overhead when scaffolds strip <think> on fake user turns; retains 72.1% vs. 73.1% on SWE-bench Verified
Offline competition math, theorem proving, and hard algorithmic puzzles (no tool calls needed) DeepSeek-V3.2-Speciale Trained with relaxed length penalty and DeepSeekMath-V2 proof verification; highest reasoning accuracy, no tool-calling support

Open research questions and follow-up experiments

Because the technical report introduces several major interventions simultaneously without full factorial ablations, it opens up five concrete research directions for the open-source community:

  1. Mapping the top-kk sensitivity curve of DSA: Since the released checkpoint allows changing index_topk at runtime, how does accuracy on multi-needle retrieval, repository QA, and math reasoning vary as kk sweeps from 256→512→1,024→2,048→4,096256 \to 512 \to 1{,}024 \to 2{,}048 \to 4{,}096 without retraining? Where does top-kk recall of dense attention mass begin to break down?
  2. Factorial ablation of the off-policy GRPO stack: Holding the MoE checkpoint and rollout staleness fixed, how much stability comes from Keep Routing versus Keep Sampling Mask, Off-Policy Sequence Masking (δ\delta), and the unbiased K3 KL gradient individually?
  3. Training adaptive stopping to cure redundant self-verification: Can step-level tool-call penalties or marginal-information rewards teach an agent to stop re-running passing tests on MCP-Mark and SWE-bench before overflowing the 128K context window?
  4. **State-aware context compaction for mutating agents:**On read-only web search (BrowseComp), wiping 100% of tool history at 80% capacity (Discard-all) beat summarization by +7.4 points. What is the right analog for stateful coding and database agents, where the workspace persists across context resets—for instance, pairing Discard-all with an automatically injected git status / git diff state header?
  5. Auditing synthetic verifier correlation: In automated environment synthesis (Chapter 14), both solution() and verify() are written by the same LLM from the same prompt. Quantifying the rate of correlated specification bugs—and testing whether generating solution() and verify() with independent models or formal property checkers improves transfer—would sharpen synthetic RL pipelines further.

Sources: Report §5 (sections/02-post.tex) and synthesis of Chapters 3–22. Continue with the glossary, equations, and source atlas.

25. Glossary, Equations, and Source Atlas

This reference chapter consolidates the paper's source file locations, revision checksums, architectural constants, key equations, and technical glossary in one place.

Primary sources and revision checksums

The primary paper is DeepSeek-AI, DeepSeek-V3.2: Pushing the Frontier of Open Large Language Models (arXiv:2512.02556v1, submitted 2 December 2025). The unmodified TeX source archive is preserved at ../2512.02556v1-source.tar.gz with SHA-256 checksum:

ebac277dba6a19100bec4fc921e6716157bf96d48b2f417e27cc4289a3d61c7d

Its top-level entry point is ../main.tex (as specified in ../00README.json), accompanied by the section files under ../sections/, tables under ../tables/, and original figures under ../figures/.

Official open-weights configuration, inference, and encoding files are preserved under ../_sources/ from the DeepSeek-V3.2 Hugging Face repository pinned at commit:

a7e62ac04ecb2c0a54d736dc46601c5606cf10a6

and cross-checked against the DeepSeek-V3.2-Exp GitHub repository at commit:

87e509a2e5a100d221c97df52c6e8be7835f0057

Per-file SHA-256 digests are recorded in ../_sources/source-manifest.json.

TeX source map

All paths below are relative to papers/dsv32/:

Topic TeX source file & lines Book chapters
Title and model-name macros (\dsv, \dsr, etc.) main.tex, lines 75–98 1, 25
Abstract sections/00abs_new.tex 1
Introduction and core motivation sections/01-0-intro.tex 1, 24
DSA formulation and MLA MQA instantiation sections/01-method.tex, lines 2–42 3–5
Dense warm-up and sparse training stages sections/01-method.tex, lines 44–73 6
Architectural parity check (Terminus vs. V3.2-Exp) sections/01-method.tex, lines 75–83 6, 19
Computational complexity and H800 cost curves sections/01-method.tex, lines 86–109 7
Specialist distillation, mixed RL, and Speciale recipe sections/02-post.tex, lines 3–27 8, 12, 21
GRPO objective, K3 KL, and off-policy stability sections/02-post.tex, lines 29–94 9–11
Thinking with tools and cold-start bootstrapping sections/02-post.tex, lines 97–126 13
Agent task table and environment synthesis pipelines sections/02-post.tex, lines 129–296 14–16
Main benchmark protocol and harness notes sections/02-post.tex, lines 298–317 19–20
Main reasoning & agent evaluation table (Table 2) tables/eval_main.tex 19–20
Speciale token efficiency and Olympiad results (Tables 4–5) sections/06-high.tex 19, 21
Synthetic-task difficulty audit and RL transfer curves sections/05-thinking-with-tool.tex, tables/synthesis-eval.tex 17
BrowseComp context-management scaling study sections/03-seach-agent.tex 18
Conclusion and limitations sections/02-post.tex, lines 328–end 24
Appendix A: MLA MHA vs. MQA execution diagrams sections/appendix.tex, lines 3–22 4
Appendix B: Cold-start prompt templates sections/appendix.tex, lines 38–143 13
Appendix C: Thinking vs. Non-Thinking agent table tables/nonthink.tex 20
Appendix D: IOI, ICPC, IMO, and CMO competition protocols sections/appendix.tex, lines 149–160 21

Official code and configuration map

Preserved artifact Key symbol or section Location
_sources/config.json Hugging Face model dimensions, YaRN, FP8 config Full file
_sources/inference-config.json config_671B_v3.2.json overrides for ModelArgs Full file
_sources/model.py ModelArgs dataclass Line 18+
_sources/model.py apply_rotary_emb (interleaved flag) Line 405+
_sources/model.py Indexer class (DSA lightning indexer) Line 435+
_sources/model.py MLA class (Multi-head Latent Attention) Line 498+
_sources/model.py Gate class (group-limited sigmoid router) Line 646+
_sources/model.py MoE class (shared + routed SwiGLU experts) Line 747+
_sources/model.py Block class (pre-norm transformer layer) Line 807+
_sources/model.py Transformer class (top-level model) Line 854+
_sources/encoding_dsv32.py drop_thinking_messages Line 254+
_sources/encoding_dsv32.py encode_messages Line 270+
_sources/encoding_dsv32.py parse_message_from_completion_text Line 341+
_sources/model-card.txt Official README.md usage notes and chat template guide Full file

(Backbone parameter counts of ~671B total and ~37B active per token trace to the inherited DeepSeek-V3 architecture in ../dsv3/main.tex, arXiv:2412.19437.)

Master table of architectural and training specifications

Quantity Value Notes
Total / active parameters ~671B / ~37B Inherited V3 MoE backbone scale
Vocabulary size (vocab_size) 129,280 Embedding and output LM head
Hidden dimension (dim) 7,168 Residual stream width
Transformer layers (n_layers) 61 3 initial dense FFN layers + 58 MoE layers
MLA query heads (n_heads) 128 Logical query heads per layer
Query / KV LoRA ranks 1,536 / 512 q_lora_rank / kv_lora_rank
Head widths (NoPE / RoPE / V) 128 / 64 / 128 qk_nope_head_dim / qk_rope_head_dim / v_head_dim
MoE routed / active / shared experts 256 / 8 / 1 Per MoE layer (moe_inter_dim = 2048, route_scale = 2.5)
Lightning indexer heads / width 64 / 128 index_n_heads / index_head_dim (64 RoPE + 64 NoPE)
DSA selected KV budget (index_topk) 2,048 Selected token indices per query
Stage 1 (Dense warm-up) 1,000 steps LR=10−3\text{LR} = 10^{-3}, 16×128K16 \times 128\text{K} seqs/step =2.1B= 2.1\text{B} tokens (backbone frozen)
Stage 2 (Sparse adaptation) 15,000 steps LR=7.3×10−6\text{LR} = 7.3\times 10^{-6}, 480×128K480 \times 128\text{K} seqs/step =943.7B= 943.7\text{B} tokens
Context length (Paper / HF / Demo) 128K / 163,840 / 16,384 Evaluated window (131,072131{,}072) / max_position_embeddings / ModelArgs default
Synthesized General Agent sandboxes 1,827 environments Yielding 4,417 retained general-agent tasks (pass@100>0\text{pass@100} > 0)
Code / Search / Interpreter tasks 24,667 / 50,275 / 5,908 Real execution environments; total across all 4 families =85,267= 85{,}267 tasks
BrowseComp accuracy (Thinking) 51.4% →\to 67.6% Unmanaged 128K window →\to with Discard-all at 80% capacity
SWE-bench Verified (Thinking / Non-Thinking) 73.1% / 72.1% Internal framework (72–74% across Claude Code and RooCode)
Terminal Bench 2.0 (Claude Code) 46.4% / 37.1% Thinking / Non-Thinking (Non-Thinking in Terminus =39.3%= 39.3\%)
Speciale Olympiad scores IMO 35/42, CMO 102/126, IOI 492/600, ICPC 10/12 Gold-medal performance across all four 2025 competitions
H800 cost benchmark baseline US$2 / GPU-hour Reference hardware rental assumption for Figure 2 cost curves

Key equations quick reference

  1. Lightning Indexer relevance score (Equation 1): It,s=∑j=1HIwt,jIReLU⁡(qt,jI⋅ksI).I_{t,s}=\sum_{j=1}^{H^I}w_{t,j}^I\operatorname{ReLU}\left(q_{t,j}^I\cdot k_s^I\right).
  2. Sparse top-kk MLA read: St=TopK⁡s≤t(It,s),ut=Attn⁡(ht,  {cs:s∈St}).\mathcal S_t=\operatorname{TopK}_{s\le t}(I_{t,s}),\qquad u_t=\operatorname{Attn}\left(h_t,\;\{c_s:s\in\mathcal S_t\}\right).
  3. Indexer KL alignment loss (Equations 2–3): LwarmupI=∑tDKL(pt,: ∥ Softmax⁡(It,:)),LsparseI=∑tDKL(pt,St ∥ Softmax⁡(It,St)).\mathcal L^I_{\text{warmup}}=\sum_t D_{\mathrm{KL}}\left(p_{t,:}\,\middle\|\,\operatorname{Softmax}(I_{t,:})\right),\qquad \mathcal L^I_{\text{sparse}}=\sum_t D_{\mathrm{KL}}\left(p_{t,\mathcal S_t}\,\middle\|\,\operatorname{Softmax}(I_{t,\mathcal S_t})\right).
  4. GRPO group mean-centered advantage and importance ratio (Equation 5): A^i,t=Ri−1G∑j=1GRj,ri,t(θ)=πθ(oi,t∣q,oi,<t)πold(oi,t∣q,oi,<t).\widehat A_{i,t}=R_i-\frac1G\sum_{j=1}^G R_j,\qquad r_{i,t}(\theta)=\frac{\pi_\theta(o_{i,t}\mid q,o_{i,<t})}{\pi_{\mathrm{old}}(o_{i,t}\mid q,o_{i,<t})}.
  5. Importance-weighted K3 KL estimator (Equation 6): DKL(πθ(oi,t) ∥ πref(oi,t))=πθ(oi,t∣q,oi,<t)πold(oi,t∣q,oi,<t)(πref(oi,t∣q,oi,<t)πθ(oi,t∣q,oi,<t)−log⁡πref(oi,t∣q,oi,<t)πθ(oi,t∣q,oi,<t)−1).D_{\mathrm{KL}}\left(\pi_\theta(o_{i,t})\,\|\,\pi_{\mathrm{ref}}(o_{i,t})\right)= \frac{\pi_\theta(o_{i,t}\mid q,o_{i,<t})}{\pi_{\mathrm{old}}(o_{i,t}\mid q,o_{i,<t})} \left(\frac{\pi_{\mathrm{ref}}(o_{i,t}\mid q,o_{i,<t})}{\pi_\theta(o_{i,t}\mid q,o_{i,<t})} -\log\frac{\pi_{\mathrm{ref}}(o_{i,t}\mid q,o_{i,<t})}{\pi_\theta(o_{i,t}\mid q,o_{i,<t})}-1\right).
  6. Masked GRPO objective with Off-Policy Sequence Masking (Equations 7–8): JGRPO(θ)=E[1G∑i=1G1∣oi∣∑t=1∣oi∣{min⁡(ri,t(θ)A^i,t,  clip⁡(ri,t(θ),1−ε,1+ε)A^i,t)Mi,t−βDKL(πθ(oi,t) ∥ πref(oi,t))}],\mathcal J_{\mathrm{GRPO}}(\theta)=\mathbb E\left[ \frac1G\sum_{i=1}^G\frac1{|o_i|}\sum_{t=1}^{|o_i|} \left\{ \min\left(r_{i,t}(\theta)\widehat A_{i,t},\; \operatorname{clip}(r_{i,t}(\theta),1-\varepsilon,1+\varepsilon)\widehat A_{i,t}\right)M_{i,t} -\beta D_{\mathrm{KL}}\left(\pi_\theta(o_{i,t})\,\|\,\pi_{\mathrm{ref}}(o_{i,t})\right) \right\}\right], where Mi,t=0M_{i,t} = 0 if A^i,t<0\widehat A_{i,t} < 0 and 1∣oi∣∑t=1∣oi∣log⁡πold(oi,t∣q,oi,<t)πθ(oi,t∣q,oi,<t)>δ\frac{1}{|o_i|}\sum_{t=1}^{|o_i|} \log \frac{\pi_{\mathrm{old}}(o_{i,t}\mid q,o_{i,<t})}{\pi_\theta(o_{i,t}\mid q,o_{i,<t})} > \delta, and 11 otherwise.

Technical glossary

Term Definition
Absorbed projection Folding MLA's per-head key/value up-projections WiK,WiVW_i^K, W_i^V into the query and output projections so the shared 512-dim latent csKVc_s^{KV} is read directly in MQA mode
Action support The subset of vocabulary tokens Si,t⊂VS_{i,t} \subset \mathcal V assigned nonzero probability after top-pp or top-kk truncation
DSA (DeepSeek Sparse Attention) Two-stage attention pairing a 64-head FP8 lightning indexer with top-2,048 token selection over MLA
F2P (Fail-to-Pass) A repository test case that fails on the base commit and passes after applying the candidate patch
GRPO (Group Relative Policy Optimization) Critic-free RL algorithm that normalizes trajectory rewards against the mean of GG rollouts sampled for the same prompt
Hadamard rotation Multiplying activations by an orthogonal Walsh-Hadamard matrix HH (1/d1/\sqrt{d} scaled) before FP8 quantization to smooth out channel outliers
Keep Routing Recording the exact 8 routed MoE expert IDs per layer during rollout inference and enforcing those same expert paths during training replay
Keep Sampling Mask Recording the rollout sampler's top-pp/top-kk vocabulary truncation mask Si,tS_{i,t} and applying it to πθ\pi_\theta during training updates
Lightning Indexer Lightweight 64-head ReLU scoring module (dhead=128d_{\text{head}} = 128, shared FP8 keys) that ranks historical positions for DSA
MLA (Multi-head Latent Attention) Attention architecture that compresses per-token KV states into a shared 512-dim latent csKVc_s^{KV} plus a 64-dim decoupled RoPE key ksRk_s^R
Off-Policy Sequence Masking Zeroing the policy-gradient surrogate (Mi,t=0M_{i,t} = 0) on negative-advantage trajectories (A^i<0\widehat A_i < 0) whose average log-ratio drift exceeds δ\delta
P2F (Pass-to-Fail) A regression test that passed on the base commit and fails after applying a patch (must be 00 for valid coding environments)
Specialist checkpoint Full 671B model trained via domain-specific RL to generate distillation trajectories for the unified V3.2 student model

Frequently asked questions

Is DeepSeek-V3.2 trained from scratch with sparse attention?

No. It initializes from the dense DeepSeek-V3.1-Terminus 128K base checkpoint, trains the lightning indexer for 1,000 steps (2.1B tokens) with the backbone frozen, and then co-adapts all weights under top-2,048 sparse selection for 15,000 steps (943.7B tokens).

Does DSA make the whole model O(L)O(L) over a prompt of length LL?

No. Main attention drops from O(L2)O(L^2) to O(Lk)O(Lk) (k=2,048k = 2{,}048), but the lightning indexer still scans all L(L+1)/2L(L+1)/2 causal pairs in O(L2)O(L^2) time—just with a >17×>17\times smaller arithmetic constant in FP8.

Does selecting 2,048 tokens shrink the KV cache in GPU memory?

No. Because future tokens t′>tt' > t can select any earlier position ss, all LL historical MLA latents and FP8 indexer keys must remain resident in HBM. DSA reduces memory bandwidth read per step, while adding ~1.06 GB of indexer key cache per 128K sequence.

Do the lightning indexer scores It,sI_{t,s} weight the values inside MLA?

No. The indexer scores It,sI_{t,s} are used strictly to pick the top-2,048 index set St\mathcal S_t (and to compute the auxiliary KL alignment loss LI\mathcal L^I during continued pre-training). Once St\mathcal S_t is selected, all 128 MLA heads compute their own standard softmax attention weights over s∈Sts \in \mathcal S_t.

Why does placing tool outputs in role: "user" hurt agent accuracy?

Under DeepSeek-V3.2's chat template (encoding_dsv32.py), a new "user" message signals the end of the previous user turn and strips all prior <think> blocks, whereas "tool" messages preserve <think> blocks across steps. Frameworks like Terminus or Roo Code that wrap tool outputs in "user" messages inadvertently wipe the agent's working plan after every tool execution.

Is DeepSeek-V3.2-Speciale just the main model with a higher max_tokens limit?

No. Speciale is a distinct checkpoint trained on reasoning-only RL data with a relaxed length penalty and the DeepSeekMath-V2 proof-verification reward; it learns fundamentally longer exploratory strategies and omits tool-calling support.

Return to the table of contents to jump to any chapter.