LabWired
Design circuits, run firmware, compare variants, and inspect the result in Playground. Open source. MCP for Claude or Codex. Free to try.
翻译准备中
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Unified access to Large Language Model modules using NNsight
翻译准备中
正在加载完整 README。
查看完整 README ↗nnterp gives every transformer family the same module names and the same standard values,
on top of nnsight. StandardizedTransformer is an
nnsight TransformersModel, so trace, generate, .save(), tracer.iter and
remote=True work as they do in nnsight. An experiment written once runs on GPT-2, Llama,
Qwen, Gemma, Mamba and the other supported families.
from nnterp import StandardizedTransformer
model = StandardizedTransformer("openai-community/gpt2") # or a Llama, a Pythia, ...
with model.trace("The Eiffel Tower is in"):
attn = model.layers[5].self_attn.attention_output.save() # what attention adds
resid = model.layers[5].layer_output.save() # the residual stream leaving block 5
logits = model.logits.save()
print(attn.shape, resid.shape, logits.shape)
# torch.Size([1, 7, 768]) torch.Size([1, 7, 768]) torch.Size([1, 7, 50257])
One vocabulary. Every family answers to Llama's names, lifted out of the inner .model:
model.embed_tokens, model.layers[i], model.layers[i].self_attn, model.layers[i].mlp,
model.norm, model.lm_head. They are nnsight aliases, so GPT-2's model.transformer.h[5]
and model.layers[5] are the same envoy and the native names keep working.
Standard values. A name says which module; a value says which tensor, and it means the
same thing on every family. layer_output is the residual stream leaving a block, whether
the block returns a tensor or a tuple. attention_output and mlp_output are what each
sublayer adds to the residual stream, wherever the family adds the residual or applies a
post-sublayer norm, so on every family
layers[i].input + attention_output + mlp_output == layers[i].layer_output
Values can be read, edited in place, or assigned.
Ask before you trace. Not every checkpoint has every value. model.support() says what
this one has and, for anything missing, why; reading a missing value raises
nnterp.Unavailable with the same reason.
import torch
from nnterp import StandardizedTransformer
model = StandardizedTransformer("openai-community/gpt2")
with model.trace("The Eiffel Tower is in"):
block = model.layers[5]
x = block.input.save()
a = block.self_attn.attention_output.save()
m = block.mlp.mlp_output.save()
out = block.layer_output.save()
print(torch.allclose(x + a + m, out, atol=1e-4)) # True
print(model.support(layer=5)["self_attn.attention_probabilities"])
# read inside the eager attention forward, but this model runs 'sdpa'; load with attn_implementation='eager'
| area | values and methods | docs |
|---|---|---|
| residual stream | layer_input, layer_output, attention_output, mlp_output, and the module boundaries between them: attention_norm_output, layer_mid, mlp_norm_output, mlp_input; inside the sublayers attention_premix, mlp_activation, mlp_neurons | residual-stream |
| attention interior | attention_probabilities, attention_queries / keys / values, attention_scores, attention_head_outputs (load with attn_implementation="eager") | attention-interior |
| mixture of experts | router_logits, expert_weights, expert_indices, expert_outputs, routed_output, shared_expert_output | mixture-of-experts |
| recurrent mixers and hybrids | linear_attn on gated DeltaNet, Mamba and Mamba-2 blocks: queries, keys, values, decays, betas, the recurrent state | delta-net, selective-scan, state-space |
| the whole model | logits, token_embeddings, final_norm_output, lm_head_output, , , and the sizes (, , , ...) |
Every value has one axis layout on every family, named in nnterp.components
(layouts).
import torch
from nnterp import StandardizedTransformer
model = StandardizedTransformer("openai-community/gpt2", attn_implementation="eager")
vector = torch.randn(model.hidden_size)
with model.trace("The Eiffel Tower is in"):
pattern = model.layers[3].self_attn.attention_probabilities.save() # [batch, num_heads, query, key]
lens = model.project_on_vocab(model.layers[6].layer_output).save() # logit lens at block 6
model.steer(8, vector, factor=3, token_positions=-1) # add to block 8's output
model.skip_layers(10, 11) # blocks 10..11 do not run
logits = model.logits.save()
98 families, among them GPT-2, Llama, Mistral, Qwen 2/3/3.5, Gemma 1-4, Phi, OLMo, GPT-NeoX, DeepSeek-V2/V3, GPT-OSS, Mixtral, Falcon, BLOOM, Mamba, Jamba and Nemotron-H, developed against transformers 5.17 and run on 5.19 and 5.20.1; 60 of them also run on vLLM (docs/usage/vllm.md). Sixteen of them also name the vision tower of their image-text-to-text wrappers (Llava, LLaVA-NeXT, Gemma 3, PaliGemma, Mistral 3, Pixtral, Qwen2-VL to Qwen3.5, Llama 4, Gemma 4, Idefics 3, Aya Vision, ...). The full table, with each family's native names and quirks, is docs/reference/families.md.
pip install nnterp
Extras:
pip install "nnterp[models]": the tokenizers and processors some checkpoints need
(sentencepiece, tiktoken, protobuf, pillow).pip install "nnterp[vllm]": vLLM.pip install "nnterp[test]": pytest and pytest-xdist, for the test suite.nnterp requires nnsight 0.8.0 or later (nnsight>=0.8; nnsight 0.8.0 is on PyPI).
StandardizedTransformer(repo_id, family=my_family)).The skills that teach an agent nnterp are in ndif-team/skills: nnterp for the
values, patterns for recipes that run on every family, extending for new families and values.
In Claude Code, /plugin marketplace add https://github.com/ndif-team/skills.git then
/plugin install nnterp@ndif-team; in Codex, $skill-installer install https://github.com/ndif-team/skills.
The documentation site serves every page as Markdown, listed at
llms.txt. CLAUDE.md is for agents
working in this repository.
Before opening an issue, reduce it to a minimal working example. If you can, write the
same code with nnsight's TransformersModel on the native module names: if that also fails,
the bug is in nnsight, so open it on the nnsight tracker.
Also check that the model loads with AutoModelForCausalLM from transformers. Then open an
issue on the nnterp tracker.
Contributions are welcome: a family that is not supported yet, a value you needed for your research, a fix. Read docs/developing/contributing.md for the style and workflow, and the list of open items.
If you use nnterp in your research, you can cite it as:
@misc{dumas2025nnterp,
title={nnterp: A Standardized Interface for Mechanistic Interpretability of Transformers},
author={Cl{\'e}ment Dumas},
year={2025},
eprint={2511.14465},
archivePrefix={arXiv},
primaryClass={cs.LG},
url={https://arxiv.org/abs/2511.14465},
}
next_token_probsinput_idsnum_layershidden_sizehead_dim| root-values |
| vision-language models | model.vision.layers[i] (the tower's blocks, same values over the patches), model.projector, vision.image_token_mask, vision.image_features (what enters the text model at the image tokens); load with task="image-text-to-text" | vision |
| methods | steer, skip_layers, project_on_vocab, get_topk_closest_tokens | methods |
| the vLLM engine | StandardizedVLLM: the same names, values and layouts on nnsight's VLLM, batch axis 1 | vllm |