Coverage for transformer_lens/model_bridge/supported_architectures/bamba.py: 100%
18 statements
« prev ^ index » next coverage.py v7.10.1, created at 2026-08-11 18:50 +0000
« prev ^ index » next coverage.py v7.10.1, created at 2026-08-11 18:50 +0000
1"""Bamba (``BambaForCausalLM``) adapter: Jamba-lineage hybrid alternating Mamba-2
2and llama-style GQA attention mixers per ``config.layers_block_type``."""
4from typing import Any
6from transformer_lens.model_bridge.architecture_adapter import ArchitectureAdapter
7from transformer_lens.model_bridge.generalized_components import (
8 BlockBridge,
9 EmbeddingBridge,
10 GatedRMSNormBridge,
11 LinearBridge,
12 PositionEmbeddingsAttentionBridge,
13 RMSNormalizationBridge,
14 RotaryEmbeddingBridge,
15 SSM2MixerBridge,
16 UnembeddingBridge,
17)
18from transformer_lens.model_bridge.generalized_components.depthwise_conv1d import (
19 DepthwiseConv1DBridge,
20)
23class BambaArchitectureAdapter(ArchitectureAdapter):
24 """Architecture adapter for BambaForCausalLM models.
26 Both mixers are mapped optional — each present only on its layer type.
27 The Mamba-2 mixer is wired under the canonical ``.mixer`` slot (HF path
28 ``.mamba``) so SSM analyses reach it as on GraniteMoeHybrid / NemotronH.
29 """
31 _testing_hybrid = True
32 _testing_eager = "config"
34 def __init__(self, cfg: Any) -> None:
35 """Initialize the Bamba architecture adapter."""
36 super().__init__(cfg)
38 self._set_rms_rotary_defaults()
39 # Mamba layers require per-step SSM state; generation is stateful.
40 self.cfg.is_stateful = True
42 # Normalize the per-layer mixer-type list as cfg.layers_block_type so
43 # analysis tools can find the Mamba layers, as on the hybrid siblings.
44 setattr(self.cfg, "layers_block_type", self._canonical_layer_types(cfg))
46 # Mixed mamba/attention layers: keep raw HF weight layout.
47 self.supports_fold_ln = False
48 self.weight_processing_conversions = {}
50 self.component_mapping = {
51 "embed": EmbeddingBridge(name="model.embed_tokens"),
52 "rotary_emb": RotaryEmbeddingBridge(name="model.rotary_emb", config=self.cfg),
53 "blocks": BlockBridge(
54 name="model.layers",
55 submodules={
56 "ln1": RMSNormalizationBridge(name="input_layernorm", config=self.cfg),
57 "attn": PositionEmbeddingsAttentionBridge(
58 name="self_attn",
59 config=self.cfg,
60 optional=True,
61 submodules={
62 "q": LinearBridge(name="q_proj"),
63 "k": LinearBridge(name="k_proj"),
64 "v": LinearBridge(name="v_proj"),
65 "o": LinearBridge(name="o_proj"),
66 },
67 requires_attention_mask=True,
68 requires_position_embeddings=True,
69 ),
70 "mixer": SSM2MixerBridge(
71 name="mamba",
72 config=self.cfg,
73 optional=True,
74 submodules={
75 "in_proj": LinearBridge(name="in_proj"),
76 "conv1d": DepthwiseConv1DBridge(name="conv1d"),
77 "inner_norm": GatedRMSNormBridge(name="norm"),
78 "out_proj": LinearBridge(name="out_proj"),
79 },
80 ),
81 "ln2": RMSNormalizationBridge(name="pre_ff_layernorm", config=self.cfg),
82 "mlp": self._gated_mlp(name="feed_forward"),
83 },
84 ),
85 "ln_final": RMSNormalizationBridge(name="model.final_layernorm", config=self.cfg),
86 "unembed": UnembeddingBridge(name="lm_head", config=self.cfg),
87 }
89 def create_stateful_cache(
90 self,
91 hf_model: Any,
92 batch_size: int,
93 device: Any,
94 dtype: Any,
95 ) -> Any:
96 """Unified DynamicCache carrying KV entries and SSM conv/recurrent state."""
97 from transformers.cache_utils import DynamicCache
99 return DynamicCache(config=hf_model.config)