Kimi K3: the paper and proofs side by side

Kimi K3 is an open-weight model from Moonshot AI that works with text, images, and video. Its technical report describes 2.78 trillion learned parameters and a context window of up to one million tokens. It combines attention with recurrent memory and selects a subset of its experts for each token. Kimi K3 technical report ↗

Mathematicians have spent years formalizing research papers in Lean. I think it's time we did the same for ML papers. We now have TorchLean for tensor programs and model definitions, and FloatLib for floating-point arithmetic and its proofs. I wanted to use them to work through K3's equations and understand how the model fits together.

Read by chapter

Taking autoformalization into ML

Mathematicians have been putting research papers into Lean for years. The Liquid Tensor Experiment and the Polynomial Freiman–Ruzsa project showed how people could work through substantial mathematics together, writing the definitions and filling in the arguments until Lean could check the proofs. I want us to do that for machine-learning papers too.

Now AI is helping with the translation itself. In September 2026, Anthropic reported a complete Lean formalization of Fermat's Last Theorem, building in part on Kevin Buzzard's community project. This is what people mean by autoformalization: taking mathematics written for people and producing definitions and proofs a proof assistant can check. Seeing this happen for research mathematics makes me want to push further with ML :)

There is also recent work around the Riemann hypothesis. OpenAI's Lean formalization of the quasi-Riemann hypothesis describes a zero-free region \(\operatorname{Re}(s)>7/8\) for the Riemann zeta function. The Riemann hypothesis itself would put every nontrivial zero on \(\operatorname{Re}(s)=1/2\); the zero-free-region result is a different statement. What interests me here is the practice of publishing the mathematical argument together with a formal statement that readers can inspect.

A model report contains equations we can translate into tensor functions: how a recurrent state changes, how attention reads a cache, how a router chooses experts, and how their outputs are combined. We can then ask whether an implementation computes those equations and prove properties that matter when we use it. Those definitions can use different weights and dimensions, so the proofs can cover a whole family of models. I'd call this model autoformalization. AI could help translate the equations and find proofs, while Lean checks the arguments. Here we'll work through the calculations ourselves, starting with small examples before the full tensor equations.

We can write the tensor computations and their mathematical properties together. FloatLib supplies arithmetic definitions and rounding theory for the next question: what changes when we calculate with finite precision? That matters in ML, where the choice of precision and accumulation order can change a model's output. I want those choices to be part of the formalization, close to the equations that use them.

K3 is a good place to start because several of its architectural choices interact. Kimi Delta Attention (KDA) updates a recurrent memory, while Multi-head Latent Attention (MLA) looks back at individual cached tokens. The model also retrieves summaries from earlier layers and sends each token through selected groups of weights called experts. An image goes through a vision encoder before joining the language model. To formalize the model, we have to understand how those calculations share their inputs and state. Figure 2 and §2, pp. 3–4 ↗

That leads to concrete questions. Does splitting a sequence into two chunks preserve the output when we carry the state between them? Does the graph of tensor operations compute the same function as the paper equation? How large can a capped activation become? We can answer these with theorems about the definitions, and later ask how rounding changes the calculations.

In the Kimi team's introduction to K3, the architecture serves a larger ambition: a model that can keep working through long coding and research tasks. I like that they explain the memory and routing choices behind it. Those choices also give us mathematical questions we can settle. If a serving system pauses a calculation, resumes from a cache, or changes how it groups tokens, we want to know which changes preserve the function and which change its numerical behavior.

We'll start with the transformer calculations that K3 builds on, then work through its memory, attention, experts, and vision model. I'll keep the report beside the explanation and use small examples before the full tensor equations. The training and evaluation sections give us another part of the story: how the authors used those mechanisms and what they measured.

Start with a transformer

At each generation step, a language model assigns probabilities to the next token using the preceding context. K3 does this with 93 layers, 2.78 trillion parameters, and a million-token context. A transformer gives us a starting point for understanding the calculations that K3 changes.

  1. 1

    Tokenize. The text gets split into vocabulary pieces called tokens — roughly word fragments — and each gets an integer ID. "unhappy" might become two tokens: "un" and "happy." Everything downstream works with these integer IDs.

  2. 2

    Embed. Each token ID selects a learned vector from a lookup table. A vector has ordered numerical coordinates; K3 uses 7,168 of them per token. Training adjusts those numbers so the later layers can use them when predicting the next token. A concept need not live in one particular coordinate.

  3. 3

    Compute match scores. Three learned matrices project each token's vector into a query, a key, and a value. A dot product compares the current query with each key. The resulting scores determine how much each value contributes to the attention output.

  4. 4

    Mask the future. When predicting the next token, a position can only look at itself and earlier tokens, never later ones. This causal mask excludes future positions from the weighted sum. The usual attention notation writes their scores as negative infinity.

  5. 5

    Weight the answers. Softmax converts all the match scores for one token into nonnegative weights that sum to one in the real-valued equation. For example, weights of 0.4 and 0.3 multiply their corresponding value vectors by those amounts. Adding the weighted values gives the attention output.

  6. 6

    Update and continue. A residual connection adds the old vector back to the attention output. Then a feed-forward network processes that updated vector, and another residual addition carries the result to the next layer. The residual path lets a block add an update to the existing vector rather than replace it entirely.

The standard attention equation compresses steps three through five into one line. Capital letters stand for tables with one row per token: holds the queries, the keys, and the values.

  1. takes every allowed query–key dot product. A dot product multiplies matching coordinates and sums them, giving one match score per position pair.
  2. Dividing by controls the scale of those scores. If the coordinate products are independent and each has variance one, their sum has variance ; this division brings it back to one. Large score differences can otherwise make softmax concentrate heavily on one position. The variance calculation explains the usual scaling choice, not a law that every wider learned key must produce a larger score.
  3. is zero at allowed positions and is written as negative infinity at forbidden positions, excluding them from the normalization.
  4. The final multiplication by forms a weighted combination of the value vectors from all allowed positions.

Negative infinity here is shorthand for excluding a position. A finite negative score still has a positive exponential over the real numbers, however small it is. The real-valued hard-mask definitions therefore give forbidden positions exactly zero weight. A finite sentinel in a numerical implementation has to be checked against the masking behavior we intend.

Conventional multi-head attention runs this calculation across many attention heads in parallel. Each head uses its own separate query, key, and value projection matrices, so different heads can learn to pay attention to different things — one might track syntactic structure, another semantic role, another pronoun reference. K3 uses 96 heads. Their outputs get concatenated and projected back to the model width. A conventional cache with separate keys and values for every head multiplies its payload by the head count. K3's MLA cache instead retains a shared latent representation; we'll count that smaller representation separately.

Dot products alone do not encode where a token occurs in the sequence. Many transformers add positional information; rotary positional embeddings (RoPE), for example, rotate query and key coordinates according to position. K3 uses NoPE MLA, whose shared-key coordinates remain unrotated. Its KDA layers carry order through sequential state updates: changing the order of inputs changes which state each update receives.

Every block computes , and the representation going into the next block is . If is small, the original vector survives nearly unchanged. The residual stream accumulates the blocks’ contributions, so a later block receives information written at several earlier depths in one sum. K3’s AttnRes keeps earlier block sums available for separate retrieval.

The feed-forward half of each block is what holds most of the model's parameters. It takes the current hidden vector, projects it up to a wider hidden space, applies a nonlinearity, and projects back. In K3 this becomes a mixture-of-experts layer rather than one dense network — each token only activates a small fraction of the available capacity. But the basic pattern is the same.

Training processes many token positions in parallel. Inference is different: the model generates one token, appends it, and runs again. Keys and values from previous steps don't change, so implementations save them in a KV cache. The cache grows by one entry per token per attention layer. This is the trade-off the original transformer design made: instead of compressing history into a fixed recurrent state (like an LSTM would), it keeps the full history directly accessible. Storing that history costs more as the context grows. K3's hybrid attention is one way to manage the growing cache.

The Attention Is All You Need paper from 2017 made this pattern work at scale. Later decoder models have changed normalization, positional encodings, activations, and attention layout. But the alternating rhythm — attention to mix between positions, then feed-forward to transform within one position, then residual addition, then the next layer — stayed recognizable all the way through to K3.

The cost of a longer, larger model

We can make a transformer larger by adding layers, widening its vectors, or using longer sequences. Longer sequences enlarge the attention cache; more experts increase weight storage even when each token uses only a few. Let's look at how K3 handles these costs.

Attention and a growing cache

For a full causal sequence of length , one attention layer has permitted query–key pairs. Efficient kernels can avoid storing the full score matrix, but they do not turn quadratic attention into a constant-size recurrence. During generation, the KV cache grows by one entry per new token in every full-attention layer.

Models reduce this cost in two broad ways: store less information for each previous token, or replace the growing table with a fixed state that is updated after every token. K3 uses both. Multi-head Latent Attention (MLA) keeps one compressed entry for each earlier token, so a layer can still look back at individual positions. Kimi Delta Attention (KDA) keeps a fixed-size recurrent matrix instead, so its memory does not grow with sequence length.

More parameters, more matrix work

The feed-forward network often owns most of a transformer's parameters. Sparse mixture-of-experts models keep many feed-forward networks but route each token through only a few. The Switch Transformer demonstrated this at trillion-parameter scale. Only the selected experts compute an output for a token, but all the expert weights still need storage. Routing also adds load-balancing and communication costs.

One residual stream across many layers

A conventional residual stack carries a single running sum. By layer ninety, that vector contains contributions from every earlier block, but the current layer cannot directly choose an old representation. It receives the sum. Attention Residuals changes the depth path: block summaries remain visible and the current layer retrieves a weighted mixture. K3 stores summaries of groups of layers, rather than a separate summary for every layer.

Bringing images into the sequence

A vision transformer turns an image or video into patch tokens. A multimodal language model must decide where those tokens enter, how their feature width matches the language backbone, and whether training treats visual and text examples as one sequence from the beginning. We need to specify the projection to the language backbone's width and where the visual tokens enter the sequence.

Kimi's earlier Kimi Linear work developed Kimi Delta Attention as a gated delta-rule recurrence and paired mostly recurrent layers with occasional full attention. K3 brings that hybrid into a much larger system, adds depth retrieval and a latent expert space, and trains the result as a native multimodal model.

K3's architectural choices

KDA and MLA split the sequence problem: KDA carries a fixed-size summary forward, while periodic MLA layers can still inspect individual cached tokens. AttnRes retrieves earlier summaries across depth. Stable LatentMoE expands capacity across width without running every expert. MoonViT-V2 turns images and video into vectors the language backbone can consume.

The resulting model has 2.78 trillion parameters, activates 104 billion of them for each token, accepts text, images, and video, and supports a context window of 1,048,576 tokens. Moonshot released the weights. This gives the formalization a concrete object to aim at, rather than an architecture reconstructed from an API description.

2.8Ttotal parameters
→
104Bactive per token
·
1Mmaximum context
  • sequence

    KDA compresses the earlier tokens into a fixed-size matrix that changes after each new token.

  • global

    Three KDA layers are followed by one MLA layer to look back at individual cached tokens; layer 93 is also forced to MLA.

  • depth

    AttnRes keeps block summaries so a later layer can choose among earlier depth states instead of receiving only one running sum.

  • width

    LatentMoE sends each token through 16 of 896 experts. An expert is a separate feed-forward network; sparse routing avoids running all 896.

  • vision

    MoonViT-V2 pools images and video into visual tokens with the same 7,168-wide representation expected by the language model.

Together they let K3 grow in context, depth, and parameter count while accepting both text and visual inputs. Figure 2 and §2, pp. 3–4 ↗

Across the architecture, data, and training recipe together, the Kimi team reports about 2.5× better scaling efficiency than Kimi K2. The number comes from a fitted loss-versus-compute curve on a validation set deliberately different from the training data. It is an empirical result, not a serving-speed measurement or a Lean theorem. The report does not split the gain among KDA, AttnRes, LatentMoE, data, and optimizer changes. §3.2 and Figure 7, pp. 10–11 ↗

The report also gives results for coding, search, tool use, and web development. I return later to the scores and the evaluation conditions behind them. Abstract and Figure 1, pp. 1–2 ↗

The explicit equations are enough to get started :) We can take one expert, write its matrix products and activation in Lean, and prove that the graph computes that equation. Then we can use the expert inside a routed layer. Once that calculation is clear, I want to ask what changes when we store the weights and run the operations at lower precision. FloatLib gives us arithmetic definitions and rounding bounds for that next question.

Reading the paper with Lean beside it

Okay... imma try something a little different here :) I'd like to read the paper on one side and follow the Lean definitions and proofs alongside it. This is how I imagine working through an ML formalization: we read an equation, try a small tensor example, and see exactly what we've proved about it before moving to the next part of the model.

Click “Open PDF” on the left and follow along. I'll start with one expert, then work through K3's recurrent memory, attention, and complete decoder. You can change the numerical examples as we go and open the corresponding Lean source. I'd love future model reports to be shared this way, with the mathematics and its formalization close enough to read together.

Report Figure 2, p. 3

Recurrent memory, depth attention, and experts

