spec(MODEL-MM-GLM53-FLASH): GLM-5.3-Flash is an architecture no oracle implements and no device here can hold (#1998) - #2001
Open
localai-bot wants to merge 3 commits into
Open
spec(MODEL-MM-GLM53-FLASH): GLM-5.3-Flash is an architecture no oracle implements and no device here can hold (#1998)#2001localai-bot wants to merge 3 commits into
localai-bot wants to merge 3 commits into
Conversation
…e implements and no device here can hold (#1998) `zai-org/GLM-5.3-Flash` was published 2026-08-26 and declares `Glm5NextForConditionalGeneration` / `model_type: glm5_next`. Nothing in this tree matched it. This lands the row's records and its spec; no product code. The name collides with work that is already blocked, and that misreading is the expensive one. `.agents/model-matrix.md` already carries a row labelled "GLM-5": `MODEL-TEXT-deepseek-v2-glm-moe-dsa-for-causal-lm`, `BLOCKED` at 753.9B, which is DeepSeek-V3.2 verbatim. `glm5_next` is a different model_type, a different parameter count, a different attention topology, and it has a vision tower. New row, not a revival. **vLLM implements nothing, at either end of the pin.** Read live 2026-08-26: `git grep "Glm5\|glm5_next"` returns zero hits at `555967922` and zero at `origin/main` = `c71f6f8a81`, whose `vllm/models/` package holds `common`, `deepseek_v32`, `deepseek_v4`, `dots3_note`, `inkling`, `kimi_k3` and `minimax_m3`. That is absence from vLLM `main`, not staleness in our pin, so advancing the pin — 348 commits of reconciliation — reaches nothing here. What exists upstream is vllm#53906, opened the same day, open and `mergeable: false`, and an unmerged pull request is not a revision. It is inadmissible as an oracle and is cited in the spec only as evidence of upstream shape. SGLang is the same picture with one trap worth recording: its GLM-5.3-Flash *cookbook* merged while its implementation PR stayed open, so the model card links a recipe SGLang `main` cannot run. llama.cpp has no `glm5_next` either. So the only admissible oracle is transformers, and the release is bounded rather than assumed: `modeling_glm5_next.py` is HTTP 200 at `v5.16.1` and 404 at `v5.16.0` and `v5.15.1`, making 5.16.1 the first release carrying the architecture. The `MODEL-MM-QWEN4-EXP` lane pins 5.16.0 and this one pins 5.16.1, one day apart, because `Qwen4Exp` merged before the 5.16.0 cut and `Glm5Next` after it. Two lanes, two releases, which is what a lane pin is for. Most of the model is already here, and the survey moved three conclusions. **Two of the three obvious reuses are wrong in one place each, in ways a token gate cannot see.** The KDA forget gate branches on `safe_gate_lower_bound`; the checkpoint sets `gate_lower_bound: -5.0`, so it takes the bounded branch, `-5.0 * sigmoid(exp(A_log) * (f_b(f_a(x)) + dt_bias))`, where our `kimi_kda.cpp` implements Kimi-Linear's `-exp(A_log) * softplus(g + dt_bias)`. Different functions of the same inputs, both smooth, both negative, both fluent, and the sign of `decay_rate` differs too. And the mHC head collapse is `hidden_streams.mean(dim=2)`, an unweighted mean whose own docstring says "Unlike DeepSeek-V4", where our `HcHeadCollapse` is the V4 weighted-gated collapse — the checkpoint carries no `hc_head.*` tensors at all, which settles it. Both get a red-first wave test whose failure against the wrong reuse is the deliverable. **The text stack has no rotary embedding anywhere**, which is easy to get wrong in the other direction. `qk_rope_head_dim: 0`, `mla_use_nope: true`, no `rope_theta`, no `rope_scaling`; the reference deletes the inherited `rope_parameters` field and passes `position_embeddings=None` to every layer. `indexer_rope_interleave: true` is a vestigial flag the indexer override ignores, so implementing it because the config names one is implementing a bug. Position comes only from the KDA decay and the short convs. NoPE does buy one thing: MLA weight absorption becomes trivially valid, since there is no rope slice to keep out of it. It also blocks: `MlaBlockDims::Validate` refuses `qk_rope_head_dim == 0` today, and Kimi-Linear is not the same case — it sets `mla_use_nope` while keeping `qk_rope_head_dim: 64`, so the rope slice still occupies the cache row. **The k-pool indexer is unobservable at or below 2048 tokens.** With `index_topk: 2048` a shorter context selects every candidate, the selection is the identity, the pooling is invisible, and any short-prompt gate passes over a broken indexer. That is now a stated requirement in `## Gates` rather than a note. The pooling itself is learned and per channel — 128 independent 4-way softmaxes over a learned `[4,128]` intra-pool position embedding, pools aligned to the first valid token so the grid is batch-dependent, expanded back to raw indices and widened to 2051 by an unscored ragged tail. **Nothing fits, and no GGUF exists.** Measured by HTTP RANGE over all 62 safetensors headers, payload never fetched: 76,108 tensors, 321,322,735,872 real parameters, routed experts 311.65B = 97.0%. Against ~119.63 GiB on GB10 the published FP8 is 305.78 GiB, BF16 598.53, and the smallest, an NVFP4 requant, is 181.32 — 1.52x over. All four repositories named `*-GGUF` contain zero `.gguf` files. `gateable = no` on memory, and the consequence is the scoping result: no oracle can execute this model on any device this project reaches, so no end-to-end token gate exists or can exist here. That is recorded as visible debt rather than waived, and what replaces it is a tiny-shape CPU reference oracle instantiated from the pinned transformers — a real oracle for the numerics, and explicitly not oracle gateability for the model. The developer set the W7 target as a low GGUF quant that fits the DGX. The arithmetic, with experts at the named type and the other 3% at Q6_K and bits per weight taken from our own reader's block traits: Q8_0 318.0 GiB, Q6_K 245.5, Q4_K 170.6, IQ3_XXS 118.1 which leaves ~1.5 GiB and is not a margin, Q2_K 102.6 with ~17 GiB left, IQ2_XXS 82.3. Q2_K is the recommendation and the reason is producibility, not quality: i-quants need an importance matrix, an importance matrix needs a forward pass, a forward pass needs 181 GiB, and the dependency is circular on this fleet. K-quants need none. Since llama.cpp has no `glm5_next` the converter is ours to author, with no reference GGUF to diff against and no llama.cpp floor for the arm. The `MODEL` row ratchet moves 378 -> 379 with its justification appended in the existing log format, re-derived off the matrix rather than carried forward. One row and not three, which is the arithmetic the new test exists to hold: the open vllm#53906 would register `Glm5NextForCausalLM`, `Glm5NextForConditionalGeneration` and `Glm5NextMTPModel`, so the IndexTTS-2.5 and dots3-note two-row shape is the tempting read and it does not apply. None of the three is registered at any vLLM revision, and the only architecture a published artifact declares is `Glm5NextForConditionalGeneration`; the MTP head is `layers.45` inside the same checkpoint, which the transformers reference discards outright. The at-the-pin static invariants (324/373/356/310/261) are unchanged, because the Upstream cell carries no pinned module/class target. Two anchors in `engine-matrix.md` are repaired in the same change. Inserting the new test into `tests/scripts/test_agent_record.py` shifted `ENG-RECORD-ANCHOR-RATCHET`'s two citations of that same file by 45 lines — the rot that row exists to measure, produced by an edit to the very file it cites. Rot goes 39 -> 37. Evidence. `check-agent-record.py` OK at ENGINE=173 MODEL=379 QUANT=84 KERNEL=58 BACKEND=87 ANCHOR-ROT=37; `check-model-checklist.py` OK; `tests/scripts/test_agent_record.py` 124 passed. The new test was mutation-proved three ways, each restored byte-for-byte and re-verified green: renaming the row reds it, adding a `-for-causal-lm` sibling to "match" the upstream PR reds it, and leaving the ratchet at 378 reds it. The third mutation initially read as a false red after restore because `scripts/__pycache__` still held the mutant's bytecode; it was re-run with the caches cleared on both sides. Scoping only. No product code lands under this pull request, and the eight implementation waves are dispatchable from the committed spec — W0 to W2 and W4 CPU-gateable, W3 and W5 to W8 needing a GPU, W8 unscheduled because there is no denominator. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Claude:claude-fable-5 [Claude Code]
`.agents/issue-index.md` conflicted. It was resolved by taking `origin/main`'s file whole and re-appending this branch's single added row (#1998) at the end, rather than accepting the automatic three-way merge git offered. AGENTS.md requires exactly that for a keyed record: take the complete target-branch version, apply the scoped edit again, and verify unrelated keys are byte-for-byte equal. A clean automerge of this file is the failure mode, not the success case, because it has previously duplicated a row and silently dropped a tail row. Verified after the resolution: 730 rows on `origin/main` plus this branch's one row is 731; no duplicate row key; the added row is last. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Claude:claude-fable-5 [Claude Code]
`origin/main` moved again while this branch's CI ran, and GitHub reported a conflict that does not exist locally: `.gitattributes` sets `.agents/issue-index.md merge=union` and the forge ignores that driver, so two branches appending to the same append-only file read as conflicting. This is the second re-merge this branch has needed for the same reason, and the cost is a full CI re-run each time, because CI builds the merge commit rather than the pull request head. `.agents/issue-index.md` was resolved by taking `origin/main`'s file whole and re-appending this branch's single row (#1998), derived from the diff rather than from the file's tail. The automatic three-way merge was discarded unread: a clean automerge of a keyed record is the failure mode here, not the success case. Verified after the resolution: 743 rows on `origin/main` plus this branch's one is 744; no duplicate row key; the added row is last. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Claude:claude-fable-5 [Claude Code]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
zai-org/GLM-5.3-Flashwas published 2026-08-26 and declaresGlm5NextForConditionalGeneration/model_type: glm5_next. Nothing in thistree matched it. This lands the row's records and its spec; no product code.
The name collides with work that is already blocked, and that misreading is the
expensive one.
.agents/model-matrix.mdalready carries a row labelled "GLM-5":MODEL-TEXT-deepseek-v2-glm-moe-dsa-for-causal-lm,BLOCKEDat 753.9B, which isDeepSeek-V3.2 verbatim.
glm5_nextis a different model_type, a differentparameter count, a different attention topology, and it has a vision tower. New
row, not a revival.
vLLM implements nothing, at either end of the pin. Read live 2026-08-26:
git grep "Glm5\|glm5_next"returns zero hits at555967922and zero atorigin/main=c71f6f8a81, whosevllm/models/package holdscommon,deepseek_v32,deepseek_v4,dots3_note,inkling,kimi_k3andminimax_m3. That is absence from vLLMmain, not staleness in our pin, soadvancing the pin — 348 commits of reconciliation — reaches nothing here. What
exists upstream is vllm#53906, opened the same day, open and
mergeable: false,and an unmerged pull request is not a revision. It is inadmissible as an oracle
and is cited in the spec only as evidence of upstream shape. SGLang is the same
picture with one trap worth recording: its GLM-5.3-Flash cookbook merged while
its implementation PR stayed open, so the model card links a recipe SGLang
maincannot run. llama.cpp has noglm5_nexteither.So the only admissible oracle is transformers, and the release is bounded rather
than assumed:
modeling_glm5_next.pyis HTTP 200 atv5.16.1and 404 atv5.16.0andv5.15.1, making 5.16.1 the first release carrying thearchitecture. The
MODEL-MM-QWEN4-EXPlane pins 5.16.0 and this one pins5.16.1, one day apart, because
Qwen4Expmerged before the 5.16.0 cut andGlm5Nextafter it. Two lanes, two releases, which is what a lane pin is for.Most of the model is already here, and the survey moved three conclusions.
Two of the three obvious reuses are wrong in one place each, in ways a token
gate cannot see. The KDA forget gate branches on
safe_gate_lower_bound; thecheckpoint sets
gate_lower_bound: -5.0, so it takes the bounded branch,-5.0 * sigmoid(exp(A_log) * (f_b(f_a(x)) + dt_bias)), where ourkimi_kda.cppimplements Kimi-Linear's
-exp(A_log) * softplus(g + dt_bias). Differentfunctions of the same inputs, both smooth, both negative, both fluent, and the
sign of
decay_ratediffers too. And the mHC head collapse ishidden_streams.mean(dim=2), an unweighted mean whose own docstring says"Unlike DeepSeek-V4", where our
HcHeadCollapseis the V4 weighted-gatedcollapse — the checkpoint carries no
hc_head.*tensors at all, which settlesit. Both get a red-first wave test whose failure against the wrong reuse is the
deliverable.
The text stack has no rotary embedding anywhere, which is easy to get wrong
in the other direction.
qk_rope_head_dim: 0,mla_use_nope: true, norope_theta, norope_scaling; the reference deletes the inheritedrope_parametersfield and passesposition_embeddings=Noneto every layer.indexer_rope_interleave: trueis a vestigial flag the indexer overrideignores, so implementing it because the config names one is implementing a bug.
Position comes only from the KDA decay and the short convs. NoPE does buy one
thing: MLA weight absorption becomes trivially valid, since there is no rope
slice to keep out of it. It also blocks:
MlaBlockDims::Validaterefusesqk_rope_head_dim == 0today, and Kimi-Linear is not the same case — it setsmla_use_nopewhile keepingqk_rope_head_dim: 64, so the rope slice stilloccupies the cache row.
The k-pool indexer is unobservable at or below 2048 tokens. With
index_topk: 2048a shorter context selects every candidate, the selection isthe identity, the pooling is invisible, and any short-prompt gate passes over a
broken indexer. That is now a stated requirement in
## Gatesrather than anote. The pooling itself is learned and per channel — 128 independent 4-way
softmaxes over a learned
[4,128]intra-pool position embedding, pools alignedto the first valid token so the grid is batch-dependent, expanded back to raw
indices and widened to 2051 by an unscored ragged tail.
Nothing fits, and no GGUF exists. Measured by HTTP RANGE over all 62
safetensors headers, payload never fetched: 76,108 tensors, 321,322,735,872 real
parameters, routed experts 311.65B = 97.0%. Against ~119.63 GiB on GB10 the
published FP8 is 305.78 GiB, BF16 598.53, and the smallest, an NVFP4 requant, is
181.32 — 1.52x over. All four repositories named
*-GGUFcontain zero.gguffiles.
gateable = noon memory, and the consequence is the scoping result: nooracle can execute this model on any device this project reaches, so no
end-to-end token gate exists or can exist here. That is recorded as visible debt
rather than waived, and what replaces it is a tiny-shape CPU reference oracle
instantiated from the pinned transformers — a real oracle for the numerics, and
explicitly not oracle gateability for the model.
The developer set the W7 target as a low GGUF quant that fits the DGX. The
arithmetic, with experts at the named type and the other 3% at Q6_K and bits per
weight taken from our own reader's block traits: Q8_0 318.0 GiB, Q6_K 245.5,
Q4_K 170.6, IQ3_XXS 118.1 which leaves ~1.5 GiB and is not a margin, Q2_K 102.6
with ~17 GiB left, IQ2_XXS 82.3. Q2_K is the recommendation and the reason is
producibility, not quality: i-quants need an importance matrix, an importance
matrix needs a forward pass, a forward pass needs 181 GiB, and the dependency is
circular on this fleet. K-quants need none. Since llama.cpp has no
glm5_nextthe converter is ours to author, with no reference GGUF to diff against and no
llama.cpp floor for the arm.
The
MODELrow ratchet moves 378 -> 379 with its justification appended in theexisting log format, re-derived off the matrix rather than carried forward. One
row and not three, which is the arithmetic the new test exists to hold: the open
vllm#53906 would register
Glm5NextForCausalLM,Glm5NextForConditionalGenerationandGlm5NextMTPModel, so the IndexTTS-2.5and dots3-note two-row shape is the tempting read and it does not apply. None of
the three is registered at any vLLM revision, and the only architecture a
published artifact declares is
Glm5NextForConditionalGeneration; the MTP headis
layers.45inside the same checkpoint, which the transformers referencediscards outright. The at-the-pin static invariants (324/373/356/310/261) are
unchanged, because the Upstream cell carries no pinned module/class target.
Two anchors in
engine-matrix.mdare repaired in the same change. Inserting thenew test into
tests/scripts/test_agent_record.pyshiftedENG-RECORD-ANCHOR-RATCHET's two citations of that same file by 45 lines — therot that row exists to measure, produced by an edit to the very file it cites.
Rot goes 39 -> 37.
Evidence.
check-agent-record.pyOK at ENGINE=173 MODEL=379 QUANT=84 KERNEL=58BACKEND=87 ANCHOR-ROT=37;
check-model-checklist.pyOK;tests/scripts/test_agent_record.py124 passed. The new test was mutation-provedthree ways, each restored byte-for-byte and re-verified green: renaming the row
reds it, adding a
-for-causal-lmsibling to "match" the upstream PR reds it,and leaving the ratchet at 378 reds it. The third mutation initially read as a
false red after restore because
scripts/__pycache__still held the mutant'sbytecode; it was re-run with the caches cleared on both sides.
Scoping only. No product code lands under this pull request, and the eight
implementation waves are dispatchable from the committed spec — W0 to W2 and W4
CPU-gateable, W3 and W5 to W8 needing a GPU, W8 unscheduled because there is no
denominator.
FOLLOWING_AGENTS_PROTOCOL
Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: Claude:claude-fable-5 [Claude Code]