Coverage for transformer_lens/model_bridge/supported_architectures/olmoe.py: 100%
11 statements
« prev ^ index » next coverage.py v7.10.1, created at 2026-09-01 16:23 +0000
« prev ^ index » next coverage.py v7.10.1, created at 2026-09-01 16:23 +0000
1"""OLMoE (Mixture of Experts) architecture adapter."""
3from typing import Any
5from transformer_lens.model_bridge.architecture_adapter import ArchitectureAdapter
6from transformer_lens.model_bridge.generalized_components import (
7 BlockBridge,
8 EmbeddingBridge,
9 LinearBridge,
10 MoEBridge,
11 MoERouterBridge,
12 PositionEmbeddingsAttentionBridge,
13 RMSNormalizationBridge,
14 RotaryEmbeddingBridge,
15 UnembeddingBridge,
16)
19class OlmoeArchitectureAdapter(ArchitectureAdapter):
20 """Architecture adapter for OLMoE (Mixture of Experts) models.
22 OLMoE uses a pre-norm architecture with RMSNorm, Q/K normalization in attention,
23 rotary position embeddings (RoPE), and sparse Mixture of Experts MLP. Key features:
25 - Pre-norm: RMSNorm applied BEFORE attention and BEFORE MLP.
26 - Q/K normalization: RMSNorm applied to queries and keys after projection.
27 - Sparse MoE: 64 experts with top-8 routing (configurable).
28 - Batched expert parameters: gate_up_proj [num_experts, 2*d_mlp, d_model] and
29 down_proj [num_experts, d_model, d_mlp] as single tensors, not a ModuleList.
30 - Optional QKV clipping (handled by HF's native attention forward).
31 - No biases on any projections.
33 Optional Parameters (may not exist in state_dict):
34 -------------------------------------------------
35 - blocks.{i}.attn.b_Q - No bias on query projection
36 - blocks.{i}.attn.b_K - No bias on key projection
37 - blocks.{i}.attn.b_V - No bias on value projection
38 - blocks.{i}.attn.b_O - No bias on output projection
39 - blocks.{i}.ln1.b - RMSNorm has no bias
40 - blocks.{i}.ln2.b - RMSNorm has no bias
41 - ln_final.b - RMSNorm has no bias
42 """
44 def __init__(self, cfg: Any) -> None:
45 """Initialize the OLMoE architecture adapter."""
46 super().__init__(cfg)
48 self._set_rms_rotary_defaults(final_rms=False)
49 # Force eager attention for numerical consistency with benchmark reference
50 self.cfg.attn_implementation = "eager"
52 n_kv_heads = (
53 self.cfg.n_key_value_heads
54 if self.cfg.n_key_value_heads is not None
55 else self.cfg.n_heads
56 )
58 self.weight_processing_conversions = {
59 **self._qkvo_weight_conversions(),
60 }
62 # Component mapping — PRE-NORM architecture:
63 # ln1 = input_layernorm (applied BEFORE attention)
64 # ln2 = post_attention_layernorm (applied BEFORE MLP)
65 self.component_mapping = {
66 "embed": EmbeddingBridge(name="model.embed_tokens"),
67 "rotary_emb": RotaryEmbeddingBridge(name="model.rotary_emb", config=self.cfg),
68 "blocks": BlockBridge(
69 name="model.layers",
70 submodules={
71 "ln1": RMSNormalizationBridge(name="input_layernorm", config=self.cfg),
72 "ln2": RMSNormalizationBridge(name="post_attention_layernorm", config=self.cfg),
73 "attn": PositionEmbeddingsAttentionBridge(
74 name="self_attn",
75 config=self.cfg,
76 submodules={
77 "q": LinearBridge(name="q_proj"),
78 "k": LinearBridge(name="k_proj"),
79 "v": LinearBridge(name="v_proj"),
80 "o": LinearBridge(name="o_proj"),
81 "q_norm": RMSNormalizationBridge(name="q_norm", config=self.cfg),
82 "k_norm": RMSNormalizationBridge(name="k_norm", config=self.cfg),
83 },
84 requires_attention_mask=True,
85 requires_position_embeddings=True,
86 ),
87 # OLMoE uses batched expert parameters (gate_up_proj, down_proj
88 # as 3D tensors) rather than a ModuleList of individual experts.
89 # MoEBridge wraps the entire MLP module and delegates to HF's
90 # native forward pass.
91 "mlp": MoEBridge(
92 name="mlp",
93 config=self.cfg,
94 submodules={
95 "gate": MoERouterBridge(name="gate"),
96 },
97 ),
98 },
99 ),
100 "ln_final": RMSNormalizationBridge(name="model.norm", config=self.cfg),
101 "unembed": UnembeddingBridge(name="lm_head", config=self.cfg),
102 }