Figure 2 is easier to follow as three separate directions of information flow. Along the token sequence, KDA remembers and MLA looks back globally. Along model depth, AttnRes chooses earlier summaries. Across model width, LatentMoE chooses a small set of experts.

Sequence, depth, and width Sequence KDA carries state forward;MLA reads earlier tokens. 93 layers DepthAttnRes retrievesearlier block sums. Width LatentMoE selects16 of 896 experts.
The backbone remains one 93-layer stack. KDA and MLA mix information across tokens, AttnRes retrieves across depth, and LatentMoE selects transformations across width.
In Lean

The same separation appears in the types: KDA and MLA are sequence mixers, AttnRes owns the depth state, and LatentMoE is a channel mixer.

Writing one expert in Lean

An “expert” sounds like a whole model, but here it's a feed-forward network with three learned matrices. Two matrices make the gate and value branches; SiTU combines their coordinates; the third matrix produces the output. Routing decides which experts to call. We can understand this one function before worrying about choosing among 896 of them.

Ok lets start with the sums and shapes. We'll write the tensor function, build the same calculation from graph operations, and use the existing equality theorem on a tiny example. The proof uses real-valued tensors. Rounding the arithmetic is a further question we can tackle once those two descriptions agree.

Lean keeps the program and the proof together

The part I find useful about Lean is that it's both a programming language and a theorem prover. We can define a layer as a function, run a supported numerical version of it, and state a theorem about the definition in the same language. The tensor types also record the input and output shapes.

For example, K3 caps the two branches of its SiTU activation before multiplying them. We can write that as a function of two real numbers and ask how large its result can get. The paper uses caps of 4 and 25; the theorem below bounds the scalar output by their product, 100, for every pair of real inputs. We don't need to choose particular weights to prove this property of the equation.

/-- Smoothly cap a scalar at magnitude `cap` using `cap * tanh (x / cap)`. -/
def softCap {α : Type} [Context α] (cap x : α) : α :=
  cap * MathFunctions.tanh (x / cap)

/-- Kimi K3's caps imply the concrete coordinate bound `100`. -/
theorem paper_caps_bound (gate up : ℝ) : |scalar 4 25 gate up| ≤ 100 := by
  have h := abs_scalar_le_mul_caps (gateCap := (4 : ℝ)) (upCap := (25 : ℝ))
    (by positivity) (by positivity) gate up
  norm_num at h ⊢
  exact h
Full source

Let's evaluate the cap at 2 and then the full SiTU response at gate 2, up 6. These commands use Float so we can run the calculation. Hover over softCap or the theorem name to inspect the types and assumptions. The theorem below concerns real numbers; the two decimal outputs are rounded evaluations.

import KimiK3.FeedForward.Activation

open KimiK3.SiTU

-- Float gives us a runnable value; the real-valued theorem quantifies over every input.
#eval softCap (4 : Float) 2
#eval scalar (4 : Float) 25 2 6
#check softCap
#check paper_caps_bound
Lean output
1.848469

9.585417

KimiK3.SiTU.softCap {α : Type} [Context α] (cap x : α) : α

KimiK3.SiTU.paper_caps_bound (gate up : ℝ) : |scalar 4 25 gate up| ≤ 100

Dependent types catch a different class of bug. A KDA state carries its two dimensions in the type Tensor α [keyDim, valueDim]. A matrix with those axes reversed has a different type when those dimensions differ. When the graph connects an output wire to the next layer's input, Lean checks that the shapes agree. This catches incompatible shapes before execution; it does not detect every possible mix-up between axes of the same size.

I also build the calculation as a graph. The GraphSpec files in this example connect typed tensor operations such as multiplication and tanh. Evaluating those nodes over real numbers should return exactly the same tensor as the reference function. A denotation theorem proves that equality, so we can check the graph's wiring against the equation.

We can lower that graph to a program for execution. Connecting a fused, low-precision GPU implementation to the real-valued graph needs a further proof: how much can its answer differ under the chosen arithmetic? The graph equality and that numerical bound answer different questions. We'll keep both calculations visible as we work through the model.

We'll use this approach for the recurrent update and the sequence of decoder steps too. Their statements are larger, but we can still follow the function, its assumptions, and the proof.

Writing the model in Lean

We write a layer as a function between tensors. A recurrent layer also takes a state and returns an updated one. Here is the KDA step: it updates the memory, then reads from that new memory to produce the current token's output.

A recurrent step and its return type

The colon in a Lean definition separates a name and its arguments from its type. In the block below, step takes a state and an input and returns a pair: the updated state and an output tensor. The return type appears after the final colon. The state type is the same before and after the call, so the update must preserve the matrix dimensions. The symbol := means "is defined to be," and everything after it is the actual calculation.

/-- One recurrence step returns the updated state and its current-token output. -/
def step (state : State α keyDim valueDim) (input : KDA.Input α keyDim valueDim) :
    State α keyDim valueDim × Tensor α [valueDim] :=
  let next := update state input
  (next, read next input.query)
Full source

We can try this with a zero memory, a key and query of [1, 0], and a value of [3]. The update writes into the first row; reading that row returns 3. Hover over memory, token, or step to inspect their types.

import KimiK3.Sequence.KDA
import NN.Tensor

open TorchLean

-- One head with two key coordinates and one value coordinate.
def memory : KimiK3.KDA.State Float32 2 1 := [[0], [0]]
def token : KimiK3.KDA.Input Float32 2 1 :=
  { query := [1, 0]
    key := [1, 0]
    value := [3]
    retention := [1, 1]
    writeStrength := 1 }

-- Read the first output coordinate.
#eval (KimiK3.KDA.step memory token).2.getScalar ⟨0, by decide⟩
#check KimiK3.KDA.step
Lean output
3.000000

KimiK3.KDA.step {α : Type} [Storage α] [Context α] {keyDim valueDim : ℕ} (state : KimiK3.KDA.State α keyDim valueDim)
  (input : KimiK3.KDA.Input α keyDim valueDim) : KimiK3.KDA.State α keyDim valueDim × Tensor α [valueDim]

Scalar types and tensor shapes

The Greek letter α (alpha) names the scalar type. Most proofs here use real numbers; an executable calculation can use a finite format such as a 16-bit float. Definitions that leave α open specify the operations they need, so we can reuse their tensor layout with different arithmetic. A theorem about real arithmetic still needs a refinement argument before it describes rounded execution.

A type like Tensor α [4, 2] means a tensor of α-values with four rows and two columns. The shape [4, 2] is right there in the type, not hidden in a runtime assertion. Lean checks these dimensions when it typechecks the program. Connecting incompatible shapes produces a type error before the calculation runs.

There is one small shape convention worth trying before the larger equations. Tensor α [] holds one scalar: it has no axes, rather than no values. Tensor α [0] is an empty vector, because its one axis has length zero. The number of entries is the product of the axis lengths; the product of no lengths is one. This is how a reduction can return a scalar tensor without introducing a different container type.

Indices, tensors, and growing caches

Fin n pairs a natural number with evidence that it is less than n. An expert ID of type Fin 896 therefore ranges from 0 to 895. Passing 1000 would require a proof of the false inequality 1000 < 896, so Lean rejects it.

The public sequence API takes tensors and returns tensors. Some internal caches use a List because they grow as tokens arrive, while the graph takes packed tensors with fixed shapes for one step. To relate the two, we need to show that packing the cache preserves the update and the output. Fixing the shape alone would leave the order of the cached entries unchecked.

Definitions and theorems

A structure bundles named fields. A model record can hold weight matrices; a cache record can hold state; a probability record can pair a number with evidence that it is positive. To see how those fields affect the model, follow the functions that consume them.

A def defines a function or value. It consumes structures and produces new ones, or produces tensors. This is where the actual computation happens. A theorem makes a claim about what a def returns. After theorem, everything up to := by is the statement being proved. The lines after by are tactic commands that Lean uses to build a proof term that its kernel verifies. If you see simp or ring or linarith, those tactics simplify expressions, normalize polynomial identities, or solve linear inequalities. Lean checks the proof terms they produce.

Describing tensor operations with Term

For the graph version, we use Term Γ shape. This is a typed expression in a computation graph. Its result is a tensor of shape shape, and Γ lists the shapes of its available inputs. You build expressions by composing Term values with Term.op, naming each primitive operation explicitly. Term.eval gives the graph a mathematical meaning by plugging in actual tensors. specFwd evaluates a whole graph model at once.

We'll often prove an equality of this form: model.specFwd params inputs = referenceFunction inputs. That equation says the graph and the reference function produce the same result. We can inspect the function first, then check how the graph implements each operation.

From an expert equation to its graph

Let's put an equation next to each part of Expert.forward. I'll use a row vector for the input, matching the [input, output] matrix layout in our source. That convention matters when we write the products.

Three matrix products and SiTU

Write \(d\) for the input width, \(h\) for the hidden width, and \(o\) for the output width. The expert has gate and up matrices \(G,U\), and a down matrix \(D\):

Input and the two projection matrices.
Output projection and hidden branches.

A projection makes each hidden coordinate by weighting and adding the input coordinates. For \(0\le j<h\), the two sums are:

Gate projection.
Up projection.

Now take positive caps \(c_g,c_u\). The sigmoid \(\sigma(t)=1/(1+e^{-t})\) lies between zero and one. SiTU uses it to gate two smoothly capped branches, giving a hidden vector \(z\):

The SiTU hidden coordinate.
The final output projection.

Notice that the sigmoid sees the original \(g_j\), before capping. Applying it to \(c_g\tanh(g_j/c_g)\) instead would give a different activation, even though every tensor shape would still match. That is one of the choices our equation and graph need to agree on.

/-- Evaluate one SiTU-GLU expert. -/
def forward (expert : Expert α inputDim hiddenDim outputDim) (gateCap upCap : α)
    (x : Tensor α [inputDim]) : Tensor α [outputDim] :=
  let gate := vecMatMulSpec x expert.gateWeight
  let up := vecMatMulSpec x expert.upWeight
  vecMatMulSpec (SiTU.vector gateCap upCap gate up) expert.downWeight
Full source

This is the same calculation in Lean. gate and up both have shape [hiddenDim], so SiTU can combine matching coordinates. The final multiplication returns [outputDim].

Each weight matrix has one axis for the incoming coordinates and another for the outgoing coordinates. For an input of width inputDim, both gateWeight and upWeight have shape [inputDim, hiddenDim]. The two products therefore meet at the same hidden width, where SiTU combines matching coordinates. downWeight has shape [hiddenDim, outputDim]. Reading those shapes tells us which matrix acts at each stage before we inspect any values.

The same calculation as a graph

/-- Build the typed DAG term for one SiTU expert from explicit input and parameter terms.

Use this form to embed an expert in a larger graph such as Stable LatentMoE. Both input
projections and the final output projection remain explicit graph operations.
-/
def term {Γ : List Shape} (inputDim hiddenDim outputDim : Nat)
    (input : Term Γ [inputDim])
    (gateWeight upWeight : Term Γ [inputDim, hiddenDim])
    (downWeight : Term Γ [hiddenDim, outputDim])
    (gateCap upCap : Term Γ []) : Term Γ [outputDim] :=
  let gate := Term.op (PrimOp.broadcastVecMat [] [] [] inputDim hiddenDim
      (Shape.CanBroadcastTo.refl []) (Shape.CanBroadcastTo.refl []))
    (.cons input (.cons gateWeight .nil))
  let up := Term.op (PrimOp.broadcastVecMat [] [] [] inputDim hiddenDim
      (Shape.CanBroadcastTo.refl []) (Shape.CanBroadcastTo.refl []))
    (.cons input (.cons upWeight .nil))
  let cappedGate := GraphSpec.softCapTerm [hiddenDim] gateCap gate
  let sigmoidGate := Term.op (NN.GraphSpec.DAG.PrimOp.sigmoid [hiddenDim])
    (.cons gate .nil)
  let gated := Term.op (NN.GraphSpec.DAG.PrimOp.mul [hiddenDim])
    (.cons cappedGate (.cons sigmoidGate .nil))
  let cappedUp := GraphSpec.softCapTerm [hiddenDim] upCap up
  let hidden := Term.op (NN.GraphSpec.DAG.PrimOp.mul [hiddenDim])
    (.cons gated (.cons cappedUp .nil))
  Term.op (PrimOp.broadcastVecMat [] [] [] hiddenDim outputDim
      (Shape.CanBroadcastTo.refl []) (Shape.CanBroadcastTo.refl []))
    (.cons hidden (.cons downWeight .nil))
Full source

The graph keeps those operations visible. Its two matrix products make \(g\) and \(u\); softCapTerm makes each capped branch; the sigmoid node reads the uncapped gate. Multiplication combines them before the down projection. Lean checks the shape of every connection.

I'm checking two things here. The types tell us that the dimensions fit. The equality theorem tells us that this particular wiring computes the intended function. Exchanging two same-shaped matrices would pass the first check, but would generally change the equation we have to prove.

A tiny expert we can work through

For a hand calculation, choose two input coordinates, two hidden coordinates, and one output. These toy matrices make the first two products easy:

Toy input and gate weights.
Toy up and down weights.

