@@ -98,7 +98,14 @@ def _infer_attn_pattern(layer_types: list[str]) -> tuple[int, int] | list[str]:
9898 return (len (layer_types ), 0 )
9999
100100
101- def _attention_config_value (hf_config : Any , layer_type : str , field_name : str , default : Any ) -> Any :
101+ def _attention_config_value (
102+ hf_config : Any ,
103+ layer_type : str ,
104+ field_name : str ,
105+ default : Any ,
106+ * ,
107+ legacy_field_name : str | None = None ,
108+ ) -> Any :
102109 """Read an attention field from a concrete HF layer config when available."""
103110 layer_types = getattr (hf_config , "layer_types" , None )
104111 per_layer_config = getattr (hf_config , "per_layer_config" , None )
@@ -110,9 +117,10 @@ def _attention_config_value(hf_config: Any, layer_type: str, field_name: str, de
110117 else :
111118 return getattr (per_layer_config [layer_index ], field_name , default )
112119
113- # Transformers 5.15 rejects direct reads of fields that vary by layer. The
114- # global value is still the correct fallback for the local-attention config.
115- return getattr (hf_config , "__dict__" , {}).get (field_name , default )
120+ # Transformers 5.15 rejects direct reads of fields that vary by layer.
121+ # Older configs instead serialize separate flat local/global field names.
122+ fallback_name = legacy_field_name or field_name
123+ return getattr (hf_config , "__dict__" , {}).get (fallback_name , default )
116124
117125
118126def _layer_types_from_provider (provider : Gemma4ModelProvider | Gemma4DenseProvider ) -> list [str ]:
@@ -245,7 +253,8 @@ def _build_dense_provider(self, hf_config) -> Gemma4DenseProvider:
245253 hf_config ,
246254 "full_attention" ,
247255 "num_key_value_heads" ,
248- getattr (hf_config , "num_global_key_value_heads" , num_query_groups ),
256+ num_query_groups ,
257+ legacy_field_name = "num_global_key_value_heads" ,
249258 )
250259
251260 self ._dense_num_attention_heads = num_attention_heads
@@ -265,7 +274,13 @@ def _build_dense_provider(self, hf_config) -> Gemma4DenseProvider:
265274 num_attention_heads = num_attention_heads ,
266275 num_query_groups = num_query_groups ,
267276 kv_channels = _attention_config_value (hf_config , "sliding_attention" , "head_dim" , 256 ),
268- global_kv_channels = _attention_config_value (hf_config , "full_attention" , "head_dim" , 512 ),
277+ global_kv_channels = _attention_config_value (
278+ hf_config ,
279+ "full_attention" ,
280+ "head_dim" ,
281+ 512 ,
282+ legacy_field_name = "global_head_dim" ,
283+ ),
269284 num_global_query_groups = num_global_query_groups ,
270285 seq_length = hf_config .max_position_embeddings ,
271286 vocab_size = hf_config .vocab_size ,
@@ -307,12 +322,19 @@ def _build_moe_provider(self, hf_config) -> Gemma4ModelProvider:
307322 provider .kv_channels = head_dim
308323 provider .qk_layernorm = True
309324
310- provider .global_head_dim = _attention_config_value (hf_config , "full_attention" , "head_dim" , 512 )
325+ provider .global_head_dim = _attention_config_value (
326+ hf_config ,
327+ "full_attention" ,
328+ "head_dim" ,
329+ 512 ,
330+ legacy_field_name = "global_head_dim" ,
331+ )
311332 provider .num_global_key_value_heads = _attention_config_value (
312333 hf_config ,
313334 "full_attention" ,
314335 "num_key_value_heads" ,
315- getattr (hf_config , "num_global_key_value_heads" , 2 ),
336+ 2 ,
337+ legacy_field_name = "num_global_key_value_heads" ,
316338 )
317339 provider .attention_k_eq_v = getattr (hf_config , "attention_k_eq_v" , False )
318340
@@ -447,16 +469,23 @@ def maybe_modify_loaded_hf_weight(
447469 text_config , "num_attention_heads" , getattr (self , "_dense_num_attention_heads" , 8 )
448470 )
449471 kv_head_dim = q_weight .shape [0 ] // num_q_heads
450- num_kv_heads = getattr (text_config , "num_key_value_heads" , getattr (self , "_dense_num_query_groups" , 2 ))
472+ num_kv_heads = _attention_config_value (
473+ text_config ,
474+ "sliding_attention" ,
475+ "num_key_value_heads" ,
476+ getattr (self , "_dense_num_query_groups" , 2 ),
477+ )
451478 layer_match = re .search (r"layers\.(\d+)\." , q_name )
452479 layer_types = getattr (text_config , "layer_types" , None )
453480 if layer_match and layer_types :
454481 layer_idx = int (layer_match .group (1 ))
455482 if layer_idx < len (layer_types ) and layer_types [layer_idx ] == "full_attention" :
456- num_global_kv_heads = getattr (
483+ num_global_kv_heads = _attention_config_value (
457484 text_config ,
458- "num_global_key_value_heads" ,
485+ "full_attention" ,
486+ "num_key_value_heads" ,
459487 getattr (self , "_dense_num_global_query_groups" , None ),
488+ legacy_field_name = "num_global_key_value_heads" ,
460489 )
461490 if num_global_kv_heads is not None :
462491 num_kv_heads = num_global_kv_heads
0 commit comments