源码评估报告

Graphify 全面解析 & GitNexus 替换评估

"看下这个项目是不是噱头 · 需不需要把工作看板的代码图谱换成这个"
日期 2026-04-13 Graphify v0.4.8 · 8,237 LOC · Python GitNexus · 31,367 LOC · TypeScript 仓库快照 ~/Projects/research/20260413-graphify-analysis/
结论
Graphify 不是噱头,是一个被过度营销的实用单项目 AST 索引工具,"GraphRAG / 多模态 AI 架构助理" 是包装话术。 但不要替换工作看板的 GitNexus —— GitNexus 在代码静态分析这一维度比 Graphify 领先一个量级。
目录
  1. 一、Graphify 架构速览
  2. 二、执行流程 & 关键发现
  3. 三、核心模块逐个解剖(带行号)
  4. 四、"GraphRAG" 噱头验证
  5. 五、"71.5× token 节省" 真相
  6. 六、设计亮点(可抄)
  7. 七、技术短板
  8. 八、GitNexus vs Graphify 对比
  9. 九、最终建议

一、Graphify 架构速览

一句话:tree-sitter AST 提取器 + networkx 图 + Leiden 社区检测 + 10 种导出格式 + 9 种 Agent 平台集成脚本。 零 LLM 依赖,"智能"部分全部外包给宿主 Agent(Claude Code / Codex / OpenCode / ...)。

文件行数作用
extract.py2804tree-sitter AST 提取(22 语言)—— 真正的发动机
export.py1001HTML / SVG / GraphML / Cypher / Obsidian 导出
__main__.py972CLI + 9 种 AI 平台 install/uninstall 脚本
analyze.py537god nodes(度数排序)+ surprising connections(跨社区边)
detect.py502文件扫描 + 类型识别(含论文启发式)+ .graphifyignore
serve.py364MCP stdio server(7 个工具)
ingest.py297URL 抓取:twitter/arxiv/github/youtube/pdf/image/web
hooks.py198git post-commit/checkout 自动重建(纯 AST)
security.py197SSRF 防护 + URL 校验 + redirect 再验证
watch.py183文件监听,代码变更增量重建
transcribe.py182whisper 视频/音频转写(可选)
report.py175GRAPH_REPORT.md 生成
cache.py154SHA256 文件级缓存(markdown 剥 YAML frontmatter)
cluster.py137Leiden / Louvain 社区检测 + 大社区拆分
benchmark.py129token reduction 计算 —— 71.5× 来源
build.py87dict → networkx.Graph 组装
(其余小文件:validate / wiki / __init__ / manifest · 共 ~130 行)
合计8,23720 个 .py 文件 · MIT License · PyPI: graphifyy

依赖(全部本地库,无 LLM SDK)

# 核心
networkx
tree-sitter >= 0.23.0
tree-sitter-{python,javascript,typescript,go,rust,java,c,cpp,ruby,
             c-sharp,kotlin,scala,php,swift,lua,zig,powershell,
             elixir,objc,julia}  # 22 种语言

# 可选 extras
mcp            # MCP server
neo4j          # 直推图数据库
pypdf          # PDF 文本提取
graspologic    # Leiden(否则回落 Louvain)
python-docx    # Office
faster-whisper # 视频转写
yt-dlp         # YouTube 下载

二、执行流程 & 关键发现

关键发现:完整 pipeline 不在 CLI 里

__main__.pymain() 只有 install / query / benchmark / save-result / hook 等子命令 (__main__.py:780-968)—— 根本没有 "build graph" 子命令

完整 pipeline 是被 skill.md 驱动的:宿主 Agent 按 skill.md 的 step 1..N,用内联 python3 -c "from graphify.X import Y" 挨个调各模块。这种"skill 脚本驱动"设计 把 LLM 部分合法地外包给宿主 Agent,Python 包就完全 offline。

# 实际执行顺序(由 skill.md 协调)
detect.detect(root)                        # detect.py:329  扫描+分类并行
  ├── extract.extract(code_paths)          # extract.py:2639  tree-sitter AST
  └── [宿主 Agent subagent 读 PDF / 图 / markdown] → JSON