Then \(g=(1,2)\) and \(u=(2,6)\). With the paper's caps of 4 and 25, we get these values to six decimal places:

Illustrative hidden activation.
Illustrative output.

Here's how I instantiate the graph theorem for that example. The square brackets construct tensors because the weight fields and input have tensor types; Lean checks the rows and columns while elaborating them. We use \(\mathbb R\) to prove a statement about real-valued tensors; the decimals above help us work through the calculation.

import KimiK3.GraphSpec.Expert

open TorchLean

namespace ExpertExample

-- Two input coordinates, two hidden coordinates, and one output coordinate.
noncomputable def expert : KimiK3.Expert ℝ 2 2 1 :=
  { gateWeight := [[1, 0], [0, 1]]
    upWeight := [[2, 0], [0, 3]]
    downWeight := [[1], [-1]] }

noncomputable def input : Tensor ℝ [2] := [1, 2]

-- Instantiate the existing theorem with these weights and the paper's caps.
example :
    (KimiK3.GraphSpec.Expert.model 2 2 1).specFwd
        (KimiK3.GraphSpec.Expert.parameters expert)
        (KimiK3.GraphSpec.Expert.inputs input 4 25) =
      expert.forward 4 25 input := by
  exact KimiK3.GraphSpec.Expert.specFwd_eq_forward expert input 4 25

end ExpertExample

We reuse the existing expert and its proof; we don't need a new model wrapper for these dimensions. The theorem below leaves the weights and widths general.

Graph equivalence for arbitrary weights

/-- The typed executable graph denotes the original SiTU expert equation. -/
theorem specFwd_eq_forward {inputDim hiddenDim outputDim : Nat}
    (expert : KimiK3.Expert ℝ inputDim hiddenDim outputDim)
    (input : Tensor ℝ [inputDim]) (gateCap upCap : ℝ) :
    (model inputDim hiddenDim outputDim).specFwd
        (parameters expert) (inputs input gateCap upCap) =
      expert.forward gateCap upCap input := by
  simp [model, parameters, inputs, NN.GraphSpec.DAG.Model.specFwd,
    TorchLean.TensorPack.append, Args.vars, Args.weakenLeft, Args.rename,
    Term.rename, Term.eval, Env.tget,
    KimiK3.Expert.forward, Params, Inputs]
Full source

The source proof expands the model's parameter and input packaging, then uses the evaluation rules for the graph operations. Those rules leave the three matrix products and SiTU expression from Expert.forward. That's why the result works for every choice of weights and dimensions, not only our tiny example.

We can then lower the graph with toProgram. To connect a GPU answer to this real-valued theorem, we still need a rounding argument for the operations that actually execute. The graph equality gives us the equation that argument must use.

A bound on the expert's output

For the hidden activation, we can get a bound without inspecting any learned weights. Since \(|\tanh(t)|\le1\) and \(0<\sigma(t)<1\), the paper's caps \(c_g=4\) and \(c_u=25\) give:

The paper's hidden-coordinate bound.

I want to be careful about where that 100 applies. The down matrix can amplify the hidden vector. For an output coordinate, the triangle inequality gives:

Bound the absolute value of the output sum.
Use the SiTU bound for each hidden coordinate.

In the toy example, the absolute down weights sum to two, so this gives \(|y_0|\le200\). It's a loose bound, but it holds for every real input to those weights. The example above gives one output; the inequality tells us what can happen across all inputs. That's a useful first result to have before putting the expert inside a larger routed layer :)

The output bound in Lean

We reuse the SiTU theorem for each hidden coordinate, expand the vector–matrix product, and apply mathlib's bound on the absolute value of a finite sum.

import KimiK3.GraphSpec.Expert
import NN.Proofs.Tensor.Algebra

open TorchLean
open scoped BigOperators

example {d h o : Nat} (expert : KimiK3.Expert ℝ d h o)
    (input : Tensor ℝ [d]) (k : Fin o) :
    |(expert.forward 4 25 input).getScalar k| ≤
      100 * ∑ j : Fin h, |Spec.get2 expert.downWeight j k| := by
  let z := KimiK3.SiTU.vector 4 25
    (Spec.vecMatMulSpec input expert.gateWeight)
    (Spec.vecMatMulSpec input expert.upWeight)
  have hz (j : Fin h) : |z.getScalar j| ≤ 100 := by
    simpa [z, KimiK3.SiTU.vector, Tensor.stackLeading] using
      KimiK3.SiTU.paper_caps_bound
        ((Spec.vecMatMulSpec input expert.gateWeight).getScalar j)
        ((Spec.vecMatMulSpec input expert.upWeight).getScalar j)
  change |(Spec.vecMatMulSpec z expert.downWeight).getScalar k| ≤ _
  rw [Proofs.TensorAlgebra.getScalar_vec_mat_mul_spec]
  calc
    |∑ j : Fin h, z.getScalar j * Spec.get2 expert.downWeight j k| ≤
        ∑ j : Fin h, |z.getScalar j * Spec.get2 expert.downWeight j k| :=
      Finset.abs_sum_le_sum_abs _ _
    _ ≤ ∑ j : Fin h, 100 * |Spec.get2 expert.downWeight j k| := by
      apply Finset.sum_le_sum
      intro j _
      rw [abs_mul]
      exact mul_le_mul_of_nonneg_right (hz j) (abs_nonneg _)
    _ = 100 * ∑ j : Fin h, |Spec.get2 expert.downWeight j k| := by
      rw [Finset.mul_sum]
GraphSpec/Expert.lean, complete worked pattern ↗

Figure 2, p. 3 · Table 1, p. 11

Checking K3's published dimensions

The same Lean definitions work for tiny examples and the published 93-layer model. All published dimensions live in one checked configuration; the 2.78-trillion-parameter architecture is one value of those general definitions.

7,168language width
93backbone layers
96attention heads
896routed experts
16active experts
1,048,576maximum context

Explore the 93-layer schedule

KDA fills three positions, MLA fills the fourth, and layer 93 is forced to MLA so the backbone ends with global attention.

69 KDA24 MLASelect a layer

§2.1.1, pp. 4–5 · Equation 1

KDA's fixed-size recurrent memory

For one head, KDA carries a matrix \(S_t\) from one token to the next. Its rows correspond to key channels and its columns to value channels. That matrix is the memory. It has a fixed size even when the sequence keeps growing.

Equation 1 packs three actions into one line. Reading left to right matters: fade the old memory by α, erase the part aligned with the current key, then write the current value back along that same key. Only after the update does the query read the state.

(1)
S_t = (I - beta k k^T) Diag(alpha) S + beta k v^T
o-tilde_t = S_t^T q_t
  1. 01

    Decay. Diag(alpha)S scales each key row. Small retention forgets that row quickly.

  2. 02

    Correct. k^T Diag(alpha)S asks what value the old state already associates with this key.

  3. 03

    Write and read. The delta rule adjusts that association toward v_t, with strength β_t; the query q_t then reads the updated matrix.

Let's reduce this to one key coordinate and one value coordinate. The memory is now one number s. Set the key and query to one. Decay first changes the old memory to αs; correction and writing then give:

The new memory adds a scaled prediction error to the decayed memory.

Suppose the old memory is 6, retention is 0.8, the current value is 10, and write strength is 0.5. The old prediction after decay is 4.8. Its error relative to the current value is 5.2, so the update adds half that error and leaves memory 7.4. A write strength of one would replace 4.8 with 10; a strength of zero would leave only the decay. These are small real-number examples of the equation, not measurements from the released model.

Token order still matters. Starting from zero with retention and write strength both 0.5, values 2 then 10 leave memory 5.25. Values 10 then 2 leave memory 2.25. Parallel implementations can regroup compositions of state updates, but cannot permute the tokens and expect the same result. The matrix version stores many key-to-value associations at once; the same correction principle applies along the current key.

Run a 2 × 2 delta updatesmall dimensions, same equation
incoming S
1.000.20−0.300.70
→
decay
→
correct + write

§2.1.1, pp. 4–5 · Equations 2–6 · Figure 3

Preparing the queries, keys, values, and decay

Before KDA updates memory, the token is turned into query, key, and value vectors. A short convolution mixes each vector with a few earlier tokens; a smooth activation is applied, and the queries and keys receive regularized L2 normalization. A separate smaller projection chooses how quickly each row of memory decays.

The regularizer is part of the equation. For a projected vector z, we divide each coordinate by . The result has norm strictly below one over the real numbers, rather than exactly one; a zero vector stays zero. The regularizer keeps its denominator positive even in that case. KDA uses 10⁻⁶ here, while its RMSNorm operations use a different stabilizer.

(2)

q, k projections

(5)

bounded decay

(6)

output gate

What the slider is showing

The sigmoid keeps the log-decay between g_min and zero. Exponentiating turns that into a retention strictly between exp(g_min) and one. Move the logit right to forget faster; move it left to keep more of the row.

Lower-bounded retention\(g_{\min}=-5\)
log-decay g−2.5000
retention α = exp(g)0.0821
proved intervale−5 < α < 1

The lower bound keeps the accumulated log-decay for a 16-token chunk above −80. This is why the report says the chunk remains in a numerically safe range. Lean proves the real-number bound, not the rounding behavior of the low-precision GPU kernel.

§2.1.2, pp. 5–6 · Equation 7

MLA compresses the attention cache

DeepSeek-V2 introduced MLA. At an MLA layer, a token still gets global attention. The saving comes from what survives in the cache. Instead of storing a separate key and value for all 96 heads, the model keeps one 512-wide key/value latent and one shared 64-wide key.

When a head needs the old token, it reconstructs that head's 128-wide content key and 128-wide value from the shared latent. The reconstruction costs computation, but the cache grows by 576 scalars per token. A fully expanded per-head layout would store 30,720. Drag the token count below and watch the difference accumulate linearly.

The smaller number is 512 latent coordinates plus 64 shared-key coordinates. All heads can read that stored entry through their learned reconstruction maps. The larger baseline stores a content key, shared-key coordinates, and value for each of 96 heads: 96 × (128 + 64 + 128) = 30,720. This comparison counts stored scalar coordinates; converting it to bytes also requires the representation used for each cache.

That expanded baseline repeats the shared-key coordinates for every head. A layout that retained those 64 coordinates only once would use 96 × (128 + 128) + 64 = 24,640 scalars instead. The 53⅓ ratio below compares the specific fully expanded layout with the 576-coordinate latent cache; it is not a claim about every possible cache layout or an inference-speed ratio.

MLA still keeps an entry for every token. If a prompt doubles in length, this cache doubles too. KDA's recurrent matrix stays the same size, but no longer provides a separate stored entry that a query can inspect for every old token. K3 retains both mechanisms so the sequence calculation can use recurrent memory at most layers and global attention at selected layers.

Fully expanded per-head layout96 heads × (128 key + 64 shared + 128 value)30,720 scalars / token
÷ 53⅓
Gated MLA cache512 KV latent + 64 shared key576 scalars / token
Cache growthone compressed entry per token per MLA layer
uncompressed3,932,160scalars
MLA73,728scalars
saved3,858,432scalars

§2.2, p. 6 · Equations 8–10

AttnRes: attention across depth

A normal residual stream gives layer ell one running sum of everything below it. AttnRes keeps several depth sources visible. The current layer scores those sources, normalizes the scores, and retrieves a weighted combination.

K3 does not retain all 93 layer outputs separately. Every 12 layers are folded into a completed block sum, while the unfinished block remains separate. The embedding is always source zero. This is why the memory grows by blocks rather than by layers.

(9)
depth attention weights
depth retrieval
Try layer 12, then layer 13

Processing the twelfth member commits the completed sum immediately and resets the partial size to zero. Layer thirteen starts the next partial block. At every stored state, the partial size stays strictly below twelve.

Walk through the block stateblock size 12

After all 93 layers, the final retrieval can see nine depth sources when the original embedding is counted. Seven complete groups of twelve account for 84 layers. Nine layers remain in the partial group. Together with the embedding, that gives seven completed sums, one partial sum, and one embedding source. Completing a group changes which tensor is stored; it must not duplicate the completed layers in both the full and partial lists.

The query chooses how to combine these sources. If all source scores are equal, softmax gives them equal weight. A different query can favor one source over another. Normalization is used to compute the scores, while the weighted sum uses the original source vectors. Normalizing those values as well would change the retrieved vector, which is why the distinction appears in both the function and the graph proof.

§2.3, pp. 6–8 · Equations 11–13

Each token selects 16 of 896 routed experts

Shared experts operate at the full 7,168-wide model dimension. Routed experts operate at the 3,584-wide latent dimension. A token is projected down once, processed by its 16 selected experts, normalized, and projected back up.

tokenx ∈ ℝ7168
shared pathrouted path
2 shared expertsfull model width
W↓ → 16 of 896 → RMSNorm → W↑latent width 3,584
sumy ∈ ℝ7168
(11)
routed latent sum
shared and routed output
  1. A

    The shared experts see the original 7,168 coordinates and run for every token.

  2. B

    The routed branch projects once to 3,584 coordinates, then sends the same latent vector to 16 distinct experts.

  3. C

    The selected outputs are weighted, then RMSNorm rescales their combined vector by its root-mean-square size. A final projection restores 7,168 coordinates and adds the shared path.

