Skip to content

fix(bridge): remove orphaned convert_weights override from nanogpt adapter - #1602

Merged
jlarson4 merged 1 commit into
TransformerLensOrg:dev-4.xfrom
sohv:fix/nanogpt-convert-weights
Aug 4, 2026
Merged

fix(bridge): remove orphaned convert_weights override from nanogpt adapter#1602
jlarson4 merged 1 commit into
TransformerLensOrg:dev-4.xfrom
sohv:fix/nanogpt-convert-weights

Conversation

@sohv

@sohv sohv commented Aug 4, 2026

Copy link
Copy Markdown

Description

NanogptArchitectureAdapter.convert_weights ended in return super().convert_weights(remote_module), but ArchitectureAdapter has had no convert_weights method since 3efbd6e ("Cleanup (#1129)", 2025-11-15). Every call therefore raised AttributeError: 'super' object has no attribute 'convert_weights'.

The defect was invisible to CI because of the # type: ignore[misc] on that line. With the ignore removed, uv run mypy . reports it directly:

transformer_lens/model_bridge/supported_architectures/nanogpt.py:103: error: "convert_weights" undefined in superclass  [misc]

This PR deletes the orphaned override together with its ignore, and drops the now-unused torch import.

Why removal rather than repair:

  • The method had no callers. A search over *.py / *.ipynb / *.md, plus a check for dynamic getattr dispatch, finds only two definitions of convert_weights in the tree — this one and bd3lm.py:208 (a different signature returning {}, likewise never called). Both are orphans from the base-class removal.
  • Its _orig_mod. prefix strip was a no-op regardless. nn.Module.state_dict() returns a fresh dict, so the pop/reassign loop mutated a throwaway copy and then passed the original remote_module to super().
  • Removal cannot regress behaviour, because every path through the method already raised.

Deliberately not re-homed into preprocess_weights. That hook runs on self.state_dict() inside process_weights (transformer_bridge.py:608) — after loading, with TL-renamed keys — so it would never observe _orig_mod.-prefixed checkpoint keys. Moving the logic there would look like a fix while doing nothing.

Regression guard: with the # type: ignore gone, the CI type-check job fails if the override is reintroduced.

Adjacent gap, not addressed here: TransformerBridge consequently has no _orig_mod. handling for torch.compile()'d nanoGPT checkpoints, while the HookedTransformer path does (transformer_lens/pretrained/weight_conversions/nanogpt.py:14). That is HT→Bridge drift, but adding it is a feature with its own design question (which load path should own the strip), so it is out of scope for a dead-code removal. Happy to file it separately.

On unit coverage: nanogpt sits in _COVERAGE_EXEMPT_MODULES (tests/unit/model_bridge/supported_architectures/test_thin_subclass_adapters.py:94) as an internal-only adapter, so no test file accompanies this change. I have a structural unit suite for the adapter ready if you want it — note that adding it also requires dropping "nanogpt" from that exemption set, since test_coverage_exemptions_are_still_uncovered is self-cleaning. That is a policy call on an intentionally-exempt adapter, so I did not make it unilaterally.

Fixes #1601

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Checklist:

  • I have commented my code, particularly in hard-to-understand areas — the change is a deletion; the rationale is in the commit message and above
  • I have made corresponding changes to the documentation — no documented behaviour changes; the removed method was unreachable
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works — see "On unit coverage" above: nanogpt is an exempt module, and the # type: ignore removal makes the CI type-check job the regression guard. A structural unit suite is ready if you want the exemption retired.
  • New and existing unit tests pass locally with my changes
  • I have not rewritten tests relating to key interfaces which would affect backward compatibility

…apter

NanogptArchitectureAdapter.convert_weights ended in
super().convert_weights(remote_module), but ArchitectureAdapter has had no
such method since 3efbd6e ("Cleanup (TransformerLensOrg#1129)"), so every call raised
AttributeError. The failure was invisible to CI because of the
# type: ignore[misc] on that line; without it mypy reports
'"convert_weights" undefined in superclass'.

The override had no callers anywhere in the tree, and its _orig_mod. prefix
strip was a no-op regardless: nn.Module.state_dict() returns a fresh dict, so
the loop mutated a throwaway copy before passing the original module to
super(). Removing it cannot regress behaviour, since every path through it
raised. Dropping the ignore leaves the CI type-check job as the guard against
reintroduction.

Not re-homed into preprocess_weights: that hook runs on self.state_dict()
inside process_weights, i.e. after load with TL-renamed keys, so it never
observes _orig_mod.-prefixed checkpoint keys.
@sohv

sohv commented Aug 4, 2026

Copy link
Copy Markdown
Author

Sibling instance of the same pattern, from the same commit: ArchitectureAdapter._enable_ht_attention (architecture_adapter.py:1076-1126) calls _extract_linear_ht_format (:1100-1102) and _extract_qkv_neox_style (:1106), whose definitions 3efbd6e deleted while keeping the call sites — four # type: ignore[attr-defined] hide it. Only the GPT-2 branch works; the split-QKV (Llama/Qwen/Gemma) and NeoX branches raise AttributeError.

The same commit also removed its two callers (architecture_adapter.py:1249 and bridge.py:1144 as of 3efbd6e^), so it is unreachable — no user impact. That makes :1076-1171 dead: its three remaining helpers are called only from it, and _disable_hook_conversions is already pass.

Fold the removal into #1602, separate PR, or leave it? If component-level HT-vs-bridge weight comparison is still wanted, restoring the two extractors from 3efbd6e^ would be the right direction instead.

@jlarson4

jlarson4 commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

@sohv in response to your question, feel free to make that as a separate PR, I am going to merge this because it looks great!

@jlarson4
jlarson4 merged commit 29a6baf into TransformerLensOrg:dev-4.x Aug 4, 2026
25 checks passed
@sohv

sohv commented Aug 4, 2026

Copy link
Copy Markdown
Author

@jlarson4 Thank you! I will create it as a separate PR and will request merging with the dev-4.x branch.

jlarson4 pushed a commit that referenced this pull request Aug 4, 2026
…rs (#1604)

_enable_ht_attention dispatched on three attention layouts, but two of the
three branches called methods that no longer exist: _extract_linear_ht_format
(split Q/K/V - Llama, Mistral, Qwen, Gemma) and _extract_qkv_neox_style
(fused query_key_value - GPT-NeoX, Falcon). 3efbd6e ("Cleanup (#1129)")
deleted both definitions while keeping the call sites, so only the GPT-2
branch could run; the other two raised AttributeError on entry. Four
# type: ignore[attr-defined] comments kept mypy quiet about it.

The same commit removed both callers (architecture_adapter.py:1249 and
bridge.py:1144 as of 3efbd6e^), leaving the method unreachable - no user
impact, but it reads as a finished "architecture-agnostic" helper to anyone
wiring it into component testing.

Its three remaining helpers are called only from it, so they go too:
_extract_qkv_gpt2_style, _extract_output_proj, and _disable_hook_conversions
(whose body was already `pass`). einops becomes unused and is dropped.

setup_component_testing and _wire_rotary_for_testing are untouched.

Follow-up to #1601/#1602, which fixed the same pattern in the nanogpt
adapter; separate PR per maintainer request.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants