Add from scratch pretrain converter#1506
Open
Cacapice wants to merge 1 commit into
Open
Conversation
4768b46 to
63ed83c
Compare
Adds a converter and loader that bring checkpoints from an external decoder-only pretraining framework (RoPE with adjacent-pair rotation, RMSNorm, SwiGLU, optional dropless top-k MoE) into HookedTransformer so their residual streams can be read with the standard hook API. - convert_maritime_pretrain_weights: splits the fused QKV projection into per-head W_Q/W_K/W_V, maps SwiGLU gate/up/down onto W_gate/W_in/W_out, and emits router + per-expert weights under the MoE component's names. - maritime_pretrain_loader: builds the matching HookedTransformerConfig (rotary_adjacent_pairs=True, normalization_type=RMS, gated_mlp=True, norm_topk_prob=True for MoE), merges tensor-parallel shards, returns a ready HookedTransformer. - Tests assert bit-exact logit equivalence (max|delta| < 1e-4) for both dense and MoE configs plus converter key/shape correctness.
63ed83c to
1616b7d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds a weight converter and loader that bring checkpoints from an external
from-scratch pretraining framework into HookedTransformer, so a
foundation model trained outside the HuggingFace ecosystem can be analysed with
the standard TransformerLens hook API (run_with_cache, resid_post, etc.).
The source architecture is a decoder-only transformer with RoPE (adjacent-pair
rotation), RMSNorm, SwiGLU MLPs, and optional dropless top-k Mixture-of-Experts.
Its checkpoints are not loadable through from_pretrained because they are not
a HuggingFace model; this PR follows the same pattern as the existing
nanogpt / mixtral converters to support them.
Motivation: this is the base-model half of an interpretability project — the
model whose residual stream downstream linear probes read. Loading it into
TransformerLens means the probing side can use the library's tooling directly
instead of a bespoke activation-extraction path.
Fixes # (no issue — new-feature contribution)
Type of change
New feature (non-breaking change which adds functionality)
This change requires a documentation update (docstrings included; happy
to add a docs/ loading example if the maintainers would like one)
What's included
weight_conversions/maritime_pretrain.py — convert_maritime_pretrain_weights.
Splits the fused QKV projection into per-head W_Q/W_K/W_V, maps SwiGLU
gate/up/down onto TransformerLens's W_gate/W_in/W_out, and (for MoE) emits
the router plus every expert under the names MoE/MoEGatedMLP expect. No
Q/K reordering is needed because RoPE is applied inside attention, not baked
into the weights.
pretrained/maritime_pretrain_loader.py — build_config and
load_maritime_pretrain. Builds the matching HookedTransformerConfig
(positional_embedding_type="rotary", rotary_adjacent_pairs=True,
normalization_type="RMS", final_rms=True, gated_mlp=True, and
num_experts/experts_per_token/norm_topk_prob for MoE), merges
tensor-parallel weight shards, and returns a ready HookedTransformer.
weight_conversions/init.py — export the new converter (alphabetical).
Tests — tests/unit/pretrained_weight_conversions/test_maritime_pretrain.py.
Key correctness detail
The source rotates adjacent RoPE pairs ([x0, x1] -> [-x1, x0]), which maps to
rotary_adjacent_pairs=True (the GPT-NeoX-style d -> (d 2) frequency layout),
not the default half-split convention. Getting this wrong still loads without
error but silently corrupts every activation, so the equivalence tests below are
the real guardrail.
Checklist
I have commented my code, particularly in hard-to-understand areas
I have made corresponding changes to the documentation (module + function docstrings)
My changes generate no new warnings
I have added tests that prove my feature works
New and existing unit tests pass locally with my changes
I have not rewritten tests relating to key interfaces which would affect backward compatibility
Test evidence
test_maritime_pretrain.py asserts bit-exact logit equivalence between the
source model and its converted HookedTransformer, parametrised across the axes
a future change is most likely to break, plus structural, failure-path and
tensor-parallel coverage (13 tests):
dense and MoE MLPs
tied and untied embeddings
four (d_model, n_heads) combinations
converter key/shape correctness for the MoE branch
a config/checkpoint shape mismatch raises a clear ValueError (not an opaque
reshape error)
tensor-parallel shard merge reconstructs the original weights for
N ∈ {1, 2, 4} shards
$ python -m pytest tests/unit/pretrained_weight_conversions/test_maritime_pretrain.py -q
13 passed
Observed max|Δlogit| between source and converted model ≈ 1e-5
(floating-point noise) across every parametrisation. Converter validates each
source weight's shape before reshaping, so a mismatched config fails with an
actionable message. Files formatted with the repo's pinned black==23.3.0 /
isort==5.8.0; pylint 10.00/10 and pyright clean on the new modules.
Notes / open questions for reviewers
Naming. I've used the project-specific name maritime_pretrain to mirror
nanogpt. If you'd prefer a generic name (e.g. swiglu_moe_gpt) since the
converter isn't domain-specific, I'm glad to rename.
Loader placement. The loader lives at pretrained/maritime_pretrain_loader.py
rather than being wired into loading_from_pretrained.py, because these
checkpoints load from a local run directory, not a hub ID. If you'd rather
register it as an official model source, point me at the preferred hook.
Targeting dev per the contribution guidelines (this is a feature, not a
fix against the released version).