The router first passes each raw score through sigmoid, a smooth function whose output lies between zero and one. Top-k then means choosing the 16 largest adjusted scores. The selection bias can change which experts enter that set. After selection, the weighted sum uses the original sigmoid scores, so the bias does not directly change how strongly a chosen expert contributes.

For a smaller example, imagine four experts with sigmoid scores 0.8, 0.7, 0.6, and 0.2, and select two. Without a bias, the first two win. Add a selection bias of 0.3 to the third expert, and its adjusted score becomes 0.9. The selected pair is now the third and first experts. Their mixture weights still use 0.6 and 0.8, normalized by their sum: 3/7 and 4/7. Using 0.9 in that mixture would implement a different rule.

The shared experts have no top-k decision: they process every token at model width. The routed experts all receive the same down-projected latent input, then their weighted outputs are combined before normalization and the up-projection. Sparse selection saves those unselected expert computations; it does not remove their weights from the checkpoint.

§2.3.2, p. 7 · Appendix B, p. 43 · Equations 18–19

SiTU caps both linear branches

SwiGLU is the gated activation inside a feed-forward expert: one transformed branch decides how much of another transformed branch passes through. Two of its factors can grow with the input, so its output has no fixed ceiling. SiTU smoothly caps both factors while keeping the sigmoid gate. Near zero it still behaves like SwiGLU; at large magnitude it stays bounded. The two squashing functions make the bound possible: sigmoid stays between zero and one, while tanh stays between minus one and one.

(19)
SiTU definition
SiTU bound

Drag past 25. The purple SwiGLU curve keeps climbing; the blue SiTU curve bends toward its ceiling. The formal theorem below proves that ceiling for every real pair (g,u), including points away from the plotted diagonal.

Scalar responsedrag the preactivation
SiTU-GLUSwiGLU

Both branches use the same input, g = u = x. SwiGLU continues above the plotted range; SiTU approaches 100.

§2.3.3, p. 8 · Appendices C–D, pp. 43–44

Balancing expert loads with score quantiles

K3 chooses the 16 experts with the highest adjusted scores for each token. For one expert, subtract each token’s 16th-highest cutoff from its raw score. That difference is the expert’s margin: adding a bias can move it above or below the selection threshold. A quantile is a cutoff in an ordered set of scores, eg the point above which a chosen number of margins lie. Quantile balancing chooses the bias to aim for a target load. We can check the resulting count when the cutoff is exact, characterize thresholds that minimize the coordinate objective, and bound histogram interpolation error within a known bin. The production histogram configuration and an exact-cutoff guarantee remain open.

routing margin
selection rule
quantile bias
target count

The two bars for each expert answer different questions. The raw-score bar shows the sigmoid score used in the mixture. The biased-score bar adds the balancing bias and decides whether the expert crosses the top-k cutoff.

Bias changes selection, not mixture weightfour experts, top-2

§2.4, pp. 9–10

MoonViT turns images and video into visual embeddings

MoonViT-V2 alternates spatial attention within each frame and temporal attention across frames at a fixed patch position. Temporal pooling collapses the frame axis. A 2 × 2 spatial merge trades four neighboring tokens for four times as many channels before the projector maps into the language width.

spatial merge preserves the number of scalars
four neighboring tokens become four channel groups

Switch from image to video and follow the third stage. With one frame the temporal attention axis has one position, but the block still applies its normalization, projections, output map, and residual. With several frames the same code attends along that axis at each spatial location.

The merge preserves the number of scalars by grouping four spatial tokens into one wider row. The language model sees fewer visual positions, each carrying more channels before projection.

Figure 2, p. 3 · §§2.1–2.4

How the K3 language model fits together

A backbone layer follows the same order every time. It makes two depth queries. The first retrieves input for KDA or MLA. Its output joins the partial depth block. The second query retrieves input for the dense or sparse channel mixer. Only after both submodules run does the block counter advance.

  1. 1

    Retrieve a sequence-mixer input from the current depth sources.

  2. 2

    Normalize and mix sequence with KDA or Gated MLA.

  3. 3

    Retrieve again with the sequence output included.

  4. 4

    Mix channels with the dense FFN or routed LatentMoE.

  5. 5

    Commit once to the AttnRes block state.

Text and visual positions remain distinct until embedding. A visual slot indexes MoonViT's projected sequence; a text slot indexes the vocabulary table. Both become 7,168-wide tensors.

Proof Language backbone · §§2.1–2.3

A token step through the decoder

The state has two representations in this development. The public causal calculation in Model.lean uses list caches and an AttnRes block state. The graph in GraphSpec/LanguageModel.lean takes an ordered pack of tensors whose shapes are known when the graph is built. Its component theorems compare graph operations with reference functions using that same pack. We still need to show that packing the public state preserves its transitions.

We can now compose the component proofs. Fix a valid K3 configuration, a current text token, fixed-shape caches, and one expert route for every sparse layer. The resulting graph updates every layer cache and produces the vocabulary logits for the next token. Under TorchLean's real-number semantics, those outputs equal runSpecAuto, the packed reference calculation, exactly. Both calculations use packed tensors; this does not yet prove equality with the public BackboneLayer.forwardToken.

“Packed” means that differently shaped KDA, MLA, and depth states sit in one ordered bundle whose shapes are recorded in its type. The graph is a directed acyclic graph (DAG): a one-way network of tensor operations with no loop back to an earlier node. A denotation theorem proves what that graph computes when its nodes are interpreted as real-number tensor functions.

A recurrent model can still appear as a DAG because this theorem covers one incremental step. The old caches enter as inputs; the updated caches and logits leave as outputs. A generation loop would feed those outputs into the next step, but that outer loop is not part of this graph yet.

route-staged token graph
parameters and causal state
one-token packed denotation

The brackets mean “evaluate the typed graph as a real-valued function.” The equality is exact. It includes the scheduled KDA/MLA choice, dense or sparse channel path, causal state packing, final depth retrieval, and vocabulary projection. A route trace lists the experts chosen at every sparse layer. The graph builder receives that trace; hRoutes proves each staged choice agrees with the top-k scores computed by the packed reference run. Vocabulary scores, also called logits, are the raw numbers softmax later turns into next-token probabilities.

primitive operationsRMSNorm · matmul · broadcast · reshape · activationTorchLean GraphSpec primitives
↓
component graphsKDA · MLA · AttnRes · Expert · MoEcomponent denotation theorems
↓
four backbone casesKDA/dense · KDA/sparse · MLA/dense · MLA/sparseBackbone.model_specFwd_eq_specStep
↓
route-staged token graphgraph_specFwd_eq_runSpecAutoupdated causal states and current vocabulary logits

Shape mistakes fail while the graph is elaborated. A semantic mismatch in cache order, layer case, reshape, parameter packing, or output packing breaks the proof. A wrong route trace prevents the caller from supplying hRoutes. This comparison catches disagreements between the two formal paths; it cannot detect an equation or assumption encoded incorrectly in both.

The next sections turn to updating the parameters and running training. Their proofs cover particular formulas and contracts, such as per-head matrix layout and bounded rewards. The training curves and systems measurements require evidence from the runs.

§2.5, p. 10

Per-Head Muon and matrix layout

For the query, key, and value projections, Kimi K3 applies Muon independently to each attention head. Muon applies an approximate matrix orthogonalization to its updates. Here we first check that the head split preserves the matrix entries. A matrix with \(\text{heads}\times\text{columns}\) outputs must split into head blocks and reassemble without moving an entry.

split one head block
the layout round trip

Hover one color. Those adjacent columns form a single head matrix. Orthogonalization runs inside that block, then merge restores every entry to its original global column.

Projection layouthover a head block

Each colored group is orthogonalized independently.

The full optimizer includes momentum updates, Newton–Schulz-style orthogonalization, and a distributed gather strategy. The formalization isolates the per-head layout and the contract an orthogonalizer must satisfy.

Pre-training · Report §3, pp. 10–12

How K3 was pre-trained

The reported 2.5× scaling gain compares training recipes that change the model shape, attention pattern, data mixture, optimizer, and context curriculum together. I follow those choices here to understand what the comparison includes: the capacity available to each token, the examples the model learns from, and the work spent on longer contexts.

More layers and experts, the same hidden width

Kimi K2 already had more than a trillion parameters, but K3 does not obtain its extra capacity by widening the residual stream. Both models keep a hidden dimension of 7,168. K3 grows from 61 to 93 language-model layers, expands the routed pool from 384 to 896 experts, doubles the active routed experts from eight to sixteen, and adds a second shared expert. The expert hidden dimension rises from 2,048 to 3,072. The result is 2.78 trillion stored parameters and 104.2 billion active parameters per token, compared with 1.04 trillion stored and 32.6 billion active in K2.

A mixture-of-experts checkpoint stores all its experts, even though a token uses only the selected ones. Total parameters count that stored capacity; active parameters better approximate the matrix work for a token. K3 stores about 2.7 times as many parameters as K2 and activates about 3.2 times as many, so both storage and computation grow. To estimate the time per token, we also need the routing, communication, memory format, batch size, and kernels.

Kimi K2 and Kimi K3 as reported in Table 1
QuantityKimi K2Kimi K3Change
Language-model layers6193+52%
Total parameters1.04T2.78T+167%
Active parameters per token32.6B104.2B+220%
Hidden dimension7,1687,168unchanged
Routed experts384896+133%
Active routed experts816+100%
Shared experts12+100%
Attention heads6496+50%
Attention stack61 MLA69 KDA + 24 MLAhybrid
Training context128K1M8×

The K3 column also lists a 3,584-dimensional latent MoE space and a 401-million-parameter MoonViT-V2 with 27 layers, patch size 14, and 12 heads. Sixty-nine of the 93 language layers use KDA; the remaining 24 provide global MLA attention. Table 1, p. 11 ↗

The reported 2.5× scaling gain

Figure 7 fits validation loss against training compute using data that was not used for training and was deliberately chosen to differ from it. At the same fitted loss, a K3-family run used about 40 percent as much compute as a K2-family run. That is the reported 2.5× gain. This compares fitted model-family curves, not serving speed or the total cost of the final checkpoint. Because architecture, data, optimization, and dimensions changed together, I read this as a gain for the combined recipe. To attribute it to KDA, the data mixture, or another component, we'd need runs that change those choices separately. §3.2 and Figure 7, pp. 10–11 ↗

The data mixture starts multimodal

The text corpus is organized around web text, code, mathematics, and knowledge. The pipeline combines rules, learned quality classifiers, and deduplication. Sampling rates for the domains come from ablations on smaller models. The report names that selection process, though the sampling rates are not given.

The team rewrites knowledge and mathematics sources before base-model pre-training. Prompts ask for different styles and viewpoints; long sources are rewritten chunk by chunk. A later fidelity check tries to keep the facts intact. The model therefore learns from transformed versions of some source material as part of its base corpus. That fidelity check matters: a rewrite can change a formula or factual detail even when the new prose sounds convincing.

The vision corpus covers captions, documents with interleaved images and text, OCR, perception, video, and visual coding. Localization examples use both absolute coordinates and coordinates normalized to the unit square. Programmatic examples pair code with rendered outputs such as SVG images, webpages, games, 3D assets, and CAD drawings. Those pairs let the model learn from code alongside the image or application it produces. We'll see related tasks again in the web-development and visual-agent evaluations. §3.1, p. 10 ↗

Joint vision-language training

MoonViT-V2 and the language model train together from the first step under the same next-token objective. Visual features are resized to the language embedding width and interleaved with text tokens, so the language loss also changes the vision encoder. The report calls this native multimodal training. For example, a wrong answer to an image question can change both the features extracted from the image and the language model that uses them. The two parts learn to work together under that objective.

textweb · code · math · knowledge
visionimages · documents · video · rendered code
→
one token streamjoint next-token prediction
→
one backboneMoonViT-V2 + K3 language model
Text and visual examples enter the same pre-training objective. Media-control tokens can remain in the input while selected positions are masked from the loss.

The optimizer and context schedule

Per-Head Muon updates the query, key, and value projection matrices in separate head blocks. K3 also keeps K2’s weight clipping and uses Quantile Balancing to adjust expert selection in place of the earlier auxiliary MoE balancing loss. The learning rate rises during a one-percent linear warmup, then follows cosine decay; weight decay is 0.1. These choices describe the update schedule, but they are not enough to replay the run: the peak learning rate, batch size, clipping threshold, and total token budget are not specified.

Context length grows late because attention and activation costs make long sequences expensive. Ordinary pre-training begins at 8K and later reaches 64K. During cooldown, the model advances to 256K and then one million tokens. The authors describe the long-context stages as a small fraction of training. They upsample scarce coherent long documents and videos, clean them with exact and fuzzy deduplication, use perceptual hashes for frames, and add synthetic examples that scatter the evidence needed for one answer across several concatenated documents and subtasks.

