Summary
Gemma3ArchitectureAdapter maps each block's MLP with self._gated_mlp(), which creates a GatedMLPBridge and supplies the standard gated-MLP aliases:
hook_pre -> gate.hook_out
hook_pre_linear -> in.hook_out
hook_post -> out.hook_in
Gemma4ArchitectureAdapter maps the same gate_proj / up_proj / down_proj structure to a bare GeneralizedComponent. As a result, Gemma 4 exposes only the MLP boundary hooks (hook_in and hook_out); the three neuron-basis hooks are absent from hook_dict.
This is a mapping gap rather than an architectural limitation: Hugging Face's Gemma4TextMLP is an ordinary gated MLP, and the TransformerLens adapter already identifies all three projection submodules.
Versions
transformer-lens==3.7.0
transformers==5.15.0
- Python 3.12
I also checked the v3.7.1 source. The Gemma 4 MLP mapping is unchanged.
Reproduction
This is a config-only reproduction; it does not load model weights.
transformers==5.15.0 also exposes a separate Gemma 4 heterogeneous-config crash in TransformerLens. The two-line opt-in below is used only to get past that independent crash and inspect the adapter mapping. It is not a proposed runtime workaround.
pip install "transformer-lens==3.7.1" "transformers==5.15.0"
python gemma4_mlp_hooks.py
# gemma4_mlp_hooks.py
from transformers import AutoConfig
from transformer_lens.config import TransformerBridgeConfig
from transformer_lens.factories.architecture_adapter_factory import (
ArchitectureAdapterFactory,
)
from transformer_lens.model_bridge.sources.transformers import (
determine_architecture_from_hf_config,
map_default_transformer_lens_config,
)
for model_id in ("google/gemma-3-270m", "google/gemma-4-E2B"):
hf_config = AutoConfig.from_pretrained(model_id)
# Isolate the adapter-mapping question from the separate heterogeneous-config crash.
for config_obj in (hf_config, hf_config.get_text_config()):
config_obj.allow_global_per_layer_attribute_access = True
mapped = map_default_transformer_lens_config(hf_config)
cfg = TransformerBridgeConfig.from_dict(dict(mapped.__dict__))
cfg.architecture = determine_architecture_from_hf_config(hf_config)
adapter = ArchitectureAdapterFactory.select_architecture_adapter(cfg)
mlp = adapter.component_mapping["blocks"].submodules["mlp"]
aliases = getattr(type(mlp), "hook_aliases", {})
print(f"{model_id:22s} {type(adapter).__name__}")
print(
f"{'':22s} mlp -> {type(mlp).__name__}, "
f"submodules {sorted(mlp.submodules)}"
)
print(f"{'':22s} hook_aliases {aliases or '{}'}")
Observed:
google/gemma-3-270m Gemma3ArchitectureAdapter
mlp -> GatedMLPBridge, submodules ['gate', 'in', 'out']
hook_aliases {'hook_pre': 'gate.hook_out', 'hook_pre_linear': 'in.hook_out', 'hook_post': 'out.hook_in'}
google/gemma-4-E2B Gemma4ArchitectureAdapter
mlp -> GeneralizedComponent, submodules ['gate', 'in', 'out']
hook_aliases {}
The two adapters identify the same three MLP projections, but only Gemma 3 installs the compatibility aliases.
Expected behavior
For the dense Gemma4TextMLP submodule, these hooks should be available with the same semantics as other gated MLPs:
blocks.N.mlp.hook_pre
blocks.N.mlp.hook_pre_linear
blocks.N.mlp.hook_post
Actual behavior
None of those names is present for Gemma 4. Code written against the Gemma 3 hook interface fails when it attempts to select the corresponding Gemma 4 MLP activation.
Root cause
Gemma 3 uses the gated-MLP helper:
GatedMLPBridge defines the expected aliases:
Gemma 4 instead uses a bare GeneralizedComponent, despite naming gate_proj, up_proj, and down_proj:
The Hugging Face module has exactly those three projections:
Impact
The missing aliases block the standard TransformerLens MLP-neuron interface on Gemma 4. The failure is loud (hook_dict has no matching key), but it prevents existing activation-caching and intervention code from using the same hook names that work on Gemma 3 and other gated-MLP families.
Suggested fix
Replace the bare MLP mapping with the same helper used by Gemma 3:
"mlp": self._gated_mlp(),
The submodule names already match the helper's defaults.
Suggested regression tests:
- Assert that all three aliases are present on a Gemma 4 block.
- Assert that they resolve to
gate_proj output, up_proj output, and down_proj input.
- Cover a standard-width layer and a double-wide MLP layer on E2B/E4B.
- Cover a model with Gemma 4's optional MoE branch to ensure changing the dense
mlp mapping does not disturb the separate router/expert components.
Summary
Gemma3ArchitectureAdaptermaps each block's MLP withself._gated_mlp(), which creates aGatedMLPBridgeand supplies the standard gated-MLP aliases:Gemma4ArchitectureAdaptermaps the samegate_proj/up_proj/down_projstructure to a bareGeneralizedComponent. As a result, Gemma 4 exposes only the MLP boundary hooks (hook_inandhook_out); the three neuron-basis hooks are absent fromhook_dict.This is a mapping gap rather than an architectural limitation: Hugging Face's
Gemma4TextMLPis an ordinary gated MLP, and the TransformerLens adapter already identifies all three projection submodules.Versions
transformer-lens==3.7.0transformers==5.15.0I also checked the
v3.7.1source. The Gemma 4 MLP mapping is unchanged.Reproduction
This is a config-only reproduction; it does not load model weights.
transformers==5.15.0also exposes a separate Gemma 4 heterogeneous-config crash in TransformerLens. The two-line opt-in below is used only to get past that independent crash and inspect the adapter mapping. It is not a proposed runtime workaround.Observed:
The two adapters identify the same three MLP projections, but only Gemma 3 installs the compatibility aliases.
Expected behavior
For the dense
Gemma4TextMLPsubmodule, these hooks should be available with the same semantics as other gated MLPs:Actual behavior
None of those names is present for Gemma 4. Code written against the Gemma 3 hook interface fails when it attempts to select the corresponding Gemma 4 MLP activation.
Root cause
Gemma 3 uses the gated-MLP helper:
GatedMLPBridgedefines the expected aliases:Gemma 4 instead uses a bare
GeneralizedComponent, despite naminggate_proj,up_proj, anddown_proj:The Hugging Face module has exactly those three projections:
Impact
The missing aliases block the standard TransformerLens MLP-neuron interface on Gemma 4. The failure is loud (
hook_dicthas no matching key), but it prevents existing activation-caching and intervention code from using the same hook names that work on Gemma 3 and other gated-MLP families.Suggested fix
Replace the bare MLP mapping with the same helper used by Gemma 3:
The submodule names already match the helper's defaults.
Suggested regression tests:
gate_projoutput,up_projoutput, anddown_projinput.mlpmapping does not disturb the separate router/expert components.