4747logging .basicConfig (level = logging .INFO , format = FORMAT )
4848logger = logging .getLogger (__name__ )
4949
50+ _GEMMA4_MODEL_ID = "google/gemma-4-E2B-it"
51+ _GEMMA4_PROBLEM_LAYER_FQN = "model.language_model.layers.22.mlp.down_proj"
52+
53+
54+ def _get_submodule_by_fqn (root : torch .nn .Module , fqn : str ) -> torch .nn .Module :
55+ cur = root
56+ for part in fqn .split ("." ):
57+ if part .isdigit ():
58+ cur = cur [int (part )] # type: ignore[index]
59+ else :
60+ cur = getattr (cur , part )
61+ return cur
62+
63+
64+ def _capture_gemma4_float_fallback_weight (
65+ model_id : str ,
66+ qlinear : Optional [str ],
67+ model : torch .nn .Module ,
68+ ) -> Optional [torch .Tensor ]:
69+ if model_id != _GEMMA4_MODEL_ID or qlinear != "4w" :
70+ return None
71+
72+ layer = _get_submodule_by_fqn (model , _GEMMA4_PROBLEM_LAYER_FQN )
73+ weight = layer .weight .detach ().clone ()
74+ logger .info (
75+ "Saving %s in floating point to avoid the current Gemma 4 4w mismatch" ,
76+ _GEMMA4_PROBLEM_LAYER_FQN ,
77+ )
78+ return weight
79+
80+
81+ def _restore_gemma4_float_fallback_weight (
82+ model_id : str ,
83+ qlinear : Optional [str ],
84+ model : torch .nn .Module ,
85+ weight : Optional [torch .Tensor ],
86+ ) -> None :
87+ if weight is None or model_id != _GEMMA4_MODEL_ID or qlinear != "4w" :
88+ return
89+
90+ layer = _get_submodule_by_fqn (model , _GEMMA4_PROBLEM_LAYER_FQN )
91+ layer .weight = torch .nn .Parameter (weight , requires_grad = False )
92+ logger .info (
93+ "Restored %s in floating point after quantization" ,
94+ _GEMMA4_PROBLEM_LAYER_FQN ,
95+ )
96+
5097
5198def _export_with_optimum (
5299 model_id : str ,
@@ -81,6 +128,10 @@ def _export_with_optimum(
81128
82129 from executorch .backends .mlx .llm .quantization import quantize_model_
83130
131+ gemma4_float_weight = _capture_gemma4_float_fallback_weight (
132+ model_id , qlinear , exportable .model
133+ )
134+
84135 quantize_model_ (
85136 exportable .model ,
86137 qlinear_config = qlinear ,
@@ -92,6 +143,9 @@ def _export_with_optimum(
92143 )
93144 and not no_tie_word_embeddings ,
94145 )
146+ _restore_gemma4_float_fallback_weight (
147+ model_id , qlinear , exportable .model , gemma4_float_weight
148+ )
95149
96150 logger .info ("Exporting model with torch.export..." )
97151 exported_progs = exportable .export ()
@@ -277,6 +331,10 @@ def _export_with_custom_components(
277331
278332 from executorch .backends .mlx .llm .quantization import quantize_model_
279333
334+ gemma4_float_weight = _capture_gemma4_float_fallback_weight (
335+ model_id , qlinear , exportable .model
336+ )
337+
280338 quantize_model_ (
281339 exportable .model ,
282340 qlinear_config = qlinear ,
@@ -286,6 +344,9 @@ def _export_with_custom_components(
286344 tie_word_embeddings = getattr (model .config , "tie_word_embeddings" , False )
287345 and not no_tie_word_embeddings ,
288346 )
347+ _restore_gemma4_float_fallback_weight (
348+ model_id , qlinear , exportable .model , gemma4_float_weight
349+ )
289350
290351 logger .info ("Exporting model with torch.export..." )
291352 seq_length = 3
0 commit comments