KDA uses no explicit positional encoding. Its recurrent decay and gating make the order of tokens affect the state, so the team can extend the sequence without rescaling rotary positional embeddings (RoPE), a common way to rotate query and key coordinates according to token position, or interpolating position indices. Removing RoPE removes one engineering obstacle. We still need to ask whether the state retains the information required by a long-context task. The later retrieval benchmarks address that question under their evaluation setups. §§3.3–3.4, pp. 11–12 ↗

I find the shared training objective and the late context expansion useful to think about together. K3 first learns from many kinds of input, then spends part of its final training on much longer examples. The report lets us understand that sequence of choices; reproducing its cost or attributing the scaling gain would require the underlying runs.

§§3.3–3.4, pp. 11–12

Loss masks and longer training contexts

The report describes a joint next-token objective for language and vision. Here we'll write a masked version of that objective, choosing which target positions contribute to the loss. The reported context schedule grows from 8K to 64K, then 256K and one million tokens during cooldown.

declared masked-gradient formula

At each trained position, softmax turns the vocabulary scores into probabilities. The stated gradient for one vocabulary item is its predicted probability, minus one when that item is the correct token, averaged over all trained positions. A masked position contributes zero. Its token can still appear in the input context; only its loss is omitted. Lean records this formula but does not yet derive it from the loss.

pre-training8K
extension64K
cooldown256K
cooldown1M

Example shifted sequence

Themodel<media>seestokens
In the declared formula, supervised rows receive the scaled cross-entropy term and the masked row contributes zero.

The masked loss and gradient formula are our mathematical specification of the next-token objective; the report does not give this formula or a complete loss mask. The four context lengths come from §§3.3–3.4. The report does not disclose the total token count or duration of each stage.

Post-training · Report §4.1, pp. 12–14

Training nine specialists, then combining them

Post-training proceeds in three stages. Supervised trajectories establish a usable agent. Reinforcement learning then separates domains and reasoning budgets into nine specialist policies. Multi-Teacher On-Policy Distillation brings their behavior back into one student.

Starting with supervised examples

Supervised fine-tuning (SFT) gives the base model a common interaction format and enough worked examples to begin agent training. Earlier domain-specialized Kimi models generate complex trajectories. Those trajectories pass through several verification stages and human annotation before training. Every conversation uses XTML, the text format used to serialize messages, tool calls, and tool results for the configurable agent wrappers and inference system.

These demonstrations are meant to teach the model to adjust reasoning effort, call tools precisely, and keep working through long tasks before reinforcement learning begins. This also gives RL a better starting point: the model can already attempt the interaction that the reward will judge. The report does not separately measure how much each part of the cold start contributes. §4.1.1, p. 12 ↗

Three domains crossed with three effort levels

The RL stage separates capability and computation. The first axis has three domains. General-task training covers ordinary experience, vision, reasoning, faithfulness, search, and knowledge work. General-agent training covers long-horizon assistants, deep research, and paragraph-level writing. Coding-agent training covers software engineering, coding experience, kernel work, and web development.

The second axis has low, high, and max reasoning effort. Crossing the two axes produces nine teachers. A low-effort coding policy learns under a tighter budget than a max-effort coding policy; both are distinct from a max-effort general agent.

low
high
max
general tasks
reasoning under a short budget
more search and thought
largest allowed budget
general agents
compact tool use
longer agent work
long-horizon execution
coding agents
fast coding tasks
repository work
extended coding and kernels

As RL computation increases in Figure 8, the plotted coding, tool-use, web-development, search, office, chart, and visual-puzzle capabilities rise. So does the average number of assistant or tool-call steps. This connects the training story to longer attempts at the tasks. I can read the direction of those trends, but the missing numerical axis labels, effect sizes, and variance prevent an estimate of improvement per unit of computation. §4.1.2 and Figure 8, pp. 12–13 ↗

Pausing and resuming unfinished rollouts

Agent trajectories vary in length. A batch that waits for its slowest trajectory leaves finished workers idle; a batch that discards unfinished work wastes the most expensive examples. K3 uses partial rollouts. For \(N\) prompts and \(K\) completions per prompt, the system maintains \(N \times K\) active trajectories. It pauses an iteration when a fraction λ has finished, queues the unfinished states, and gives them priority in the next iteration. A prompt enters policy optimization only after all of its \(K\) responses complete.

  1. 1

    Launch several responses for every prompt and retain their model, tool, cache, and environment state.

  2. 2

    When λ of all responses finish, stop waiting for the longest tail and start the next policy iteration.

  3. 3

    Resume the paused responses first. Their exact sandboxes and cache prefixes survive the boundary between iterations.

  4. 4

    Once every response for one prompt is ready, compute the group reward and make that prompt eligible for optimization.

A paused trajectory can resume after several parameter updates. Its earlier actions were sampled by an older policy, so learning from them is off-policy. The team says a per-token regularization penalty limits large policy changes enough to keep this stable. This creates a trade-off between finishing expensive work and learning from a recent policy. The report explains the mechanism, but does not quantify the age of the resumed trajectories or the throughput gained over synchronous rollouts.

Training with problem-specific token budgets

The effort levels are enforced through length-relative penalties. A cold-start model first estimates a baseline budget \(b_0(x)\) for each problem. A trajectory receives reward −1 when its length exceeds τ times that baseline. On general tasks, length counts thinking tokens. On agent tasks it counts cumulative output, including reasoning and tool-call arguments. Training begins with a large τ for the max-effort teacher, still under an absolute cap, and anneals τ to produce high- and low-effort teachers. The settings vary by domain with human guidance.

This penalty sits beside a competing trend: the capability curves improve as the agents take more steps. K3 is trained to spend extra computation when it earns reward and to stop when the trajectory becomes wasteful. To compare the effort modes, I would want to plot task success against tokens spent for each one. Figure 8 shows the broader training trends, rather than that budget-by-budget comparison.

Many agent tasks have deterministic or programmatic verifiers. Writing and other non-verifiable work uses an Agentic Generative Reward Model. The grader reads the output, writes a rubric, scores each candidate against it, and records the scores in a scratch area. Candidates compete through tournament-style binary comparisons. A response longer than σ times the cold-start verbosity loses automatically. This gives verbosity its own control instead of treating every extra token as evidence of better work. For these tasks the quality of the grader matters as well as the policy: a model can learn to satisfy a judge without making its answer more useful. §4.1.2, p. 13 ↗

Combining the specialists through distillation

Nine separate deployment models would be costly and awkward. MOPD samples a domain and effort pair, rolls out the unified student, and scores each sampled token with the matching teacher. The reward is the teacher-to-student log-probability ratio. It is treated as a fixed score, so differentiation does not flow back through its calculation, and it is clipped to a symmetric interval. The following section writes out that reward and shows the Lean bound.

Because the student generates the trajectories, teachers score the states it reaches during its own attempts. The report also tried a denser top-\(k\) objective that transferred several token probabilities at each position and found no clear improvement in convergence or final performance. The practical attraction is having one student that can switch domains and effort levels without loading a different model. The report does not give a separate retention score for each teacher, so the final evaluation measures the student rather than a teacher-by-teacher transfer rate. §4.1.3, pp. 13–14 ↗

§4.1.3, pp. 13–14 · Equation 15

MOPD compares teacher and student token probabilities

MOPD chooses one of nine domain-and-effort teachers, evaluates its probability for the student's sampled token, and clips the log probability ratio. The dense reward is bounded even when teacher and student probabilities differ sharply.

(15)
MOPD reward

Set the teacher probability high and the student probability close to zero. The raw log ratio increases, while the value passed to the objective stops at five in this illustration. Reverse them and the same clamp applies at minus five.

Inspect the clipped reward\(R_{\max}=5\)
log ratio2.169
clipped reward2.169

Start with the displayed probabilities, 0.70 and 0.08. Their ratio is 8.75, so its natural logarithm is about 2.169. The teacher assigns this sampled token more probability than the student does, giving a positive score. Exchanging the probabilities reverses the sign. Equal probabilities give zero. Clipping limits how strongly a very large disagreement can affect the reward; the slider uses an illustrative cap of five, not a cap value disclosed in the report.

The stop-gradient operation also matters. The student probability is used to calculate the reward, but that reward is held fixed while differentiating the policy update. Differentiating through both its log ratio and the policy objective would produce a different update. The scalar bound below describes the reward; it does not by itself identify either update rule.

§4.1.4, p. 14

What four-bit expert weights mean

Quantization replaces a high-precision number with one of a small set of coded values. MXFP4 gives each expert weight a four-bit code; MXFP8 gives each expert activation an eight-bit code. “MX” means microscaling: 32 neighboring values share a separate scale. The OCP Microscaling specification defines these formats. In the diagram, E8M0 is that shared exponent-like scale and E2M1 is the four-bit element format: one sign bit, two exponent bits, and one fraction bit. The formal model makes both parts explicit, so its error theorems state exactly what they assume.

shared-scale block decoding
E2M1 reference error

The purple chip belongs to all 32 cells. Changing that scale moves the range of the whole block; changing one E2M1 code changes only one cell. The slider isolates the element quantizer before the later theorems accumulate its error.

E8M0
20
Quantize one E2M1 valuereference semantics
nearest decoded value3.00
absolute error0.30
proved ceiling≤ 1

§4.1.4, p. 14 · Equation 16

A smaller model drafts tokens for K3 to check

EAGLE-3 is a smaller draft model that proposes several future tokens before full K3 checks them together. This is speculative decoding: cheap proposals can speed generation, while an acceptance-and-correction rule preserves the full model's final distribution. The draft starts from K3 features taken at low, middle, and high depths and from the pretrained multi-token prediction (MTP) layer, a small head trained to predict beyond the immediate next token. Its fusion matrix begins as [0 0 I], so the first fused feature is exactly the high-level feature the MTP layer already saw. Later draft steps feed their own hidden output forward. The training unroll has seven positions.

target featureslow · mid · high
[0 0 I]

Lossless speculative sampling accepts the overlap between the target distribution \(p\) and draft distribution \(q\). Kimi K3 minimizes the negative log of that overlap. Total variation, abbreviated TV below, is half the sum of the absolute probability differences: it is zero for identical distributions and one when they do not overlap.

(16)
acceptance loss
overlap and total variation

Each group of three bars is one possible next token. Blue is the target probability, purple is the draft, and gold is the overlap that can be accepted. Move the draft sliders toward the target. The gold area grows and the loss falls.

Acceptance is distribution overlapthree-token vocabulary
Σ min(p,q)
total variation
−log acceptance

For a proposed token y with positive draft probability, the acceptance probability is . Multiplying by the probability of proposing it gives . Summing those accepted contributions over the vocabulary gives the overlap shown above.

In the initial example, the target is (0.55, 0.30, 0.15) and the draft is (0.25, 0.45, 0.30). Their accepted contributions are (0.25, 0.30, 0.15), with total mass 0.70. The remaining target mass is (0.30, 0, 0). On rejection, the correction distribution therefore chooses the first token. Combining the accepted mass with that 0.30 rejection mass recovers exactly (0.55, 0.30, 0.15). Simply retrying the draft would not implement this correction.

This explains both the training loss and its limit. More overlap means more draft proposals survive verification. It does not alone determine wall-clock speed: drafting, checking a block, and restoring rejected state still take time. The equation trains the draft toward a useful acceptance rate; the serving section describes the remaining work needed to turn that into a faster generator.

RL environments · Report §4.2, pp. 14–17

Tools, tasks, and rewards

The training tasks specify what tools the agent can use and how its work is checked. The team creates tools, websites, repositories, office applications, machines, hidden tests, and reward rules that allow a trajectory to last for hours while still producing a checkable result.

Training across agent interfaces

Agent policies can overfit to the wrapper around a task. Tool names, message templates, available memories, context-management rules, subagent APIs, and even error formats become shortcuts. K3's white-box environment makes those pieces configurable. It can reproduce the interaction style of Kimi Code, Claude Code, Codex, OpenClaw, and Hermes, or assemble a new setup from the same parts.

The aim is to teach file inspection, search, and code execution across several tool schemas, so the agent can recognize those operations when their names or message formats change. A wrapper defines what the policy observes and which actions it can take; varying it changes the learning problem even when the underlying task stays the same. I would need a cross-wrapper ablation to measure whether this training improves transfer to a new interface. The report gives the design argument, but no such comparison. §4.2.1, pp. 14–15 ↗

A knowledge graph becomes a task generator

Broad seed topics are recursively expanded into a directed acyclic graph. An agent runs several web searches for each node, splits coarse ideas into finer ones, reuses an existing node when two branches reach the same concept, and stops when it judges a node atomic. The direction of an edge records movement from coarse to fine. Nodes at several levels can then supply retrieval queries, source bundles, and task prompts.

This mechanism produces related problems without copying one template at a time. A broad banking node can lead to financial statements, ratios, sector rules, and source-specific questions. A visual-science node can lead to plots, diagrams, measurements, and small computation tasks. Reusing equivalent nodes also connects areas that would otherwise grow as isolated trees.

seedprofessional analysis
bankingfilingsriskvaluation
data worktableschartssources
legalrulesevidencecitations
retrieval + sources + verifiernew agent tasks
An illustrative task graph: related topics supply different source bundles and questions. The report describes this construction in Figure 9; these labels are not a dump of its training graph.

§4.2.2 and Figure 9, p. 15 ↗

Search, professional work, and visual tools

The search tasks ask for an answer and supporting sources. Professional tasks cover banking, data analysis, and legal work, with trajectories lasting dozens or hundreds of steps. The verifier can inspect the final artifact, citations, calculations, or state of the simulated workspace. This rewards completion rather than fluent narration about what the agent intended to do.

Visual tasks put Python inside the observation loop. The agent may crop an image, zoom, transform it, measure a diagram, run a calculation, and feed the generated image back as the next observation. That design treats image tools as part of reasoning rather than a one-time preprocessing stage. The authors say scores rise with more operations and observations, though they supply no curve or effect size in §4.2.3.

Grading kernel correctness and speed

Kernel optimization problems range from one operator to large fused kernels and cover several GPU programming systems, including CUDA, Triton, CuTe DSL, Gluon, ThunderKittens, and TileLang. Tasks use 16-bit, 8-bit, and 4-bit number formats. A candidate whose numerical error crosses the private threshold gets zero. Matching an expert implementation earns 0.5, and approaching the hardware roofline moves the reward toward one. Separate detectors penalize replaying a captured CUDA graph, caching the input, or silently lowering precision.

The numerical check has to come before the speed reward. Caching an input or lowering precision could improve a timing result while changing the computation the task asked for. The report describes detectors for those shortcuts, though it does not publish the numerical threshold and timing protocol needed to reproduce the grading. §4.2.4, p. 16 ↗

Multi-day assistant tasks

The personal-assistant environment supplies mock versions of Gmail, Notion, Slack, and Canvas. Events unfold over several simulated days and cross application boundaries. An email may create a calendar obligation, a Slack message may change a document, and a later event may test whether the agent remembered the earlier instruction. Each event has either a deterministic check or a model-based judge.

A single rollout can reach thousands of tool calls and millions of accumulated context tokens. The report presents that as a possible upper range, not the typical trajectory. These workloads explain several later systems choices: paused generation must preserve the application state, repeated prefixes must remain cached, and an idle sandbox cannot reserve full memory while waiting for the next model response.

day 1read mailrecord a request
→
day 2edit Notionuse prior context
→
day 3answer Slackreconcile changes
→
laterhidden checkinspect final state

§4.2.5, p. 16 ↗

Grading tasks with no reference solution

Autonomous Execution Tasks give the agent a goal, constraints, action space, resource budget, and verification interface. They do not give it a procedure or reference trajectory. The reward depends on the final state of the environment. Example domains include reproducing a system, discovering quantitative factors, and auditing taxes.

Public diagnostic checks help the agent make progress, while hidden checks decide the final reward. Submission limits and penalties discourage blind probing. This resembles ordinary engineering work more closely than a benchmark with a known sequence of steps: several valid plans may exist, intermediate work can fail, and only the finished state settles whether the task was completed.

Figure 10 shows one camera-repair-system replication task. Its legend reports K3 at 1.000, Opus 4.8 at 0.918, GPT-5.5 at 0.893, and Kimi K2.6 at 0.560. The caption describes verifier-assessed progress, but does not fully define what each displayed scalar aggregates. One demonstration cannot establish a distribution of task performance; it shows the sort of work the environment permits. §4.2.6 and Figure 10, p. 16 ↗

Web development joins code and visible output

Web tasks start from briefs ranging from one line to several paragraphs. Expected outputs include ordinary sites, games, 3D and WebGL scenes, data visualizations, SVG work, and full-stack applications. Deterministic checks inspect structure, behavior, and pixels; an internal model judge assesses aspects that are hard to encode as a fixed test. Build failure, a runtime error, or a faked artifact produces zero reward.

The RL environment asks the model to build against an explicit visual and functional target. Later, the report's blind web-development comparison finds that judges prefer K3's output to Opus 4.8 in 58.6 percent of pairings, with the largest advantage in 3D and WebGL tasks. The evaluation section below discusses the judging conditions and limits. §4.2.7, p. 16 ↗

Infrastructure · Report §5, pp. 17–25

Training and serving infrastructure

K3 creates three different engineering problems at once: KDA has a recurrent state, sparse experts must move across a multi-trillion-parameter training cluster, and agent trajectories can retain a million tokens plus a live computer for hours. The report's infrastructure section describes how the team allocates memory, distributes expert computation, and stores unfinished rollouts.

KDA trades a growing cache for a serial state update

Full attention offers parallel work across a prompt but stores keys and values that grow with its length. KDA stores a fixed-size state for each head, which cuts cache growth and transfer volume. Its recurrence introduces a different problem: token \(t\) depends on the state from token \(t-1\). A literal implementation would process the prompt serially and leave much of the GPU idle.

FlashKDA breaks the prompt into chunks. Tokens inside one chunk can be processed in parallel; only the small summary passed from one chunk to the next remains sequential. The implementation uses CUTLASS, NVIDIA's building blocks for GPU matrix operations, and changes its work schedule for short, long, small-batch, and large-batch inputs. The report explains how operations overlap and reuse memory, but gives no throughput comparison. §5.1.1, pp. 17–18 ↗

Splitting KDA across devices with transition summaries

If we split a sequence across devices, the second segment needs the state left by the first. The third needs the state after both. Each device summarizes its segment with a small state update. Those updates can be combined in order. A prefix scan computes the summary after A, then after A+B, then after A+B+C, so every device recovers the state entering its own segment without exchanging all of the tokens.

segment Asegment Bsegment Csegment D
(transition, zero-state)(transition, zero-state)(transition, zero-state)(transition, zero-state)
fixed-size all-gather + associative prefix scan
state 0state after Astate after A+Bstate after A+B+C

Communication depends on the state summary rather than the number of tokens in a segment. The authors therefore describe communication as independent of sequence length and compute scaling as linear in the number of context-parallel devices. The claim follows from the algorithm's message shape; the report does not include an end-to-end scaling chart. §5.1.2, p. 18 ↗

In Lean, each segment summary is an affine map: it applies a linear transition to the incoming state and adds the segment’s zero-state output. Composing these maps gives the same state as applying them one after another. Identity, associativity, and the append law let us regroup the work for a prefix scan. Connecting the summaries to actual KDA updates is still open, as are the network collectives and measured scaling. Parallel/Context.lean ↗

Two scalar summaries make the ordering easy to see. Let and . Applying A and then B gives . Reversing them gives . Composition is associative, so a parallel scan can change the parentheses while keeping A before B. It is not commutative, so it cannot exchange the segments. These toy summaries illustrate the scan law; their coefficients are not measured K3 states.

Dividing a 2.78T model across devices

The model is too large for one GPU. Training therefore divides layers, experts, optimizer memory, gradients, and long sequences across many devices. Each division addresses a different limit: how much a GPU can store, how much work it can perform, or how much data workers must exchange.

The distribution names used in the report

Pipeline parallelism gives consecutive groups of layers to different workers. Expert parallelism spreads the 896 experts across workers. Context parallelism divides a long token sequence. ZeRO-1 shards optimizer memory, while Pipeline ZeRO-2 also limits which gradient pieces stay resident. Virtual pipeline stages interleave smaller layer groups to reduce waiting time.

These partitions interact. Routing may send many tokens to an expert located on another rank. Pipeline stages create bubbles, idle time while one stage waits for another. Sharded states have to arrive before their operation runs. Vision adds a separate encoder whose patch tokens and activations occupy memory. The paper concentrates on three solutions: balance expert work, manage saved activations through one policy, and schedule vision into otherwise idle pipeline time. §5.2, pp. 18–19 ↗

MoonEP and balanced expert assignments

Ordinary expert parallelism can be balanced in expectation and still stall on one rank that receives too many routed tokens. MoonEP migrates redundant copies of popular experts so every rank processes exactly \(S \times K\) token-expert assignments, where \(S\) is the token capacity per rank and \(K\) is the number of active routed experts. The placement changes dynamically with the measured load.

The report proves that no rank needs more than \(E/R\) redundant expert slots for \(E\) experts across \(R\) ranks. Its fixed receive buffer holds \(S \times K\) assignments. The existing DeepEP expert-communication layout can require \(S \times K \times R\), because any sending rank may contribute the full amount. Static shapes also remove a CPU synchronization step for discovering the next receive size. Lean now proves the per-destination upper bound from explicit home-capacity and one-source hypotheses, plus the capacity pigeonhole lower bound. It does not verify the online planner or distributed migration runtime.

conventional worst caseS × K × R

space for every possible sender contribution

MoonEP fixed bufferS × K

exact work assigned to each receiving rank

§5.2.1, pp. 19–20; Appendix E, pp. 44–45 ↗

Parallel/Experts.lean, counting bounds ↗

Saving, recomputing, and offloading activations

Activations are intermediate tensors that later computations may need again. Keeping all of them on the GPU consumes memory, while recomputing or moving them costs work. A unified manager plans their lifetimes and chooses which to keep, recompute, quantize, move to host memory, or send to remote memory. Most saved activations use a blockwise 8-bit format before offload. A common buffer plan lets the system overlap transfers with forward and backward computation across modules.

Pipeline ZeRO-2 further limits resident gradients, and reference weights for RL stream through two reusable gradient slots: one slot serves the current virtual pipeline chunk while the other prefetches the next. MoonViT-V2's image patches are sharded, and its encoder work is placed inside language-model pipeline bubbles. Both schedules try to make room for the next operation before it needs to run, rather than keeping every saved tensor resident for the whole update. §§5.2.2–5.2.3, pp. 20–21 ↗

Million-token RL preserves unfinished work

The RL cluster is co-located so one experiment fits within a few hundred GPUs. Policy training, rollout generation, reference-model work, and cache storage share that footprint. Partial rollouts cross iteration boundaries, so the system retains their prefix state in an external KV pool backed by CPU DRAM. Adaptive throttling slows generation before cache pressure becomes an out-of-memory failure.

At one million tokens, rebuilding the prefix on every resume would repeat a large amount of attention work. The pool keeps that work available while a trajectory is paused, allowing the next iteration to continue from its cached state. How much time this saves depends on reuse and transfer costs. Keeping a prefix in CPU memory still costs storage and a transfer back to the GPU; the design trades that cost against recomputing the prefix. The report does not measure that trade-off end to end. §5.3.1, pp. 21–22 ↗

Pausing and restoring agent sandboxes

Early container-based experiments caused kernel panics and deadlocks when agents explored aggressive system operations. AgentENV instead runs Firecracker microVMs: small virtual machines with their own guest operating-system kernel. The stronger isolation lets tasks mount disks, start containers, or even launch nested virtual machines without giving the agent control of the host kernel.

Incremental checkpointing saves only pages dirtied since the previous checkpoint. The report measures checkpoint latency as low as 133 milliseconds and resume latency as low as 49 milliseconds. Pausing releases the running sandbox's CPU and RAM while retaining its saved snapshot, which matters because waiting for model inference can occupy up to 98 percent of its lifetime. Forking creates a side-effect- free copy for reward judging, while snapshots provide recovery points.

The team also changed image storage, virtual-disk input and output, memory sharing, and direct transfer between machines. Together those changes produce subsecond launches at scale and up to 6.5× memory overcommit in the reported workloads. Across K3 training and evaluation, the system created 51,219,741 sandboxes from 1,505,678 images. These are among the report's most concrete operational numbers. They describe the environment fleet, not the number of unique RL tasks or successful trajectories. §5.3.2, p. 22 ↗

The storage mechanisms behind those numbers

OverlayBD shares read-only layers between virtual-disk images. The custom ublk driver handles block storage in user space. Copy-on-write memory lets sandboxes share pages until one modifies a page, and page-cache changes improve reuse of recently read file data. Peer-to-peer transport moves state directly between machines.

133 mscheckpoint, as low as
49 msresume, as low as
98%lifetime possibly waiting
6.5×memory overcommit, up to
51.2Msandboxes created

Restoring the recurrent state and attention cache together

A K3 block has three KDA layers and one MLA layer. MLA keeps a per-token cache that grows with the prompt. KDA keeps one large fixed state per request. A reusable prefix needs both caches at the same token boundary. The serving engine packs them into one paged pool so allocation, reference counting, transfer, and eviction use a shared implementation even though the page contents have different types.

KDA checkpoints are too large to store at every token. Physical cache blocks therefore span 1,024 to 6,144 tokens. If prefix matching used only those coarse blocks, a shorter shared prefix could not hit. The engine separates allocation granularity from hash granularity: MLA prefixes are hashed at 512-token boundaries inside a physical page, and sparse KDA state checkpoints are retained at eligible hash endpoints, often conversation turns.

one 6,144-token physical block
5121,0241,5362,0482,5603,0723,5844,0964,6085,1205,6326,144
2,800 matching tokensrestore at 2,560 and recompute only the suffix
The example in Figure 12 finds five matching 512-token hash blocks and a KDA checkpoint at token 2,560, even though that point lies inside one physical page.

