From 22ea8d8d3d67f56e919706d45226c2ab5503dce1 Mon Sep 17 00:00:00 2001 From: Csaba Kecskemeti Date: Wed, 17 Jun 2026 20:16:47 -0700 Subject: [PATCH 1/3] llama-quant : fix FFN layer bounds crash for models with nextn/MTP blocks Models like GLM-5.2 (glm-dsa arch) and BailingMoE2 have nextn/MTP prediction blocks appended after the main transformer layers. These extra blocks share the same blk.%d.ffn_*_exps tensor naming convention and are present in the GGUF file, but n_layer() excludes them: n_layer() = n_layer_all - n_layer_nextn For GLM-5.2: block_count=79, nextn_predict_layers=1, so n_layer()=78. The MoE path in layer_info() parses the block index from the tensor name via sscanf. When it hits blk.78.ffn_down_exps.weight it gets i_layer=78, which fails the check i_layer >= n_layer(78) with: "Bad layer 78 for tensor blk.78.ffn_down_exps.weight. Must be in [0, 78)" Fix: use n_layer_all (79) instead of n_layer() (78) when initializing the FFN layer counters, so nextn block tensors are within valid range. Regressed in #24060 (2026-06-05) which changed hparams.n_layer from a raw field equal to n_layer_all into n_layer() = n_layer_all - n_layer_nextn. Quantizations of GLM-5.2 made before that commit were unaffected because the old hparams.n_layer was 79 (= n_layer_all). Assisted-by: Claude Sonnet --- src/llama-quant.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/llama-quant.cpp b/src/llama-quant.cpp index cf92ce4bb8b7..9f0967f96d1d 100644 --- a/src/llama-quant.cpp +++ b/src/llama-quant.cpp @@ -847,7 +847,11 @@ static void init_quantize_state_counters(quantize_state_impl & qs, std::vector Date: Wed, 17 Jun 2026 21:12:41 -0700 Subject: [PATCH 2/3] glm-dsa : fix missing indexer tensors on sparse-indexer blocks GLM-5.2 only has DSA lightning indexer tensors on a subset of blocks: the 3 dense-lead blocks (0-2) and every 4th MoE block (6, 10, 14, ..., 78). The remaining MoE blocks have no indexer tensors at all. glm-dsa.cpp required them on every block, so loading failed with: "missing tensor 'blk.3.indexer.k_norm.weight'" Two changes: - glm-dsa.cpp: mark all 5 indexer tensor creates as TENSOR_NOT_REQUIRED - deepseek32.cpp: guard the lightning indexer block with a null check on indexer_attn_q_b; when absent, top_k stays nullptr and build_attn_mla falls back to full attention for that layer Regressed in #23346 (2026-05-29) which wired the DSA lightning indexer into the shared deepseek2 graph used by GLM_DSA. Before that PR the indexer tensors were loaded but never accessed in the graph. Assisted-by: Claude Sonnet --- src/models/deepseek32.cpp | 4 ++-- src/models/glm-dsa.cpp | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/models/deepseek32.cpp b/src/models/deepseek32.cpp index 9a20e2ce9077..8a5b8074d148 100644 --- a/src/models/deepseek32.cpp +++ b/src/models/deepseek32.cpp @@ -219,8 +219,8 @@ llama_model_deepseek32::graph::graph(const llama_model & model, const llm_graph_ ggml_tensor * top_k = nullptr; - // lightning indexer - { + // lightning indexer - skipped when tensors are absent (e.g. GLM-5.2 only has them on certain blocks) + if (model.layers[il].indexer_attn_q_b) { ggml_tensor * indexer_q = ggml_mul_mat(ctx0, model.layers[il].indexer_attn_q_b, qr); cb(indexer_q, "indexer_q", il); diff --git a/src/models/glm-dsa.cpp b/src/models/glm-dsa.cpp index 11d91312defc..dd70f5374387 100644 --- a/src/models/glm-dsa.cpp +++ b/src/models/glm-dsa.cpp @@ -100,12 +100,13 @@ void llama_model_glm_dsa::load_arch_tensors(llama_model_loader &) { layer.ffn_norm = create_tensor(tn(LLM_TENSOR_FFN_NORM, "weight", i), {n_embd}, flags); - // DSA indexer - layer.indexer_k_norm = create_tensor(tn(LLM_TENSOR_INDEXER_K_NORM, "weight", i), {hparams.indexer_head_size}, flags); - layer.indexer_k_norm_b = create_tensor(tn(LLM_TENSOR_INDEXER_K_NORM, "bias", i), {hparams.indexer_head_size}, flags); - layer.indexer_proj = create_tensor(tn(LLM_TENSOR_INDEXER_PROJ, "weight", i), {n_embd, hparams.indexer_n_head}, flags); - layer.indexer_attn_k = create_tensor(tn(LLM_TENSOR_INDEXER_ATTN_K, "weight", i), {n_embd, hparams.indexer_head_size}, flags); - layer.indexer_attn_q_b = create_tensor(tn(LLM_TENSOR_INDEXER_ATTN_Q_B, "weight", i), {q_lora_rank, hparams.indexer_n_head * hparams.indexer_head_size}, flags); + // DSA indexer - only present on a subset of blocks (dense-lead blocks + every 4th MoE block), + // so mark all as TENSOR_NOT_REQUIRED; the graph skips the indexer path when these are null. + layer.indexer_k_norm = create_tensor(tn(LLM_TENSOR_INDEXER_K_NORM, "weight", i), {hparams.indexer_head_size}, flags | TENSOR_NOT_REQUIRED); + layer.indexer_k_norm_b = create_tensor(tn(LLM_TENSOR_INDEXER_K_NORM, "bias", i), {hparams.indexer_head_size}, flags | TENSOR_NOT_REQUIRED); + layer.indexer_proj = create_tensor(tn(LLM_TENSOR_INDEXER_PROJ, "weight", i), {n_embd, hparams.indexer_n_head}, flags | TENSOR_NOT_REQUIRED); + layer.indexer_attn_k = create_tensor(tn(LLM_TENSOR_INDEXER_ATTN_K, "weight", i), {n_embd, hparams.indexer_head_size}, flags | TENSOR_NOT_REQUIRED); + layer.indexer_attn_q_b = create_tensor(tn(LLM_TENSOR_INDEXER_ATTN_Q_B, "weight", i), {q_lora_rank, hparams.indexer_n_head * hparams.indexer_head_size}, flags | TENSOR_NOT_REQUIRED); if (i < (int) hparams.n_layer_dense_lead) { layer.ffn_gate = create_tensor(tn(LLM_TENSOR_FFN_GATE, "weight", i), {n_embd, n_ff}, flags); layer.ffn_down = create_tensor(tn(LLM_TENSOR_FFN_DOWN, "weight", i), { n_ff, n_embd}, flags); From 40e9bb43fc5f008793e77d71d4b56d704f41f343 Mon Sep 17 00:00:00 2001 From: Csaba Kecskemeti Date: Thu, 18 Jun 2026 15:10:29 -0700 Subject: [PATCH 3/3] convert : bump transformers requirement to >=5.0.0 GLM-5.2 (and other recent models) reference TokenizersBackend in their tokenizer_config.json. This class was introduced in transformers 5.0 and does not exist in 4.x, causing AutoTokenizer.from_pretrained() to abort with "TokenizersBackend does not exist" during GGUF conversion. The previous pin (==4.57.6) prevented installation of 5.x even when explicitly requested. Relaxing to >=5.0.0 lets users install the version required by their model without needing a manual override. Co-Authored-By: Claude Sonnet 4.6 --- requirements/requirements-convert_legacy_llama.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/requirements/requirements-convert_legacy_llama.txt b/requirements/requirements-convert_legacy_llama.txt index 28221fad0ce9..1f46a105b0f9 100644 --- a/requirements/requirements-convert_legacy_llama.txt +++ b/requirements/requirements-convert_legacy_llama.txt @@ -1,7 +1,9 @@ numpy~=1.26.4 sentencepiece>=0.1.98,<0.3.0 -transformers==4.57.6 +# GLM-5.2 and other recent models require transformers 5.x; the TokenizersBackend class +# referenced in their tokenizer_config.json does not exist in 4.x +transformers>=5.0.0 gguf>=0.1.0 protobuf>=4.21.0,<5.0.0