Seven hundred fifty-three billion parameters, zero architectural changes, and not one capability number anyone else can check.
Z.ai announced GLM-5.3 on 14 August 2026, under the title "Frontier Coding with Emergent Cyber Capabilities." The company's own documentation opens with the whole release in one sentence: GLM-5.3 "uses the same base model as GLM-5.2," and "all improvements come from post-training." The architecture did not change. The context window did not change. Not a single field of the config changed, because there is no config: no weights have been released, no technical report exists, no license has been stated, and the launch page's huggingface link is the literal string "#". The weights are promised roughly two weeks out, pending what Z.ai calls safety evaluation and hardening.
Three weeks ago I read Kimi K3 end to end and called it the best-documented frontier model in existence. This notebook is that one's mirror image. GLM-5.3 is, as of this writing, the least checkable frontier release I have looked at: every capability number in circulation was produced by the vendor, several of the comparison numbers turn out to be another lab's measurements wearing the wrong label, and the model itself cannot be downloaded, bought through an API, or benchmarked by anyone outside the company.
So this notebook reads what can actually be read. The GLM-5.2 checkpoint is public, and if Z.ai's sentence is true, it is GLM-5.3's machine, byte for byte. I reconstructed its parameter budget from the raw safetensors headers and it reconciles against Hugging Face's count to the parameter. The launch blog renders nothing to a plain fetch, so I recovered its benchmark table and its serving contract from the compiled JavaScript bundle. Four papers, three independent inference engines, and a stack of leaderboards fill in the rest. Everything below is one of two kinds of claim. Most of it is checked against an artifact I can point at: a tensor header, a config field, a line of somebody's inference engine. The rest rests on Z.ai's word, or on my own reading of the evidence, and I flag those where they occur rather than collecting them into a caveats section at the end.
One more thing before the machine. This notebook was written in the two days after launch, deliberately, before the weights land. That window is what makes it possible to do something explainers usually cannot: state a falsifiable prediction in public, with a date on it, and be around to be wrong. It is at the end.
The release you cannot see
A word on who this is, because it comes back near the end of this notebook. Z.ai is a Beijing lab with deep Tsinghua roots: its papers carry Tsinghua faculty as co-authors, and the training framework behind this release ships from the university's data-mining group. GLM is its flagship line, and it ships an architecture roughly once per major version and then rides it. GLM-4.6 and GLM-4.7 have byte-identical config files, the strongest form of "nothing changed" that exists. GLM-5 and GLM-5.1 differ in exactly one field, transformers_version, a bookkeeping string. And GLM-5.3, on the vendor's own statement, changes nothing at all from GLM-5.2. Two of the four releases in the 5.x line are architecturally invisible, and the pattern repeats one version back.
| config field | GLM-5 | GLM-5.1 | GLM-5.2 | GLM-5.3 |
|---|---|---|---|---|
| model_type | glm_moe_dsa | glm_moe_dsa | glm_moe_dsa | same |
| num_hidden_layers | 78 | 78 | 78 | same |
| hidden_size | 6,144 | 6,144 | 6,144 | same |
| n_routed_experts | 256 | 256 | 256 | same |
| num_experts_per_tok | 8 | 8 | 8 | same |
| max_position_embeddings | 202,752 | 202,752 | 1,048,576 | same |
| rope_theta | 1e6 | 1e6 | 8e6 | same |
| indexer_types | absent ยท all 78 index | absent ยท all 78 index | 21 full of 78 | same |
| index_share_for_mtp_iteration | absent | absent | true | same |
| index_topk_pattern | absent | absent | null | same |
| head_dim | 64 | 64 | 192 | same |
| transformers_version | 5.0.2.dev0 | 5.4.0 | 5.12.0 | no file |
- real changes the arithmetic
- book bookkeeping only
- dead overwritten at construction
- release
- GLM-5.2
- fields moved
- 7
- of those, behavioural
- 4
- dead fields moved
- 1
- config published
- yes
GLM-5.1 moved one field, transformers_version, and it moves no arithmetic. GLM-5.2 moved 7 fields, of which 4 change what the model computes โ a longer window, a bigger rotary base, an indexer that only 21 layers run, and a draft loop that reuses its indices. Everything else is the same file.
claimed, unverified The GLM-5.3 column is drawn dashed because there is no GLM-5.3 config to read. Z.ai says the architecture is unchanged; that is a sentence, not a file, and nothing in this figure checks it. head_dim is in the table only to show that a field can move without meaning anything: the model overwrites it at construction, so its value has never been read. The MIT licence on the published weights is precedent for what Z.ai has done before, not a promise about what 5.3 will ship under.
The one release that did change things is GLM-5.2, in June. Its diff against 5.1 has three real moves in it: the declared context window grew from 202,752 tokens to 1,048,576, the rotary base rose from one million to eight million, and a family of new config keys appeared that cut the model's sparse-attention indexer from 78 copies to 21. Everything this notebook says about GLM-5.3's machine is really a statement about that June checkpoint, carried forward on one sentence of vendor prose. The figure draws the 5.3 column dashed for that reason. There is no zai-org/GLM-5.3 repository, so there is no config to read; the column is 5.2's values plus a claim.
The claim does have corroboration of an unusually credible kind: code written by people whose only motivation was making the thing run. No inference engine anywhere carries GLM-5.3 support, and none needs to. A comment in xLLM's model loader says it plainly: GLM-5.2 shares its model_type, glm_moe_dsa, with GLM-5.0 and 5.1, and the releases are told apart by config values alone. The entire 5.x line is one architecture discriminated by numbers in a JSON file. Fifteen independent implementations run it, and not one has a glm5 file.
What exists of GLM-5.3, then, as of this writing: a subscription tier. The model is reachable only through the GLM Coding Plan, locked to a list of approved coding tools. The API is "coming soon." Z.ai's own release-notes page had not acknowledged the launch a day later, and its price list still stops at GLM-5.2. The announcement date at the top of this notebook is itself an inference, from CDN image timestamps, because it appears in plain text nowhere.
This is the first GLM-5.x release to separate the announcement from the weights. GLM-5, 5.1 and 5.2 all landed on Hugging Face the day they were announced, on a cadence of 51, 74 and 59 days. The two-week weights delay is new, and the stated reason for it, safety hardening, is one of the threads this notebook follows to the end. A model whose headline is emergent cyber capability is the first one its own maker held back.
One layer, whole
Before taking anything apart, here is the entire machine, working. Everything later in this notebook is a drill-down into one stage of this figure, so give it thirty seconds and just watch a token go through.
in. One token arrives as 6,144 numbers on the residual stream. Nothing has happened to it yet.
- active this layer
- 515,718,144
- stored this layer
- 9,877,404,672
- active / stored
- 5.22%
- adds per layer
- 2
- layers with an indexer
- 21 of 78
The proportions are the surprise. The nine experts are 65.88% of what this token touches and the whole indexer โ the mechanism the rest of this notebook is about โ is 1.82%. The faint tick on each bar is that band's share of what is stored in the layer, which is the census figure in miniature: the experts own 98.22% of the disk and attention owns 1.67%.
Two caveats the diagram flattens. Only 21 of 78 layers own an indexer; the other 57 read the indices the nearest preceding full layer wrote. And the first 3 layers have no router at all โ they run one dense feed-forward of 12,288 instead.
A token enters as an id and leaves as a distribution over 154,880 vocabulary entries. In between sit 78 transformer layers plus one extra. Each layer reads a running vector of 6,144 numbers, the residual stream, which is the token's working state as it moves up the stack, and each layer writes its own contribution back into it. The path is strict pre-norm: normalize the stream, apply attention, add the result back, normalize again, apply a feed-forward block, add that back. Two RMSNorms, two residual additions, nothing else. GLM-4.5 wrapped its layers in extra post-norms for stability; at twice the size, GLM-5.x dropped them.
The attention stage is the elaborate one, and it has two unusual organs. The stream is compressed into a small cached summary, 576 numbers per token, from which all 64 attention heads later reconstruct what they need. That is MLA, and it is why this model's memory bill is a fiftieth of what it would naively be. In front of the attention sits an indexer: a cheap scoring pass that reads the whole context and picks the 2,048 tokens the expensive attention is allowed to look at. That is DSA. Only 21 of the 78 layers own an indexer; the other 57 borrow the most recent selection.
The feed-forward stage comes in two kinds. Layers 0 through 2 are ordinary dense blocks. Layers 3 through 77 are mixture-of-experts layers: 256 separate small networks, of which a router chooses 8 per token, plus one shared expert that runs on everything. Those banks are where this model keeps 97.49 percent of its parameters, almost all of it asleep for any given token.
After layer 77, a final norm and an output projection produce the distribution. And then there is layer 78, which is not part of the stack at all: a complete spare layer, attention and experts and all, whose job is to draft the next token early so that serving can check several guesses in one pass.
Step the figure through those stages once and the proportions are the surprise: two norms, a compressed cache, a cheap scoring pass, and then a bank of experts that is most of the machine by weight and almost none of it by design effort. The rest of this notebook works through that figure stage by stage, in roughly that order.
A few oddities of the shipped checkpoint belong here before the autopsies, because each one carries information. The model contains one classical LayerNorm and one bias tensor, and they are the same object: the little norm on the indexer's 128-dimensional key. Everything else in 753 billion parameters is bias-free RMSNorm. My best reading, offered as a reading, is that the indexer is the one place where a small numerical error changes a ranking rather than a value: its output feeds a top-2,048 cut, and a token nudged below the line silently vanishes from attention's world. The one component whose mistakes are discrete got the one norm with a mean-subtraction and a bias.
Two norms that look like a safety feature are not one. The 2,048- and 512-wide norms inside the attention block sit on MLA's compression bottlenecks, and they are easy to mistake for QK-norm. GLM-5.x has no QK-norm anywhere. Then there are the counts, which all have to agree, and agreement is the closest thing a checkpoint offers to an audit: 79 attention blocks, 78 of them in the stack; 3 dense plus 75 expert layers; 21 indexers plus a 22nd hiding in the draft layer; 76 expert-router bias vectors, one per expert layer plus that same draft layer. Every one of those is a term in the budget the next section closes to the byte.
Where the model lives
A word about proportion, out loud, because the shape of this notebook could otherwise mislead you. This chapter and the three after it are the architecture, and the architecture is the part of GLM-5.3 that did not change. It gets the most room anyway, for one reason: it is the part that can be known. The GLM-5.2 checkpoint is downloadable, so every claim about the machine can be pushed one layer deeper, checked against tensor shapes, recomputed from a script. The part that actually changed, the post-training, is one blog post with no weights, no paper and no independent number, and it gets the space that evidence supports. Length here is a map of what is knowable, not of what matters.
One convention for all four, so I can stop repeating it. Unless a sentence says otherwise, every number in them was read off the GLM-5.2 checkpoint, its config, or the source of an engine that runs it, and you can recheck any of them. There are maybe half a dozen exceptions, they are all interesting, and each one announces itself where it sits.
A census that closes to the byte
Hugging Face reports GLM-5.2 at 753,329,940,480 parameters. I rebuilt that number from scratch: HTTP range-requests pull the JSON headers out of the safetensors shards without downloading the 1.5 TB of weights behind them, the headers list 59,585 tensors with their exact shapes, and summing the products gives 753,329,940,480. An exact match, to the parameter, and it is what licenses every other number in this chapter. The reconstruction ships with this notebook as a runnable script, and the figure below rebuilds its bars from the same per-layer constants.
- stored
- 753,329,940,480
- attention, stored
- 1.73%
- attention, active
- 31.94%
- the inversion
- 18.46ร
- routed experts, stored
- 97.49%
- reconstruction residual
- 0
- matches Hugging Face
- yes
Attention is 1.73% of what is on disk and 31.94% of what one token touches โ an 18.5ร inversion, and the whole reason a model advertised as โsparseโ still spends most of a decode step inside the attention block. The routed experts are the mirror image: 97.49% of the disk, 56.20% of the token. The faint tick on each bar is that band's share in the other ledger.
Both columns are reconstructions, not quotations. The stored column sums to 753,329,940,480, which is Hugging Face's reported total for GLM-5.2 to the byte; the residual above is the check. The embedding is a gather, so it costs 0 active parameters while holding 951,582,720 on disk โ and Z.ai's advertised 39.35B active is this token's total minus the output head.
The stored view is almost comically lopsided. Routed experts are 97.49 percent of the checkpoint. Attention, the mechanism this whole model line is famous for, is 1.73 percent. The embeddings and output head together are a quarter of a percent, and the 22 indexers, the organ two chapters of this notebook revolve around, are 0.0274 percent: about 206 million parameters in a model of 753 billion.
Flip to the active view and the picture inverts. A token touches 40,298,947,584 parameters, 5.35 percent of the model. That set is every layer's attention, the 21 indexers, nine experts out of 257 in each of the 75 sparse layers, the three dense feed-forward blocks, and the output head. Within that set, attention is 31.94 percent. On disk it was 1.73 percent. Nearly a third of the parameters this model actually reads for a token belong to the mechanism that is a fiftieth of it at rest, an eighteen-fold inversion, and it is the single most useful fact for reading everything that follows: the part of this model that barely exists on disk is a large fraction of what has to be hauled out of memory to use it.
Two details of the count settle real confusions. First, the number spread. You will see this model quoted at 744B, 750B, 753.3B and "40B active," and all of them are one model under different counting conventions. The 40,298,947,584 active figure includes the output head, which is a dense 6,144-by-154,880 matrix that runs on every token and alone is 2.36 percent of the active budget. Subtract it and you get 39,347,364,864, which is exactly the "39.35B active" Z.ai advertises. The embedding matrix, same shape, costs nothing per token, because looking up a row costs a memory read and no arithmetic.
Second, a forensic gem. Hugging Face's dtype breakdown lists exactly 19,456 parameters stored in full FP32 precision, in a checkpoint that is otherwise all BF16. That number is 256 ร 76. The only FP32 tensor in the model is a per-layer vector of 256 expert-routing biases, there are 75 expert layers in the stack, and 75 does not divide 19,456. The 76th copy is inside layer 78, the draft layer, which is how you can know, from a dtype histogram alone, that the draft layer carries a complete 256-expert block of its own. Checkpoints leak structure through their bookkeeping.
One conflict belongs on the record, because it says something about reports versus artifacts. The GLM-5 technical report states, in a sentence I am quoting verbatim, that the model "reduces its layer count to 80" and totals "744B" parameters. Every shipped config says 78 layers, the tensor index contains nothing beyond layer 78's draft module, and the measured total is 753.3 billion. The checkpoint wins. A technical report is testimony; a safetensors header is evidence.
The cache is the model
Attention has a memory problem that compounds with context. To generate token one million and one, a model must consult keys and values for the million tokens before it, and the naive ledger for this model is brutal: 78 layers ร 64 heads ร 512 numbers per head ร 2 bytes is 5,111,808 bytes of cache per token of context. At the full window that is 4.88 tebibytes, for one conversation, before a single weight is loaded.
- cached row
- 576 numbers
- bytes per token
- 95,232
- MLA, this context
- 18.0 GiB
- MLA, share of frame
- 1.76%
- naive, this context
- 965.3 GiB
- naive, share of frame
- 94.26%
- whole-model ratio
- 53.7ร
- per-layer ratio
- 56.9ร
The frame is one tebibyte, fixed, so both bars are read against the same ruler. The naive bar runs out of frame at 215,092 tokens โ a fifth of the way into the window โ and by 1,048,576 it is 4.88 TiB, off the right edge and still going. The MLA bar at that same context is 93.0 GiB, which is 9.08% of the frame: a stripe.
Two ratios circulate for this, and they are not the same number. Per layer, MLA keeps 576 numbers where multi-head attention keeps 32,768 โ 56.9ร. Whole-model, the indexer's own 5,376 bytes per token join the ledger and the ratio falls to 53.7ร. Both are drawn here; the first is the mechanism, the second is what a serving box actually pays. Everything is counted at two bytes per number, which is what BF16 costs.
MLA is the fix, and GLM's version stores 576 numbers per token per layer. Not per head. The layer compresses each token's key-value information into a 512-dimensional latent plus one 64-dimensional rotary key shared by all 64 heads, and caches only that row. The heads' actual keys and values are reconstructed from the latent on demand, or, as the next section shows, never reconstructed at all. The arithmetic: 78 ร 576 ร 2 bytes is 89,856 bytes per token, plus 5,376 bytes of indexer keys on the 21 layers that keep one, for 95,232 bytes all-in. Against the naive 5,111,808 that is a 53.7ร compression. A million tokens of context costs 93.0 GiB instead of 4.88 TiB. Push the figure's context slider to the right and the naive bar leaves the frame while the MLA bar is still a stripe; there is no scale on which you can draw both at a million tokens.
Two versions of that ratio circulate and both are right, so let me pin which is which. The 53.7ร above is the honest serving number: all layers, indexer included. The 56.9ร you will see quoted is one layer's MLA row alone, 32,768 naive numbers against 576. Use the first for anything about memory bills. The 93.0 GiB carries two caveats of its own: it assumes BF16 cache entries, which serving stacks halve to FP8 on newer hardware, and it is what production engines achieve, not what the reference transformers implementation does. That implementation caches the fully expanded keys and values, MHA-sized, with a to-do comment in the source admitting it. Measure GLM's memory with the reference code and you will conclude this section is wrong.
Why does GLM use MLA at all? The GLM-5 report is unusually frank about this: in their experiments, "MLA with a 576-dimension latent KV-cache cannot match the performance of GQA with 8 query groups." The compression was costing quality, and the fix was an optimizer change rather than an architectural one. Muon Split orthogonalizes each attention head's projection block independently instead of treating the fused matrix as one unit, and that closed the gap. That sentence explains more about GLM's attention than anything else Z.ai has published, including the model's oddly shaped heads: 256-dimensional values against 192-plus-64 query-key dimensions are the settlement of a quality deficit, not a clean derivation.
One config field deserves a warning label. num_key_value_heads: 64, equal to the attention head count, looks like it contradicts everything above. It describes the logical heads after reconstruction, not what is stored. The cache is the 576 row.
The rotation that breaks the trick
MLA's economy rests on an algebraic move, and the move has one enemy. This section is the hardest idea in the model and the most rewarding one to watch happen, because it is a fact about matrix multiplication that you can see.
With no rotation in the way, the two projection matrices sit next to each other and multiply out once, at load. The score never touches them again.
- t
- 96
- s
- 704
- s โ t
- 608
- ฮธ pair 0
- 608.000 rad ยท 96.8 turns
- ฮธ pair 31
- 0.000125 rad ยท 1 turn in 50,309
- absorbable dims
- 192
- rotating dims
- 64
- rotary key stored
- 64, not 4,096
The rotation blocks above are computed, not drawn: each tile is a genuine two-by-two [[cos, โsin], [sin, cos]] at ฮธ = (s โ t) / ฮธโ^(2i/64), with the fill opacity carrying the magnitude and the tone carrying the sign. Drag either handle and every tile changes. That is the argument: there is no matrix here to precompute, because there is a different one for every pair of positions, and there are 1,048,576 positions.
The repair is a split, not a compromise. 192 of each head's 256 dimensions carry no rotation and fuse exactly as in the first panel; the other 64 carry all of it and are computed the ordinary way. The rotating key is not per head at all โ one 64-vector comes off the hidden state and is handed to all 64 heads by a stride-0 view, which is why the cached row is 512 + 64 = 576 and not 512 + 4,096.
The move goes like this. An attention score is a dot product between a query and a key. In MLA neither of those exists in memory; both get built on demand from small cached vectors, each by multiplying with a fixed matrix. The query is one matrix times the query token's compressed vector. The key is another matrix times the key token's 512-number cached row.
Now write the whole score out as a single expression and look at what sits where. The two cached vectors end up on the outside, one at each end. The two matrices end up in the middle, back to back. And that middle pair is the same for every token in the sequence, because a projection matrix is a weight: it stopped changing when training finished. So you can multiply those two matrices together once, at load time, and from then on attend directly against the cached row, never building a single per-head key at all. That fold is called absorption, and it's the entire reason a 576-number cache can serve 64 heads. Drag the figure's first stage and watch the two blocks fuse.
Now add position. Transformers need to know where tokens are, and this family uses RoPE: rotate each query and key by an angle proportional to its position before taking the dot product. A rotation is itself a matrix, so writing the score out now gives you six things in a row instead of four. Reading from the query end: the query's cached vector, its matrix, its rotation, then the key's rotation, the key's matrix, the key's cached vector.
The two rotations meet in the middle and combine into one rotation by the difference of the two positions. That collapse is the elegant part of RoPE, and it's why the mechanism encodes relative position without storing anything. But look where it leaves the survivor. The combined rotation is now wedged between the two projection matrices, in exactly the spot where absorption needed them touching, and it is a different rotation for every pair of positions in the sequence. The figure's second stage lets you drag the two positions: the would-be fused block changes on every drag. A matrix that changes per pair cannot be precomputed once. Absorption dies, and the cache saving dies with it. Rotation does not commute with low-rank fusion.
The fix, inherited from DeepSeek and confirmed line by line in GLM's modeling code, is surgical. Split each head's 256 query-key dimensions into two parts that never mix. The large part, 192 dimensions, carries no position at all and flows through the absorbable path, where the fusion replays untouched. The small part, 64 dimensions, carries all of the position, and it cheats: its key is produced directly from the raw hidden state, bypassing the compressed latent, rotated once, and cached already-rotated. Because that rotary key never involves the up-projection matrix, there is nothing for the rotation to break. The score becomes an absorbable term plus a small positional term, summed.
The implementation details are quietly elegant. The 64 rotary dimensions are deliberately excluded from the latent's normalization, since they are not part of the latent. The rotary key is created with a head dimension of one and then broadcast to all 64 heads as a stride-0 view, an .expand() that copies nothing: 64 numbers per token per layer, read 64 times. Per-head rotary keys would have cost 4,096. That one broadcast is the difference between MLA surviving position and not.
Deciding what to look at
Attention's other problem is arithmetic. Every token scoring every earlier token is a cost that grows with the square of the context, and at a million tokens the square is monstrous: run this model dense at its full window and 98.56 percent of the per-token compute is core attention. The 753 billion parameters become a rounding error against their own quadratic term. GLM's escape is a chain of three mechanisms, and the property that makes the chain worth following is that each fix promotes a new bottleneck for the next one to attack. This is the heart of the machine, and it is where the research for this notebook kept turning up things nobody has written down.
Attention that skips
DSA, DeepSeek Sparse Attention, is a bet that most of a long context does not matter for any given token. Instead of attending to everything, each layer attends to a keep-set of 2,048 tokens, chosen fresh for every query by a cheap scoring pass called the lightning indexer. At the full window, 2,048 of 1,048,576 is 0.1953 percent. The expensive machinery reads one token in five hundred, and the whole question becomes whether the cheap machinery picks the right five-hundredth.
32 query heads of 128, one shared 128-wide key head
- I
ฮฃ_j w_j ยท ReLU(q_j ยท k_s) - keep
topk(min(2048, end_pos))
- context
- 1,048,576
- keep-set, min(2048, ctx)
- 2,048
- survives
- 0.1953%
- ReLU zeroed
- 35.3%
- one head agrees
- 0.0%
- regime
- sparse
The key side is the shape nobody writes down. All 32 query heads dot against one shared 128-dimensional key head, MQA-style, which is why the indexer banks 128 numbers per token instead of 4,096. Each head's dot product goes through a ReLU before the weighted sum, per head and per key, so a head's negative evidence is thrown away rather than cancelling another head's positive evidence. Across the 5,120 products drawn here that discards 35.3% of them. DeepSeek's stated reason is "for throughput consideration" โ speed, not accuracy.
At 1,048,576 tokens the expensive machinery reads 0.1953% of the context โ one token in 512 โ and the whole question becomes whether the cheap machinery picked the right one. Drag left, past 2,048, and watch the sparsity switch itself off.
Honesty note: GLM's learned indexer weights are not public, so the score distribution above is synthetic โ seeded, deterministic, with a sink, a recency ramp and five planted topics for the query to find. Real are the head structure, the order of operations, the causal mask, the keep-set arithmetic and every count in the readout. The ribbon samples 160 positions, so each cell stands for 6,554 real tokens and the lit count is the true survival fraction rounded to the drawing.
The indexer's shapes are the mechanism, and one of them appears in no writeup I could find. Its query side has 32 heads of 128 dimensions, read from the same compressed latent the main attention uses. Its key side is the surprise: the key projection is a single 128-dimensional head, shared by all 32 query heads. That is why the indexer's cache costs 128 numbers per token instead of 4,096, and it is why the indexer is affordable at all. DeepSeek's paper confirms the intent in passing, and the tensor header confirms the shape directly.
There is a second economy in it, and it matters later. The indexer runs in FP8, both operands quantized, where the attention it gates generally does not. DeepSeek says so with visible satisfaction: because the lightning indexer "has a small number of heads and can be implemented in FP8, its computational efficiency is remarkable." Hold onto that, because this notebook is about to spend a chapter counting the indexer's share of the arithmetic, and a count of operations quietly assumes every operation costs the same.
The scoring formula repays writing out, because two details in it are easy to get wrong. Each of the 32 heads dots its query against a token's shared key. Each head's score is passed through a ReLU, then the 32 rectified scores are combined by a weighted sum whose weights the token generates from its own hidden state. The ReLU comes before the sum, per head, per key: a head's negative evidence is discarded before it can cancel another head's positive evidence. DeepSeek states the reason with disarming honesty: ReLU was chosen "for throughput consideration." Speed, not accuracy. The figure computes this pipeline literally, and one honesty note applies to it: GLM's learned indexer weights are not public, so the score distribution you see is synthetic. The selection arithmetic, the head structure and every count are real.
Then the detail that reframes the whole mechanism. The kernel takes the top min(2048, context) scores, so when the context is shorter than 2,048 tokens, the indexer selects everything, and DSA is exactly full attention. Serving stacks go further and skip the indexer below that line. Drag the figure's context slider to the left and watch sparsity switch itself off. Nothing sparse happens to your short prompts, ever; the entire apparatus is dormant until the context is long enough for it to matter. Sparsity here is a regime the model enters, at a context length you can point to.
GLM's DSA differs from DeepSeek's in scale and in appetite. Same keep-set of 2,048, half the indexer heads, 32 against 64, and a declared context 6.4 times longer, which stretches the same keep-set over a far larger haystack: against its own declared window DeepSeek keeps 1.25 percent, GLM keeps 0.195 percent. And one thing DeepSeek concedes in its own report deserves the emphasis it rarely gets: DSA reduces core attention from quadratic to linear, but the indexer that enables it still scores every token against every token. The quadratic term did not die. It moved into the cheap pass, and that fact sets up everything in the next section.
Which layers get to decide
Run the numbers on DSA at a million tokens and the fix reveals its own successor. Core attention collapses by a factor of 512, and the indexer, the cheap pass, becomes 88.35 percent of the remaining per-token compute. The thing that picks what to look at now costs more than everything it was protecting combined. GLM-5.2's response is called IndexShare: stop running the indexer at every layer.
- layer 45
- shared ยท reads 42
- indexer passes
- 21 of 78
- indexer FLOPs
- 3.71ร
- blended, at 1M
- 2.82ร
- vs Z.ai's 2.9ร
- 2.7%
- KV cache
- โ13.3%
Full layers, from the config's literal 78-entry indexer_types array: 0, 1, 2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62, 66, 70, 74. Only the reference implementation reads that array. The two engines that serve this model re-derive the identical pattern from two integers โ skip(โ) = max(โ โ 3 + 1, 0) % 4 โ 0 โ and this figure checks the two against each other: they agree at 78 of 78 layers. So the config carries an explicit, human-readable description of which layers think for themselves, and the code path that matters never looks at it.
Three savings, and only the first gets advertised. Compute: 21 indexer passes instead of 78 is 3.71ร fewer, blending to 2.82ร of total per-token prefill at a million tokens, against Z.ai's advertised 2.9ร. Weights: 57 layers carry no indexer.* tensors at all, 5.34e8 parameters that simply are not in the checkpoint. And cache, which nobody advertises: 19,968 bytes per token of index keys become 5,376, taking the total from 109,824 to 95,232 bytes per token, a 13.3% cut in the quantity the decode section shows is the actual bill.
Two things the drawing is careful about. The attention column runs at every layer in both releases: shared layers skip the scoring pass, never the attending. And the arrow runs backwards, to the nearest preceding full layer, never forward โ layer 0 is always full, so there is always something to inherit. The buffer is one buffer, overwritten in place; the ghosted stamps below the live one have already been discarded, which is why the whole mechanism costs no extra memory.
One config key tells a sharper story than the array does. Both engines check index_topk_pattern first, which can hold an arbitrary per-layer pattern โ precisely where a searched, non-periodic pattern would go, and the search is not hypothetical. GLM-5.2 sets it to null. The machinery for shipping a smarter pattern exists in every engine that runs this model, and Z.ai left it empty.
The config ships a literal 78-entry array assigning each layer full or shared. The full layers are 0, 1, 2, and then every fourth layer from 6 to 74: twenty-one in all. A full layer computes fresh indices over the whole context and attends over its selection. A shared layer has no indexer whatsoever, no weights for one in the checkpoint, and inherits the selection from the nearest full layer before it. The paper behind the technique implements this as a single buffer, overwritten at each full layer and read by the layers above it, which means the whole mechanism costs one buffer instead of 78, and one conditional branch. The figure shows the buffer being stamped and re-read as you walk the stack.
Two misreadings to close off immediately, because both are natural and both are wrong. Shared layers still run full sparse attention; only the scoring pass is skipped, never the attending. Inheritance also runs backward, to the most recent full layer, not forward or nearest-in-either-direction. Layer 0 is always full so there is always something to inherit.
There's an oddity in how that 78-entry array gets used, or rather does not. Only the reference implementation reads indexer_types at all. The two engines that actually serve this model in production ignore it completely and re-derive the identical pattern from two integers, a period and an offset. So the config carries an explicit, per-layer, human-readable description of which layers think for themselves, and the code path that matters never looks at it.
What one shared buffer buys turns out to be three different savings, and the figure draws all three bars. Compute: 21 indexer passes instead of 78 is 3.71ร fewer, which blends to 2.82ร fewer total attention-side FLOPs at a million tokens; Z.ai advertises 2.9ร, and my reconstruction lands within three percent of that, so the claim checks. Weights: 57 layers carry no indexer tensors at all. And cache, the saving nobody advertises: without IndexShare every layer would bank its own 128-number index key per token, 19,968 bytes; with it, 5,376. The total cache falls from 109,824 to 95,232 bytes per token, a 13.3 percent cut in the quantity the section on decode will show is the actual bill.
One config key tells a small, sharp story about roads not taken. Both major serving engines, before applying the periodic every-fourth-layer rule, first check a field called index_topk_pattern, which can hold an arbitrary per-layer pattern. That is the slot where a searched, non-periodic pattern would go, and the search is not hypothetical: the technique's own paper ships one. GLM-5.2 sets the field to null. The machinery for shipping a smarter pattern exists in every engine that runs this model, and Z.ai left it empty. Whether that was laziness or confidence is the subject of the next two sections.
Put the two config fields side by side and they make a small joke about each other. One describes the layer pattern explicitly, in full, and no production engine reads it. The other is the one every engine checks first, and it's empty.
A naming note, since the literature will otherwise fork on you. Z.ai's marketing calls this IndexShare. The paper, from Z.ai and Tsinghua authors, calls it IndexCache, never uses the word IndexShare, and never mentions GLM-5.2 or 5.3. One mechanism, two names, linked only by Z.ai's own citation.
And one sentence from the GLM-5 report reads differently a release later. It calls DSA "lossless by construction," on the grounds that the indexer selects without discarding long-range dependencies, and concludes that it can therefore be applied "to all layers with no quality degradation." GLM-5.2 then took the indexer out of 57 layers of 78. The two claims are compatible if you are careful: losslessness is a property of the selection, and IndexShare is about reusing a selection rather than making one. Still, a lab that had just finished arguing for indexers everywhere deleted three quarters of them within four months, and the report gives no hint that was coming.
How the indexer learns what to keep
Nothing so far explains why a 32-head scoring pass should agree with 64 heads of real attention about what matters. The answer is the best mechanism in this whole architecture, and I have not seen it explained anywhere outside the primary papers: the indexer is never trained by the language-modeling loss. It is a distilled student of the attention it replaces.
- stage
- dense warm-up
- KL, nats
- 0.1238
- scored over
- all 24
- gradient paths
- disjoint
- sparse tokens
- 47ร fewer
The indexer is a distilled student of the attention it replaces. Stage one freezes the whole model, runs attention dense with no selection at all, sums the real scores across heads, normalizes each query's row into a distribution, and trains the indexer alone to predict it. The lesson is literally here is what I looked at, learn to predict it, and the loss is how many bits you would waste encoding the teacher's answer with the student's guess. Restricting that same KL to the 8 positions the indexer selected โ stage two โ changes the number above, because both sides are renormalized over the selected set, and the selection here captures 47.8% of the teacher's mass.
Nothing is detached yet, because nothing else is training. Everything except the indexer is frozen, so there is only one gradient in the graph and it has exactly one destination.
The budgets reproduce from published step counts, and the two labs diverge spectacularly at the second stage: 2.84e9 tokens of warm-up against DeepSeek's 2.10e9 โ nearly the same modest number โ then 2.0e10 against 9.437e11, which is 47.2ร less, with the report stating flatly that they "find that it is enough." The two groups are drawn on their own scales, since one is four hundred times the other. Honesty note: these are GLM-5's numbers. Nothing published describes how GLM-5.2's sparse attention was trained, at what length, or on how many tokens โ and the distributions above are synthetic, since the real ones are inside a training run nobody released.
Stage one is a dense warm-up. Freeze the entire model except the indexer and run attention dense, no selection. At every step, take the real attention scores, sum them across heads, and normalize each query's row into a probability distribution over the context: that distribution is the target. Train the indexer, alone, to produce a distribution as close to that one as possible, scored by how many bits you would waste encoding the teacher's answer using the student's guess. That measure is the KL divergence, and it is the whole loss. The model is the teacher, the indexer is the student, and the lesson is literally here is what I looked at, learn to predict it. GLM-5 ran this for 2.84 billion tokens; DeepSeek's equivalent used 2.10 billion. Two labs, nearly the same modest budget, teaching the same imitation.
Stage two turns the selection on and trains everything at once, and its critical mechanism is a single graph operation. The main model now trains normally on its language loss, attending only over keep-sets. The indexer keeps training on its imitation loss, now computed only over the selected tokens. And the indexer's input is detached from the computation graph: gradients from the language loss cannot flow into the indexer, and the indexer's loss touches nothing but itself. Two objectives, two disjoint gradient paths, one forward pass. The figure draws the detach as a physically cut wire, and lets you reconnect it to see the failure the design prevents, each loss dragging the other's parameters toward a different goal.
Here the two labs diverge spectacularly. DeepSeek's sparse adaptation ran 943.7 billion tokens, a figure that reproduces from its published step counts. GLM-5's ran 20 billion, forty-seven times less, with the report stating flatly that they "find that it is enough." Whether it is enough is a live question this notebook returns to, and one label matters for honesty: those training numbers are GLM-5's. Nothing published describes how GLM-5.2's sparse attention was trained, at what length, or on how many tokens. The shipped config describes the machine; the training of the machine at its current scale is undocumented.
Which layers matter, and why the answer evaporates
If 21 layers get to keep their indexers, which 21? The paper behind IndexShare ran that question to ground, and its answer is the most epistemically interesting result in this notebook, because it depends on when you ask.
- pattern under test
- 21 of 78 full
- differs from shipped
- 0 of 78
- searched vs shipped
- 31 of 78
- training-free score
- 43.0
- vs baseline
- -7.2
Training-free, the choice of layers dominates everything. On GLM-5 itself at a 200K window, a searched quarter-pattern gives up 0.4 points of long-context average, 78.4 to 78. A naive uniform quarter gives up 5.7, and GraphWalks alone collapses 92.7 โ 74.9. The paper's own summary sentence: which indexer layers are retained matters far more than how many. Early layers are the most sensitive, and the stated mechanism is quotable โ "their perturbations traverse the longest propagation path." An error in layer 2's selection compounds through 76 more; an error in layer 70's has nowhere to go.
GLM-5.2's shipped pattern has no published score of its own โ nothing has ever been measured on this exact layer set. The bar highlighted above is uniform 1/4, the nearest published configuration in the same family, and it is a proxy rather than a measurement of what shipped.
Two honest touches in that paper deserve their own sentence. It reports a failed method by name โ choosing the pattern by maximizing cross-layer index overlap, no better than uniform โ with a diagnosis of why the cheap proxy fails: overlap counts how many tokens are shared, and quality hinges on which ones differ. And it reports where the technique breaks: training-free from that testbed's 50.2 baseline, a uniform quarter costs 7.2 points and a uniform eighth costs 14.9. The shipped quarter sits near the edge of the tested-safe region.
Honesty note: the searched layer list is not published. The paper publishes its constraints and its distance from the shipped pattern, so the middle strip is a reconstruction consistent with all of them โ the five checks above are computed from the drawn list, not asserted. Positions outside those constraints are my construction and should not be read as the paper's answer. The score axis is zoomed to [33, 52], because the whole finding lives inside a two-point range.
The figure has a switch for the training regime, and that switch is the finding. Ask it training-free, dropping indexers from a finished model with no retraining, and the choice of layers dominates everything. On GLM-5 itself, at a 200K window, a searched quarter-pattern gives up 0.4 points of long-context average, 78.4 to 78.0. A naive uniform quarter-pattern gives up 5.7, and one benchmark, GraphWalks, collapses from 92.7 to 74.9. The paper's own summary sentence: which indexer layers are retained matters far more than how many. Early layers are the most sensitive, and the stated mechanism is quotable: "their perturbations traverse the longest propagation path." An error in layer 2's selection compounds through 76 more layers; an error in layer 70's has nowhere to go.
Then ask it training-aware, distilling the model to expect sharing while it trains, and the entire finding evaporates. Take the paper's 30B testbed. A retrained model that keeps every indexer scores 51.0. Drop half of them on a uniform pattern, retrain, and it scores 51.6, above the model it was supposed to be approximating. Drop three quarters uniformly, which is the shape GLM-5.2 ships, and it scores 50.6, four tenths below the baseline. And the searched pattern, worth seven points in the training-free world, lands below the all-indexer baseline too. Read that again: after retraining, the careful pattern loses to the dumb one, and throwing away half your indexers beats keeping them all. The paper's explanation is the mechanism worth keeping: retrained shared layers learn to adapt their attention to inherited indices, and the joint adaptation "eliminates the layer-specific sensitivity entirely." The model absorbs the constraint. Which layers matter is a real, measurable property of a frozen model, and it is not a property of the architecture at all.
That inversion is the strongest available defense of GLM-5.2's choices, because what GLM-5.2 ships is emphatically not the paper's answer. The searched GLM-5 pattern has 22 full layers, clustered non-periodically, with a knot at layers 38 through 42. The shipped config has 21, on a strict period-4 rule. The two disagree at 31 of 78 positions. Whatever Z.ai did, it did not copy its own paper's search result; the coherent reading, and I flag it as inference, is that Z.ai did the training-aware version, after which the search stops paying and a periodic rule is free. The paper's closing line promises that application to GLM-5, dated March; GLM-5.2 shipped in June.
Two honest touches in that paper deserve their own sentence. It reports a failed method by name, choosing the pattern by maximizing cross-layer index overlap, which came out no better than uniform, with a diagnosis of why the cheap proxy fails: overlap counts how many tokens are shared, and quality hinges on which ones differ. And it reports where the whole technique breaks. Training-free again, from that testbed's 50.2 baseline, a uniform quarter costs 7.2 points and a uniform eighth costs 14.9, collapsing to 35.3. Index reuse is not free at arbitrary ratios; the shipped quarter is near the edge of the tested-safe region.
There is also a cautionary tale in Z.ai's own prior work, and it earns a beat because it looks like a contradiction without being one. The GLM-5 report tested sliding-window attention on a 9B model with a fixed alternating pattern, and it collapsed: 75.28 at 128K for full attention, 6.51 for the naive interleave. A searched pattern retained 53.95. The mechanisms differ in a way that saves IndexShare from that fate: a sliding window discards distant tokens outright, while a shared layer still attends globally over another layer's selection. The reason to carry it anyway is that a fixed periodic pattern is what GLM-5.2 ships, and the published justification for it, in the DSA setting, is the training-aware result above and nothing else.
The only long-context curve that exists
Everything above concerns cost. The question that determines whether any of it was a good idea is quality, and for sparse attention at long context, the published evidence base is one curve. This section shows it, because it deserves to be seen.
- context
- 131,072 tok
- dense baseline
- 79.21
- warm-up only
- 71.35
- full DSA
- 78.86
- skipping stage 2 costs
- -7.86
- indexer keeps
- 1.56%
The revealing row is the middle one: warm-up only, the frozen model with a distilled indexer bolted on, stage one without stage two. From 4K to 16K it is indistinguishable from the baseline. At 32K it slips 2.87. At 131,072 it has lost 7.86. The damage from imperfect selection is invisible in the regime where most testing happens and concentrates where the keep-ratio tightens โ and joint training is what repairs it. The fully trained sparse model tracks the dense baseline within a point everywhere and beats it at three of the six lengths, which is the whole proposition: neutral, at 512-fold savings.
At 131,072 the indexer keeps 1.56% of the context, and that is the deepest point on the only published curve. GLM-5.2's headline window sits 8 times past it, at 8ร tighter a keep-ratio, where this figure has nothing to draw. Not because the model does badly there โ because nobody, Z.ai included, has published a number.
First, the context for the curve. Does DSA cost quality at all? The best evidence anywhere is DeepSeek's, and it is genuinely controlled: same base checkpoint, same post-training pipeline and data, with sparse attention as the sole deliberate variable. Across its 14 benchmarks the sparse model wins 7, loses 6 and ties 1, with the losses concentrated where the model generated fewer reasoning tokens, a confound DeepSeek names itself. And GLM's own 128K ablation on the GLM-5 base shows the same rough wash: sparse wins two of four tasks, one by 6.3 points. At the contexts these tests ran, roughly neutral is a fair verdict, and neutral-at-512-fold-savings is the entire proposition.
The curve that complicates it is Z.ai's, from the GLM-5 report: GLM-4.7-Flash on RULER at six lengths from 4K to 128K, in three variants. The dense baseline drifts down as context grows, ending at 79.21. The fully trained sparse model tracks it within a point everywhere, actually beating it at three of the six lengths, and gives up 0.35 at 128K. Sparsity, trained through, costs almost nothing on this instrument.
The revealing row is the middle one: warm-up only, the frozen model with a distilled indexer bolted on, stage one without stage two. From 4K to 16K it is indistinguishable from the baseline, within half a point. At 32K it slips three points. At 128K it has lost 7.86. Sweep the figure's context control and watch the line peel away only at the right edge. The damage from imperfect selection is invisible in the regime where most testing happens and concentrates where the keep-ratio tightens, and joint training is what repairs it. At 128K the indexer keeps 1.56 percent of the context. That is the deepest point on the only published curve.
GLM-5.2's headline window sits eight times past it, at a keep-ratio eight times tighter, and here the evidence simply stops. I looked hard for anything at longer range, and the full census is: no RULER, MRCR, LongBench, HELMET or long-context reasoning score exists for GLM-5.2 or 5.1, from any party, at any length. The deepest quality-suite evaluation of any GLM sparse-attention model is that 200K window from the pattern paper, on GLM-5, before IndexShare existed. The deepest independent probe of any kind is a hobbyist's, not a lab's: a reproducible 4ร DGX Spark recipe that retrieved a needle verbatim from a 249,945-token prompt, with a companion claim of stable decode to 638,976 tokens. A single needle is a smoke test, not a benchmark; it saturates on models that fail RULER badly, and the same caveat applies to the only other third-party long-context result I could find, 15 of 15 needle retrievals to about 118,000 tokens in SGLang's own validation notes. And at the advertised million, there is nothing. Not from Z.ai, not from anyone, on any GLM model, ever. The headline feature of this machine is unaudited, and the sections that follow keep having to say so.
The bulk
Attention got two chapters because attention is where the ideas are. The parameters are somewhere else. This chapter is the 97.49 percent, plus the two subsystems that ride alongside it: the rotations that carry position, and the spare layer that guesses ahead.
Two hundred fifty-six experts, eight chosen
Every layer from 3 to 77 replaces its feed-forward block with a bank of 256 experts, each a small three-matrix network a third as wide as the residual stream. A router picks 8 per token, one shared expert runs on every token regardless, and the other 248 sit idle. Multiply it out and those 75 mixture-of-experts blocks come to 727,724,870,400 parameters between them, 96.6 percent of the checkpoint. Counting only the routed experts, and counting the draft layer's bank as well, gives the 97.49 percent from two chapters back. Either way, everything else in this notebook is a story about the last few percent.
- sigmoid over 256 router logits
- add the per-expert selection bias
- top-8 on the biased scores
- gather the weights from the unbiased scores
- renormalize the eight to sum to one
- multiply by 2.5
Every bar is one expert's unbiased sigmoid score, and no bar moves when you drag. The short dash above each bar is that expert's score plus the bias, and the dashed rule is the eighth-highest of those. Dragging the bias moves the dashes and the rule, so it changes which experts are chosen โ and changes nothing about what a chosen expert is worth, because the weights are gathered back from the bars. That is auxiliary-loss-free balancing in one gesture: a lever on selection that is not a lever on the output.
- routed weights, summed
- 2.500
- shared weight
- 1.000
- routed : shared
- 2.5 : 1
- experts firing
- 9 of 257
- winners the bias moved
- 6
One group of 256, one group selected. The mask is all ones, so it does nothing.
8 groups of 32, scored by their top 2. Four groups โ 128 experts โ are masked out before the top-8 runs, and 0 of GLM's 8 winners would not survive it.
Both panels are the same code path. GLM inherits DeepSeek's grouped top-k verbatim and then sets n_group to 1 and topk_group to 1, which makes the group mask a matrix of ones. The machinery is structurally present and numerically inert โ a fact you can only see by reading the config against the implementation, because the forward pass is byte-identical either way.
stand-inThe router's learned weights are not published, so the scores here come from a fixed seeded distribution โ deterministic, identical on server and client, and not a measurement. What is real: the order of the six steps, the sigmoid rather than a softmax, the gather from the unbiased scores, the renormalization, the 2.5 scale, and every count on the page. The 76 fp32 bias vectors are physically in the checkpoint, 256 numbers each; the rule that updates them during training is not.
An expert here is nothing exotic. It's the same feed-forward block a plain transformer puts after attention: project the token up, bend it through a nonlinearity, project it back down. GLM's version is a bias-free SwiGLU with three matrices, and its inner width is 2,048 against a residual stream of 6,144. That makes one expert a twelfth the size of the four-times-wider block a classic transformer would use. Fine-grained, in this literature, means cutting the feed-forward into many small pieces so the router has real choices, instead of a few fat ones where picking two of eight barely counts as a decision.
The routing is where the design lives, and the order of operations is the trick. The router is one matrix, 256 rows of 6,144 numbers, run in fp32 and carrying no bias of its own. It emits one score per expert. Those scores go through a sigmoid, applied to each expert independently, so they are not a probability distribution and do not sum to anything in particular. Then a per-expert bias vector is added, 256 numbers held separately in the checkpoint. The top 8 of the biased scores win. And then the bias is thrown away: the weights that actually scale the winners' outputs are gathered from the unbiased sigmoid scores, renormalized to sum to one, and multiplied by 2.5.
That discard is the step reimplementations get wrong, and it's the entire definition of auxiliary-loss-free load balancing. The bias moves which experts win. It never moves how much a winner contributes.
The reason it has to work that way repays a paragraph, because the alternative is what everyone used to do. A router left alone collapses. Whichever experts start out slightly popular receive more tokens, more tokens mean more gradient, more gradient makes them better, and better makes them more popular. Left alone for long enough, a 256-way bank ends up doing the work of a handful, and the rest is dead weight you paid to train. The classical fix bolts a balancing penalty onto the loss, which then competes with the language objective for the same gradient, and the model pays for balance in quality. The bias is a controller instead. It sits outside the gradient machinery, nudged by hand between training steps, pushing over-subscribed experts down and starved ones up until load flattens. Because it's stripped off before the gate weights are read, none of that pressure leaks into the model's arithmetic. Drag the bias in the figure: the set of lit experts shifts, and the heights of the bars stay pinned. The two rails underneath say the same thing twice over. The upper one is what the bias chose; the lower one is what plain top-8 would have chosen from the same scores. Drag the hump along the bank and the upper rail follows it while the lower rail does not move at all.
One honest gap. Those bias tensors are physically in the checkpoint, 76 of them, shape 256, registered as buffers outside the gradient and pinned to fp32. The rule that updates them is not published. I scanned the GLM-5 report end to end for any description of a bias update, a rate, or a sequence-level balance loss, and there is none; MoE routing is close to absent from its architecture section. GLM-4.5's paper gives a rate of 0.001 for the first 15 trillion tokens and zero after, and it's plausible that carried over, but plausible is all it is. Importing DeepSeek's number here would be worse, because that's a different lab's hyperparameter for a different model.
Two structural consequences fall out of the ordering. First, because renormalization pins the eight weights to sum to one, the multiply by 2.5 makes the routed branch's total gate mass exactly 2.5 for every token, always. The shared expert sits outside all of it with an implicit weight of one. So the amplitude ratio between the routed bank and the shared expert is 2.5 to 1 by construction, identical for every token the model has ever seen. Swap the renormalization and the multiply around, so the scaling happens before the sum is pinned, and 2.5 becomes a soft scale on a wandering total. You have built a different model.
Second, and this one is invisible unless you read the config's small numbers. GLM inherits DeepSeek's noaux_tc routing code, which implements group-limited routing: experts are partitioned into groups, a token may only draw from a few groups, and the rest are masked to negative infinity before the top-k. DeepSeek-V3.2 sets 8 groups with 4 selected, capping each token at 128 candidate experts and, once the 256 experts are spread across a cluster, at most four machines. GLM sets one group, one selected. The mask is all ones. The masking operation runs and masks nothing. GLM-5.x performs plain global top-8 over all 256 experts, and does no node-limited routing at all, which means it gave up the bound on cross-machine traffic in exchange for unconstrained routing freedom, and leans on a fast library for shuffling tokens between machines to absorb the difference. The figure's second panel draws both configurations side by side; the code path is identical and the config decides whether it does anything.
Then there's a result that inverts the usual intuition, and I had to check it twice. A GLM MoE layer is computationally wider than a GLM dense layer. Nine experts fire per token, eight routed plus the shared one, at 2,048 each, for 18,432 of active feed-forward width, three times the residual stream. The dense layers at the bottom of the stack are 12,288 wide, only two times. Everyone repeats that MoE layers cost about what a dense layer costs, and here they cost 1.5 times more. GLM did not buy sparsity to make layers cheaper. It bought capacity, at a 50 percent increase in per-token feed-forward work, and paid for that by making the three dense layers unusually narrow. The total routed capacity sitting in one layer is 524,288 units of width, eighty-five times the residual stream, of which any given token touches a thirty-second.
Rotations, and the sixty-four dimensions that carry them
Attention compares tokens by dot product, and a dot product doesn't know about order. Something has to tell the model that a word came before another word, and in this family the answer is a rotation.
- pairs outlasting this distance
- 11 of 32
- 1e6 at 202,752
- 7
- 1e6 at 1,048,576
- 4
- 8e6 at 1,048,576
- 7
- smallest base that suffices
- 4.84e6
- pair 0 wavelength
- 6.28 tokens
derived The count above is the figure. 1e6 at the old window left 7 of 32 pairs with a wavelength longer than the whole context โ pairs whose angle has not yet come back around, and which can therefore still tell โfarโ from โvery far.โ Stretching the window to 1,048,576 without touching the base drops that to 4. Raising the base to 8e6 restores it to 7. Z.ai does not state this quantity anywhere; it is computed here from the two numbers they did publish, and the smallest base that would have worked is 4.84e6, so 8e6 is a round number with margin rather than a tuned one.
The base does not stretch every pair. Pair 0's exponent is zero, so its wavelength is 2ฯ โ 6.28 tokens under 1e6 and under 8e6 alike โ the fastest pairs wrap constantly at every base and always have, by design. What the base moves is the slow end, progressively more the slower a pair already is: pair 31 stretches by 7.50ร, and pair 0 by exactly 1.00ร. The layout matters as much as the count. The first 192 dimensions are one contiguous block that never rotates, but inside the 64 that do, rope_interleave pairs each dimension with its immediate neighbour โ the alternating shading above โ where DeepSeek's default pairs dimension i with i + 32. Same angles, different memory layout, and a checkpoint moved between the two conventions without permuting is silently wrong in a way no shape check catches.
RoPE works by pairing up dimensions and treating each pair as a point on a plane. Before the dot product, each pair is rotated by an angle proportional to the token's position. Pair number zero rotates fast, a full turn every handful of tokens. The last pair rotates slowly enough that it barely moves across the whole context. Think of a row of clock hands at wildly different speeds, all reading the same time: the fast hands resolve fine distinctions between nearby positions, the slow hands keep coarse track of far-apart ones, and what the rotation contributes to a dot product turns on the difference of the two positions and nothing else. Relative position falls out of absolute rotation, for free, with no extra parameters.
GLM rotates 64 of each head's 256 query-key dimensions and leaves the other 192 alone. The absorption argument two chapters back explained why: the unrotated 192 flow through the absorbable path that makes the small cache possible, and only the 64 carry position. Thirty-two pairs, then, in a head of 256, for a partial-rotary factor of one quarter.
There's a trap in the config here, and it is an easy one to fall into. GLM-5.2's config.json contains "head_dim": 192, and GLM-5 and 5.1 both say 64. Neither value is used for anything. The config class overwrites the field in its constructor, unconditionally, pointing it at the rotary width, because the rotary table is inherited from a Llama implementation that reads config.head_dim to decide how many frequencies to build. So the rotary table is 64 dimensions wide in all three models, and the actual attention head is 256. Any description that quotes head_dim: 192 as the head size is reading a field the model ignores.
GLM-5 and 5.1 shipped a base of one million and a window of 202,752. GLM-5.2 raised the base to eight million and the window to 1,048,576. The context grew 5.17 times; the base grew 8 times. And that's the whole long-context recipe. The rope_type field says "default", which means no YaRN, no NTK scaling, no interpolation, no extension technique of any kind.
Why eight, though? The angle for pair i at position p is p divided by the base raised to a power that grows with i, so the base is the only knob in the scheme, and it does not act evenly. The fastest pair's exponent is zero, so raising the base does nothing to it whatsoever: pair zero turns once every 6.3 tokens under either base. Everything slower stretches, and stretches more the slower it already was. Going from one million to eight multiplies the slowest pair's wavelength by 7.5 and the middle of the range by about 2.8.
The slow end is where it matters. A pair whose wavelength is shorter than the context repeats inside it, so two positions a full wavelength apart get an identical rotation and that pair cannot tell them apart on its own. Only pairs whose wavelength exceeds the whole context stay unambiguous across it, and there are never many.
Count them and the decision falls out. At the old 202,752 window with a base of one million, 7 of the 32 pairs had a wavelength longer than the context. Stretch the window to 1,048,576 and leave the base alone, and that falls to 4. Raise the base to eight million and it returns to 7. On this reading GLM-5.2 did not choose 8 to reach a million tokens. It chose 8 to arrive at a million tokens carrying the same long-range budget the model had at 200K. Switch the figure's base control and watch the count come back. Watch how, too: the spans stretch unevenly, the slow pairs shoot outward, and pair 0 does not move at all.
That last step is my arithmetic rather than Z.ai's: the config states the base and says nothing about why. It is at least not a fitted coincidence. The threshold has a closed form, and it works out to 4,838,354; eight million is a round number sitting 65 percent past it.
DeepSeek-V3.2, which shares nearly every other architectural choice with this model, does the exact opposite. Its base is ten thousand, the original transformer's value, sized for a 4,096-token window, rescued out to 163,840 by YaRN at a factor of 40. Two labs, one architecture, and two philosophically opposed answers to position: GLM retrained the frequencies it wanted, DeepSeek stretched the ones it had. One downstream consequence, since YaRN normally adjusts the attention temperature to compensate for its own stretching: with rope_type at default that adjustment is one, so the number GLM divides its attention scores by before the softmax is the textbook inverse square root of 256, computed across all 256 concatenated dimensions.
Two layout traps close the section, and both fail silently. GLM pairs dimensions interleaved, taking neighbors as pairs, while DeepSeek pairs each dimension with the one 32 slots away. The two produce identical results given matching kernels and silently wrong output given mismatched ones, because nothing crashes when you rotate the wrong pairs. And inside a single GLM layer the two attention paths disagree with each other about concatenation order: the main attention builds its head as unrotated-then-rotated, and the indexer builds its own as rotated-then-unrotated. Opposite orders, same layer, both correct, both load-bearing.
Saying more than one word at a time
The model has 79 attention blocks and uses 78 of them. The last one is a complete spare layer whose only job is to guess.
eh_proj is the whole mechanism: it takes where the model was โ the residual coming out of layer 77 โ concatenated with what it just said โ the embedding of the token it emitted โ and fuses 12,288 numbers back down to 6,144. Its output feeds the same layer again. Nothing is added for a deeper draft: the depth is a loop count, not a parameter count.
- 1 storedone MTP layer in the checkpoint
- 3 trainedthree draft steps in the GLM-5 report
- 4 evaluatedacceptance measured at four steps
- 5 servedfive steps in the published vLLM recipe
- draft depth
- 4
- MTP parameters stored
- 9,952,920,576
- extra parameters at this depth
- 0
- indexer forwards in the draft
- 1 of 4
- layers owning an indexer
- 22 of 79
- accepted per pass, four steps
- 2.76
The two axes are drawn separately because merging them is the natural mistake. IndexShare reuses one layer's indices in the 57 layers below it, inside a single forward pass. index_share_for_mtp_iteration reuses the draft head's own indices across 4 repeats of that head, in time. They are different savings on different axes, and a serving stack can have either without the other.
The draft layer is deliberately outside the layer skip pattern: it owns an indexer of its own, which is why 22 blocks carry one and not 21. A layer that inherited would be reading a top-k buffer nobody wrote on the draft's first iteration. The reported 2.76 accepted tokens per verified pass is Z.ai's own measurement at 4 draft steps; the depth-5 rung on the ladder above comes from a serving recipe, not from an acceptance number, and nobody outside the lab has published what acceptance does at that depth.
Generating text one token at a time is a bandwidth problem before it's a compute problem. To produce a single token, a serving stack reads every active weight out of memory, roughly 40 billion parameters' worth, does a comparatively trivial amount of arithmetic with them, and throws the read away. Speculative decoding is the standard escape: have something cheap guess the next few tokens, then run the real model once over the whole guess and check all of them in parallel. Verification costs about as much as generating one token, because the expensive part was the weight read and you only did it once. Every guess that survives is a token you got for free.
GLM's guesser is multi-token prediction, and it lives at model.layers.78. The checkpoint stores it as one layer, and it's a serious one: two norms, a fusion matrix of 6,144 by 12,288, a full attention block, its own indexer, and a complete 256-expert mixture-of-experts block. Nearly ten billion parameters of spare machine. It shares the embedding table and the output head with the main model, so it speaks the same vocabulary.
The fusion matrix is the mechanism. It takes two things and makes one: the residual stream at the end of the main stack, which is where the model was, and the embedding of the token just emitted, which is what it just said. Concatenate those, project back down to 6,144, and you have a state that knows both. Run the layer on it and you get a guess at the next token. Feed that guess's embedding back in with the layer's own output and you get a guess at the token after. The layer is applied recurrently, so drafting deeper costs more compute and not one extra parameter.
Four numbers describe this layer in different sources and they look like a contradiction. The config says one. The GLM-5 report says three. The report's evaluation says four. The vLLM serving recipe says five. All four are correct, and together they make a ladder: one layer stored, unrolled three deep during training, evaluated four deep, served five deep. Training with the parameters shared across three unrolled steps is what teaches one layer to be recursive at all. GLM reports an accept length of 2.76 at four speculative steps, against DeepSeek-V3.2's 2.55, meaning that on average a little under three tokens come out of each real forward pass.
There's a second kind of reuse hiding in this layer, and it's the one piece of the architecture that no vendor documentation describes. A config flag called index_share_for_mtp_iteration sits in GLM-5.2's file, absent from the reference implementation's own config class, surviving only as an unrecognized keyword argument. I looked for it in the serving stacks and initially concluded it wasn't implemented anywhere. That was simply wrong; it's implemented in both major engines. Draft step zero computes its own sparse-attention selection over the context, and steps one and onward reuse it, skipping the indexer on every guess after the first.
Keep that separate from IndexShare, because merging them is the natural mistake. IndexShare reuses one selection across layers, going up the stack. This reuses one selection across draft steps, going forward in time. Two independent axes on which this model refuses to recompute what it thinks it already knows, and the figure draws them as two axes for that reason.
The payoff is a count that the parameter census could not previously explain. If the draft layer inherited the backbone's skip pattern it would be a shared layer, and a shared layer reads a buffer written by the layer below it. The draft layer has no layer below it inside its own pass, so it would read a buffer nobody wrote. The engines therefore exclude it from the pattern and give it a full indexer of its own, always. That's why the checkpoint carries indexer tensors on 22 layers when the config's array names 21.
The arithmetic
Three separate sparsities are running in this model at once, and they compose. This chapter multiplies them out, then spends its second half taking most of the result back, because the number everyone will quote is true in a regime nobody has measured and false in the one the model actually shipped in.
Everything here is per token and at prefill, which is the pass that reads your prompt rather than the one that writes the answer. Those two are bound by different things, and the last section of this chapter is about the one that sets the price. The numbers come out of a script that ships with this notebook. Where a figure appears below, it computes its own bars from the per-layer constants.
Three sparsities, multiplied
Start with the model that GLM-5.2 would be if you deleted every clever thing in it: full attention over the whole context, all 257 experts firing, no indexer. At a million tokens of context that hypothetical model costs 6.842 trillion floating-point operations per token.
Every one of the 257 experts fires, attention reads the whole window, and there is no indexer because nothing needs choosing.
- context
- 1,048,576
- FLOPs / token
- 6.842e12
- vs previous stage
- โ
- vs dense attention
- 1.26ร more
- largest band
- core attention 78.34%
Watch the second track rather than the first. The total falls 20.19ร from dense attention to the shipped model, but the interesting motion is the bands trading places inside it. Dense, 98.56% of the arithmetic is core attention: every token scoring every earlier token, at a million tokens, burying 753 billion parameters under their own quadratic term. Turn DSA on and core attention falls by exactly 512 โ 1,048,576 over 2,048, with nothing left over โ to 1.38%, while the indexer, which did not exist a moment ago, becomes 88.35% of what is left. Each fix works, and each fix promotes the next bottleneck.
IndexShare attacks precisely that band, and after cutting it by 3.71ร the indexer is still 67.13% of the budget. That is the spine of the argument, and it fits in one line: at a million tokens this model does not spend its time on its weights, it spends its time deciding what to look at.
Two qualifiers, and both are load-bearing. First, the top row is derived rather than configured: ./data prices the expert banks at the nine experts a token activates, so "every expert active" scales that band by 257/9. The notebook's 5.438e12 baseline is the row below it โ dense attention, MoE routing already on โ and the small gap between the two rows is the MoE saving at this context. Second, and worse for the story: these are counts of operations, and the indexer runs in FP8 where the attention it gates generally does not. The next figure hands you that dial.
A word on the unit, since "FLOPs per token" is doing a lot of work here. It counts arithmetic operations, two per multiply-accumulate as everyone in this literature counts them, needed to push one token through the network once. It's a proxy for cost, and it ignores everything about how fast memory is, which matters enormously and gets its own section in a moment. As a way of comparing architectural choices against each other it's the cleanest instrument available, because it doesn't depend on whose GPU you ran on.
Switch the three sparsities on one at a time in the figure and the bar does not shrink evenly. One of them takes almost everything, and what makes the sequence worth watching is not the total at the end but the way the colored bands inside the bar keep changing places.
The first sparsity is the mixture of experts, and it's the one everybody already knows about. Eight of 256 routed experts fire instead of all of them, so the feed-forward banks cost a thirty-second of what they would dense, and the total falls to 5.438 trillion. A thirty-two-fold cut in the banks buys a 1.26-fold cut in the bill.
That gap is the first thing this chapter has to teach. The saving everyone talks about is nearly invisible here, because at a million tokens of context the expert banks are 0.94 percent of the budget and the model is not spending its time on its weights at all. Every number after this one keeps 8 of 256 firing, which is why the dense baseline you will see quoted elsewhere, including by me until I checked, is the 5.438 and not the 6.842.
Look at where that attention-dense model's 5.438 trillion operations actually go: 98.56 percent of them are core attention. Every token scoring every earlier token, at a million tokens, buries 753 billion parameters under their own quadratic term. The weights are a rounding error. This is the fact that turns long context from a memory problem into an architecture problem, and it's the reason the next two sparsities exist.
The second sparsity is DSA. Attention reads 2,048 tokens instead of 1,048,576, so core attention falls by a factor of exactly 512. Not approximately: 1,048,576 divided by 2,048 is 512 with nothing left over. Total per-token cost drops to 760 billion operations, a 7.16-times saving. The composition rearranges with it. Core attention, which was 98.56 percent, is now 1.38 percent. The indexer, which didn't exist in the dense model, is 88.35 percent.
Read that twice, because it's the shape of the whole design. The mechanism that decides what to look at now costs more than everything it was protecting, combined and multiplied by seven. DSA did not remove the quadratic term. Every token still scores every earlier token; it just does it with 32 cheap heads against one shared key instead of 64 expensive heads against 64 keys. DeepSeek says so plainly in its own report, and the point tends to get lost in the excitement about the 512.
The third sparsity is IndexShare, and it exists to attack that. Twenty-one indexer passes instead of 78 cuts the indexer's cost 3.71 times, and the total falls to 269 billion operations per token. Against the 5.438 baseline that's 20.19 times cheaper. Z.ai advertises 2.9 times fewer total FLOPs from IndexShare alone; my reconstruction lands at 2.82 blended, inside three percent, so the claim checks out. And the indexer, after being cut by three quarters, is still 67.13 percent of the budget.
That's the spine, and it fits in one line before the next section takes it apart: at a million tokens, GLM-5.3 does not spend its time on its weights. It spends its time deciding what to look at. Each fix works, and each fix promotes the next bottleneck.
One qualifier belongs on that number, and on every share in this chapter, and it cuts against the story I am telling. These are counts of operations, and operations are not all priced alike. The indexer runs in FP8; the attention it gates generally does not. So a count overstates the indexer's share of the clock, by up to a factor of two on hardware with FP8 units. Price the indexer's operations at half and its 67.13 percent becomes 50.52 percent of the time, which is still a majority and barely. The headline says the indexer costs twice everything else put together. The honest version says it costs about the same as everything else put together, and that is a different sentence.
One number in circulation does not belong on this axis. The GLM-5 report says DSA "reduces the attention computation by roughly 1.5-2ร for long sequences," which is a third of the smallest defensible FLOP ratio here. I don't think it's a contradiction; I think it's a wall-clock measurement rather than an operation count. The precision point above is one reason a real speedup lands far below the arithmetic, and there are four more. Kernels at these shapes are memory-bound, so removing arithmetic buys less than proportionally. The indexer's own cost is inside the measurement. Packed training batches average about half the nominal sequence length. And every prefix shorter than 2,048 tokens gets no sparsity at all, because there's nothing to prune. That reading is my inference and the report doesn't state it. Treat 1.5 to 2 as an observed speedup and 5 to 20 as a FLOP ratio, and never offer one as evidence for the other.
Where the bottleneck actually sits
Everything in the last section was computed at a million tokens of context. That was a choice, and it turns out to be the choice that decides the answer.
- context
- 1,048,576
- largest band
- indexer 67.13%
- indexer
- 67.13%
- indexer > MoE at
- 293,941
- indexer > 50% at
- 512,337
- measured here?
- no public number
Run the same arithmetic at 202,752 tokens, the window GLM-5 and GLM-5.1 actually shipped, and the ordering is not merely different โ it is inverted. MoE feed-forward is 41.16% and the indexer only 28.49%, against 18.92% and 67.13% at a million. At 200K this is a feed-forward-dominated model: the experts are the bill, and the entire "the indexer is the bottleneck" story has not happened yet. So the bottleneck is not a property of this architecture. It is a property of where you run it.
Now put the thresholds next to the evidence. The deepest quality-suite evaluation of any GLM sparse-attention model is a 200K window, on GLM-5, before IndexShare existed. The deepest independent probe of any kind is a hobbyist's needle test at 249,945 tokens โ a smoke test, not a benchmark. Both crossings fall beyond both, inside the shaded region, which is the honest shape of this result and considerably more interesting than the uncaveated version.
The axis label is a claim, so read it carefully: these bands count operations, and operations are not all priced alike. The indexer runs in FP8 on both operands where the attention it gates generally does not, so a count overstates its share of the clock, by up to a factor of two on hardware with FP8 units. The second slider prices an indexer operation against everything else: at 1.00ร the indexer's share at a million tokens is 67.13%, against 67.13% unweighted. The headline says the indexer costs twice everything else put together. At half price it costs about the same as everything else put together, and that is a different sentence.
Run the same arithmetic at 202,752 tokens, the window GLM-5 and GLM-5.1 actually shipped, and the ordering is not merely different. It's inverted:
| Component | at 202,752 | at 1,048,576 |
|---|---|---|
| MoE feed-forward | 41.16% | 18.92% |
| indexer | 28.49% | 67.13% |
| attention projections | 20.79% | 9.56% |
| core attention | 8.46% | 3.89% |
| dense feed-forward | 1.10% | 0.50% |
At 200K this is a feed-forward-dominated model. The experts are the bill, the indexer is a quarter of it, and the entire "the indexer is the bottleneck" story that the last section built has not happened yet. Drag the figure's slider and watch the bands trade places.
Solving for where they cross gives two thresholds, and both are solved numerically in the same script as everything else. The indexer overtakes the expert banks at 293,941 tokens, where both sit at 36.53 percent. It becomes an outright majority of the budget at 512,337 tokens.
So the bottleneck is not a property of this architecture. It's a property of where you run it. That single sentence is the most important thing in this chapter, and I nearly published the chapter without it.
Now put the thresholds next to the evidence. The deepest quality-suite evaluation of any GLM sparse-attention model is a 200K window, from the IndexCache paper, measured on GLM-5 before IndexShare existed. The deepest independent probe of any kind is a hobbyist's needle test at 249,945 tokens. Both crossover points fall beyond both. Everything to the right of about 250,000 tokens on that figure is territory where no public measurement of this model family exists, from Z.ai or from anyone else, and the figure shades it for that reason.
The uncomfortable conclusion, stated plainly: the regime in which this architecture's story is most dramatic is a regime that only exists in GLM-5.2 and later, and that nobody has ever published a measurement in. The 20.19 times headline is true. The indexer-is-the-bottleneck framing is true as an operation count, and a coin flip once you price FP8 in. All of it lives in unmeasured territory. I find the caveated version more interesting than the clean one, because it says something real about how far ahead of measurement this whole field is running.
None of this applies at decode
A FLOP analysis will never tell you the next part, and the next part is what sets the price.
- intensity
- 1.50 F/B
- of the ridge
- 0.5%
- attained
- 5.0 TF/s
- read / token
- 53.73 GB
- KV : weights
- 0.30ร
- batch โ โ
- 6.5 F/B
Every point this figure can draw sits on the sloped roof, which means the limit is bytes moved and not arithmetic done. At batch 1 and 131,072 tokens the model reads 53.73 GB to emit one token and gets 0.5% of the card's arithmetic. Drag batch right and the dot does move right โ more tokens amortize the same 41.25 GB of weights โ but each added sequence brings its own KV cache, so the denominator grows with the numerator and the gain decays. The dashed vertical is where it ends up: 6.5 FLOP/byte at infinite batch, against a ridge at 295.4.
Push the batch to 256 and see where it stalls. Ignoring the KV cache entirely, the ridge would need a batch of 152; with the cache counted, no batch reaches it at all.
Which reframes MTP. Multi-token prediction is usually filed under "faster sampling", but on this chart it is a bandwidth optimization and nothing else: one verified pass emits 2.76 tokens on average, so the weight read is amortized 2.76 ways and the effective bytes per emitted token fall to 19.47 GB. The toggle moves the dot right by exactly that factor โ and at 8,192 tokens with an infinite batch and MTP credited in full, the ceiling is still 285.1 against a ridge of 295.4. The roof holds.
The roofs are datasheet peaks โ 989.5 TFLOP/s of BF16 over 3.35 TB/s of HBM โ so real kernels land under both, and the KV term assumes the whole cache is re-read every step, which paged and quantized caches soften. Neither correction moves the conclusion: the gap to the ridge is a factor of 196.92ร, and no amount of kernel engineering closes a gap that large.
A language model does two very different things. Prefill reads your prompt: thousands of tokens arrive at once, the GPU has an enormous amount of parallel arithmetic to do, and the limit is how fast it can compute. Everything above this section is about prefill. Decode writes the answer: one token at a time, each depending on the last, with no parallelism to be had inside a single sequence. For every single token generated, the machine must read every active weight out of memory and the entire conversation's key-value cache along with it. Then it does a few billion operations, which for a modern GPU is nothing, and throws the read away.
The ratio between those two quantities has a name. Arithmetic intensity is operations performed per byte moved, and every accelerator has a break-even value where its compute throughput and its memory bandwidth are balanced. An H100 does 989.5 trillion operations per second and moves 3.35 terabytes per second, so its break-even is 295.4 operations per byte. Above that number you're limited by math. Below it you're limited by memory, and buying a faster chip does nothing unless the memory got faster too.
GLM-5.3 at decode:
| batch | context | KV cache bytes | KV vs weights | intensity |
|---|---|---|---|---|
| 1 | 8,192 | 0.78 GB | 0.02x | 1.92 |
| 1 | 131,072 | 12.5 GB | 0.30x | 1.50 |
| 32 | 8,192 | 25.0 GB | 0.61x | 38.95 |
| 32 | 131,072 | 399.4 GB | 9.68x | 5.85 |
| 256 | 8,192 | 199.7 GB | 4.84x | 85.63 |
Every entry is far under 295.4. The best case in the table, batch 256 at short context, reaches 85.6, which is 3.45 times below the break-even. The obvious move is to raise the batch size, since serving more users at once amortizes one weight read across all of them. Ignoring the cache, you'd need a batch of 152 to reach the ridge. But the cache grows linearly with batch, so every user you add to chase compute brings along the traffic that keeps you underneath. Drag the figure's batch slider all the way right and watch the dot refuse to arrive. There is no batch size that makes this model compute-bound at decode.
Three things follow. Two of them send you back to earlier chapters, and the middle one is new.
First, the key-value cache stops being a footnote and becomes the bill. At batch 32 with 131,072 tokens of context, the cache is 9.68 times the size of the weights, which means 90.6 percent of everything the memory system moves is cache. I presented MLA's 53.7-fold compression and IndexShare's 13.3 percent cut as storage savings, which is how they're usually described and which undersells them. They are bandwidth savings, and bandwidth is the scarce thing.
Second, FP8 is not the two-times weight-read saving it's sold as. Quantizing the model to eight-bit halves most of it, but the output head stays in higher precision, along with the router gates, the norms and the entire draft layer. The output head alone is 951 million parameters of dense work on every token. The real speedup on the weight read is 1.954, and the gap between that and 2.0 is almost all one matrix.
Third, this changes what the draft layer is for. I introduced multi-token prediction as a latency trick, the standard framing. In bandwidth terms it's better than that: a draft token that survives verification is a token that never required its own weight read. At batch 1 and 8K of context, MTP takes the effective bytes moved per output token from 42.0 gigabytes down to 15.2. It's a 2.76-times cut in the dominant cost term, which is to say that multi-token prediction is a bandwidth optimization wearing a latency costume.
The scope here is single-device arithmetic. No tensor-parallel communication, no attention operations counted in the intensity figure, and H100 numbers because they're public. All three omissions push the intensity down, so the conclusion survives them: decode is bandwidth-bound by a factor of three and a half at its very best.
What it costs, and what you get
The architecture chapters exist to explain a pricing fact. A model that reads a fiftieth of the memory and a twentieth of the arithmetic of its dense equivalent is a model you can serve cheaply, and cheap serving is what pays for the thing GLM-5.3 actually is. Reinforcement learning on long-horizon agentic tasks means generating enormous quantities of tokens that get thrown away, over and over, for weeks. The machine is the reason the training run was affordable.
So this chapter follows the money, and it turns up three things you would want to know before the release itself: what a token costs, what precision you were actually sold, and what the model literally receives when you talk to it.
One name, thirty-three prices
Z.ai's own list price for GLM-5.2 is $1.40 per million input tokens and $4.40 per million output. Anthropic's Fable 5 scores higher on Artificial Analysis's intelligence index, 62 against 53, and running AA's full evaluation suite cost $734.50 on GLM-5.2 against $5,455.22 on Fable 5. That's the pitch in one comparison: most of the capability at an eighth of the bill.
- index gap
- 9 points
- cost to run AA's suite
- 7.4ร
- per index point
- $525
- GLM-5.3 on AA
- 404
The first panel is the ordinary version of the argument: nine points of Artificial Analysis index cost 7.4 times as much to run AA's own suite โ $735 on GLM-5.2 against $5,455 on Fable 5 โ which is roughly $525 per point of index. That is a real gap in both directions and the honest reading is that you are buying most of the capability for a seventh of the money, not all of it for free.
The second panel is the stronger one, and you have to drag it to see the argument. Thirty-three endpoints serve one model name, and they agree on nothing: the input price spans 7.11ร from $0.3248 to $2.31, the context window spans 10.8ร from 96,890 to 1,048,576, and only 22 of 33 serve the full window โ the other 11 fall visibly short of the line. Price does not track precision either: one provider sells fp4 at Z.ai's exact list price, another sells fp8 at a quarter of it, and 7 endpoints decline to say. Z.ai's own endpoint sits near the top of its own market, undercut by 18 others, the cheapest by 4.3ร.
Two cautions. These are 33 endpoints, not 33 operators: Alibaba, BaseTen, Cloudflare, Fireworks, Wafer each appear twice at different prices, presumably as throughput tiers, so the market has 28 distinct names on it. And every count on this panel is computed from the endpoint list at render time rather than quoted, which is why it may differ by one or two from a summary written by hand โ the list is what OpenRouter served, and the arithmetic is done here.
The more interesting number is what happens when you go to buy it. I pulled OpenRouter's endpoint list for the single model name z-ai/glm-5.2 and got 33 distinct served endpoints, and they do not agree with each other about anything.
Input price runs from $0.3248 to $2.3100, a spread of 7.1 times, for the same weights. Context windows run from 96,890 tokens to 1,048,576, a spread of 10.8 times, and only 22 of the 33 serve the full million. A reader who chose this model for its headline context window has a two-in-three chance of getting it, and no interface tells them which they landed on. Drag the figure's handle to whatever you actually need, a floor on context or a ceiling on price, and every endpoint that cannot meet it drops into the gutter along the bottom, with a running count. The million-token line is the one to watch: eleven endpoints sit under it.
The third surprise is that price does not track precision. One provider serves four-bit quantized weights at Z.ai's exact list price. Another serves eight-bit at a quarter of that price. Seven endpoints decline to say what precision they run at all, and two of those charge $2.10. Meanwhile Z.ai's own endpoint sits near the top of its own market: eighteen of the thirty-three undercut the lab that trained the model, the cheapest by 4.3 times.
One correction to my own reading of that list, since the number invites a wrong conclusion. Five providers appear twice at different prices, presumably as latency or throughput tiers, so 33 endpoints is not 33 operators. The spread is real; the count of independent sellers is smaller.
And then the part that grays the whole panel out. None of this exists for GLM-5.3. OpenRouter lists thirteen GLM models and the newest slug is z-ai/glm-5.2. Z.ai's own price list stops at GLM-5.2. The only way to reach GLM-5.3 as I write this is a subscription called the GLM Coding Plan, whose credits are metered by a formula that bills output tokens at 24 times the rate of input, and which is locked to a list of approved coding tools, with no general API access. Two different Z.ai documents describe two different peak-hour multipliers for that plan, one saying off-peak costs half and the other saying peak costs triple, and GLM-5.3 is named explicitly in the harsher of the two.
The plan also ships a vision service backed by GLM-4.6V, an older and much smaller model. That's the vendor conceding in its own product that the flagship cannot see. Every image in your repository is handled by something else.
What you actually bought
Precision is sold as a billing detail. It is a capability variable, and the numbers are not subtle.
- 8 ร H2001128 GB
- 8 ร B2001536 GB
- 4 ร DGX Spark512 GB
- 2 ร DGX Spark256 GB
- 1 ร RTX Pro 6000 + NVMe96 GB
- fp8 on disk
- 753 GB
- top-1 agreement
- not measured
- rigs that hold it
- 2 of 5
- API vs llama.cpp
- 127 vs 0.7 tok/s ยท 181ร
The ghost bar is arithmetic โ parameters times bits over eight โ and the solid bar is what community builds actually weigh. They diverge at the bottom, and the divergence is the point: a one-bit build should be 94 GB and is 223, because you cannot take attention and the embeddings down with the experts. Against that, Unsloth's measured top-1 agreement falls to about 82 percent at two bits and about 76 at one. A model that disagrees with itself on a quarter of its next tokens is a different model wearing the same name.
The honest floor is at the bottom of the ladder: 0.7 tokens per second, measured on llama.cpp with a three-bit build streaming off NVMe on a single card, against 127 tokens per second from Z.ai's own API on the previous model. That is a factor of 181 between the two ends of โyou can run it yourselfโ. Open weights is a licence, not a deployment.
Two caveats. The per-rig capacities are vendor board specifications rather than anything from the launch material, so treat the fit indicator as an order-of- magnitude check: a build that nominally fits still needs room for the KV cache, and the full million-token window pushes an fp8 deployment from eight H200s to eight B200s. And every size and agreement number here was measured on GLM-5.2, because GLM-5.3's weights have not shipped โ the arithmetic transfers only if the architecture does.
In its native BF16 the checkpoint is about 1.5 terabytes, which is more memory than any single machine you can rent has. At native FP8 it fits on one eight-GPU H200 node, though not at the full million tokens of context; that wants a B200 node. Below that the community quantizations take over: about 465 gigabytes if you compress only the experts to four-bit, 372 to 475 for a general four-bit build, 245 at two-bit, and 223 at one-bit. A 753-billion-parameter model on a machine you could put under a desk. Step the figure down that ladder and watch the second track: the memory requirement falls off a cliff, and somewhere below four bits the model's agreement with itself starts falling too.
The cost of that compression has been measured, and the instrument is top-1 agreement: how often the quantized model's most likely next token matches the original's. Four-bit and five-bit builds come out close enough to call lossless. Two-bit agrees about 82 percent of the time. One-bit agrees about 76 percent of the time, which means roughly one token in four is a different token, and errors in autoregressive generation compound rather than average out.
Set that beside the seven endpoints that decline to declare their precision, and the picture is uncomfortable. You can buy a model whose identity is a name, at a price that doesn't tell you what you got, and the difference between the best and worst version of it is larger than most of the model-to-model gaps in the benchmark table this notebook is about to audit.
For scale at the other end: Z.ai's own API measures around 127 tokens per second, an eight-GPU H20 node with a speculator manages 70-plus, and the honest floor is a three-bit build on a single workstation card spilling to an NVMe drive at 0.7 tokens per second, which the person who measured it described as not remotely usable interactively. Same weights, a factor of 180 between the ends.
What the model actually sees
Every conversation you have with this model is a single flat string, assembled by a template you never see, and GLM's template does something unusual with your history.
[gMASK]<sop><|system|>Reasoning Effort: Low<|user|>Which of these two commits introduced the regression?<|assistant|><think>The diff touches the cache eviction path. I should read it before guessing.</think><|assistant|><tool_call>read_file<arg_key>path</arg_key><arg_value>src/cache.rs</arg_value></tool_call>
reasoning_effortthe server runs low โ exactly what you asked forthinking.type accepts only enabled โ a request with disabled fails- lines in context
- 5
- reasoning blocks erased
- 0 of 1
- GLM-5.3 accepts
- 3 values
- collapsing to
- 3 behaviours
Advance the turns and watch the <think> blocks from earlier turns disappear. GLM sets clear_thinking by default, so the reasoning that produced turn one is not in the context when the model answers turn three; it reads its own conclusions without its own working. Kimi K3 does the exact opposite and preserves the trace, which is the toggle on the right. Neither is obviously correct โ one saves an enormous number of tokens, the other keeps the chain intact โ but they are different models of what a conversation is, and nothing in either API tells you which one you are talking to.
The serving contract has its own quiet edge. GLM-5.3 cannot turn thinking off at all: thinking.type accepts only enabled, and a request with disabled fails outright. It exposes three effort levels, default max. GLM-5.2 accepts 7 โ and collapses them into 3 behaviours, silently. Ask 5.2 carefully for low and you get high; the injected Reasoning Effort line above changes with it, which is the only place the substitution is visible at all. No error, no warning, no field in the response telling you what actually ran.
One label the figure has to wear. This template is GLM-5.2's, read out of the tokenizer configuration on Hugging Face โ [gMASK]<sop>, the injected Reasoning Effort system line, <|observation|> for tool results and GLM's bespoke tool-call XML are all verified there. On 5.2 that line only ever reads High or Max, because the lower values resolve upward before the template sees them; drawing it as Low under GLM-5.3 assumes 5.3 reuses the template, which it may not. The role markers around user and assistant turns are drawn in the same style for legibility but are reconstruction. GLM-5.3 ships no chat template, because it ships no weights.
The frame is [gMASK]<sop>, followed by a system message carrying a line that reads Reasoning Effort: and a level. Reasoning goes in a <think> block. Tool results come back under a marker called <|observation|>, and tool calls use a bespoke XML shape where everyone else emits JSON. Tools marked for deferred loading are held out of the prompt and injected mid-conversation when they become relevant, which is a thoughtful piece of context management.
The unusual part is what happens to the model's own thinking. GLM strips prior-turn reasoning by default. Turn three does not get to see how the model reasoned in turn two; only the conclusion survives. Kimi K3 does the opposite and preserves it. Both choices are defensible and they encode opposite bets: GLM is betting that stale reasoning is a contaminant and the conclusion is the artifact, Moonshot is betting that a chain of thought is context worth keeping. Advance the turns in the figure and watch the blocks disappear behind you.
Then there's the effort parameter, which is where the two versions of this model differ in a way callers can actually feel. GLM-5.3 accepts three levels, low, high and max, defaulting to max. And it cannot be told to stop thinking. The old way of disabling reasoning is gone, the launch post says requests that try it will fail outright, and migrating requires an explicit code change. Given that the Coding Plan bills output at 24 times the input rate and reasoning tokens are output tokens, a model that reasons hard unless told otherwise, and that cannot be told to stop, is a commercial decision as much as a technical one.
GLM-5.2's contract is stranger and better as a teaching example. It advertises seven values and honors two. Ask for none or minimal and thinking is skipped. Ask for low or medium and you silently get high. Ask for xhigh and you silently get max. A caller who carefully tunes down to low to save money is billed for high and never told. The template corroborates it from the other side: it can only emit High or Max, which is why the seven-value enum has two real settings. Send a value in the figure and watch what the server does with it, against what the documentation promised.
I should flag how thin the ground is under all of this. The template is GLM-5.2's, read from its tokenizer config, because no GLM-5.3 repository exists to read one from. And Z.ai's own documentation contradicts itself across four pages: one says the effort parameter is supported only by GLM-5.2, another says 5.2 and above, a third still documents the disable flag that the launch post says now fails, and the release notes page does not mention GLM-5.3 at all. The reconciling fact is that the GLM-5.3 API has not shipped. The three-level contract is currently the subscription plan's contract, and the API reference has not been written yet.
The release
Everything up to here has been about a machine that did not change. This chapter is GLM-5.3.
Z.ai is unusually direct about what it did, and I'd take the sentence at face value: "It carries over the RL strategies introduced in GLM-5.2, including SAO with compaction." No new algorithm. No new architecture. What scaled was the environments, and the blog states the thesis in a form that I think is the most interesting claim in the release:
"As agent capability improves, much of the difficulty in scaling post-training moves from the model to the environment."
If that's right, it relocates the hard part of building frontier models. For a decade the bottleneck was the model: better architectures, better optimizers, more data. The claim here is that once a model can plan and use tools competently, progress is limited by your ability to manufacture situations worth learning from, at volume, with a grader that can be trusted. That's a simulation problem and a software engineering problem more than a machine learning one.
I want to be careful, because it's also a convenient thing for a lab to say when its architecture is frozen. But it's testable in principle, and the pipeline Z.ai describes is specific enough to argue with.
The environment factory
Reinforcement learning needs three things: a task, a way to attempt it, and a grader. In the agentic setting the task is a job, the attempt is a long trajectory of tool calls, and the grader is the hard part. Get the grader wrong and the model optimizes the grader instead of the job, and that failure is as old as the field.
Patterns collected out of real work become a runnable environment: multi-step dependencies, hidden state, nothing a single file's pattern-match can close. The stated ambition is a task representing several days of work for an experienced engineer.
What falls out here is what will not run. A service that does not start, a dependency that does not resolve, a described goal that contradicts the state of the world.
- authored
- 64
- still alive
- 50 of 64
- compound, 80% ร 5 gates
- 32.8%
- published by Z.ai
- never
The five stages are the release's actual thesis made operational: as agent capability improves, much of the difficulty in scaling post-training moves from the model to the environment. None of these gates is about the model. Every one of them is about manufacturing a situation worth learning from, at volume, with a grader that can be trusted โ which is a simulation problem and a software engineering problem before it is a machine learning one.
The pipeline is a filter, and the interesting question about any filter is what fraction survives it. That is the dial above, and it is a dial rather than a measurement because Z.ai publishes no survival rate, no environment count, no compute figure and no token count. What the arithmetic does say is that five gates compound: at a gentle 80% each the cohort ends at 32.8%, and the difference between a 90% gate and a 70% gate is a factor of 3.5 in how much authoring you must do to fill a training run.
The 64 candidates are seeded pseudo-random draws, not a sample of anything. Which gate stops a given dot is fixed before the slider is touched, so raising the rate only ever moves a dot forward. The split of the fourth gate's rejections across its three checks is an even three-way partition of the rejection region, chosen because the real split is not public either.
Z.ai's pipeline has five stages, and I'll walk them in order because the ordering is the argument.
A research agent authors the environment, starting from patterns collected out of real work: multi-step dependencies, hidden state, things that cannot be solved by pattern-matching a single file. The stated ambition is tasks that "represent several days of work for an experienced engineer." Their example is machine-learning infrastructure work, where the model gets the same working environment a person would, with access to compute clusters, storage, internal documentation, codebases and past experiment results, and is asked to diagnose bottlenecks across a training stack, implement optimizations, run experiments, and deliver a measurable end-to-end speedup without breaking correctness. That is not a coding exercise. It's a week.
A judge agent then attempts the task, and this gate exists to catch a specific failure: environments that are broken rather than hard. An automatically authored task can be unsolvable because a dependency is missing, a service does not start, or the described goal contradicts the state of the world. Training on unsolvable tasks teaches nothing and burns compute at the scale where compute is the constraint.
A verifier is synthesized without access to the reference solution. This is the subtle one and it deserves its own beat. If you write the checker while looking at the answer, you write a checker that tests for that answer. The model then learns to reproduce a particular solution rather than to solve the problem, and every alternative approach, including better ones, scores zero. Withholding the solution forces the verifier to be written against the task's actual success condition. It's the same instinct as writing tests before implementation, applied to a machine that will attack the tests with far more creativity than a person would.
The verifier is gated on three checks before it's trusted. The known-good solution must pass. Doing nothing must fail. And an unsolved intermediate state must fail. Those three catch, in order, verifiers that are too strict, verifiers that pass everything, and verifiers that reward partial progress they shouldn't. Anything that survives produces a binary reward, and a binary reward that has been adversarially checked is worth more than a rich reward that has not.
Solver trajectories are then mined for shortcuts. Once real attempts exist, you read them for cases where the model got paid without doing the work, and you close those holes. Reward hacking is discovered empirically. All five stages run inside one training framework that puts the trainer and the rollout engine in a single dataflow, so an environment plugs in as data generation rather than as a change to the training loop.
Watch candidates fall out at each gate in the figure and the shape of it lands better than a list of stages does. The pipeline is a filter, and the interesting question about any filter is what fraction survives it. Z.ai does not publish that.
That omission is representative. There's no environment count, no compute figure, no token count, and one statement about duration: "Over the past month we kept scaling on this stack." GLM-5.2 shipped on 16 June and GLM-5.3 on 14 August, which is 59 days. Either the run occupied roughly the back half of that window or the phrase is loose, and it's the only public statement of how long the work that constitutes this entire release actually took. Z.ai does concede the honest limitation, which I credit: these pipelines "still require a meaningful amount of human-in-the-loop work," and making them autonomous is named as future work rather than claimed as done.
One rollout at a time
The algorithm underneath repays a close look, because it inverts a design everyone in the field converged on, and the reason comes out of scheduling.
- GRPO cluster busy
- 41.1%
- SAO cluster busy
- 91.3%
- wall clock, same work
- 2.22ร
- longest / shortest trajectory
- 24.0ร
Both timelines run the identical set of 40 trajectories on the identical 8 workers. The only difference is the barrier: GRPO cannot take a step until every member of the group is back, so the short ones finish and the cluster holds still while one straggler grinds through a long tool-use chain. Drag the spread to zero and the bubbles vanish, which is the honest version of the claim โ the barrier costs nothing when every trajectory is the same length, and agentic trajectories never are.
L = min(rยทA, clip(r, 1โฮต, 1+ฮต)ยทA)
- objective, PPO
- 1.00
- gradient, PPO
- A = 1, in full
- objective, SAO
- 1.00
- gradient, SAO
- A = 1, in full
Sample a group of N attempts at one prompt, take the group mean as the baseline, and wait for the slowest of them before stepping.
The four strips are the whole point, and the usual one-line version of this โ clipping keeps a flattened gradient, masking keeps noneโ is wrong. PPO's clip is one-sided. It keeps whichever of the two branches is worse, so with a positive advantage a token that drifted upward, in the direction that would flatter the update, has its gradient zeroed, while a token that drifted down keeps its gradient in full. Flip the advantage sign and the zeroed side flips with it. SAO's mask does not care: outside the window the token is dropped from the gradient computation in both directions, at either sign. Conditional and one-sided against unconditional and two-sided, which is a different claim from diminished against none.
The paper sells stability, not speed. Standard GRPO suffers from a performance collapse at approximately 160 training steps; SAO trains stably for a thousand. On long-horizon tasks where one trajectory can run for hours, being able to keep training past step 160 is worth more than any throughput multiplier โ which is fortunate, because the paper reports no efficiency numbers at all. The 2.22ร above is this simulation's own arithmetic on seeded trajectory lengths, not a published measurement.
The caveat that limits all of it: no GLM model is trained anywhere in the SAO paper. Every experiment is Qwen3-30B-A3B at 30 billion parameters. The connection to GLM-5.2 is a single sentence in the abstract with no supporting table, figure or section, and the variant Z.ai says GLM-5.3 actually uses, SAO with compaction, appears nowhere in the paper. Cite it for mechanism. Do not cite it as evidence at GLM scale. The window here is drawn at ฮต = 0.2 either side, the textbook PPO value; SAO's own ฮต_โ and ฮต_h are not published, and nothing above depends on where exactly the boundary sits.
Here's the setup in plain terms. Reinforcement learning on a language model means: sample an attempt, score it, and adjust the weights so that tokens which led to a good score become more likely. The catch is that "good" needs a reference point. A score of 0.6 means nothing until you know whether 0.6 is better or worse than this model usually does on this prompt. That reference point is called the baseline, and the difference between the score and the baseline is the advantage, which is the signal the gradient actually follows.
GRPO, the method most open labs use, gets its baseline for free by sampling a group of attempts at the same prompt and using the group's mean. Elegant, no extra machinery, and it has one operational flaw: you cannot take a training step until every member of the group comes back. Agentic trajectories vary wildly in length, so the short ones finish and sit idle while one straggler grinds through a long tool-use chain. Z.ai's description is blunt: "large portions of the GPU cluster idle."
SAO's move is to set the group size to one. Every trajectory becomes trainable the moment it finishes, and the cluster never waits. Two consequences follow, and both are more interesting than the speedup.
The value model comes back. With no group there's no group mean, so the baseline has to be predicted rather than measured, which means training a second network to estimate expected return. The field spent years removing that component, because critics are finicky, expensive, and unstable at the start of training when they know nothing. SAO puts it back and then spends real engineering on making it work: two value updates per policy update, fine-tuning the value head with attention frozen, and pretraining the critic at scale so it doesn't start cold. A reintroduction, with the reasons it was removed addressed one at a time.
And the update rule changes shape. Once training is asynchronous, a trajectory finishing now may have been generated by a policy several updates old. Correcting for that properly means knowing the exact probability the generating policy assigned to each token, which the paper calls computationally prohibitive, so SAO uses the rollout engine's own recorded probabilities as a stand-in and computes an importance ratio from them. When that ratio strays too far from one, the sample is stale enough to be dangerous.
What you do about it is the part I find clever, and the usual one-line version of it is wrong, including the one I wrote first. PPO, the standard, clips, and its clip is deliberately one-sided. It compares the raw objective against a version with the ratio pinned to the edge of the trust region and keeps whichever is worse. So a token that has drifted in the direction that would flatter the update gets its gradient zeroed, and a token that has drifted the other way keeps its gradient in full. Half of the suspect samples still vote.
SAO masks instead. Any token whose ratio lands outside the region is dropped from the gradient computation, in both directions, whether or not it flatters the update. The trust region stops being a pessimistic bound on the objective and becomes a filter on the data. Sweep the ratio in the figure across the boundary and watch which of the two leaves anything behind, on which side.
The paper sells stability rather than speed, and the number is stark: standard GRPO "suffers from a performance collapse at approximately 160 training steps," while SAO trains stably for a thousand. On long-horizon tasks where a single trajectory can run for hours, the ability to keep training past step 160 is worth more than any throughput multiplier.
Three caveats limit how far any of this can be pushed, and they matter enough to state here instead of in a footnote. No GLM model is trained anywhere in the SAO paper. Every experiment uses a 30-billion-parameter Qwen backbone. The connection to GLM is a single sentence in the abstract with no supporting table, figure, or section. The variant Z.ai says GLM-5.3 uses, "SAO with compaction," appears nowhere in the paper. The paper also contains no efficiency numbers at all, so every RL efficiency figure in circulation traces back to the blog. Cite it for mechanism. Do not cite it as evidence at GLM scale.
Grading the student's own words
One more training idea earns a section, partly because it's a beautiful piece of reasoning about distributions and partly because I have to be honest that its role in GLM-5.3 is unclear.
- overlap
- 19.5%
- KL(teacher โ student)
- 2.88
- KL(student โ teacher)
- 4.01
- student mass off support
- 43.0%
Collect the teacher's transcript and train the student on it. The student is graded on text it would never have written, and gets no supervision at all in the region it actually visits at inference.
Drag the supports apart and watch the dots. Under offline distillation they stay parked under the teacher's hump no matter where the student goes, and 43.0% of the student's own mass sits where the teacher has effectively nothing to say โ under a hundredth of its own peak. That is the structural flaw: the student gets very good at continuing sentences it will never start, then wanders into its own territory at inference time, where it received no supervision at all, and errors compound because every wrong step moves it further from the region it was taught. Switch to on-policy and the dots follow the student. Add the second teacher and the envelope covers where the student actually is, which is what multi-teacher buys: 4.01 against 4.01 on the same reverse KL.
The honesty note, and it is a large one. On-policy distillation is documented as a capability of the training framework, not as a stated step in GLM-5.3's recipe. No distillation stage, and no supervised fine-tuning stage, is described anywhere for this release. This figure explains a mechanism in the stack Z.ai built; it is not evidence that the mechanism ran.
These are two Gaussians on a line standing in for distributions over sequences drawn from a 154,880-token vocabulary, where "different support" is a statement about which continuations are ever sampled rather than about an interval. The geometry is the honest part: the overlap, both divergences and the unsupervised mass are real integrals over the curves drawn, and none of the four is a published number for any model.
Distillation means training a small model to imitate a big one. The classical version collects the teacher's outputs and trains the student on that transcript. And it has a structural flaw that took the field a surprisingly long time to name: the student is graded on text it would never have written. The teacher's transcript lives in a region of possible outputs that the student, left to itself, essentially never visits. So the student gets very good at continuing sentences it will never start, and at inference time it wanders into its own territory, where it received no supervision at all. Errors compound from there, because every wrong step moves it further from the region it was taught.
On-policy distillation flips which distribution the training data comes from. The student samples. The teacher then scores the student's own tokens, and a penalty derived from the disagreement rides along with the reinforcement learning advantage. The gradient now lands on text the student actually produces, the only text that matters. The figure draws the two distributions and their overlap, and under the axis it draws a row of dots: the tokens each regime actually trains on. Drag the supports apart and watch them. Under the classical version they stay parked under the teacher's hump however far the student walks away; switch to on-policy and they follow the student, and the ones that land where the teacher has nothing left to say turn red.
The extension is multi-teacher: score against several models at once and let the student learn from whichever is most informative per token. It generalizes from top-k probabilities to the full vocabulary depending on how much bandwidth you're willing to spend.
The honesty note. This is documented as a capability of the training framework, not as a stated step in GLM-5.3's recipe. No distillation stage, and no supervised fine-tuning stage, is described anywhere for this release. I'm explaining it because it's part of the stack Z.ai built and because understanding it pays off, not because I can tell you it ran.
Two implementations of one model
The last piece of the release is filed under systems engineering, and it's actually a correctness result. It's my favorite finding in this chapter.
- per-token gap
- 1.00e-3
- ratio at 32,768 tokens
- 0.7965
- leaves the trust region
- 30,339 tokens
- end-to-end RL throughput
- >2.3ร
Megatron and SGLang disagree on a token's log-probability in the third decimal place. Same weights, same mathematics on paper, two implementations tuned for opposite goals โ different kernels, different reduction orders, different precision along the way โ and floating-point addition is not associative, so the two stacks assign slightly different probabilities to the same token in the same context. One token's importance ratio moves by 1.0e-3, which is nothing.
It is nothing per token and it accumulates. The trajectory-level ratio is the product of the per-token ones, so the log-ratio is a random walk and grows with the square root of the length. At 1.00e-3 the walk leaves a ยฑ20% trust region after 30,339 tokens, which is an ordinary length for a long-horizon coding trajectory. On-policy RL assumes the probabilities you correct by are the ones that actually generated the text. They are not, the correction is wrong in a direction nobody controls, and your nominally on-policy algorithm has quietly become off-policy. Everything runs. The loss curve looks fine.
Worse, the same drift feeds the mask from the figure above: tokens get dropped from the gradient for having a stale ratio when what they actually have is a different reduction order. Z.ai reports driving the disagreement down to 1.00e-7, a reduction of more than 99.99%, and that these systems-level alignment fixes improved end-to-end RL throughput on long-horizon coding tasks by more than 2.3ร โ the only RL efficiency figure that exists in any source for this release, and it is attributed to the alignment work as a whole rather than to any single kernel.
Two things here are derived rather than quoted. The 1.00e-3 starting point is 1.00e-7 divided by the published reduction of 99.99%; Z.ai states the endpoint and the ratio, not the beginning. And the walk itself is a model of accumulation โ independent zero-mean per-token gaps at the stated scale โ not a trace of anyone's training run. The square-root growth is the part that is not negotiable: any unbiased per-token disagreement does this, and the axis runs to 1,048,576 tokens because that is the model's own declared window.
Training and inference are different workloads, so labs run different code for them. Z.ai trains under Megatron and generates rollouts under SGLang. Same weights, same mathematics on paper, two separate implementations tuned for opposite goals. And they do not produce identical numbers. Different kernel choices, different reduction orders, different precision along the way, and floating-point arithmetic is not associative, so the two stacks assign slightly different probabilities to the same token given the same context.
Ordinarily that's a rounding error nobody cares about. In reinforcement learning it is not, and here's why. On-policy RL assumes the probabilities you're correcting by are the probabilities that actually generated the text. Compute the token's probability under the training implementation, and it's a different number from the one the rollout engine used when it sampled. The correction is now wrong, in a direction nobody controls. Your nominally on-policy algorithm has quietly become off-policy, and no error is raised. Everything runs. The loss curve looks fine. The gradient is subtly aimed at the wrong thing.
Z.ai drove the disagreement between the two implementations down to one part in ten million, which they describe as a reduction of more than 99.99 percent against their previous setup. And they report that these systems-level alignment fixes improved end-to-end reinforcement learning throughput on long-horizon coding tasks by more than 2.3 times, which is the only RL efficiency figure that exists in any source for this release.
The general lesson is one I keep meeting in different clothes: at this scale, the boundary between a numerical detail and an algorithmic assumption stops existing. A bug that would be invisible in any other context becomes the difference between the algorithm you designed and a different algorithm with the same name.
The evidence
Every number in the last chapter came from Z.ai. So does every number in the launch table. This chapter is about what happens when you go check the other columns, which nobody does, and which turns out to be where the story is.
I want to be upfront about the conclusion, because the forensics can read as prosecution and that isn't the finding. Z.ai disclosed its own evaluation settings in more detail than most labs bother with. What it left unsourced is everybody else's numbers. The result is a table in which the vendor's own row is the most verifiable thing in it, and I think that's a general property of launch tables rather than a fact about this company.
The table, and where its numbers came from
Eight columns: GLM-5.3, GLM-5.2, Kimi K3, DeepSeek-V4 Pro, Qwen3.8-Max, Claude Opus 4.8, Claude Fable 5 with fallback, GPT-5.6 Sol. Seventeen rows. The movements first.
| Benchmark | GLM-5.2 | GLM-5.3 | Best in the table |
|---|---|---|---|
| Terminal-Bench 3.0 | 4.6 | 28.3 | Sol ยท 34.6 |
| DeepSWE | 46.2 | 66.9 | Sol ยท 72.7 |
| SWE-Marathon | 19.4 | 42.5 | Opus 4.8 ยท 48.8 |
| FrontierSWE | 67.5 | 78.1 | Fable 5 ยท 88.2 |
| CyberGym | 77.2 | 84.5 | GLM-5.3 |
| ExploitBench | 24.4 | 54.4 | Fable 5 ยท 78 |
| ExploitGym, 2h / 6h | 29 / 39 | 105 / 130 | Sol ยท 216 / 293 |
| AutomationBench | 26.2 | 48.2 | GLM-5.3 |
| GDPval-AA, Elo | 1508 | 1769 | GLM-5.3 |
| Agents' Last Exam | 23.8 | 28.5 | Sol ยท 28.6 |
Those are large moves for 59 days on a frozen base, and where they are largest is informative. The exploitation rows roughly doubled and tripled, which is where vulnerability data was deliberately added. Terminal-Bench 3.0 went up six-fold, from a floor so low that almost any improvement looks dramatic. The rows that barely moved are the ones already crowded near their ceiling: CyberGym gained seven points because everybody in the column is between 77 and 85, and Agents' Last Exam gained under five because the whole column sits within five points of itself. Post-training bought the most where there was the most room and the most data.
GLM-5.3 is first in Z.ai's own table on exactly three rows: CyberGym, AutomationBench, and GDPval-AA. The launch framing is considerably stronger than the table, and one thing it should not be called is best-of-open-weights, because in Z.ai's own numbers Kimi K3 beats it on four rows and DeepSeek-V4 Pro on two.
One of those rows needs a note before you can read it. GDPval-AA is scored in Elo, the chess rating, where a gap of a few hundred points means one side wins most of the time. Its scale is anchored so that human experts sit at 1000. So GLM-5.3's 1769 is not a percentage of anything. It sits 769 points above the human anchor, and on a standard Elo scale a gap that size corresponds to winning the head-to-head roughly 99 times in 100. The anchor is real and I checked it. What the head-to-head consists of, Z.ai does not say, and where the number came from is a worse problem that comes later in this section.
| benchmark | GLM-5.3subject | GLM-5.2same base | Kimi K3open | DeepSeek-V4 Pro0813 ยท open | Qwen3.8-Maxopen | Opus 4.8closed | Fable 5w/ fallback | GPT-5.6 Solclosed |
|---|---|---|---|---|---|---|---|---|
| Terminal-Bench 2.1Claude Code 2.1.207, 6h timeout. Z.ai's whole row sits above the official leaderboard's #1. | 88.2 | 81 | 88.3 | 87.9 | 86.6 | 85 | 88 | 88.8โ |
| Terminal-Bench 3.0Continuously authored, rotating pool. GLM-5.2's 4.6 against its own 81 on 2.1 is a benchmark change, not a model change. | 28.3 | 4.6 | 17.4 | โ | โ | 21.1 | 33.7 | 34.6โ |
| DeepSWE (v1.1)mini-swe-agent harness, 400K context, 6h timeout. | 66.9 | 46.2 | 67.5 | 62.7 | 56.6 | 58 | 69.7 | 72.7โ |
| NL2RepoRule-based plus an LLM judge blocking unauthorised pip or curl. | 58 | 48.9 | 58 | 61.1 | 55.9 | 69.7โ | โ | โ |
| ProgramBench (Almost Solved) | 19 | 9.5 | 17.5 | โ | 10.5 | 15.5 | 33โ | 23 |
| FrontierSWERun by Proximal, a third party. The one row in the table Z.ai loses and publishes anyway. | 78.1 | 67.5 | โ | โ | โ | 66.5 | 88.2โ | โ |
| SWE-Marathon (v1.1)Z.ai removed strip-clone's anti-cheat import checks for this run. | 42.5 | 19.4 | 48.1 | โ | โ | 48.8โ | 33.1 | 42.5 |
| PostTrainBenchZ.ai replaced the benchmark's pattern-matching checks with an LLM inspector. | 39.8 | 31.7 | 32 | โ | โ | 32.9 | 41.8โ | 36.2 |
| CyberGymBerkeley sunblaze. The leaderboard is a 404, so four of the six comparator cells cannot be checked at all. | 84.5โ | 77.2 | 80 | 83.3 | 78.5 | 83.6 | ||
| ExploitGym (2h)Solve counts over 869 tasks. Budgets TPS-normalised at 115 for GLM-5.3, 40 for Kimi K3, 47 for Qwen3.8-Max. | 105 | 29 | 36 | โ | 14 | 80 | 181 | 216โ |
| ExploitGym (6h)Same normalisation. Extending two hours to six is worth 36 percent more solves on GLM-5.3's own row. | 130 | 39 | 70 | โ | 26 | 120 | 247 | 293โ |
| ExploitBench41 V8 bugs on a 16-rung ladder, from Brumley and Lee at Carnegie Mellon. Five of six comparators appear on no leaderboard. | 54.4 | 24.4 | 32.2 | โ | 28.8 | โ | 76.5 | |
| Toolathlon VerifiedOfficial evaluation service, pass@1 averaged over three runs. | 73 | 59.9 | 76.5โ | 74.1 | 72.5 | 76.2 | 74.7 | 74.9 |
| AutomationBench (v1.0.6)Run with an unmerged PR #13 patch applied. The comparators do match Zapier's published numbers to rounding. | 48.2โ | 26.2 | 46.7 | 43.2 | 39.8 | 41 | 46.2 | 45.8 |
| Agents' Last Exam (ALE-CLI)105 tasks, Docker-isolated, official ALE evaluators. | 28.5 | 23.8 | 27.6 | 25.7 | 27 | 25.7 | 23.8 | 28.6โ |
| HLE w/ ToolsJudge was GPT-5.6-luna at medium effort. | 62.5 | 54.7 | 59.8 | 60 | 56.2 | 57.9 | 63.9 | 64.5โ |
| GDPval-AA v2 (Elo)Anchored so human experts sit at 1000 Elo. 1769 is 769 points above the human anchor. | 1769โ | 1508 | 1682 | 1590 | 1739 | 1588 | 1743 | 1730 |
- cells shown
- 120
- unattributed
- 63 of 120
- GLM-5.3 firsts
- 3 of 17
- rounding drift
- +10.99 Elo to rivals
Provenance mode is not a scoring of honesty. Unattributed is a statement about the post โ no footnote, no citation, no link โ and it is the default state of every cell Z.ai did not run itself. The other nine states are what checking those cells against the benchmarks' own leaderboards turned up. The vendor's own column is the most verifiable thing in the table, which I take to be a property of launch tables rather than a fact about this company.
Four cells reproduce Anthropic's system card to the digit, and two of them sit under a header reading Fable 5 while carrying Mythos 5's numbers. Click either one. The header flips to the model that produced them and Anthropic's own non-comparability caveat slides in underneath. The flip stops at the cyber rows. On Terminal-Bench 2.1 the same test fails: Z.ai's Opus cell reads 85 against the card's 82.7 and the leaderboard's 78.9, so that row genuinely is Z.ai's own harness and 88 โ 88.0 is suggestive at most.
Two things for fairness, and a figure that left them out would be lying. The GDPval-AA rounding runs against Z.ai every time โ Fable 5 1743 against a true 1738.86, Sol 1730 against 1725.18, Qwen 1739 against 1736.97, and none of GLM-5.3's own โ which is sloppiness rather than manipulation, because manipulation does not round in the other side's favour. And FrontierSWE is the one externally-run row, evaluated by Proximal, and the one row Z.ai publishes a loss on: 78.1 against 88.2. Publishing it was a choice.
Adding the column Z.ai stopped one release short of removes two of the three firsts: GDPval-AA 1848.77 against 1769, AutomationBench 50.3 against 48.2. And whatever else this table supports, it does not support best of open weights: in Z.ai's own numbers Kimi K3 beats GLM-5.3 on 4 rows and DeepSeek-V4 Pro on 2. The defensible form is best open-weights model on the cyber and computer-use rows.
One column header deserves unpacking before the provenance work, because the parenthetical on it isn't decoration. Fable 5 ships with safety classifiers that can decline a request outright, and a declined request comes back as a successful response carrying a refusal. Anthropic exposes a server-side setting that catches those and routes them to a different model instead. So a row labeled Fable 5 can contain answers Fable 5 did not write. Anthropic quantifies it in the one place it publishes both numbers: on Terminal-Bench 2.1, 20.9 percent of Fable 5's trials hit a safety refusal and fell back to Opus 4.8. One trial in five. Z.ai carries the label and never says which model its own fallback pointed at, or how often it fired.
Now switch the figure into provenance mode, where each cell is colored by its source rather than its value.
The GLM-5.3 column is vendor-run and disclosed: settings named, harness named, effort level named. Every closed-frontier cell is unattributed. No footnote, no citation, no link, anywhere in the post. Z.ai's footnotes name only its own model, plus two competitors on a single row. So the comparison rests on numbers whose origin is not stated.
Some of those numbers can be traced anyway, and the trace goes somewhere strange.
Four cells in the cyber section reproduce Anthropic's own system card to the digit. Two of them are Anthropic's Opus 4.8 figures, sitting in the Opus 4.8 column, correctly. The other two sit under a header reading Claude Fable 5 and carry the numbers Anthropic attributes to a different model.
| Benchmark | Z.ai's "Fable 5" cell | Anthropic's Fable 5 | Anthropic's Mythos 5 |
|---|---|---|---|
| ExploitBench | 78 | not published | 78 |
| CyberGym | 83.8 | not published | 83.8 |
Two independent benchmarks, four exact matches, no misses. The plainest reading is that the cyber comparator column was transcribed out of Anthropic's system card, and the transcription took Mythos 5's scores and printed them under Fable 5's name. Z.ai's own prose corroborates it from the other side, because the prose says Mythos for numbers the table labels Fable. There is no Mythos column at all.
So it matters what Mythos 5 is. Anthropic describes it in one sentence: it "shares Claude Fable 5's capabilities without the safety classifiers." Same model, same pricing, guardrails removed, available by invitation to approved organizations through a program called Project Glasswing. It was suspended for eighteen days in June by a US government export-control directive and restored on 1 July to approved US organizations only.
And Anthropic publishes no Fable 5 cyber numbers at all, for a reason it states plainly: Fable 5's classifiers fire on those evaluations, so there is nothing to report. The Mythos figures exist because Anthropic ran them, in its words, "with all safeguards turned off," alongside an explicit written warning that the results "may not be directly comparable to public leaderboard entries produced under vendors' deployed conditions." Z.ai reprints the numbers and drops the sentence.
Click one of those cells in the figure and the header flips to Mythos 5 while the caveat slides in underneath. GLM-5.3's CyberGym first place, 84.5 against 83.8, becomes a 0.7-point lead over an unguarded configuration of a model the public cannot buy, measured by its own vendor with the protections switched off. The honest sentence isn't "GLM-5.3 leads on CyberGym." It's "GLM-5.3 comes within a point of what Anthropic's restricted model does unguarded," which is a more alarming claim rather than a less impressive one.
That conclusion stops at the cyber rows, and the discipline matters. On Terminal-Bench the same test fails: Z.ai's Opus cell does not match the system card, or the leaderboard, or anything else. That row really is Z.ai's own harness, and the near-agreement there is suggestive at most.
Two more states in the figure. Contradicted, where a cell disagrees with the benchmark's own leaderboard, and no such entry, where the model does not appear on that leaderboard in any configuration. Five of six comparator scores on ExploitBench fall into the second category. Two whole rows have no leaderboard at all: Terminal-Bench 3.0's repository redirects elsewhere, and CyberGym's leaderboard is a 404. The row carrying the open-source-state-of-the-art headline is unverifiable in principle rather than merely unverified.
One row gets a provenance state all to itself, and it's the GDPval-AA row I promised to come back to. Z.ai's footnote on it does not say Z.ai ran the evaluation. It says "Models are evaluated by Artificial Analysis", crediting an independent organization by name. Artificial Analysis has published nothing: its page for GLM-5.3 is a 404, and the model appears nowhere in its GDPval results. So the most striking single number in the table, the one that reads as a model beating human experts by 769 Elo, is credited to a party that has not confirmed producing it. I had this wrong in an earlier pass, and the correction runs in Z.ai's favor: I first wrote that Z.ai had run someone else's harness and reported its own result, which is not what the footnote says. Z.ai says a third party did it. That absence turns up again later in this chapter, doing more damage.
Then the toggle I'd build this figure for even if it had nothing else. Z.ai's comparator set stops at Claude Opus 4.8. Claude Opus 5 exists. Add one column and two of the three first places disappear: GDPval-AA 1848.77 against GLM-5.3's 1769, AutomationBench 50.3 against 48.2. Watch the crowns fall off.
Two things belong here for fairness, and a figure that omitted them would be dishonest. The rounding drift in the GDPval-AA row runs against Z.ai in every single instance: three competitor scores are rounded up, by between two and five points, from their true values, and none of GLM-5.3's are. That's sloppiness, and sloppiness that costs you is evidence against manipulation rather than for it. And there's one row run by a genuine third party, FrontierSWE, evaluated by an outside firm. It's the only externally run row in the table, and it's a row Z.ai loses, 78.1 against 88.2. Publishing it was a choice.
The number that isn't in the table
The launch does not lead with any of that. It leads with a coding improvement of about fifty percent, and that number comes from somewhere the table cannot reach.
Its source is Z.ai Code Bench, which is Z.ai's own benchmark, held private and run in-house. GLM-5.2 scores 23.4 and GLM-5.3 scores 34.5, which is a gain of 47 percent, rounded up in the headline. And it arrives at fewer output tokens, 75,000 per task against 96,000, so the claim is as much about efficiency as capability. At the level below, GLM-5.3 scores 31.4 at around 50,000 tokens, against Claude Opus 4.8's 29.5 at 120,000. Scoring higher on under half the token budget is a real result if the measurement is real.
- 5.2 โ 5.3
- +11.1 pts ยท +47%
- and tokens
- โ21.9%
- 5.3 high vs Opus 4.8 max
- +1.9 at 42% of the budget
- independent replication
- none
Up and to the left is better, and GLM-5.2 โ GLM-5.3 moves both ways at once: 11.1 points up on 22 percent fewer output tokens. The headline rounds 47 percent to fifty. At the level below, GLM-5.3 scores 31.4 at around 50,000 tokens against Opus 4.8's 29.5 at 120,000, which is a real result if the measurement is real.
The vertical axis is drawn without a name because Z.ai never gave it one. That is the figure. Everything else here is a plotted number; the axis is the hole. Hover it, or press the control, for the sentence the two candidate meanings come from.
Two more things worth the ink. Fable 5 reaches 39.5 on this benchmark and Z.ai prints it โ a vendor publishing a competitor's higher score on the vendor's own private benchmark โ but its token count is not published, so it is drawn as a line across the plot rather than at an invented x. And GLM-5.3's high-effort point is quoted as โaround 50,000โ tokens, so that one marker carries a tilde. Z.ai Code Bench is in-house and held private, for a reason that is genuinely good โ contamination from public test sets โ and simultaneously uncheckable, forever, by construction.
Before the caveats, look at what the figure's vertical axis is called. It isn't called anything, and that is deliberate on my part for a reason I get to third.
Three things about that measurement, in ascending order of how much they bother me.
Z.ai names its own ceiling in the same breath. Claude Fable 5 reaches 39.5 on this benchmark at maximum effort, five points clear of GLM-5.3, and Z.ai prints that. A vendor publishing a competitor's higher score on the vendor's own private benchmark is not the usual move, and after a chapter of provenance forensics it should count for something.
The reason for keeping it private is a good reason and an uncheckable one, and those turn out to be the same sentence. Z.ai says a private benchmark "reduces the risk of contamination from public test sets and gives us a more faithful measure of real-world user experience." The next section shows what public-set contamination does to a benchmark, so this is not a pretext. It is also a claim that nobody can check, forever, by construction.
And the headline is quoted on an axis nobody states. Z.ai says Code Bench evaluates agents "along two dimensions: end-to-end task completion rate and fine-grained checklist accuracy." It never says which one the percentages are. Completion rate is all-or-nothing; checklist accuracy awards partial credit; a 34.5 means very different things under the two, and Opus 4.8 and Fable 5 are placed on the same unnamed axis. I could not resolve it from anything published, and it is the fairest question to put to the vendor in this entire notebook.
When the benchmark resets
One pair of numbers in that table does more to explain modern evaluation than the rest of it combined. GLM-5.2 scores 81 on Terminal-Bench 2.1 and 4.6 on Terminal-Bench 3.0. The model is identical. Only the benchmark changed.
- GLM-5.2, 2.1 โ 3.0
- 81 โ 4.6
- same weights, ratio
- 17.6ร
- Z.ai's lowest 2.1 comparator
- 81 ยท outranks 14 of 17
- 3.0 leaderboard
- none
GLM-5.2 scores 81 on Terminal-Bench 2.1 and 4.6 on 3.0. Not one weight changed between those two numbers. The benchmark did: 3.0 is continuously authored against a rotating task pool specifically so that a score cannot be chased, which works, and which also means every 3.0 number in circulation is a number about a pool that no longer exists in the form it was measured on.
The band above the strip is Z.ai's whole 2.1 row. Its lowest comparator, GLM-5.2 at 81, would outrank 14 of the 17 entries on the benchmark's own board โ and GLM-5.2 was never submitted to it. Z.ai's only leaderboard entry is GLM-5.1, at 58.7. That gap is not necessarily cheating; harness, timeout, scaffolding and effort all move Terminal-Bench, and Z.ai discloses all four. It does mean the row and the board are not the same measurement, and only one of them is checkable.
Six of the seventeen 2.1 entries are drawn at their published scores. The other eleven are hollow: the board's length, its ceiling of 83.8 and the rank of 81 are published, the individual scores are not in my notes, so those marks are reconstructed from a seeded generator to satisfy exactly those three constraints and nothing more. Their horizontal positions carry no information beyond the ordering. On 3.0 the right panel is empty because there is nothing to draw: no board, no submissions, no external check โ every 3.0 number in the launch table is vendor-supplied and unfalsifiable.
Terminal-Bench 2.1 is 89 fixed tasks, mirrored publicly on Hugging Face, and scores had bunched up near the ceiling: the public leaderboard tops out at 83.8, and vendor-reported numbers run higher still. A frozen public task pool degrades in a specific way: it stops measuring capability and starts measuring exposure. The tasks leak into training data, directly or through the enormous secondary literature of blog posts and solutions, and every lab's score rises for reasons that have nothing to do with the models getting better at terminals.
Terminal-Bench 3.0 is continuously authored and rotating, written by a consortium of data companies plus Nicholas Carlini, and hosted by the Laude Institute. Scores fall through the floor because the tasks are new. A drop from 81 to 4.6 is not a regression. It's the removal of a subsidy.
There's a second finding in this figure that I did not expect and that reframes the first. Put Z.ai's Terminal-Bench 2.1 row next to the official leaderboard's seventeen entries. Z.ai's entire row floats above the whole board. Its lowest comparator, GLM-5.2 at 81, outranks fourteen of the seventeen real entries, and its highest exceeds every published figure from any source. Meanwhile GLM-5.2 has never been submitted to that leaderboard; the only Z.ai entry among the seventeen is GLM-5.1, at 58.7.
That isn't evidence of fabrication. It's evidence that the whole row is a different harness, run in-house, plotted against numbers nobody else can reproduce. Which is the subject of the next section.
One awkwardness complicates any simple reading. Two of the labs whose models appear as comparators in Z.ai's table also sponsor compute for the benchmark on whose 3.0 row Z.ai claims the open-source lead. Everyone in this story is entangled with everyone else.
The harness is part of the model
An agentic benchmark does not measure a model. It measures a model wearing a harness: the tools it's given, how errors are surfaced, how many turns it gets, how its edits are applied. And the harness is not a small term.
mini-swe-agent, 400K context, 6h timeout โ the harness the launch table names
- GLM-5.3, published
- 66.9
- under this tool
- 66.9
- harness term
- up to 64.6 pts
- widest model term
- 53.6 pts ยท ExploitBench
Hold the weights still and change only the tool the model edits files with. In the one controlled study I have of this, that moved pass rate by up to 64.6 points, and an edit-format mismatch on its own made 46.2 percent of GLM-4.7's patches fail to apply. Nothing about the model changed in either case. The bars above are the same eight sets of weights every time you press a control.
Now compare the two terms. Across all 14 percentage-scored rows of the launch table, the widest worst-to-best distance between models is 53.6 points, on ExploitBench; all 14 of them are smaller than the 64.6-point harness swing. So on this table the scaffolding term can be larger than the model term, and a launch number is a claim about a model-and-harness pair, never a model.
Two honesty notes. The two magnitudes are real and measured, but they were measured on other models on other suites; applying them to this row shows what a swing of that size would do here, not what a swap actually did. (And the 46.2 in the second control is the patch-failure rate; GLM-5.2 scoring 46.2 on this row is a coincidence, not a derivation.) The credit runs the other way too: Z.ai ran nearly every one of these evaluations inside Claude Code 2.1.207 โ a rival lab's harness, version pinned in the disclosure โ which is the opposite of hiding the confound.
An independent study changed only the edit tool and moved pass rate by up to 64.6 points. Format mismatch alone, where the model emits patches in a shape the harness cannot apply, produced a 46.2 percent patch failure rate for one GLM model. Swap the tool in the figure and watch a capability number move without the model changing by one weight.
Hold that beside the launch table. On every percentage-scored row in it, the distance from the worst model to the best is smaller than 64.6. Which means the harness term can exceed the model term, and every cross-model comparison run under different harnesses is comparing two things at once without saying which moved.
Nearly every GLM-5.3 evaluation was run inside Claude Code, a rival lab's coding harness, at a pinned version. I read that as a fairness move: it's the harness the comparators were plausibly designed against, and using it costs Z.ai any home-field advantage. Disclosing the version is more than most labs do.
Three other methodology decisions run the other way, and all three are in Z.ai's own footnotes. On one benchmark, Z.ai removed the anti-cheat import checks the benchmark ships with. On another, it replaced pattern-matching verification with a language model inspector, which is a defensible change and also a change that makes the grader softer in a way nobody can quantify. And on the cyber benchmark, wall-clock time budgets were normalized by throughput, so a faster model gets more real time inside the same nominal budget.
That third one has a problem underneath it that took me a while to see. The throughput figures are attributed to Artificial Analysis, an independent benchmarking organization. Artificial Analysis does not list GLM-5.3. I raised that earlier about the GDPval row; here it does more work. I scanned their full models page, 1.29 megabytes of it, and got zero hits; the newest GLM entries are 5.2. The figure they do publish for GLM-5.2 is 127 tokens per second, and the figure Z.ai cites for 5.3 is 115, so it isn't a carry-over either. A first-party number is wearing a third-party label, and it's the number that sets the competitors' time budgets: normalized at 40 tokens per second against GLM-5.3's 115, one open-weights competitor gets roughly 2.9 times less real API time, on a benchmark where extending the budget from two hours to six is worth 36 percent more solves.
The general form is the thing to carry away. Every GLM-5.3 number in circulation today is first-party, including the ones that look sourced elsewhere. I checked Artificial Analysis, OpenRouter, Hugging Face, GitHub, and Z.ai's own release notes. None of them had heard of it.
The exploitation ladder
The cyber results are the reason this release has the title it has, and the benchmark behind them is better designed than most, so it pays to know what it actually measures.
- 16
- 15execution
- 14
- 13defeat mitigations
- 12
- 11
- 10controlled write
- 9
- 8
- 7controlled read
- 6
- 5
- 4shape the heap
- 3
- 2
- 1trigger the bug
- GPT-5.6 Sol76.5not found in any configuration
- Claude Opus 4.840not found in any configuration
- Kimi K332.2not found in any configuration
- Qwen3.8-Max28.8not found in any configuration
- GLM-5.224.4not found in any configuration
- rung 1 of 16
- 3 of 3 reach it
- GLM-5.2 โ 5.3
- 24.4 โ 54.4
- gap to the top entry
- 23.60 pts
- comparators on the board
- 1 of 6
Each rung is strictly harder than the one below it: trigger the bug, shape the heap, get a controlled read, get a controlled write, defeat the mitigations, reach execution. That is why a scalar pass rate is the wrong instrument here โ it collapses a 16-step progression into one bit, and โcan it exploit this bugโ is not a question with a yes or no answer. The heights above are the published scalars re-expressed on equally weighted rungs; the per-rung pass rates are not published, so read the ladder as a scale, not as a measurement of which rungs were actually cleared.
Two corrections the figure has to carry. The 78 credited to Fable 5 is the leaderboard's Claude Mythos Preview [AutoNudge][5 seeds] โ a five-seed autonudge run that the site itself flags as inflated against the standard three-seed budget โ while Z.ai ran 3 revisions, no nudges. Equalise the budgets and the same entry reads 59.69, so the gap falls from 23.6 points to 5.29. That conversion assumes independent trials and is derived, not measured; it is a better comparison than the published one, not a good one.
And five of the six comparator scores are not on the leaderboard at all, in any configuration, which is why they are listed as absent rather than drawn as bars. Two of the five โ Opus 4.8 at 40 and the number filed under Fable 5 โ trace instead to Anthropic's own system card. The benchmark comes from David Brumley and Seunghyun Lee at Carnegie Mellon, not from Berkeley and not from an independent body, and its README asks labs not to run reinforcement learning against it.
ExploitBench, from two researchers at Carnegie Mellon, takes 41 real bugs in the V8 JavaScript engine and grades attempts on a sixteen-rung ladder. That structure is the insight. Finding a crash is not exploitation. Neither is controlling a register. Real exploitation is a chain: trigger the bug, shape the heap, gain a controlled read, escalate to a controlled write, defeat the mitigations, and arrive at execution. Each rung is strictly harder than the last, and a scalar pass-rate would collapse the entire progression into a single bit.
GLM-5.3 climbs from 24.4 to 54.4 on that ladder in 59 days, more than doubling. The number credited to the top comparator is 78. And Z.ai's own account of why this happened undercuts the word "emergent" in the launch title: vulnerability discovery data and environments were deliberately introduced into the training mix. What surprised them, they say, was how fast the capability kept developing as training scaled, and that the model began "to reason across multiple stages of exploitation, forming coherent plans for complete exploitation chains." Deliberate ingredient, unexpected slope.
The benchmark's README asks labs not to run reinforcement learning on it. Whether Z.ai complied is not stated either way, and I'm not going to assume either answer.
Two corrections to the comparison, one in each direction, and I'll show both.
The 78 is not what it looks like. On the leaderboard, that entry was produced with a five-seed budget under an automated retry policy, a configuration the site itself flags as inflated relative to its standard three-seed protocol. Z.ai ran three revisions with no retries. So the gap GLM-5.3 is chasing is overstated in the competitor's favor, which is a rare direction for a launch table to err in. The figure lets you equalize the budget and watch the distance shrink.
And a correction that runs against my own argument, which I'm keeping in because leaving it out would be the sin this chapter is about. On the other cyber benchmark I initially reported that Z.ai's figure for a competitor contradicted the official submission by 41 percent. It doesn't. I had computed the wrong metric. That benchmark scores under at least four definitions, which diverge enormously: capture a flag by any bug at all, capture it via the intended vulnerability with mitigations off, with mitigations on, or across all profiles. The published headline metric is the second one, Z.ai used that one, and the number I thought was missing was mine. The second time in this research that a discrepancy turned out to be me comparing incompatible metrics.
What survives the audit on this row: the throughput provenance problem, the effect of the normalization on the two open-weights competitors, and several comparator cells that appear on no leaderboard anywhere. What does not survive: my own headline finding about it.
What it means
Two things in this release point outside it. One is a ledger of real bugs in real software. The other is a piece of information that isn't in any document, and its absence is the finding.
The bugs that waited forty-five years
Z.ai runs a public disclosure ledger, in Chinese only, tracking what its models have found in real codebases. I read it first-party, and the numbers reframe the cyber results from a benchmark story into something with weight.
- mean dormancy
- 26.6 years
- critical + high
- 1,097
- publicly disclosed
- 53 of 2,436 ยท 97.8% dark
- reconstruction
- mean 26.6 yr ยท 420 of 420 marks
Each mark is one defect: a dot at the year it entered a codebase, a line running forward to the year a model found it. The mean length of those lines is 26.6 years. The oldest reaches back to 1981, which is code written before most of the people now maintaining it were born, and which sat in 269 projects being read by humans the entire time. 1,097 of the 2,436 findings are rated critical or high; 1,286 more are medium. This is the part of the launch that is not a benchmark, and it is the part that should worry you.
Ninety-eight percent of the marks are faded out, and that is not a rendering choice: 53 of 2,436 findings are public. Everything else is known to Z.ai and to whoever it was reported to and to nobody else. Press the control and watch the plot nearly empty.
Two things this figure is not. The per-defect years are not published โ only the span, the earliest year and the mean โ so the marks are a seeded reconstruction satisfying exactly those three constraints: they average 26.6 years against the published 26.6, the oldest reaches 1981, and none of them runs past 2026. Read the shape of the cloud, never an individual line. And the ledger is the output of a private engagement with security teams in China, not of public inference: that is why the disclosure rate is what it is, and it is also why this cannot be read as a measurement of how well the model generalises. It is a measurement of what one pipeline found where it was pointed.
2,436 vulnerabilities recorded. Of those, 1,097 are rated critical or high, with a further 1,286 rated medium. They span 269 open-source projects. The impact span is 45 years, and the earliest defect traced runs back to 1981. The mean time a vulnerability sat undiscovered before a model found it is 26.6 years.
Sit with that last number. The average defect in this ledger had been sitting in shipped code since the late 1990s. It survived the entire history of open-source code review, outlived several complete turnovers of the maintainer base, and was finally found by a machine reading faster than any of them could. The figure draws each one as a line from the year it entered the codebase to the year it was caught, and the lines are long.
Where the ledger came from matters, and it corrects a cynical reading I initially had. This is not the exhaust of public inference. Z.ai says it has been working with several security teams in China since GLM-5.2, running its models against real-world codebases, and the ledger records the affected project, the severity, a CVE where one exists, and how long the defect had been present. So it's the output of an ongoing private engagement, which explains both why it's large and why only 53 of the 2,436 are publicly disclosed: undisclosed findings are undisclosed because disclosure belongs to the security teams and the affected projects, on their timeline, not Z.ai's. That's the responsible way to run a program like this, and it also means 98 percent of the ledger is a count of things nobody outside can inspect.
There's a subtler consequence that Z.ai does not address. The same blog post says vulnerability discovery data and environments were fed into post-training. So the pipeline that produced the ledger and the pipeline that produced the training data are the same pipeline. Z.ai never says whether the codebases behind those 2,436 findings were excluded from the training mix. On a benchmark that would be contamination; here there's no benchmark, only a count, so it isn't misconduct. But it does mean the ledger cannot be read as a measurement of generalization. It's a record of what the system found, not evidence about what it would find somewhere new. That's the sharpest question nobody has asked, and I'd want it answered before treating the number as a capability claim.
Three threads about safety converge here, and each one is checkable.
Z.ai is withholding the weights on safety grounds, deferring the open release about two weeks for evaluation and hardening. This is the first release in the 5.x line to separate the announcement from the weights, and the model whose headline is offensive-security capability is the first one its maker has held back.
The comparator setting the frontier on these benchmarks is a model shipped without safety classifiers, measured with its remaining safeguards off, sold to approved organizations only, briefly switched off by a government directive. That is the current state of measured offensive-security capability: the best public numbers come from configurations the public cannot obtain.
And the demand for an unguarded version is already visible. Within hours of the announcement, someone created a gated repository named for an abliterated GLM-5.3 built for offensive cyber work. It is empty, and it has to be, because no weights exist. It's evidence of intent and nothing more, and it should be read that way.
The counter-current is the part that complicates any tidy conclusion, and it comes from practitioners. The censorship complaint in the first-week discussion runs toward Western models refusing defensive security work: bug fixes on security-related code, monitoring tools, ordinary defensive engineering, declined. So the same capability is simultaneously too dangerous to release, only fully measurable with the guardrails off, already awaited by people who want the guardrails off, and under-served for the legitimate uses. Every position in that sentence is held sincerely by someone.
The silicon nobody names
The GLM-5 technical report is 187 authors and a full infrastructure section. It names no training hardware.
- training tokens28.5 trillion
- corpus27 trillion tokens
- mid-training context4K โ 200K
- SFT sequence length202,752
- sparse-attention warm-up1000 steps ร 14 seqs ร 202,752
- sparse adaptation20B tokens
- optimizerMuon Split
- an approach that failedMLA with a 576-dim latent KV cache
- MTP layers3 shared ยท accept length 2.76
- authors187
- GPU typeโ not stated โ
- cluster sizeโ not stated โ
- GPU-hoursโ not stated โ
- Huawei Ascendinference
- Moore Threadsinference
- Hygoninference
- Cambriconinference
- Kunlunxininference
- MetaXinference
- Enflameinference
- recipe fields disclosed
- 10
- hardware fields disclosed
- 0 of 3
- platforms named
- 7
- named for training
- 0
A team of 187 people wrote a technical report with a full infrastructure section, disclosed the token count to a decimal place, disclosed the sequence lengths, the warm-up schedule, the optimizer, and even an approach that failed โ an MLA variant whose 576-dimension latent cache could not match grouped-query attention โ and then left three fields blank: what the model was trained on, how many of them there were, and for how long. Not hedged. Absent.
The report does name seven domestic platforms โ Huawei Ascend, Moore Threads, Hygon, Cambricon, Kunlunxin, MetaX, Enflame โ and every one of them appears in the inference section. None is named as training hardware. That is the concrete refutation of the claim circulating that GLM-5 was trained on Ascend: the report that would have said so has an entire page about domestic silicon and says something else. What the training silicon was remains unstated, and the absence is a fact about export controls, not about engineering.
No GPU type. No cluster size. No GPU-hour figure. The infrastructure section describes techniques and stays silent on what they ran on. A report at this scale would normally name the hardware, often with the total accelerator-hours beside it, because at this scale the number is a flex. Here it's a blank.
The report does name seven chip platforms, all domestic: Huawei Ascend, Moore Threads, Hygon, Cambricon, Kunlunxin, MetaX, and Enflame. Every one of them is named for inference. Deployment, not training.
This is the concrete refutation of a claim I have seen repeated confidently, that GLM-5 was trained on Ascend hardware. The report does not say so. The only place those chips appear is the serving path, and the training hardware is simply not disclosed. I can't tell you what they trained on, and neither can anyone else outside the company, which is the point of the figure: it draws a recipe with one field left out. An omission that specific, in a section that describes everything around it, is the one thing in this release that cannot be an oversight.
The surrounding context is not hard to reconstruct. Export controls make training hardware a politically loaded disclosure for a Chinese lab, in both directions: naming Western chips invites scrutiny of how they were obtained, and naming domestic chips invites scrutiny of whether they were sufficient. Silence is the only move that costs nothing. What the report does disclose is generous by comparison, 28.5 trillion training tokens from a 27-trillion-token corpus, a full optimizer story, and an honest account of an approach that failed. The one field left blank is the one with a government on either side of it.
The read
I've spent this notebook on a machine that did not change, and I should close by saying what I actually think about the thing that did.
As I write this, no independent measurement of GLM-5.3's capability exists. I want to be careful with that sentence, because the stronger version of it is false and the stronger version is what I wrote first.
Independent measurements do exist. They are all economic. A third-party agent evaluation ran GLM-5.3, got billed, and recorded the rate it paid: $1.68 per million tokens in, $5.28 out. Somebody's endpoint telemetry shows a 97.9 percent cache hit rate across 58 million tokens. LMArena has the model staged in its database as glm-5.3 (max), with a null rating, no votes, and a flag saying users cannot select it yet. The world has measured what GLM-5.3 costs and how it is plumbed. Nobody outside Z.ai has measured what it can do.
The baseline that does have outside numbers is GLM-5.2: an intelligence index of 53 against Fable 5's 62 at an eighth of the evaluation cost, and an LMArena rating of 1471 in text against 1585 in code, ranked 33rd and 9th on 27,000 and 8,000 votes. That split says something on its own. This family rates far higher at coding than at general conversation, which is what the product line is aimed at, and it's a more honest summary of the model than any row in the launch table.
The first-week impressions are mixed in an informative pattern. The complaints cluster on agentic reliability rather than raw capability: tool calling that fails and then repairs itself, models that wander off task and build things nobody asked for, a suspicion that the benchmark numbers are ahead of the experience. One heavy user running about a billion tokens a week gave the most useful review in the whole thread, which was "10/10 if it had vision." The bull case, from the same threads, is that it's "still shy of Sol and Fable, but only just by a hair." Both readings hold together if the gap is small and concentrated in reliability. My guess is that it is.
There's a structural incentive here, named plainly by people better placed than me to name it: for labs in this position, benchmark scores map to capital. That doesn't make any particular number false. It does mean the prior on a launch table should be set by who benefits, and this chapter has shown what happens when you check.
So here's my read, in three parts.
The architecture is genuinely good, and it is optimized for a regime nobody has measured. MLA plus DSA plus IndexShare compose into a twenty-fold reduction in per-token prefill cost at a million tokens, and the whole chain is real, reproducible, and confirmed against three independent implementations. But the crossover points where that story becomes true sit above 290,000 tokens, and the deepest public measurement of any GLM sparse-attention model is a quarter of a million tokens on a hobbyist's needle test. The headline feature of this model has never been evaluated at its headline setting, by anyone, ever. That's not a criticism of Z.ai specifically. It's a statement about how far the field's claims have outrun its instruments.
The post-training thesis is the most interesting claim in the release and the least checkable. If the bottleneck really has moved from the model to the environment, the competitive picture changes shape: the advantage goes to whoever can manufacture verifiable long-horizon work at volume, which is an engineering and data-acquisition problem rather than a research one. It also implies the frozen base model was the point of the design: you don't need a new architecture if what you're scaling is situations.
And the verification asymmetry is the durable lesson. A launch table is a rhetorical object. The load-bearing part is not the vendor's own row, which was disclosed here in more detail than most labs manage. It's the columns nobody audits, which turned out to contain another company's system card with a different model's name on the header. I did not expect the strongest finding in this research to be about Anthropic's numbers.
The wager
This notebook was written in the two days after launch, on purpose, before the weights land. That window makes something possible that explainers usually cannot do: state predictions in public, with dates, and be around to be wrong.
- 1The weights land on or about 2026-08-28.resolves 2026-09-11unresolved
- 2GLM-5.3 loads under the existing GlmMoeDsaForCausalLM with no engine PR.resolves on releaseunresolved
- 3The released config.json differs from GLM-5.2's in bookkeeping fields only.resolves on releaseunresolved
- 4No long-context benchmark ships with the weights.resolves on releaseunresolved
- 5The licence is MIT.resolves on releaseunresolved
- claims
- 5
- resolved so far
- 0
- stated with confidence
- 4
- stated as precedent only
- 1
Every card carries a date and a condition that would kill it, because a prediction you cannot lose is not a prediction. Flip any card to see what would refute it. The states read unresolved and will keep reading unresolved until something actually happens, which is the point: a figure that quietly goes stale is worse than one that admits it is waiting.
Card five is drawn weaker than the other four on purpose. The licence for GLM-5.3 is not stated anywhere โ not in the API documentation, not in the launch post, not in any listing. MIT is what Z.ai has used before, and precedent is a reason to expect something, not a reason to assert it. An earlier draft of this notebook hardened that expectation into a constant in a figure, which is exactly the failure the rest of this piece is about, so it is drawn here as what it is: the one guess on the board.
Each card in the figure has two faces. The front is the claim; turn it over and you get the single observation that would kill it, which is the only thing that makes a prediction worth publishing. The strip above the cards is a clock. Run it forward and each claim crosses its own date into a lane that says nothing stronger than past its date, still unanswered, because that is the only honest second state for a piece written in front of the thing it is predicting.
The weights land around 28 August 2026. Z.ai said roughly two weeks, pending safety evaluation. The prior releases in this line shipped weights on announcement day, so this is the first time the promise and the artifact have been separated, and a missed date would say something about which of the two the safety language describes.
They will load under the existing model class with no new engine code. This is the real test of the whole thesis, and it's binary. Fifteen independent implementations run the GLM-5.x line today, and every one of them tells the releases apart by config values alone. If "the same base model as GLM-5.2" is true, GLM-5.3 loads under the same class, with no pull request anywhere, and the serving stacks stay silent. A new model type, or any architectural pull request, refutes it outright. I think the claim holds, mostly because no engine has needed to prepare for anything.
The released config will differ from GLM-5.2's in bookkeeping fields only. Version strings, maybe a name. Anything touching layer counts, expert counts, the indexer pattern, or the rotary base falsifies the frozen-base story in a way no amount of prose can rescue.
No long-context benchmark will ship with the weights. Not RULER, not MRCR, not LongBench. Z.ai has now shipped two consecutive releases advertising a million-token window and has published no measurement at any length for either of them. I would very much like to be wrong about this one, and it's the prediction I'd bet on hardest.
The license will be MIT, and this is the card I am least sure of. Every prior GLM release used it. But no license has been stated for 5.3, precedent is not a fact, and this is the first model in the line its maker has held back on safety grounds. A use restriction on a model marketed for finding exploits would be defensible and would also be new for this family, and it would quietly change what "open weights" means here. Refuted by any license carrying a use-restriction clause, and settled only by the file itself.
The loop closes where it opened. A release whose entire content is post-training, on a machine whose every number I could check to the byte, announced with a table whose comparator columns came from somewhere else, evaluated on capabilities whose consequences run to bugs older than the people fixing them, and none of it downloadable. The most checkable thing about GLM-5.3 is the part that didn't change.
The weights answer the rest. Check back in two weeks.