cache.save_semantic_cache(...)             # cache.py:119
build.build([ast_result, semantic_result]) # build.py:84
cluster.cluster(G)                         # cluster.py:59  Leiden/Louvain
analyze.god_nodes + surprising_connections # analyze.py:42/61
report.generate(...)                       # report.py:14
export.to_html / to_json / to_obsidian     # export.py:329/285/447

三、核心模块逐个解剖

3.1 extract.py(2804 行) —— 真正的发动机

架构模式:LanguageConfig dataclass(extract.py:24-60)+ 通用 _extract_generic()(extract.py:645-1010)+ 每种语言一个配置实例 + 少数语言特有的 walker。

class LanguageConfig:
    class_types        # 哪些 tree-sitter 节点类型算"类"
    function_types     # 哪些算"函数"
    import_types
    call_types
    name_field         # 默认从哪个 field 拿名字
    body_field
    function_boundary_types  # 递归到这里停
    import_handler     # 每种语言 import 语法不一样,单独回调
    resolve_function_name_fn # C/C++ 用 declarator 解包
    extra_walk_fn      # JS 箭头、C# namespace 等特殊分支

13 种语言走通用路径(extract.py:419-627),7 种独立手写(因为 tree-sitter 节点命名差太大): extract_go(190 行)extract_rust(168 行)extract_zigextract_powershellextract_objcextract_elixirextract_julia

两遍 walk:

  1. 结构 walk(extract.py:703-866):进 class 建节点 + contains/method/inherits 边;进 function 记下 body 挂到 function_bodies 列表
  2. 调用图 walk(extract.py:877+):对每个 function body 再 walk,找 callee 名字,查 label_to_nidcalls

亮点: Python 独有的 _resolve_cross_file_imports

extract.py:2110-2240,130 行 —— 整个项目 唯一真正跨文件推理的地方。

Pass 1:扫所有 Python 文件的 AST 节点,建 stem_to_entities[stem][ClassName] = nid 全局映射表。
Pass 2:对每个文件找 from .models import Response,在映射表里查到 Response 的 nid,然后对当前文件里的每个 class,添加 DigestAuth --uses--> Response 的 INFERRED 边。

这是"god nodes / surprising connections"最后能出东西的关键 —— 没这步,Python 项目全是 contains 边的垃圾。其他 21 种语言都没做这个,只有结构 + 同文件 calls。

3.2 detect.py(502 行) —— 文件扫描

3.3 cache.py(154 行) —— SHA256 内容缓存

3.4 cluster.py(137 行) —— Leiden / Louvain

3.5 analyze.py(537 行) —— "智能"层

其实都是 networkx 一行题

god_nodes(analyze.py:42)= dict(G.degree()) 排序,过滤掉文件节点 + concept 节点,取 top_n。 所谓"god nodes" = 度数最高的真实实体。_is_file_node(analyze.py:11-38)过滤三类伪节点:文件级 hub、.method() 方法桩、孤立 func()

_surprise_score()(analyze.py:131-184)是一个朴素加权:

3.6 serve.py(364 行) —— MCP 服务器

暴露 7 个 MCP 工具:query_graphget_nodeget_neighborsget_communitygod_nodesgraph_statsshortest_path(serve.py:156-226)。

注意:"查询"不是语义搜索

_score_nodes(serve.py:42)就是把问题 split 成 >2 字符的词, 在 label 里子串匹配 +1 / source_file +0.5,排序取 top3 当 BFS 起点。 没有 embedding、没有 BM25、甚至没有 stemming。对中英混合语料很不友好。

3.7 export.py(1001 行) —— 十种输出

3.8 security.py(197 行) —— SSRF 防护

validate_url 解析 hostname → getaddrinfo → 拒绝 is_private / is_reserved / is_loopback / is_link_local,加黑名单 metadata.google.internal (security.py:14-64)。_NoFileRedirectHandler 重写 HTTPRedirectHandler, 每次 redirect 都重新校验一遍 —— 防 open-redirect SSRF。写一个抓取模块就自带这种层次的防护,不常见。

四、"GraphRAG" 噱头验证

"GraphRAG" 按微软原论文定义:LLM 抽实体 + LLM 抽关系 + LLM 写社区摘要 + 分层答案合成。Graphify 对齐情况:

GraphRAG 环节Graphify 做法状态
LLM 抽实体tree-sitter AST(代码)/ 宿主 Agent subagent(非代码)
LLM 抽关系AST + 字符串 heuristics
社区检测Leiden / Louvain
LLM 写社区摘要只有 label 模板,宿主 Agent 可能帮忙写
分层答案合成BFS + term-frequency 子串匹配

结论:这不是 GraphRAG,是"一个有置信度标签的 tree-sitter 代码图谱工具 + Obsidian 导出器 + 9 个 Agent 平台的 SKILL.md 胶水"。 技术本身合格(8k LOC 大部分在 extract.py 真的干活),但把它叫 "GraphRAG AI 架构助理" 是营销话术。

五、"71.5× token 节省" 真相

拆开 benchmark.py 看(benchmark.py:1-130):

_CHARS_PER_TOKEN = 4
corpus_tokens   = corpus_words * 100 // 75   # 1 词 ≈ 1.33 token
query_tokens    = BFS 子图渲染文本长度 // 4
reduction_ratio = corpus_tokens / avg(query_tokens of 5 个固定英文问题)

# 5 个固定问题(benchmark.py:55-61)
"how does authentication work"
"what is the main entry point"
"how are errors handled"
"what connects the data layer to the api"
"what are the core abstractions"

71.5× 是怎么来的

= "整个语料的 token 数" 除以 "单次 BFS 子图的 token 数"。不包含建图时烧掉的 subagent token

代码库很好看(AST 零 token + 后续查询便宜),对论文/截图混合语料有水分 —— 首次建图那一次 PDF subagent 读取的 token 会把 ratio 稀释。

而且固定 5 个英文问题 + 子串匹配选起点 —— 换一个中文项目可能选不到起点直接返回 0。

六、设计亮点(这些可以抄)

1. LanguageConfig 模式

extract.py:24。通用 walker + 每语言差异填配置。13 种语言共用 200 行通用代码。

2. SHA256 内容缓存 + Markdown 剥 frontmatter

cache.py:20。"改 metadata 不触发重抽取"这种细节。

3. 三档置信度 + score

每条边打 EXTRACTED/INFERRED/AMBIGUOUS,INFERRED 再带 0.6-0.95 的 confidence_score,报告里直接出现 "avg confidence: 0.78",诚实度拉满

4. Python 跨文件 class 级 uses 边

extract.py:2110。让 god nodes 变得有意义的关键。

5. 单 HTML 交互图

export.py:329。内嵌 vis.js,无需服务器,发一个文件给客户直接看。

6. 9 平台集成脚本

__main__.py:49-105。Claude/Codex/Cursor/OpenCode/Aider/Copilot/OpenClaw/Factory/Trae/Antigravity/Gemini。

7. SSRF 防护默认打开

security.py:14-64。默认写一个 URL 抓取模块就有这种层次的防护,业界少见。

8. 大社区自动拆分

cluster.py:93。>25% 超大社区二次 Leiden 拆,防退化。

七、技术短板

  1. 22 语言"支持"很不均匀:只有 Python 做了跨文件 uses 推断,其他 21 种只有"同文件级 calls + imports"。多语言 polyglot 项目图质量会肉眼可见不如 Python。
  2. _extract_python_rationale(extract.py:1011)基于 docstring 的 "X because Y" heuristics 脆得很。
  3. 查询不是语义搜索,是子串 +1/+0.5 打分,没有 embedding/BM25/stemming。中英混合语料不友好。
  4. _make_idre.sub(r"[^a-zA-Z0-9]+", "_", combined)(extract.py:14)—— 对中文/非 ASCII 标识符直接 collapse 成空串,中文代码库识别不了
  5. C++ 模板/宏、Python metaclass/装饰器动态类、JS Proxy/Reflect 这类 AST 看不穿的东西通通识别不出来 —— 本质上是静态结构提取。
  6. benchmark 的 71.5×:固定 5 个英文问题 + 子串匹配选起点。
  7. 无类型系统:没有 symbol table、没有 type env、没有方法解析顺序(MRO)。
  8. _is_file_node 启发式(analyze.py:11-38)在非 Python 语言下容易误伤 —— Go/Rust 函数都是 () 结尾,又按 degree 判断……补丁摞补丁。
  9. PyPI 包名 graphifyy(两个 y,因为 graphify 被占),看得出作者赶时间。

八、GitNexus vs Graphify 对比

