koboldcpp/conversion
DevVexus 9a7570587c
convert : write explicit recurrent_layers for Qwen3-Next / Qwen3.5 (#28208)
Problem
- Loader prefers `<arch>.attention.recurrent_layers`, falls back to `full_attention_interval` if missing
- Converter only ever writes the interval. gguf-py has no constant/writer for the array
- Interval can only describe evenly spaced full-attention layers. Any non-uniform `layer_types` gets reconstructed wrong
- No error, no warning. Model loads, runs, wrong layers get wrong ops. Full-attn layers marked recurrent lose their KV cache
- Every published Qwen3.5 checkpoint is uniform so nobody's hit it yet

Repro
12 layers, periods 4/3/5:

    layer:  0 1 2 3 4 5 6 7 8 9 10 11
    actual: L L L F L L F L L L  L  F
    loader: L L L F L L L F L L  L  F
                        ^ ^

Layer 6 is full attn, loaded as recurrent. Layer 7 the reverse.
52-layer non-uniform stack: 15/52 mis-typed.

Fix
- `constants.py`: add `Keys.Attention.RECURRENT_LAYERS` (name already registered in llama-arch.cpp)
- `gguf_writer.py`: add `add_recurrent_layers()`, same shape as `add_rope_pattern()`
- `conversion/qwen.py`: emit array from `layer_types` in `Qwen3NextModel.set_gguf_parameters` (covers 3-Next, 3.5, 3.5-MoE)

Notes
- Array is padded with `false` for MTP blocks. `get_key_or_arr` checks length against `n_layer_all`, which includes MTP. Matches the fallback's `i < n_layer()` guard
- Interval is still written. Old builds only understand the interval
- `layer_types` length != `num_hidden_layers` now raises in converter instead of producing a GGUF that fails at load

Tested
- End-to-end on a 62-layer non-uniform Qwen3.8-27B (2 linear layers removed). Loader reads the array, 62 blocks, 0 mismatches. Without fix: interval fallback, mis-typed
- MTP padding NOT tested on a real MTP model. Reasoned from qwen35.cpp + get_key_or_arr. Would appreciate a check

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 10:12:50 +03:00
..
__init__.py [Model] Support for Spark2_5ForCausalLM implementation (#27868) 2026-09-06 17:43:58 +02:00
afmoe.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
arctic.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
baichuan.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
bailingmoe.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
bailingmoe3.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
base.py convert : add --fuse-qkv flag to fuse Q/K/V into QKV during HF-to-GGUF conversion (#22780) 2026-09-07 00:47:05 +08:00
bert.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
bitnet.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
bloom.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
chameleon.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
chatglm.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
codeshell.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
cogvlm.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
command_r.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
dbrx.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
deci.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
deepseek.py convert : skip bias_vl tensor in DeepSeek-V4 DSpark conversion (#28294) 2026-09-03 10:37:23 +03:00
dots1.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
dots3.py mtmd: support dots3-note vision+audio (#27524) 2026-08-22 10:35:50 +02:00
dotsocr.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
dream.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
ernie.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
exaone.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
falcon.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
falcon_h1.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
gemma.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
glm.py convert: fix GLM regression in index_tensors (#27655) 2026-08-24 13:21:00 +03:00
gpt2.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
gpt_oss.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
gptneox.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
granite.py model : GraniteSWAForCausalLM / GraniteMoeSWAForCausalLM (#25505) 2026-08-19 16:53:31 +02:00
grok.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
grovemoe.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
hunyuan.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
hy_v4.py model : add Tencent Hy 4 (hy_v4) preview architecture support (#28127) 2026-09-04 14:31:36 +02:00
internlm.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
internvl.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
jais.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
jamba.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
januspro.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
kimi_k3.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
kimi_linear.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
kimivl.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
laguna.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
lfm2.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
lighton_ocr.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
llada.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
llama.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
llama4.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
llava.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
maincoder.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
mamba.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
mellum.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
mimo.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
minicpm.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
minimax.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
mistral.py convert : fix conversion for Mistral-Medium-3.5-128B (#24268) 2026-06-07 21:41:39 +02:00
mistral3.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
mpt.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
muse_glimmer.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
nanbeige.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
nemotron.py model: add NVIDIA Nemotron-3-Puzzle-75B-A9B (NemotronHPuzzle) support (#25444) 2026-09-03 08:53:08 +02:00
olmo.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
openelm.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
orion.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
pangu.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
phi.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
pixtral.py Refactor: convert_hf_to_gguf.py (#17114) 2026-05-15 15:18:12 +02:00
plamo.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
plm.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
pockettts.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
qwen.py convert : write explicit recurrent_layers for Qwen3-Next / Qwen3.5 (#28208) 2026-09-07 10:12:50 +03:00
qwen3tts.py mtmd: Fix Qwen3-tts-0.6b (#28231) 2026-09-02 12:46:16 +02:00
qwen3vl.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
qwen4exp.py model: add Qwen3.8-Flash-Next (qwen4exp) (#27742) 2026-08-27 21:32:31 +02:00
qwenvl.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
refact.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
rwkv.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
sarashina2.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
smallthinker.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
smolvlm.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
spark2_5.py [Model] Support for Spark2_5ForCausalLM implementation (#27868) 2026-09-06 17:43:58 +02:00
stablelm.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
starcoder.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
step3.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
t5.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
talkie.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
ultravox.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
wavtokenizer.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
xverse.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00
youtuvl.py convert: add @ModelBase.example (#27208) 2026-08-17 10:15:11 +02:00