Skip to content

Commit 37c46b4

Browse files
committed
Add validation for GGUF per-layer array lengths
Address PR review comments: - Validate sliding_window_pattern length matches num_hidden_layers - Validate head_count_kv array length matches sliding_window_pattern - Add layer_types length check in Gemma4TextDecoderLayer.__init__ Clear ValueError messages on malformed GGUF metadata instead of cryptic IndexError at runtime. Signed-off-by: Justin Chu <justinchu@microsoft.com>
1 parent f2fa769 commit 37c46b4

2 files changed

Lines changed: 20 additions & 0 deletions

File tree

src/mobius/integrations/gguf/_config_mapping.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,13 @@ def _gemma4_postprocess(
402402
sliding_pattern = metadata.get(f"{arch}.attention.sliding_window_pattern")
403403
layer_types: list[str] | None = None
404404
if sliding_pattern is not None:
405+
if len(sliding_pattern) != config.num_hidden_layers:
406+
raise ValueError(
407+
f"GGUF metadata length mismatch: "
408+
f"attention.sliding_window_pattern has "
409+
f"{len(sliding_pattern)} entries but "
410+
f"num_hidden_layers is {config.num_hidden_layers}."
411+
)
405412
layer_types = [
406413
"sliding_attention" if is_sliding else "full_attention"
407414
for is_sliding in sliding_pattern
@@ -430,6 +437,14 @@ def _gemma4_postprocess(
430437
num_global_key_value_heads: int | None = None
431438
raw_kv_heads = metadata.get(f"{arch}.attention.head_count_kv")
432439
if isinstance(raw_kv_heads, (list, np.ndarray)) and sliding_pattern is not None:
440+
if len(raw_kv_heads) != len(sliding_pattern):
441+
raise ValueError(
442+
f"GGUF metadata length mismatch: "
443+
f"attention.head_count_kv has {len(raw_kv_heads)} entries "
444+
f"but attention.sliding_window_pattern has "
445+
f"{len(sliding_pattern)} entries. "
446+
f"Both must equal num_hidden_layers."
447+
)
433448
full_kv_heads = {
434449
int(raw_kv_heads[i])
435450
for i, is_sliding in enumerate(sliding_pattern)

src/mobius/models/gemma4.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,11 @@ class Gemma4DecoderLayer(nn.Module):
925925
def __init__(self, config: Gemma4Config, layer_idx: int):
926926
super().__init__()
927927
layer_types = config.layer_types or ["sliding_attention"] * config.num_hidden_layers
928+
if len(layer_types) != config.num_hidden_layers:
929+
raise ValueError(
930+
f"Gemma4Config.layer_types length ({len(layer_types)}) "
931+
f"must match num_hidden_layers ({config.num_hidden_layers})"
932+
)
928933
first_kv_shared = config.num_hidden_layers - config.num_kv_shared_layers
929934
layer_type = layer_types[layer_idx]
930935
is_full = layer_type == "full_attention"

0 commit comments

Comments
 (0)