Lookup first finds the longest MLA hash match, then requires a compatible checkpoint in every KDA cache group. Shared blocks are pinned before private allocation, freshly copied pages cannot be matched before their GPU copy completes, and eviction of one KDA group invalidates sibling checkpoints atomically. Those rules keep the two cache families at the same declared token boundary under concurrent scheduling. §5.4.1 and Figure 12, pp. 22–24 ↗

Speculative decoding retains the projections it needs

KDA decoding updates its recurrent state in place. If speculative verification rejects a drafted suffix, the state has already advanced beyond the accepted prefix. Saving one full state per draft position would multiply the dominant memory traffic. The K3 kernel caches the much smaller projected inputs for each draft token, replays the accepted ones on chip, and writes back only the verified and bonus-token states.

The serving kernels combine several small operations so intermediate values need not make separate trips through memory. During prefill (the first pass over the existing prompt), AttnRes spreads activations across sequence workers. During token-by-token decoding, it performs some depth work on a second GPU stream. LatentMoE overlaps worker communication with expert computation and begins its all-gather in the final stage of a matrix multiplication. Each change tries to keep a useful operation running while another waits for data. The report describes the schedules without an end-to-end speedup table. §5.4.2, pp. 24–25 ↗

Placing requests near their cached prefixes

A typical million-token coding request is described as carrying a 400K cached prefix and only 4K new tokens. The scheduler sends the request to the cluster holding that prefix. Consistent hashing, a deterministic rule that moves only part of the traffic when machines change, assigns a primary and a secondary cluster. The secondary accepts the session after a failure and recomputes its cache, spreading failover work across the fleet.

Requests under 2K tokens share the fleet with requests near one million, spanning roughly three orders of magnitude in per-request cost. The scheduler uses admission control, which limits how much work each request class can admit, to give the classes separate resource budgets. A burst of long prompts then has a budget of its own while short requests keep theirs. To evaluate this scheduler we would need to measure how long each class waits under mixed traffic, including bursts and failures. The report describes the policy rather than those latency distributions. §5.4.3, p. 25 ↗

What ties these systems choices together is the amount of work a long-lived request leaves behind: recurrent states, attention caches, tool processes, and a filesystem. Reusing that work requires more than keeping a tensor in memory. The caches have to agree on a token boundary, and the sandbox has to resume at the corresponding point in the task. That is why so much of this section concerns state lifetimes and recovery.

Evaluation · Report §6, pp. 25–32

Reading K3's evaluation results

K3 leads several coding, search, office, document, and web-development tests. It remains behind the best proprietary models on parts of research reasoning, difficult computer use, and some long-form knowledge work. The setup details explain why close scores should be read carefully.

How the benchmark runs were configured

Every K3 result in the main table uses max reasoning effort and temperature 1. Single-step reasoning and vision tasks use top-p 0.95: sampling keeps the smallest set of likely tokens whose probabilities add to at least 95 percent. Agent and coding tasks use top-p 1, which leaves the full vocabulary available. The proprietary baselines also run at their highest listed effort, except GPT-5.5 at xhigh. Claude Fable 5 may fall back to another model, and GPT-5.6 Sol may apply cyberguards. These policies change both capability and cost.

Coding scores may use Kimi Code, Claude Code, or Codex. Terminal-Bench reports the best score obtained across the available execution setups for each model. DeepSWE lists 67.5 in the comparison table while the official mini-SWE-agent result is 67.3. SWE-Marathon uses an H20-calibrated pre-release branch dated July 9, 2026, and Fable falls back on 35 percent of those tasks. These are disclosed choices, but they make small gaps poor evidence of an intrinsic model ordering.

BrowseComp uses context compaction at 300K tokens and reaches 91.2. With the raw one-million- token window and no context management, K3 scores 90.4. MCP-Atlas and AutomationBench use public subsets. WorldVQA required prompt changes to force answers after several models refused. Most vision scores average three runs, and ZeroBench uses five, but the table gives no confidence intervals. Several entries come directly from third-party leaderboards rather than a single common runner. §§6.1.1–6.1.3, pp. 25–27 ↗

Reasoning scores and harder research questions

K3 scores 93.5 on GPQA Diamond, tied with GPT-5.5 and 0.6 points behind GPT-5.6 Sol. It leads AA-LCR at 74.7. The harder research tests are less favorable. CritPt is 23.4, below Fable 5 at 28.6, Sol at 32.3, and GPT-5.5 at 27.1. Humanity's Last Exam is 43.5 without tools and 56.0 with tools; Fable reaches 53.3 and 63.0, while Sol reaches 44.5 and 58.0.

GPQA DiamondK3 93.5leader: Sol 94.1
AA-LCRK3 74.7best reported
CritPtK3 23.4leader: Sol 32.3
HLE with toolsK3 56.0leader: Fable 63.0

K3 handles graduate-level questions very well and leads one long-context reasoning test, while frontier research questions still expose a gap. That split matches the report's own interpretation. Table 2 and §6.1.4, pp. 27–28 ↗

Coding is one of the clearest strengths

K3 leads ProgramBench at 77.8, two tenths above Sol. It reaches 88.3 on Terminal-Bench 2.1, half a point below Sol. SWE-Marathon is 42.0, ahead of Opus at 40.0, Sol at 39.0, and Fable at 35.0 under the paper's branch and hardware conditions. FrontierSWE is 81.2, second to Fable's 86.6 and well above the other reported models.

DeepSWE is weaker relative to the leaders: K3's 67.5 trails Sol at 73.0 and Fable at 70.0. PostTrainBench and MLS-Bench-Lite are also led by Fable. On SciCode, K3 reaches 58.7, behind Fable's 60.2 but ahead of the rest. It is especially strong on terminal work, long-horizon repository tasks, GPU-oriented work, and program synthesis.

BenchmarkK3Best other scoreRead
ProgramBench77.8Sol 77.6leader
Terminal-Bench 2.188.3Sol 88.8near tie
FrontierSWE81.2Fable 86.6second
SWE-Marathon42.0Opus 40.0leader
DeepSWE67.5Sol 73.0third

Search, tools, and office work

BrowseComp is 91.2, DeepSearchQA is 95.0 F1, ResearchRubrics is 76.2, MCPMark-Verified is 94.5, and AutomationBench is 30.8; each is the best number in Table 2. K3 also leads SpreadsheetBench 2 at 34.8, τ³-Banking at 33.4, and Harvey Lab-AA at 94.6. These tasks ask the model to retrieve, use tools, operate applications, or produce a professional result, which closely matches the post-training environments described in §4.2.

K3 ranks third on GDPval-AA v2 at 1,686 Elo and second on AA-Briefcase at 1,548; Fable leads both. OfficeQA Pro is 63.3, below Fable at 69.9 and narrowly below Opus at 63.9. OSWorld 2.0 is 58.3, behind Fable at 66.1 and Sol at 62.6. SaaS-Bench is 60.1 versus Sol at 61.4. The harder desktop and long-form professional tests leave room above K3 even when narrower tool suites favor it.

OSWorld-Verified shows how close some comparisons are: K3 scores 84.8 and Fable 85.0. CorpFin v2 has the same two-tenths gap, 71.6 to 71.8. Such differences are smaller than many plausible sources of run-to-run and setup variation. The report gives repeated runs only for selected tests and no error bars, so “competitive” is a better reading than a stable rank for those cases. Table 2 and §6.1.4, pp. 27–28 ↗

Vision improves when the model can use Python

K3 leads OmniDocBench at 91.1. It reports 90.0 on Video-MME and 82.1 on MMVU, above the other models for which the table supplies scores, although Fable is absent from both rows. BabyVision with Python is 85.7, below Fable at 90.5 and Sol at 88.9. WorldVQA is 51.0, second to Fable's 56.7 under the forced-answer prompt.

The paired rows show what the Python observation loop adds. Math-Vision rises from 94.3 to 97.8. CharXiv rises from 84.8 to 91.3. MMMU-Pro moves from 81.6 to 83.4. ZeroBench pass@5 climbs from 23.0 to 41.0. Python does not uniformly give K3 the best score: Fable remains higher on tool-assisted CharXiv and ZeroBench and reaches 98.6 on Math-Vision. The consistent within-model gains still support the training choice to let visual agents crop, transform, calculate, and look again.

Math-Vision94.3→97.8+3.5
CharXiv RQ84.8→91.3+6.5
MMMU-Pro81.6→83.4+1.8
ZeroBench pass@523.0→41.0+18.0
Each pair compares K3 without and with the Python tool under the report's evaluation protocol.

The team's internal evaluations

The Kimi team maintains private tests for coding experience, always-on assistants, multi-agent coordination, autonomous execution, instruction learning, agentic vision, online deliverables, deep research, and conversation. K3 leads the reported Swarm Bench at 76.3 and DeepResearch Bench at 90.0. Kimi Code Bench 2.0 reaches 73.7 under Claude Code, below Fable at 76.9; under Kimi Code, K3 is 72.9. Coding Experience is 59.9, one tenth above Fable at 59.8.

To rerun these comparisons, I would need the tasks, graders, refresh rules, and contamination checks. Those are not released, and the table gives no uncertainty. Competitor fallbacks and refusals affect some rows; agent wrappers differ across models. I read the scores as measurements of these particular setups. Establishing a public ranking would require reproducing the setups and seeing how much the scores vary. §6.2.1 and Table 3, pp. 28–29 ↗

K3 wins 58.6% of the blind web-development comparisons

Experts blindly compare K3 and Opus 4.8 outputs on the internal web-development suite. K3 wins 58.6 percent of pairings, ties 13.8 percent, and loses 27.6 percent, a net win rate of 31 points. Its largest category advantage is 59.1 net points on 3D and WebGL work. The report also notes weaker or closer categories, which makes the breakdown more useful than a single averaged judge score.

K3 preferred 58.6%tie 13.8%Opus preferred 27.6%

Blind judging reduces brand bias, but the suite and internal judge procedure remain private. The result aligns with the public WebDev Arena, discussed below, and with the pre-training and RL emphasis on rendered code. Table 4, pp. 29–30 ↗

K3 finds real vulnerabilities, but the end-to-end result is 0 of 41

The defensive tier asks K3 to discover and reproduce vulnerabilities. Human review confirms roughly 70 percent of the findings submitted for review, including 16 previously unknown vulnerabilities across six projects. The report does not give the total number of raw findings, so that confirmation rate has no published denominator for all generated candidates.

The offensive tier contains 36 human-solvable tasks: 16 user-space targets and 20 Linux kernel targets. K3 completes 14, compared with GLM-5.2's eight. Ten of K3's successes are in user space, leaving only four kernel completions. The team names recurring failures: finishing an exploit chain after obtaining primitives, choosing a poor strategy under mitigations, entering long debugging loops, and failing to verify the final deliverable.

An independent UK AISI and NIST CAISI assessment reports 32 percent versus GLM's 24 percent on ExploitBench and 17 versus 11 completed steps in a simulated enterprise network. K3 still achieves arbitrary code execution on zero of 41 end-to-end tasks in that assessment. The combination matters: K3 can find real vulnerabilities and finish some live exploits, while hardened end-to-end exploitation remains far from expert completion. OpenAI and Anthropic models are excluded from the paper's internal exploit comparison because their policies refuse parts of the test. §6.2.2, pp. 29–31 ↗

Independent evaluations at the time of the report

As of July 23, 2026, Artificial Analysis places K3 fourth among 580 entries with an Intelligence Index of 57.1. Counting Sol's effort variants as one model moves K3 to third. Vals AI places it second among 39 models at 74.7, behind Fable at 75.1 and ahead of Sol at 73.1. These aggregates use each organization's own test mix and setup.

Human-preference arenas tell a more specialized story. K3 is first of 99 on WebDev Arena at 1,678 Elo, ahead of Fable at 1,634. It is eighth of 200 on Text Arena at 1,486 and fourth of 37 on Agent Arena at 9.1. Arena scores move as votes accumulate, and the Agent Arena was only a few days old at the report's cutoff. The public web-development lead is still an important independent match for the internal web result. §6.3 and Table 5, pp. 31–32 ↗

#4of 580

Artificial Analysis

#2of 39

Vals Index

#1of 99

WebDev Arena

#8of 200

Text Arena

#4of 37

Agent Arena

Cost changes the practical comparison

On Kimi Code Bench 2.0, K3 is four points behind Fable at 38 percent of its cost. On BrowseComp it scores 91.2 at $2.03 per task, about half the reported cost of Sol and an order of magnitude below the max-effort Claude runs. On GDPval-AA v2, K3 sits within 50 Elo of Sol at 13 percent lower cost and costs 2.6 times less than Fable. On AA-Briefcase it places second at roughly half Fable's cost.

The comparisons mix sources. Kimi Code costs come from internal runs with different agent wrappers. BrowseComp combines Kimi measurements with published competitor charts. GDPval and Briefcase use pay-per-token API prices from Artificial Analysis. They should be read as deployment examples at a dated price point, not a controlled systems benchmark. Even with that caution, the numbers explain why K3 can be a strong model without topping every row: it often approaches the highest score at much lower reported inference cost. §6.4 and Figure 13, pp. 31–32 ↗

Case studies · Report §7, pp. 32–34

Long-running coding, research, and design tasks

