Robert Joseph George · TorchLean Verified Examples
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
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
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
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
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
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
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.
takes every allowed query–key dot product. A dot
product multiplies matching coordinates and sums them, giving one match score per
position pair.
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.
is zero at allowed positions and is written as
negative infinity at forbidden positions, excluding them from the normalization.
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.
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α] (capx : α) : α :=
cap * MathFunctions.tanh (x / cap)
/-- Kimi K3's caps imply the concrete coordinate bound `100`. -/
theorem paper_caps_bound (gateup : ℝ) : |scalar425gateup| ≤ 100 := by have h := abs_scalar_le_mul_caps (gateCap := (4 : ℝ)) (upCap := (25 : ℝ)) (by positivity) (by positivity) gateup 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.
#evalsoftCap (4 : Float) 2#evalscalar (4 : Float) 2526#checksoftCap#checkpaper_caps_bound
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αkeyDimvalueDim) (input : KDA.InputαkeyDimvalueDim) :
StateαkeyDimvalueDim × Tensorα [valueDim] :=
letnext := updatestateinput
(next, readnextinput.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.StateFloat3221 := [[0], [0]]
def token : KimiK3.KDA.InputFloat3221 :=
{ query := [1, 0]
key := [1, 0]
value := [3]
retention := [1, 1]
writeStrength := 1 }
-- Read the first output coordinate.
#eval (KimiK3.KDA.stepmemorytoken).2.getScalar ⟨0, by decide⟩
#checkKimiK3.KDA.step
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.
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 {Γ : ListShape} (inputDimhiddenDimoutputDim : Nat)
(input : TermΓ [inputDim])
(gateWeightupWeight : TermΓ [inputDim, hiddenDim])
(downWeight : TermΓ [hiddenDim, outputDim])
(gateCapupCap : TermΓ []) : TermΓ [outputDim] :=
letgate := Term.op (PrimOp.broadcastVecMat [] [] [] inputDimhiddenDim
(Shape.CanBroadcastTo.refl []) (Shape.CanBroadcastTo.refl []))
(.consinput (.consgateWeight .nil))
letup := Term.op (PrimOp.broadcastVecMat [] [] [] inputDimhiddenDim
(Shape.CanBroadcastTo.refl []) (Shape.CanBroadcastTo.refl []))
(.consinput (.consupWeight .nil))
letcappedGate := GraphSpec.softCapTerm [hiddenDim] gateCapgateletsigmoidGate := Term.op (NN.GraphSpec.DAG.PrimOp.sigmoid [hiddenDim])
(.consgate .nil)
letgated := Term.op (NN.GraphSpec.DAG.PrimOp.mul [hiddenDim])
(.conscappedGate (.conssigmoidGate .nil))
letcappedUp := GraphSpec.softCapTerm [hiddenDim] upCapuplethidden := Term.op (NN.GraphSpec.DAG.PrimOp.mul [hiddenDim])
(.consgated (.conscappedUp .nil))
Term.op (PrimOp.broadcastVecMat [] [] [] hiddenDimoutputDim
(Shape.CanBroadcastTo.refl []) (Shape.CanBroadcastTo.refl []))
(.conshidden (.consdownWeight .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ℝ221 :=
{ 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.model221).specFwd
(KimiK3.GraphSpec.Expert.parametersexpert)
(KimiK3.GraphSpec.Expert.inputsinput425) =
expert.forward425input := by exact KimiK3.GraphSpec.Expert.specFwd_eq_forwardexpertinput425
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.
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.
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 MLA
§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
01
Decay.Diag(alpha)S scales each key row. Small retention forgets that row quickly.
02
Correct.k^T Diag(alpha)S asks what value the old state already associates with this key.
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.
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
A
The shared experts see the original 7,168 coordinates and run for every token.
B
The routed branch projects once to 3,584 coordinates, then sends the same latent vector to 16 distinct experts.
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
Retrieve a sequence-mixer input from the current depth sources.
2
Normalize and mix sequence with KDA or Gated MLA.
3
Retrieve again with the sequence output included.
4
Mix channels with the dense FFN or routed LatentMoE.
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.
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
Quantity
Kimi K2
Kimi K3
Change
Language-model layers
61
93
+52%
Total parameters
1.04T
2.78T
+167%
Active parameters per token
32.6B
104.2B
+220%
Hidden dimension
7,168
7,168
unchanged
Routed experts
384
896
+133%
Active routed experts
8
16
+100%
Shared experts
1
2
+100%
Attention heads
64
96
+50%
Attention stack
61 MLA
69 KDA + 24 MLA
hybrid
Training context
128K
1M
8×
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
Launch several responses for every prompt and retain their model,
tool, cache, and environment state.
2
When λ of all responses finish, stop waiting for the longest tail and
start the next policy iteration.
3
Resume the paused responses first. Their exact sandboxes and cache
prefixes survive the boundary between iterations.
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.
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.
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.
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.
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.
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.
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.
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
Kimi Team. Kimi K3: Open Frontier Intelligence, 2026, version 2.
The report followed throughout this article. Page links beside each chapter use this version.
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/}
}