Skip to content

Commit 3a3de3e

Browse files
committed
Keep Gemma 4 layer 22 down_proj in float for MLX export
1 parent b231b6e commit 3a3de3e

1 file changed

Lines changed: 61 additions & 0 deletions

File tree

backends/mlx/examples/llm/export_llm_hf.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,53 @@
4747
logging.basicConfig(level=logging.INFO, format=FORMAT)
4848
logger = 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

5198
def _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

Comments
 (0)