Coverage for transformer_lens/model_bridge/generalized_components/bloom_mlp.py: 77%
22 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"""BLOOM-specific MLP bridge component.
3BLOOM MLP requires a special 'residual' argument that standard MLPBridge doesn't handle.
4This custom component passes the residual argument through to the original component.
5"""
6from typing import Any, Dict, Optional
8import torch
10from transformer_lens.model_bridge.generalized_components.base import (
11 GeneralizedComponent,
12)
13from transformer_lens.model_bridge.generalized_components.mlp import MLPBridge
16class BloomMLPBridge(MLPBridge):
17 """MLP bridge for BLOOM models that handles residual connections.
19 BLOOM MLP has a unique forward signature that requires:
20 - hidden_states (first positional arg)
21 - residual (keyword arg): The residual connection tensor
23 This bridge ensures the residual argument is properly passed through.
24 """
26 def __init__(
27 self,
28 name: Optional[str],
29 config: Optional[Any] = None,
30 submodules: Optional[Dict[str, GeneralizedComponent]] = None,
31 ):
32 """Initialize the BLOOM MLP bridge.
34 Args:
35 name: The name of the component in the model
36 config: Optional configuration
37 submodules: Dictionary of submodules to register (e.g., dense_h_to_4h, dense_4h_to_h)
38 """
39 super().__init__(name, config, submodules or {})
41 def set_original_component(self, original_component: torch.nn.Module) -> None:
42 super().set_original_component(original_component)
43 # The Megatron-TP replay path (pretraining_tp>1 + slow_but_exact) computes
44 # dense_4h_to_h via F.linear on weight slices, bypassing the module call the
45 # out-projection hooks attach to. Force the module path; the only difference
46 # is fp summation order.
47 if getattr(original_component, "slow_but_exact", False):
48 setattr(original_component, "slow_but_exact", False)
50 def forward(self, *args: Any, **kwargs: Any) -> Any:
51 """Forward pass through BLOOM MLP with hooks.
53 BLOOM MLP requires these arguments:
54 - hidden_states (first positional arg)
55 - residual (second positional arg)
57 Args:
58 *args: Input arguments (hidden_states, residual)
59 **kwargs: Additional keyword arguments (if any)
61 Returns:
62 Output tensor from BLOOM MLP
63 """
64 if self.original_component is None: 64 ↛ 65line 64 didn't jump to line 65 because the condition on line 64 was never true
65 raise RuntimeError(
66 f"Original component not set for {self.name}. Call set_original_component() first."
67 )
69 # Apply hook_in to hidden_states (first positional argument)
70 if len(args) > 0 and isinstance(args[0], torch.Tensor): 70 ↛ 73line 70 didn't jump to line 73 because the condition on line 70 was always true
71 hooked_input = self.hook_in(args[0])
72 args = (hooked_input,) + args[1:]
73 elif "hidden_states" in kwargs and isinstance(kwargs["hidden_states"], torch.Tensor):
74 kwargs["hidden_states"] = self.hook_in(kwargs["hidden_states"])
76 # BLOOM MLP requires residual as second positional arg
77 # The original BLOOM block passes it, so we just pass everything through
78 # No need to validate since the original component will handle it
80 output = self.original_component(*args, **kwargs)
82 output = self.hook_out(output)
84 return output