From e0750da25a737c07c5c0f1724875846ff1c1421e Mon Sep 17 00:00:00 2001 From: qxZap Date: Tue, 25 Aug 2026 22:34:33 +0300 Subject: [PATCH] fix(gemma4-gguf): accept scalar attention.head_count_kv llama.cpp writes gemma4.attention.head_count_kv as a SCALAR when every layer shares a KV head count, and only as a per-layer array when they differ. The parser assumed the array form unconditionally, so any such checkpoint died at config-parse time: swa_kv = int(kv_per_layer[swa_layer_ids[0]]) ... TypeError: 'int' object is not subscriptable Reproduced with lmstudio-community/gemma-4-E2B-it-GGUF, whose metadata carries head_count_kv=1 (scalar) alongside a genuine 35-element sliding_window_pattern. Normalise to a per-layer list at the read site so both call sites below are unchanged. Note this fixes the crash, not dense gemma-4 support: parse_gguf_config still hardcodes moe_enabled=True and requires expert_count / expert_used_count / expert_feed_forward_length, which dense checkpoints do not carry. Co-Authored-By: Claude Opus 5 (1M context) --- python/freetoken/models/gemma4/gguf.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python/freetoken/models/gemma4/gguf.py b/python/freetoken/models/gemma4/gguf.py index 437822b5..2cdd5e10 100644 --- a/python/freetoken/models/gemma4/gguf.py +++ b/python/freetoken/models/gemma4/gguf.py @@ -60,7 +60,10 @@ def g(key: str): num_layers = int(g("block_count")) hidden = int(g("embedding_length")) num_qo_heads = int(g("attention.head_count")) - kv_per_layer = g("attention.head_count_kv") # per-layer list + # llama.cpp writes head_count_kv as a SCALAR when every layer shares a KV head + # count, and only as a per-layer array when they differ (e.g. gemma-4-E2B: 1). + _kv = g("attention.head_count_kv") + kv_per_layer = [int(x) for x in _kv] if hasattr(_kv, "__len__") else [int(_kv)] * num_layers # True -> sliding-window (SWA) layer, False -> full attention. swa_pattern = [bool(x) for x in g("attention.sliding_window_pattern")] assert len(swa_pattern) == num_layers, "sliding_window_pattern length != block_count"