nnsight远程神经网络解释工具Skill nnsight-remote-interpretability

nnsight是一个用于解释和操作神经网络内部的工具,支持通过NDIF远程执行,适用于大规模模型的可解释性实验。它允许研究人员在任何PyTorch模型上运行相同代码,无需本地GPU资源。关键词:神经网络解释,远程执行,nnsight,NDIF,大模型分析,PyTorch模型,深度学习可解释性。

深度学习 0 次安装 0 次浏览 更新于 3/21/2026

名称: nnsight-远程可解释性 描述: 提供使用nnsight和可选NDIF远程执行解释和操作神经网络内部的指导。适用于需要在没有本地GPU资源的情况下对大规模模型(70B+)运行可解释性实验,或处理任何PyTorch架构时。 版本: 1.0.0 作者: Orchestra Research 许可证: MIT 标签: [nnsight, NDIF, 远程执行, 机制可解释性, 模型内部] 依赖: [nnsight>=0.5.0, torch>=2.0.0]

nnsight: 透明访问神经网络内部

nnsight (/ɛn.saɪt/) 使研究人员能够解释和操作任何PyTorch模型的内部,通过NDIF支持在本地小模型或远程大规模模型(70B+)上运行相同代码的独特能力。

GitHub: ndif-team/nnsight (730+ stars) 论文: NNsight and NDIF: Democratizing Access to Foundation Model Internals (ICLR 2025)

核心价值主张

编写一次,随处运行: 相同的可解释性代码可在本地的GPT-2或远程的Llama-3.1-405B上运行。只需切换 remote=True

# 本地执行(小模型)
with model.trace("Hello world"):
    hidden = model.transformer.h[5].output[0].save()

# 远程执行(大规模模型)- 相同代码!
with model.trace("Hello world", remote=True):
    hidden = model.model.layers[40].output[0].save()

何时使用 nnsight

当您需要时使用 nnsight:

  • 在本地GPU无法处理的大规模模型上运行可解释性实验(70B, 405B)
  • 处理任何PyTorch架构(transformers, Mamba, 自定义模型)
  • 执行多令牌生成干预
  • 在不同提示之间共享激活
  • 访问完整模型内部而无需重新实现

考虑替代方案时:

  • 您希望跨模型一致的API → 使用 TransformerLens
  • 您需要声明式、可共享的干预 → 使用 pyvene
  • 您正在训练SAEs → 使用 SAELens
  • 您仅本地处理小模型 → TransformerLens 可能更简单

安装

# 基本安装
pip install nnsight

# 对于 vLLM 支持
pip install "nnsight[vllm]"

对于远程NDIF执行,请在 login.ndif.us 注册获取API密钥。

核心概念

LanguageModel 包装器

from nnsight import LanguageModel

# 加载模型(内部使用HuggingFace)
model = LanguageModel("openai-community/gpt2", device_map="auto")

# 对于更大模型
model = LanguageModel("meta-llama/Llama-3.1-8B", device_map="auto")

追踪上下文

trace 上下文管理器启用延迟执行 - 操作被收集到计算图中:

from nnsight import LanguageModel

model = LanguageModel("gpt2", device_map="auto")

with model.trace("The Eiffel Tower is in") as tracer:
    # 访问任何模块的输出
    hidden_states = model.transformer.h[5].output[0].save()

    # 访问注意力模式
    attn = model.transformer.h[5].attn.attn_dropout.input[0][0].save()

    # 修改激活
    model.transformer.h[8].output[0][:] = 0  # 清零第8层

    # 获取最终输出
    logits = model.output.save()

# 上下文退出后,访问保存的值
print(hidden_states.shape)  # [批次, 序列, 隐藏]

代理对象

trace 内部,模块访问返回代理对象,记录操作:

with model.trace("Hello"):
    # 这些全是代理对象 - 操作被延迟
    h5_out = model.transformer.h[5].output[0]  # 代理
    h5_mean = h5_out.mean(dim=-1)              # 代理
    h5_saved = h5_mean.save()                   # 保存供后续访问

工作流程 1: 激活分析

分步指南

from nnsight import LanguageModel
import torch

model = LanguageModel("gpt2", device_map="auto")

prompt = "The capital of France is"