你的工作看板现在用的是 ~/Projects/code/20260319-gitnexus/(来源 abhigyanpatwari/GitNexus,17.8k stars,浏览器端 WASM 方案)。

维度GitNexus(你已有)Graphify
代码规模 31,367 行 TypeScript 8,237 行 Python
架构 浏览器 WASM 零服务器
Tree-sitterLadybugDBSigma.js
Python CLI + networkx 内存图
图数据库 LadybugDB(Cypher 查询) JSON 文件
类型系统 symbol-table.ts + type-env.ts + type-extractors/ —— 真的做类型推导
Python MRO mro-processor.ts —— 方法解析顺序
框架识别 framework-detection.ts
入口打分 entry-point-scoring.ts
跨文件 resolver resolvers/ + resolution-context.ts + named-binding-extraction.ts 只有 Python 做了 130 行
社区检测 Leiden + cluster-enricher.ts Leiden/Louvain
可视化 Sigma.js Web UI @ 4090 单 HTML + vis.js
多项目面板 Web UI 常驻 每项目一目录,一次性
MCP Server gitnexus/src/mcp/ serve.py(7 工具)
非代码输入(PDF/图/视频) 支持(外包给 subagent)
Obsidian 导出 有(每节点一 md + 社区 hub)
Agent 平台集成 Claude plugin + Cursor integration 9 种平台
诚信度标签 未知 EXTRACTED/INFERRED/AMBIGUOUS 三档
LLM 依赖 LangChain + 多家 LLM(可选增强) 无硬依赖(委托宿主 Agent)

GitNexus 的 gitnexus/src/core/ingestion/ 目录(一瞥)

ast-cache.ts           call-processor.ts         call-routing.ts
cluster-enricher.ts    community-processor.ts    entry-point-scoring.ts
export-detection.ts    filesystem-walker.ts      framework-detection.ts
heritage-processor.ts  import-processor.ts       language-config.ts
mro-processor.ts       named-binding-extraction.ts
parsing-processor.ts   pipeline.ts               process-processor.ts
resolution-context.ts  structure-processor.ts    symbol-table.ts
tree-sitter-queries.ts type-env.ts               type-extractors/
resolvers/             workers/

光是 ingestion 里就有 20+ 个处理器。在代码静态分析这件事上 GitNexus 已经把 Graphify 吊打了

九、最终建议

不要替换

GitNexus 在代码静态分析维度领先 Graphify 一个量级:真类型系统、MRO、框架识别、入口打分、完整 resolver —— 这些 Graphify 全都没有。 替换过去你会失去跨项目 Web UI、看板集成、浏览器 WASM 零服务器架构,换来的只是一套更弱的单项目 AST 抽取和几个你不需要的 Obsidian 模板。

保持现状,按需并用

GitNexus 继续作为工作看板代码图谱主干,Graphify 作为偶尔跑一次的单项目深度报告工具(需要 Karpathy 式 /raw 混合语料场景时)。两者并不冲突。

可以从 Graphify 借鉴的东西(选抄)

  1. 三档置信度 EXTRACTED/INFERRED/AMBIGUOUS + confidence_score —— 给 GitNexus 的边也加上,报告诚实度立即拉满
  2. Markdown 剥 YAML frontmatter 再哈希(cache.py:10-17)—— 细节体验
  3. 论文启发式识别 _looks_like_paper(detect.py:68)—— 13 条正则,简单有效
  4. 敏感文件过滤 _SENSITIVE_PATTERNS(detect.py:33-40)—— 安全默认值
  5. SSRF 防护整套(security.py:14-90)—— 如果 GitNexus 要加 URL 抓取功能直接移植
  6. 大社区 25% 拆分规则(cluster.py:93)—— 防 Leiden 出一个超大社区
  7. ingest.py 的 URL 分类抓取(297 行:twitter/arxiv/github/youtube/pdf/image/web)—— 给 GitNexus 补非代码输入时有现成逻辑

下一步(如果你感兴趣)

我可以继续深入看 GitNexus 的 gitnexus/src/core/ingestion/pipeline.tstype-extractors/,给你出一份 "GitNexus 现状 + 可增强点" 的专门评估 —— 这份评估完成后, 决定要不要把上述 Graphify 的借鉴项真正落到 GitNexus 里。