Vect0rdecay/GraphSurgeon
GitHub: Vect0rdecay/GraphSurgeon
一款用于 ONNX 计算图逆向工程的工具,支持架构参数推断、结构 Motif 检测、反事实图编辑与 3D 可视化。
Stars: 0 | Forks: 0
# GraphSurgeon
GraphSurgeon 可以从命令行或 Python 对 ONNX 计算图进行逆向工程。它能总结输入和算子,映射深度和执行顺序,检测 DAG 中的结构 Motif,交叉引用对抗性机器学习(AML)文献,叙述数据流,并支持带有验证和 diff 的反事实编辑。
### 最近更新
- **架构推断**(2026 年 6 月)— `inspect` 现在可以直接从 ONNX 图中推断隐藏维度、词表大小、MLP 中间层大小、最大位置嵌入、RoPE theta、绑定嵌入、卷积分组(conv groups)和量化格式。使用 `--json` 获取结构化输出。参见[架构推断](#architecture-inference)。
- **外部数据回退** — 解析器现在通过回退到仅解析图结构的方式,加载缺失或不完整的外部权重数据的模型。损坏或存根(stub)ONNX 文件会收到清晰的错误消息,而不是 traceback。
- **3D 查看器** — 交互式太空主题可视化,支持 WASD 飞行穿梭、Motif 区域高亮、ShadowLogic 叠加层、每个节点的结构概况、反事实编辑以及可折叠的侧边栏。参见 [3D 可视化](#3d-visualization)。
该工具仅支持 ONNX。它不需要 PyTorch 或 CUDA 工具包。
## 功能说明
| 命令 | 作用 |
|---------|------|
| `inspect` | 模型摘要:I/O 张量、算子组合以及推断的架构(隐藏维度、词表大小、MLP 大小、RoPE theta、绑定嵌入、最大位置、卷积分组、量化) |
| `topology` | 图深度、前部/中部/后部层桶(buckets)、执行顺序 |
| `patterns` | 粗粒度结构块(conv 堆栈、attention、normalization 链) |
| `motifs` | 注册表支持的结构 Motif:图拓扑在架构上使得哪些攻击类别变得合理 |
| `flow` | 纯英文的执行叙述 |
| `catalog` | 查找 Gadgets、复合链、文献技术以及打包的论文笔记 |
| `operators` | 以安全相关行为为键的 ONNX 算子参考 |
| `edit` | 反事实图手术(`remove-node`),支持结构、可加载或可运行级别的验证 |
| `diff` | 在编辑后比较两个 ONNX 文件 |
| `export-scene` | 为 3D 查看器导出 SceneGraph JSON |
| `serve` | 启动一个支持反事实编辑的实时 3D 可视化服务器 |
Motif 命中描述的是攻击面概况(即该架构允许的攻击类型),而不是确认的可利用性。该工具不会分配风险评分或严重性等级。
## 架构推断
`inspect` 自动从 ONNX 图结构推断模型架构参数 — 无需配置文件或模型卡片。它仅报告它能确定的字段;未知的字段会被省略。
| 字段 | 推断方式 |
|-------|-------------------|
| 隐藏维度 | Normalization 节点(LayerNormalization, SimplifiedLayerNormalization, SkipSimplifiedLayerNormalization, SkipLayerNormalization, RMSNormalization)中一维权重形状的众数。回退到最常见的 MatMul/MatMulNBits 权重维度,然后是 Conv 输出通道数。 |
| 词表大小 | 嵌入权重(Gather/GatherBlockQuantized 节点)的第一维度,结合来自最终 MatMul/MatMulNBits/Gemm 的 LM head 输出维度。当多个信号一致时,返回频率最高的候选值。 |
| MLP 中间层大小 | 通过节点名称识别(gate_proj, up_proj, fc1, c_fc, wi)的 gate/up 投影权重的输出维度。回退到后接 Mul/Sigmoid 模式的 MatMul 节点。 |
| 最大位置嵌入 | 名称包含 cos_cache, sin_cache, cos_cached, sin_cached, pos_embed, position_embed 或 wpe 的 initializer 的第一维度。 |
| RoPE theta | 从预计算的 cos_cache 张量值逆向工程得出;回退到名称包含 inv_freq, freqs 或 rope_freq 的 initializer 张量,然后是 RotaryEmbedding 节点属性。在 1% 容差范围内吸附到常见的 theta 值(10000, 500000, 1000000 等)。 |
| 绑定嵌入 | 检测同时被嵌入节点(Gather/GatherBlockQuantized/Embedding)和图后部或 lm_head 节点(MatMul/MatMulNBits/Gemm/Transpose)消费的 initializer。也会检查在剥离量化后缀后是否共享基础权重名称。 |
| 卷积分组(Conv groups) | Conv 节点的 group 属性(仅在 > 1 时报告) |
| 量化格式 | 从 MatMulNBits 位宽属性或 DequantizeLinear 的存在中检测 |
已在 Liquid AI LFM2.5 模型(混合门控 conv + GQA + RoPE + SwiGLU)上跨 fp32、fp16、Q4 和 Q8 量化格式进行了测试。隐藏维度和 MLP 大小的回退路径涵盖了标准的基于 MatMul 和基于 Conv 的架构,但尚未在纯 CNN 或标准仅 Transformer 模型上进行验证。当外部权重数据不可用时,基于形状的字段仍然可以解析 — 只有 RoPE theta 需要实际的张量字节(所有三个恢复路径 — cos_cache, inv_freq 和节点属性 — 都依赖于加载的数据或非零属性)。
示例输出:
```
Architecture:
Hidden dimension: 2048
Vocab size: 65536
MLP intermediate size: 8192
Max position embeddings: 128000
RoPE theta: 1000000
Tied embeddings: True
Tied initializers: ['model_embed_tokens_weight_scales', 'model_embed_tokens_weight_zp']
Conv groups: 2048
Quantization: Q4
```
使用 `--json` 获取适合脚本编写和跨模型比较的结构化输出。
## 安装说明
```
cd graph-surgeon
python3 -m venv .venv
.venv/bin/python -m pip install -e ".[dev]"
```
| 包 | 用途 |
|---------|---------|
| `onnx`, `numpy` | 核心图解析、Motif、拓扑(始终安装) |
| `onnxruntime` | `edit validate --level loadable/runnable`(通过 `[dev]`) |
| `pytest` | 测试套件(通过 `[dev]`) |
| `fastapi`, `uvicorn` | 用于实时 3D 可视化的 `serve` 命令(通过 `[viz]`) |
最小化安装(无运行时验证或测试):
```
.venv/bin/python -m pip install -e .
```
## CLI
在 `pip install -e .` 之后,使用项目 venv(除非你激活 venv,否则 `graph-surgeon` 命令不在你的系统 PATH 中):
```
source .venv/bin/activate # optional; then graph-surgeon works on PATH
# 或者总是:
.venv/bin/graph-surgeon --help
.venv/bin/python -m graph_surgeon catalog --coverage
```
```
graph-surgeon inspect model.onnx # human-readable summary + architecture
graph-surgeon inspect model.onnx --json # full report as JSON
graph-surgeon topology model.onnx
graph-surgeon patterns model.onnx
graph-surgeon motifs model.onnx -o report.json
graph-surgeon flow model.onnx
graph-surgeon catalog --gadget GAP_FC_HEAD
graph-surgeon catalog --chain CHAIN-PATCH-ATTACK-SURFACE
graph-surgeon catalog --coverage
graph-surgeon operators --op Conv
graph-surgeon edit validate edited.onnx --level runnable
graph-surgeon edit remove-node model.onnx NODE_NAME -o edited.onnx
graph-surgeon diff baseline.onnx edited.onnx
graph-surgeon export-scene model.onnx -o scene.json
graph-surgeon serve model.onnx --port 9095
```
当检测到 Motif 或链时,使用 `catalog --gadget` 或 `catalog --chain` 获取注册表元数据、检测逻辑和论文综述。显示标题使用注册表 ID(例如 `GAP_FC_HEAD — Global Average Pool → FC Head`)。
反事实编辑(`edit`)目前暴露了一个手术子命令:`remove-node`。在编辑之前,使用 `inspect` 或 `topology` 发现确切的 ONNX 节点名称。
## 研究语料库
GraphSurgeon 在 `graph_surgeon/taxonomy/data/`(特别是 `attack_research_notes.md`)下提供了按论文分类的分析。该语料库为丰富的目录输出提供了动力:当你查找 Gadget 或链时,你会获得链接的 AML 文献、ONNX 图指标和攻击类映射,而无需获取外部文档。
正常使用不需要触碰这些文件。要查看完成状态:
```
.venv/bin/graph-surgeon catalog --coverage
```
## Python API
GraphSurgeon 主要是一个 CLI 工具,但同样的分析和手术路径也可以从 Python 中使用。包级别的导出(`from graph_surgeon import ...`):`GraphSurgeon`, `GraphTopology`, `GraphTopologyConfig`, `LayerPosition`, `NodeTopology`, `GraphValidationLevel`, `GraphValidationResult`。
### 分析(Motif、模式、流)
这些镜像了 `motifs`、`patterns` 和 `flow`:
```
from graph_surgeon.parsers.onnx_parser import analyze_onnx_graph, analyze_onnx_patterns, quick_scan
motif_report = analyze_onnx_graph("model.onnx", output_path="report.json")
print(len(motif_report.structural_findings), motif_report.model_flow_description)
pattern_report = analyze_onnx_patterns("model.onnx")
print(quick_scan("model.onnx"))
```
从 Motif 导出的 JSON 使用与 CLI 输出相同的清理器(内部评分字段已被剥离)。
### 拓扑和图检查
```
from graph_surgeon import GraphSurgeon, LayerPosition
surgeon = GraphSurgeon(verbose=False)
model = surgeon.load_model("model.onnx")
topo = surgeon.get_graph_topology(model.graph)
print(topo.total_nodes, topo.max_depth)
print(topo.by_position[LayerPosition.EARLY][:5])
print(topo.by_position[LayerPosition.LATE][:5])
print(surgeon.find_nodes_by_type(model.graph, "Conv"))
```
### 目录和分类体系
这些镜像了 `catalog` 查找:
```
from graph_surgeon.taxonomy.display import format_catalog_gadget, format_catalog_chain
from graph_surgeon.taxonomy.research_coverage import format_coverage_report
from graph_surgeon.taxonomy import motif_catalog
print(format_catalog_gadget("LINEAR_HEAD"))
print(format_catalog_chain("CHAIN-SKIP-HIGHWAY"))
print(format_coverage_report())
technique = motif_catalog.get_technique_by_id("AML-ADV-002")
```
### 反事实编辑
CLI 对等物:`remove_node` 匹配 `edit remove-node`。所有手术方法都会就地改变已加载的 `ModelProto`,并返回一个 `SurgeryResult`(`success`, `graph`, `message`, `nodes_added`, `nodes_removed`, `nodes_modified`, `edges_rewired`)。
```
from graph_surgeon import GraphSurgeon, GraphValidationLevel
surgeon = GraphSurgeon(verbose=False)
baseline = surgeon.load_model("model.onnx")
edited = surgeon.clone_model(baseline)
result = surgeon.remove_node(edited, "node_relu_23")
if not result.success:
raise RuntimeError(result.message)
surgeon.save_model(edited, "edited.onnx")
check = surgeon.validate(edited, level=GraphValidationLevel.STRUCTURAL)
print(check.valid, check.errors)
diff = surgeon.compare_graphs(baseline, edited)
print(diff["summary"], diff["nodes_removed"])
```
`GraphValidationLevel.LOADABLE` 和 `.RUNNABLE` 需要 `onnxruntime`(通过 `pip install -e ".[dev]"` 安装)。在最小化安装时,验证会回退并伴有警告。
其他图手术原语(`remove_subgraph`, `insert_node_before`, `insert_node_after`, `replace_node`, `modify_node_attribute`, `add_initializer`, `add_metadata`)目前仅支持 Python。完整的 `GraphSurgeon` 参考请参见 [docs/PYTHON_API.md](docs/PYTHON_API.md)。
### 架构推断
```
from graph_surgeon.parsers.onnx_parser import ONNXGraphParser
from graph_surgeon.analysis.architecture import infer_architecture
parser = ONNXGraphParser()
graph = parser.parse_file("model.onnx")
arch = infer_architecture(graph)
print(arch.hidden_dim) # e.g. 2048
print(arch.vocab_size) # e.g. 65536
print(arch.rope_theta) # e.g. 1000000.0, or None
print(arch.tied_embeddings) # True, or None if not detected
print(arch.to_dict()) # dict of non-None fields only
```
### 可选的权重统计
启发式权重分布分析(仅需核心依赖;无需 `onnxruntime`):
```
from graph_surgeon.behavior.weight_signature import analyze_onnx_weights
stats = analyze_onnx_weights("model.onnx")
print(stats.summary())
```
## 文档
| 文档 | 内容 |
|-----|----------|
| [docs/PYTHON_API.md](docs/PYTHON_API.md) | 完整的 `GraphSurgeon` 方法参考、验证级别、手术结果字段 |
## 3D 可视化
GraphSurgeon 包含一个交互式 3D 查看器,将 ONNX 模型图渲染为可导航的场景,带有太空星云背景、受 Superluminal 启发的排版以及结构分析叠加层。
### 快速开始
```
pip install -e ".[viz]"
source .venv/bin/activate
graph-surgeon serve model.onnx --port 9095
# 在浏览器中打开 http://127.0.0.1:9095
```
或者使用 Vite 导出静态场景并提供服务(用于开发):
```
graph-surgeon export-scene model.onnx -o viewer/sample_scene.json
cd viewer && npm install && ./node_modules/.bin/vite --port 5173
```
### 导航
| 控制 | 动作 |
|---------|--------|
| WASD | 飞行穿梭图(前/后/平移) |
| Q / Space | 向上飞 |
| E / Shift | 向下飞 |
| 鼠标拖拽 | 环绕相机 |
| 滚轮 | 放大/缩小 |
| 点击节点 | 打开节点详情面板 |
| 右键点击节点 | 反事实编辑菜单 |
| START / END(按钮) | 飞到图的开头或结尾 |
### Motif 和链可视化
检测到的对抗性 Motif 和复合链列在左侧边栏中。点击 Motif 会:
- **高亮** 3D 图中参与的节点(其他节点变暗)
- **在其节点周围显示一个半透明的边界区域**,按结构重要性进行颜色编码(红色 = EXCEPTIONAL,琥珀色 = PRIMARY,青色 = SECONDARY,绿色 = TERTIARY/MITIGATING)
- **打开详情面板**(右下角),显示:
- 结构重要性和置信度徽章
- 模式的技术描述
- 该架构允许的攻击类型
- 检测逻辑(GraphSurgeon 是如何发现它的)
- 来自内置 AML 语料库的研究论文参考文献
- 可点击的节点 ID,可使相机飞至每个节点
使用 "SHOW ALL REGIONS" 可一次性点亮每个 Motif 区域,以全面了解攻击面概况。重复的发现(例如 50 多个 BatchNorm 统计信息泄露实例)被分组为一个带有计数的单独侧边栏条目。
### 布局
查看器使布局适应图的形状:
- **宽图**(如 Inception 等分支架构):节点按父级连接性排序,并在每个深度水平分布
- **窄图**(如 ResNet 等序列模型):螺旋/螺线路布局,防止形成单条垂直线
- **仅参数节点**(仅消费 initializer 的 Unsqueeze, Reshape 操作):重新定位到其消费者节点旁边,而不是堆积在深度 0 处
### 附加功能
- **搜索**:在搜索栏中输入以按名称或操作类型过滤节点
- **流遍历(Flow walk)**:"WALK FLOW" 按执行顺序逐级遍历,并带有显示每个级别节点的详情面板
- **模型流描述**:"VIEW MODEL FLOW" 打开全屏的可读叙述
- **ShadowLogic 叠加层**(用于识别潜在逻辑注入点的项目定义启发式方法):在 3D 图上显示注入点标记,支持飞至导航和每个点的详情弹出窗口
- **结构模式**:切换高亮以显示梯度瓶颈、融合点、放大层和防御点
- **每节点的结构概况**:点击节点会显示拓扑衍生的结构代理指标(梯度敏感度、Lipschitz 估计、扰动放大、ShadowLogic 容量、提取泄露)的仪表条指标;这些是基于图结构的启发式估计,而不是运行时计算的值
- **可折叠侧边栏**:所有部分(流、导航、ShadowLogic、模式、Motif 和链)均可独立折叠
- **拖放**:将 `scene.json` 文件拖放到查看器上即可加载
- **反事实编辑**:右键点击节点将其移;服务器会重新分析并且视图会实时更新
## 与 Netron 的比较
Netron 是一个图查看器:在屏幕上显示节点、张量和形状。
GraphSurgeon 是在相同 ONNX 文件之上的分析和实验层:
- 位置拓扑(stem 对 middle 对 head)和有序执行,而不仅仅是邻接关系
- 带有类型化注册表和文献交叉引用的自动化 Motif 和模式检测
- 可搜索的 Gadget、链、技术和打包论文笔记目录
- 反事实编辑(移除节点、重新连线、验证、与基线进行 diff)
- 用于脚本编写和跨模型变体批量比较的 JSON 导出
使用 Netron 查看图;使用 GraphSurgeon 解释结构,将其与已发布的攻击类别相关联,测试当你改变 DAG 时会发生什么变化,并以 3D 方式可视化对抗性攻击面。
## 测试
单元测试(无外部 ONNX 文件):
```
.venv/bin/python -m pytest tests/ -v
```
需要不在本仓库中的 ONNX fixtures 的集成测试已被 gitignore 忽略,并在 `tests/README.md` 中有说明。
## 许可证
MIT
标签:CNCF毕业项目, ONNX, 人工智能, 可视化工具, 模型结构分析, 模型逆向分析, 用户模式Hook绕过, 计算图, 逆向工具