with model.trace(prompt) as tracer:
    # 1. 从多层收集激活
    layer_outputs = []
    for i in range(12):  # GPT-2 有12层
        layer_out = model.transformer.h[i].output[0].save()
        layer_outputs.append(layer_out)

    # 2. 获取注意力模式
    attn_patterns = []
    for i in range(12):
        # 访问注意力权重(softmax后)
        attn = model.transformer.h[i].attn.attn_dropout.input[0][0].save()
        attn_patterns.append(attn)

    # 3. 获取最终logits
    logits = model.output.save()

# 4. 在上下文外分析
for i, layer_out in enumerate(layer_outputs):
    print(f"层 {i} 输出形状: {layer_out.shape}")
    print(f"层 {i} 范数: {layer_out.norm().item():.3f}")

# 5. 查找 top 预测
probs = torch.softmax(logits[0, -1], dim=-1)
top_tokens = probs.topk(5)
for token, prob in zip(top_tokens.indices, top_tokens.values):
    print(f"{model.tokenizer.decode(token)}: {prob.item():.3f}")

检查清单

  • [ ] 使用 LanguageModel 包装器加载模型
  • [ ] 使用 trace 上下文进行操作
  • [ ] 在需要保存的值上调用 .save()
  • [ ] 在上下文外访问保存的值
  • [ ] 使用 .shape.norm() 等进行分析

工作流程 2: 激活修补

分步指南

from nnsight import LanguageModel
import torch

model = LanguageModel("gpt2", device_map="auto")

clean_prompt = "The Eiffel Tower is in"
corrupted_prompt = "The Colosseum is in"

# 1. 获取 clean 激活
with model.trace(clean_prompt) as tracer:
    clean_hidden = model.transformer.h[8].output[0].save()

# 2. 将 clean 修补到 corrupted 运行中
with model.trace(corrupted_prompt) as tracer:
    # 用 clean 激活替换第8层输出
    model.transformer.h[8].output[0][:] = clean_hidden

    patched_logits = model.output.save()

# 3. 比较预测
paris_token = model.tokenizer.encode(" Paris")[0]
rome_token = model.tokenizer.encode(" Rome")[0]

patched_probs = torch.softmax(patched_logits[0, -1], dim=-1)
print(f"Paris 概率: {patched_probs[paris_token].item():.3f}")
print(f"Rome 概率: {patched_probs[rome_token].item():.3f}")

系统化修补扫描

def patch_layer_position(layer, position, clean_cache, corrupted_prompt):
    """将单个层/位置从 clean 修补到 corrupted."""
    with model.trace(corrupted_prompt) as tracer:
        # 获取当前激活
        current = model.transformer.h[layer].output[0]

        # 仅修补特定位置
        current[:, position, :] = clean_cache[layer][:, position, :]

        logits = model.output.save()

    return logits

# 扫描所有层和位置
results = torch.zeros(12, seq_len)
for layer in range(12):
    for pos in range(seq_len):
        logits = patch_layer_position(layer, pos, clean_hidden, corrupted)
        results[layer, pos] = compute_metric(logits)

工作流程 3: 通过 NDIF 远程执行

在无需本地 GPU 的情况下在大规模模型上运行相同实验。

分步指南

from nnsight import LanguageModel

# 1. 加载大模型(将远程运行)
model = LanguageModel("meta-llama/Llama-3.1-70B")

# 2. 相同代码,只需添加 remote=True
with model.trace("The meaning of life is", remote=True) as tracer:
    # 访问 70B 模型的内部!
    layer_40_out = model.model.layers[40].output[0].save()
    logits = model.output.save()

# 3. 从 NDIF 返回结果
print(f"层 40 形状: {layer_40_out.shape}")

# 4. 带干预的生成
with model.trace(remote=True) as tracer:
    with tracer.invoke("What is 2+2?"):
        # 在生成期间干预
        model.model.layers[20].output[0][:, -1, :] *= 1.5

    output = model.generate(max_new_tokens=50)

NDIF 设置

  1. login.ndif.us 注册
  2. 获取 API 密钥
  3. 设置环境变量或传递给 nnsight:
import os
os.environ["NDIF_API_KEY"] = "your_key"

