LabWired
회로 설계·펌웨어 실행·변형 비교·Playground 결과 확인, 오픈소스, 무료 체험
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기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 |