Transformer 输入—输出差异分析工具
开发计划 / AI 编程任务书
一、项目目标
开发一个可本地运行的 Transformer 分析工具,用于研究:
为什么两个非常相似的输入,会产生不同的模型输出?
典型实验:
原始输入:
lqak
自动生成扰动输入:
Lqak
lQak
lqaK
LQAK
工具需要自动比较:
输入
↓
Tokenizer
↓
Embedding
↓
Transformer Layer 1
↓
Layer 2
↓
Layer 3
↓
...
↓
Output / Logits
最终给出:
输入发生了什么变化 → 哪一层开始产生明显差异 → 哪个 Attention Head 最敏感 → Q/K/V 哪部分发生变化 → 最终哪些输出概率发生变化。
二、第一阶段:确定 MVP
第一版不要追求支持所有模型。
优先支持:
- PyTorch
- Hugging Face Transformers
- GPT 类 Decoder-only Transformer
- 本地 Hugging Face 模型
- 小型模型优先,例如 GPT-2 / tiny 模型
- CPU 可以运行
- GPU 如果存在则自动使用
第一版目标:
能够完整跑通一个输入对,并显示两者在 Transformer 内部的差异。
三、核心功能
3.1 输入管理
用户输入:
lqak
工具自动生成扰动版本:
Lqak
lQak
lqaK
LQAK
同时支持手动输入:
Input A:
lqak
Input B:
lQak
未来支持:
- 替换字符
- 删除字符
- 增加字符
- 空格变化
- 标点变化
- 同义词替换
- 拼写错误
- Token 替换
四、Tokenizer 分析
首先比较两个输入经过 Tokenizer 后的结果。
显示:
Input A
lqak
Token:
[1234]
Input B
lQak
Token:
[5678]
如果 Token 数量发生变化,需要明显提示:
⚠ Tokenization changed
例如:
lqak
↓
[token 1234]
lQak
↓
[token 5678, token 8910]
这非常重要。
因为很多“模型为什么不同”的原因,其实在 Transformer 之前就已经产生了。
五、Embedding 分析
获取:
Embedding A
Embedding B
计算差异:
L2 distance
Cosine distance
Mean absolute difference
Maximum difference
显示:
Embedding Difference
Position 1 0.00
Position 2 0.82 ←
Position 3 0.00
Position 4 0.00
同时允许用户查看原始向量:
Position 2
A:
[0.12, -0.31, 0.55, ...]
B:
[0.18, -0.42, 0.61, ...]
六、Transformer 层级差异分析
这是整个项目的核心。
对每一层保存:
hidden_states
然后计算:
Difference(layer)
=
distance(
hidden_state_A,
hidden_state_B
)
得到:
Embedding 0.82
Layer 1 0.91
Layer 2 1.03
Layer 3 2.87 ← 突然增加
Layer 4 3.02
Layer 5 3.11
...
UI 用曲线显示:
Difference
↑
│ ●
│ ●
│ ●
│ ●
│ ●
│ ●
└────────────────────→
Emb L1 L2 L3 L4 ...
用户能够一眼发现:
差异从哪一层开始明显扩大。
七、Attention 分析
对每个 Transformer Layer:
Layer 1
Layer 2
Layer 3
...
进一步分析每个 Attention Head:
Layer 3
Head 1 0.12
Head 2 0.08
Head 3 0.14
Head 4 1.21 ←
Head 5 0.10
Head 6 0.07
...
得到:
哪个 Head 对输入扰动最敏感。
计算方式可以先使用:
mean(abs(A - B))
并提供:
L1
L2
Frobenius norm
Cosine distance
等指标。
八、Attention Matrix 可视化
用户点击:
Layer 3 → Head 4
显示:
Input A
l q a k
l ...
q ...
a ...
k ...
Input B
l Q a k
l ...
Q ...
a ...
k ...
同时显示:
Difference
l Q a k
l . . . ██
Q . . . ███
a . . . ██
k . . . █
目标不是单纯漂亮,而是让用户看到:
某个字符发生变化后,Attention 的信息流向发生了什么变化。
九、Q / K / V 分析
对于 Attention:
Q = X WQ
K = X WK
V = X WV
工具需要能够获取:
Q_A
Q_B
K_A
K_B
V_A
V_B
并比较:
ΔQ
ΔK
ΔV
例如:
Layer 3 / Head 4
Q difference ██████████
K difference ███
V difference █
得到一个非常直观的结果:
这个输入变化主要改变了 Query,而不是 Value。
十、权重分析
需要提供“权重查看器”。
重点不是让用户一次看到几十亿参数,而是:
只查看当前计算路径真正涉及的权重。
例如:
Layer 3
Head 4
WQ
WK
WV
WO
点击:
WQ
显示:
Shape:
[head_dim, hidden_dim]
Statistics:
mean
std
min
max
norm
并支持矩阵热力图。
十一、输入 × 权重 × 输出分析
这是项目非常重要的功能。
界面设计成:
Input
│
▼
┌───────┐
│ X │
└───┬───┘
│
┌───────┼────────┐
│ │ │
▼ ▼ ▼
WQ WK WV
│ │ │
▼ ▼ ▼
Q K V
│ │ │
└───┬───┘ │
▼ │
Q × Kᵀ │
│ │
Softmax │
│ │
└─────┬──────┘
▼
Attention
用户点击任意节点,可以查看:
输入是什么
矩阵是什么
输出是什么
shape 是什么
A/B 两个输入差多少
十二、Logits 分析
最后必须分析模型输出,而不仅仅是 Attention。
获取:
logits_A
logits_B
计算:
Δlogits
并排序:
Token Logit A Logit B Difference
the 3.21 4.82 +1.61
a 2.91 2.10 -0.81
...
同时显示 Top-K:
Input A
1. the 32%
2. a 21%
3. ...
Input B
1. a 41%
2. the 18%
3. ...
这样形成完整链条:
输入差异
↓
Token差异
↓
Embedding差异
↓
Layer差异
↓
Attention差异
↓
Q/K/V差异
↓
Logit差异
↓
Output差异
十三、“差异传播”自动分析
工具不能只展示数据,还应该自动生成一个初步结论。
例如:
分析结果
Input:
lqak
Changed:
q → Q
主要变化:
① Tokenization
发生变化
② Embedding
Position 2 差异最大
③ Layer 3
隐藏状态差异明显扩大
④ Layer 3 / Head 4
差异最大
⑤ 主要变化
Q:明显变化
K:中等变化
V:变化较小
⑥ Attention
Position 2 → Position 4
注意力增加
⑦ 最终结果
Token "the" 的 logit 增加 1.61
注意:
这里不能轻易使用“因果”这个词。
第一版应该称:
Difference tracing / sensitivity analysis
因为仅仅观察相关性,还不能证明某个 Head 是严格意义上的因果原因。
十四、增加“消融实验”
第二阶段加入真正更接近因果分析的功能。
例如发现:
Layer 3 / Head 4
非常敏感。
可以进行:
原模型
↓
关闭 Head 4
↓
重新计算
↓
比较输出
如果:
正常:
lqak → A
lQak → B
关闭 Head 4:
lqak → A
lQak → A
那么就获得了更强的证据:
Head 4 对这个输入差异具有重要作用。
进一步支持:
Head ablation
Layer ablation
Neuron ablation
十五、最终 UI
建议采用三栏结构。
左侧:输入
Model
[GPT-2 ▼]
Input A
[lqak ]
Input B
[lQak ]
[Run Analysis]
下面:
Automatic Perturbation
☑ Uppercase
☑ Lowercase
☐ Replace
☐ Delete
☐ Insert
中间:Transformer
Tokenizer
↓
Embedding
↓
Layer 1
↓
Layer 2
↓
Layer 3 ← ★
↓
Layer 4
↓
Layer 5
↓
Output
每个节点根据差异程度显示强弱。
点击:
Layer 3
进入 Layer 分析。
点击:
Head 4
进入 Attention 分析。
右侧:详细数据
根据当前选择显示:
Layer 3 / Head 4
Input difference
...
Attention Matrix
...
Q difference
...
K difference
...
V difference
...
Weights
...
A/B comparison
...
十六、技术架构
推荐:
Python
│
├── PyTorch
├── Transformers
├── NumPy
├── FastAPI
│
└── Backend
│
▼
API
│
▼
React / TypeScript
│
├── Layer Viewer
├── Attention Viewer
├── Matrix Viewer
├── Difference Chart
└── Token Viewer
第一版甚至可以不用复杂前端。
可以:
Python
+
Gradio
快速做出 MVP。
确认分析逻辑正确以后,再换:
FastAPI + React
十七、模型 Hook 机制
开发时必须设计统一的 Hook 系统。
不要把代码写死在 GPT-2 上。
建立统一接口:
ModelAdapter
例如:
get_tokenizer()
get_embeddings()
get_hidden_states()
get_attention()
get_qkv()
get_logits()
以后支持:
GPT-2
Llama
Qwen
Mistral
Gemma
其他 Hugging Face 模型
只需要增加 Adapter。
十八、数据结构
建议每次分析保存成:
AnalysisResult
├── input_a
├── input_b
├── tokens_a
├── tokens_b
│
├── embedding
│
├── layers
│ ├── layer_0
│ ├── layer_1
│ ├── layer_2
│ └── ...
│
├── attention
│ ├── layer_0
│ │ ├── head_0
│ │ ├── head_1
│ │ └── ...
│
├── qkv
│
├── logits
│
└── summary
这样以后可以保存实验:
experiment_001.json
进行不同实验之间比较。
十九、性能要求
第一版不要保存所有大型矩阵。
必须考虑:
GPU memory
CPU memory
模型大小
序列长度
原则:
按需捕获。
默认只保存:
hidden states
attention
logits
用户点击某一层以后,再进行详细:
Q/K/V
weight
intermediate activation
分析。
二十、开发阶段
Phase 1:最小实验
目标:
GPT-2
+
lqak
+
lQak
实现:
Tokenizer
Embedding
Hidden states
Logits
能够计算:
ΔEmbedding
ΔLayer
ΔLogits
Phase 2:Attention
增加:
Attention Matrix
Head comparison
Layer comparison
完成:
找出最敏感的 Layer + Head。
Phase 3:QKV
增加:
Q
K
V
WQ
WK
WV
完成:
Input → Weight → Output 分析。
Phase 4:可视化
增加:
Layer difference chart
Attention heatmap
QKV comparison
Logit comparison
Token visualization
Phase 5:自动解释
自动生成:
Difference Report
例如:
最显著变化:
Layer 3 / Head 4
主要变化:
Query
主要影响:
Position 2 → Position 4
最终影响:
Token X 的概率增加。
Phase 6:消融实验
增加:
Head Ablation
Layer Ablation
Neuron Ablation
从:
“哪里不同?”
进一步发展到:
“去掉什么以后,这个差异就消失?”
二十一、测试案例
必须建立固定测试集。
Case 1:大小写
lqak
Lqak
lQak
lqaK
Case 2:单字符替换
lqak
lqak
lqax
Case 3:增加字符
lqak
lqakk
Case 4:删除字符
lqak
laq
Case 5:空格
hello world
helloworld
Case 6:标点
hello!
hello.
Case 7:自然语言
The cat is on the mat.
The Cat is on the mat.
二十二、最重要的设计原则
整个项目必须遵守一个原则:
先观察,再解释;先定位差异,再讨论原因。
不要让 AI 一看到:
q → Q
就直接说:
“模型理解了大写代表专有名词。”
必须把解释拆成证据链:
输入发生变化
↓
Tokenizer 是否变化?
↓
Embedding 是否变化?
↓
哪一层差异扩大?
↓
哪个 Head?
↓
Q/K/V 哪一个?
↓
Attention 到哪里?
↓
哪些 Logits 改变?
↓
消融后是否仍然存在?
只有证据越来越充分,才能把:
相关
逐渐提升为:
机制假设
甚至:
因果证据
二十三、最终项目目标
这个工具最终不是一个普通的:
Transformer 可视化器。
而应该成为一个:
Transformer 显微镜
它回答三个问题:
输入
我改变了什么?
中间过程
模型内部哪里开始发生变化?
输出
这个变化最终怎样影响模型的判断?
最终形成:
输入
↓
Token
↓
Embedding
↓
Layer
↓
Head
↓
Q/K/V
↓
Attention
↓
Hidden State
↓
Logits
↓
Output
并且任何一步都可以点击进去继续观察。
第一版只要把 lqak → lQak 这一个实验完整跑通,就算 MVP 成功。
后面的所有功能,都围绕这个实验逐步扩展。