# 或直接配置
from nnsight import CONFIG
CONFIG.API_KEY = "your_key"

NDIF 上可用模型

  • Llama-3.1-8B, 70B, 405B
  • DeepSeek-R1 模型
  • 各种开源权重模型(查看 ndif.us 获取当前列表)

工作流程 4: 跨提示激活共享

在单个 trace 中在不同输入之间共享激活。

from nnsight import LanguageModel

model = LanguageModel("gpt2", device_map="auto")

with model.trace() as tracer:
    # 第一个提示
    with tracer.invoke("The cat sat on the"):
        cat_hidden = model.transformer.h[6].output[0].save()

    # 第二个提示 - 注入猫的激活
    with tracer.invoke("The dog ran through the"):
        # 用猫的激活替换第6层
        model.transformer.h[6].output[0][:] = cat_hidden
        dog_with_cat = model.output.save()

# 狗提示现在具有猫的内部表示

工作流程 5: 基于梯度的分析

在反向传播期间访问梯度。

from nnsight import LanguageModel
import torch

model = LanguageModel("gpt2", device_map="auto")

with model.trace("The quick brown fox") as tracer:
    # 保存激活并启用梯度
    hidden = model.transformer.h[5].output[0].save()
    hidden.retain_grad()

    logits = model.output

    # 计算特定 token 的损失
    target_token = model.tokenizer.encode(" jumps")[0]
    loss = -logits[0, -1, target_token]

    # 反向传播
    loss.backward()

# 访问梯度
grad = hidden.grad
print(f"梯度形状: {grad.shape}")
print(f"梯度范数: {grad.norm().item():.3f}")

注意: 梯度访问不支持 vLLM 或远程执行。

常见问题与解决方案

问题: 模型路径不同

# GPT-2 结构
model.transformer.h[5].output[0]

# LLaMA 结构
model.model.layers[5].output[0]

# 解决方案: 检查模型结构
print(model._model)  # 查看实际模块名称

问题: 忘记保存

# 错误: 值在 trace 外不可访问
with model.trace("Hello"):
    hidden = model.transformer.h[5].output[0]  # 未保存!

print(hidden)  # 错误或错误值

# 正确: 调用 .save()
with model.trace("Hello"):
    hidden = model.transformer.h[5].output[0].save()

print(hidden)  # 有效!

问题: 远程超时

# 对于长操作,增加超时
with model.trace("prompt", remote=True, timeout=300) as tracer:
    # 长操作...

问题: 保存大量激活时的内存

# 仅保存所需
with model.trace("prompt"):
    # 不要保存所有
    for i in range(100):
        model.transformer.h[i].output[0].save()  # 内存消耗高!

    # 更好: 保存特定层
    key_layers = [0, 5, 11]
    for i in key_layers:
        model.transformer.h[i].output[0].save()

问题: vLLM 梯度限制

# vLLM 不支持梯度
# 使用标准执行进行梯度分析
model = LanguageModel("gpt2", device_map="auto")  # 非 vLLM

关键 API 参考

方法/属性 目的
model.trace(prompt, remote=False) 启动追踪上下文
proxy.save() 保存值供 trace 后访问
proxy[:] 切片/索引代理(分配修补)
tracer.invoke(prompt) 在 trace 内添加提示
model.generate(...) 带干预生成
model.output 最终模型输出 logits
model._model 底层 HuggingFace 模型

与其他工具比较

特性 nnsight TransformerLens pyvene
任何架构 仅 Transformers
远程执行 是(NDIF)
一致 API
延迟执行
HuggingFace 原生 重新实现
可共享配置

参考文档

详细 API 文档、教程和高级用法,请参见 references/ 文件夹:

文件 内容
references/README.md 概述和快速入门指南
references/api.md LanguageModel、追踪、代理对象的完整 API 参考
references/tutorials.md 本地和远程可解释性的分步教程

外部资源

教程

官方文档

论文

架构支持

nnsight 适用于任何 PyTorch 模型:

  • Transformers: GPT-2, LLaMA, Mistral 等
  • 状态空间模型: Mamba
  • 视觉模型: ViT, CLIP
  • 自定义架构: 任何 nn.Module

关键是了解模块结构以访问正确组件。