The final report section leaves standardized benchmarks and shows completed work. These cases are self-reported demonstrations rather than controlled estimates of average user performance, but they reveal the duration and technical range the team is targeting.

Up to twenty-four hours of kernel optimization

Each model receives an identically configured sandbox and up to 24 hours to profile, rewrite, and benchmark four kernels: AttnRes, DeepSeek Sparse Attention, KDA, and MLA with head dimension 512. The machines include an NVIDIA Hopper GPU and a second vendor's general-purpose GPU. This setup lets the agent iterate against real timing results rather than submit one code sample for static inspection.

K3 cuts AttnRes latency from 283.6 milliseconds to 114.4 milliseconds. It reduces DSA runtime by 55.1 percent and KDA runtime by 73.6 percent, and its MLA implementation reaches more than half of the measured peak TFLOPS. Across the four tasks, the report says K3 matches Fable 5 with fallback and exceeds Opus 4.8, Sol, and GPT-5.5. Figure 14 plots the AttnRes improvement across active hours, which is useful because it shows continued gains after the first working kernel rather than only the final point.

AttnRes latency283.6 ms→114.4 ms
DSA runtime−55.1%
KDA runtime−73.6%
MLA throughput> ½ peak TFLOPS

The Kimi team also says an early K3 checkpoint handled most of its kernel optimization during late-stage model development. That statement is operational testimony from the model's maker, not a separately audited usage log. The measured kernel changes are the stronger part of the case. Figure 14 and §7, pp. 32–33 ↗

MiniTriton: building a GPU compiler

K3 built MiniTriton, a compact compiler for GPU tensor programs. A small Python language describes calculations on rectangular tiles of data. The compiler turns that language into an intermediate representation, applies rewriting passes, generates GPU instructions, and runs them through a CUDA runtime. A tensor library above it can execute operations immediately or compile them first; it also supplies differentiation, neural-network modules, distributed training, sparse operations, and visualization. The project therefore spans the whole route from user code to a training loop, not one isolated kernel.

On an NVIDIA L20, the report says MiniTriton's geometric mean beats ordinary immediate PyTorch execution and torch.compile across its core suite. The largest from-scratch matrix multiplication reaches about 90 percent of the fastest rate measured on that machine and approaches NVIDIA's tuned matrix library. Its KDA prefill kernel beats the matched Triton reference. A small GPT trains end to end with a loss curve close to PyTorch; full-model gradient differences stay within 10−4 of Torch autograd when both are compared with an FP64 reference.

This case has public code, which makes it more inspectable than a screenshot of an agent conversation. The paper still does not provide a blinded comparison of generated compiler quality or isolate which parts humans repaired. It supplies roofline plots, convergence curves, and numerical checks for the finished artifact. Figure 15 and §7, pp. 33–34 ↗

A 48-hour chip-design run

In another autonomous run, K3 builds an inference-chip prototype for a small version of its own architecture. The design includes hybrid KDA and MLA, Block AttnRes with a block size of two, sigmoid MoE routing with one shared expert, and four-bit integer weights that share quantization settings in groups of 128. Kimi Code runs for 48 hours using open electronic-design-automation tools and Nangate45, a library of reusable logic cells.

The resulting design meets a 4 mm² analytical area budget, closes timing at 100 MHz, and reports more than 8,700 tokens per second in RTL simulation. It contains 1.46 million standard cells, 0.277 MiB of on-chip static memory, and a four-bit multiply-and-add array that converts values back to a wider format as part of the operation. These are pre-silicon numbers from an RTL flow, not measured performance from fabricated hardware. The source release makes the artifact available for a deeper engineering audit.

Implementing an astrophysics calculation

For an astrophysics task about I–Love–Q universal relations, K3 reviews more than twenty papers, cross-checks their results, implements a numerical pipeline, evaluates over 300 equations of state, finds inconsistencies in published formulas, writes more than 3,000 lines of Python, and produces an interactive HTML dashboard. The report gives a runtime of about two hours and estimates one to two weeks for an experienced researcher.

The time comparison is anecdotal because no matched human study is described. A successful trajectory has to keep citations, formulas, numerical code, data products, and a user-facing explanation consistent. That combination resembles the search, professional-work, coding, and web environments used during RL.

Research with parallel agents

One Kimi Work case produces an interactive history of 42 years of the AI-ASIC industry. It goes through more than 120 revisions, reads 87 quarterly reports and 99 original PDFs totaling over 11,000 pages, runs more than 2,800 web searches, and issues more than 1,100 terminal queries. Another case analyzes 391 gravitational-wave events from GWTC-5 with more than twenty concurrent subagents, then produces seven scientific visualizations, two summary tables, and a synthesis of more than ten papers.

Each trajectory has to keep its sources and calculations consistent through many tool calls and revisions. Subagents add another coordination problem: their outputs must agree on the data and definitions they share. Checking the finished research would mean following the cited reports into the tables and calculations, then inspecting the revision history for unresolved discrepancies.

Video editing and motion design

K3 creates a motion-graphics explanation of its own architecture in the style of a popular mathematics video channel and edits a teaser from 56 source clips. The described work includes clip selection, motion-matched cuts, beat-level synchronization, audio processing, and several revisions. The team estimates one to two days for an experienced editor to make a comparable short video.

The report gives no numerical quality test for the video. What it does show is the scale of task the team wants K3 to handle: hours of tool use ending in a finished artifact. These are selected demonstrations, not an average success rate.

What the current proofs cover

The sequence result is one I especially wanted. LanguageModel.run_eq_logits proves that processing embeddings token by token gives exactly the public model's full-sequence logits. run_append goes further: splitting the input at any position preserves every logit and the final decoder state, provided the second chunk resumes from the first chunk's state. These are equalities over the real-valued model for every sequence length and parameter value, including its deterministic expert routing. Each equality covers every input admitted by its statement.

The packed graph has its own composed theorem, from token lookup through the decoder to vocabulary logits, under the stated dimension and route-agreement conditions. At a smaller scale, the quantile proof gives a complete condition for minimizing the balancing objective, including ties and interval endpoints. It corrects the strict-count equivalence in Appendix C. Finding that endpoint case was useful because the corrected theorem tells us precisely which thresholds minimize the objective, rather than leaving us with a counterexample alone.

01 · checkedPaper equation → reference function

KDA, MLA, AttnRes, experts, routing, quantization, selected training equations, and EAGLE have explicit tensor or probability semantics.

02 · checked by componentReference function → typed graph

TorchLean graphs exist for the major language components, all four sequence/channel layer combinations, and the MoonViT embedding, block, and merge/project stages.

03 · checked for one packed tokenTyped graph → packed semantics

Denotation theorems identify graph evaluation with the packed reference calculation through vocabulary logits.

04 · openPacked state → public causal model

List caches and packed tensors still need representation relations for KDA, MLA, AttnRes, the backbone, and the complete language model.

05 · openGraph → executable K3 checkpoint

Runtime top-k, released parameter loading, checkpoint-backed assembly and generation, execution refinement, and finite-precision kernel bounds remain to be connected to the K3 theorem.

The public full-sequence API now agrees with repeated causal token steps by LanguageModel.run_eq_logits. The next connection is between those public states and the packed graph: packing KDA histories, MLA caches, and AttnRes sources must preserve each step.

Report claimCurrent evidenceNeeded for a stronger claim
Pre-training data and scaling law (§§3.1–3.2)empirical

Dataset manifests, sampling code, fitted curves, and reproducible measurements.

Optimizer and context curriculum (§§3.3–3.4)reported design

Stage durations, optimizer execution, checkpoints, loss traces, and evidence that a run followed the described curriculum.

RL synthesis and agent environments (§4.2)not modeled

Environment semantics, graders, reward aggregation, sandbox behavior, and rollout traces.

KDA kernels and context parallelism (§5.1)scan algebra checked

The bridge from actual KDA updates to affine summaries, then refinement to finite-precision kernels and distributed collectives, remains open.

MoonEP and memory system (§5.2)counting checked

The online placement algorithm, communication semantics, memory accounting, and machine-checked cost assumptions.

1M-context RL infrastructure (§5.3)not modeled

Sequence packing, sandbox scheduling, failure recovery, and measured throughput.

Inference and serving (§5.4)not modeled

Prefix-cache policy, kernel implementation, fleet scheduler, latency traces, and end-to-end refinement.

Benchmarks and case studies (§§6–7)reported results

Exact prompts, judge implementations, model artifacts, seeds, and independent reruns.

Source files

The definitions and proofs used above, grouped by component. You can filter by a model name or theorem.

reference

Common.lean

tensor helpers

Shared tensor notation, vector–matrix multiplication, outer products, normalization helpers.

reference

Config.lean

checked constants

Paper dimensions, released-checkpoint validation, layer schedule, compression and block counts.

reference

FeedForward/

activation, experts, routing, MoE

Four modules for SiTU bounds, expert computations, deterministic top-k, and Stable LatentMoE composition.

reference

Microscaling.lean

formats and bounds

FloatLib OCP decoders, finite-code adapters, 32-value blocks, and conditional quantization error bounds.

reference

Model.lean

public semantics

Dependent mixer states, backbone order, multimodal slots, final depth retrieval, and logits.

reference

Sequence/

causal semantics

Separate KDA, MLA, AttnRes, and scan modules. The existing Sequence import brings them together.

proof

Model/Streaming.lean

sequence = token steps

Tensor input and output sequences, retained per-layer state, and a theorem covering the public logits API.

reference

Training/

selected equations

Separate Muon, pretraining, distillation, and draft-model modules, with their existing proofs.

reference

Vision.lean

vision semantics

Spatial and temporal blocks, pooling, pixel-shuffle merge, projector, and full vision path.

proof

FeedForward/Quantile.lean

coordinate minimum with ties

A threshold minimizes the objective exactly when strict and weak counts bracket the real-valued target. This covers ties, both endpoints, and fractional targets. The exact-count routing theorem is separate; a threshold is not constructed automatically.

proof

FeedForward/Histogram.lean

distributed counts and error

Shard-independent pooling and interpolation error within one bin width, assuming the true quantile lies in that bin.

proof

Parallel/Context.lean

associative scan

Supplied affine summaries compose associatively and agree with sequential application. Their connection to actual KDA updates remains open.

proof

Parallel/Experts.lean

counting bounds

Redundant-expert upper bound with explicit hypotheses and the capacity lower bound.

protocol

Training/Controls.lean

deterministic controls

Nine teacher indices, selected MOPD reward, token-budget override, and verbosity enforcement.

protocol

ChatTemplate.lean

typed message grammar

Context zones, generation channels, and index-safe parallel tool call/result association.

graph

GraphSpec/Primitives.lean

term builders

General SiTU cap composition and small semantic adapters to canonical TorchLean primitives.

graph

GraphSpec/Expert.lean

graph = forward

Dense expert graph equals the reference SiTU expert forward pass.

graph

GraphSpec/KDA.lean

graph = fixed step

Preparation, recurrent update, readout, window rolling, and complete KDA layer equivalence.

graph

GraphSpec/MLA.lean

graph = stepFixed

Fixed-cache Gated MLA graph and its packed denotation theorem.

graph

GraphSpec/AttnRes.lean

term = packed retrieval

Depth-attention term evaluation over a fixed leading source axis.

graph

GraphSpec/MoE.lean

route-staged graph

A fixed-route graph equals forward; specialization at one input equals forwardReal.

graph

GraphSpec/Backbone.lean

four packed cases

KDA/MLA crossed with dense/sparse channel mixing, each with a denotation theorem.

graph

GraphSpec/Decoder/

layers, depth, backbone

Separate layer graphs, AttnRes depth scheduling, and backbone composition. LanguageModel.lean adds embeddings, final retrieval, logits, and the one-token theorem.

graph

GraphSpec/Vision.lean

three component denotations

Primitive graphs for embedding, one divided-attention block, and merge/project equal the reference equations.

graph

GraphSpec.lean

public surface

Imports the typed language-graph modules and states their packed/list boundary.

Conclusion

The next proof I want for K3 connects the public causal state to the packed graph. We need to show that packing each KDA history, MLA cache, and AttnRes source preserves its transition. That would join the sequence theorems to the graph theorem, rather than leave two separate accounts of the model. Loaded weights and finite-precision execution would come next.

I'd also like to discuss the Appendix C correction with people working on expert balancing. The corrected count condition handles ties and interval endpoints, but the router still needs to choose a threshold and resolve ties. Connecting that theorem to the histogram implementation would make it useful for the update itself.

My hope is that we eventually release models with their equations and proofs alongside the code and weights. For this model, we have concrete connections left to prove. I'd be very happy to work with people interested in taking those on :)

References

Cite this article

Robert Joseph George. Kimi K3: the paper and proofs side by side. TorchLean Verified Examples, 2026.

@misc{george2026kimi,
  author = {Robert Joseph George},
  title = {{Kimi K3: the paper and proofs side by side}},
  year = {2026},
  howpublished = {TorchLean Verified Examples},
  url = {https://robertboy18.github.io/TorchLean-Verified-Examples/week-04-kimi-k3-specification/site/}
}
Download BibTeX