Coverage for transformer_lens/model_bridge/supported_architectures/openai_gpt.py: 96%
21 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"""OpenAI GPT (GPT-1) architecture adapter.
3The original GPT (``OpenAIGPTLMHeadModel``, openai-community/openai-gpt).
4GPT-2's block internals under different top-level names — combined-QKV
5``c_attn`` Conv1D, ``c_fc``/``c_proj`` MLP — but POST-norm (``ln_1(x + attn)``,
6``ln_2(n + mlp)``), no final LayerNorm, and embeddings at
7``transformer.tokens_embed`` / ``transformer.positions_embed``.
8"""
10from typing import Any
12from transformer_lens.model_bridge.architecture_adapter import ArchitectureAdapter
13from transformer_lens.model_bridge.generalized_components import (
14 BlockBridge,
15 EmbeddingBridge,
16 JointQKVAttentionBridge,
17 LinearBridge,
18 NormalizationBridge,
19 PosEmbedBridge,
20 UnembeddingBridge,
21)
24class _OpenAIGPTJointQKVAttentionBridge(JointQKVAttentionBridge):
25 """GPT-1's Block concatenates ``[h] + attn_outputs[1:]`` — it requires the
26 attention module to return a list, not the tuple modern blocks accept."""
28 def _process_output(self, output: Any) -> Any:
29 processed = super()._process_output(output)
30 if isinstance(processed, tuple): 30 ↛ 32line 30 didn't jump to line 32 because the condition on line 30 was always true
31 return list(processed)
32 return [processed]
35class OpenAIGPTArchitectureAdapter(ArchitectureAdapter):
36 """Architecture adapter for OpenAIGPTLMHeadModel (GPT-1) models."""
38 def __init__(self, cfg: Any) -> None:
39 """Initialize the OpenAI GPT architecture adapter."""
40 super().__init__(cfg)
42 self.cfg.normalization_type = "LN"
43 self.cfg.positional_embedding_type = "standard"
44 self.cfg.final_rms = False
45 self.cfg.gated_mlp = False
46 self.cfg.attn_only = False
48 # GPT-1 is post-LN; fold-LN assumes pre-LN and would fold norms into
49 # the wrong sublayers.
50 self.supports_fold_ln = False
51 self.supports_center_writing_weights = False
52 self.weight_processing_conversions = {}
54 self.component_mapping = {
55 "embed": EmbeddingBridge(name="transformer.tokens_embed"),
56 "pos_embed": PosEmbedBridge(name="transformer.positions_embed"),
57 "blocks": BlockBridge(
58 name="transformer.h",
59 config=self.cfg,
60 submodules={
61 "attn": _OpenAIGPTJointQKVAttentionBridge(
62 name="attn",
63 config=self.cfg,
64 submodules={
65 "qkv": LinearBridge(name="c_attn"),
66 "o": LinearBridge(name="c_proj"),
67 },
68 ),
69 # Post-norm: ln_1 follows attention, ln_2 follows the MLP.
70 "ln1": NormalizationBridge(name="ln_1", config=self.cfg),
71 "mlp": self._ungated_mlp(up="c_fc", down="c_proj"),
72 "ln2": NormalizationBridge(name="ln_2", config=self.cfg),
73 },
74 # Post-norm: ln2.hook_in is the post-MLP sum n+m; the true
75 # attn->MLP mid-point n = ln_1(x+a) is mlp.hook_in.
76 hook_alias_overrides={
77 "hook_resid_mid": "mlp.hook_in",
78 },
79 ),
80 "unembed": UnembeddingBridge(name="lm_head"),
81 }