Graphify:71.5x token 压缩,靠的是诚实标注"我猜的"和"我读到的"
研究对象:
Graphify-Labs/graphify
抓取日期:2026-10-20 | 当日 stars:906
许可证:MIT | 语言:Python
一个数字引发的疑问
71.5x。
这是 Graphify 在 token 消耗上的压缩比。一个 2000 行的代码仓库,直接喂给 LLM 需要约 50,000 tokens;Graphify 把它转成知识图谱后,只需要约 700 tokens 就能让 LLM 理解整个仓库的结构。
71.5x 的压缩比不是靠更好的 embedding 模型,不是靠更大的上下文窗口,也不是靠更聪明的 chunking 策略。它靠的是一个老派的方法:把代码解析成图,然后只把图喂给 LLM。
但真正让这个项目有意思的不是压缩比,而是它对"信息确定性"的诚实标注。
三级置信度:EXTRACTED / INFERRED / AMBIGUOUS
大多数代码理解工具的输出是二元:要么"我理解了这段代码",要么"我不理解"。Graphify 给每条边(edge)打了三个标签:
- EXTRACTED:从源码中直接提取的。比如函数 A 调用了函数 B——这是从 AST 语法树中直接读出来的,没有歧义。
- INFERRED:基于代码模式推断的。比如函数 A 调用了函数 B,B 调用了 C,Graphify 推断 A 间接依赖 C——这是推断,不是直接读到。
- AMBIGUOUS:无法确定的。比如一个动态分发的调用,运行时才知道具体调用哪个函数——Graphify 标注为 AMBIGUOUS,不猜。
这个三级标注是 Graphify 最核心的设计决策。它让下游的 LLM 知道哪些信息是事实,哪些是推断,哪些是猜测。
大多数 RAG 系统的问题不是"检索不到",而是"检索到了但不告诉你是真是假"。LLM 拿到一段代码片段,不知道这段代码是完整的还是截断的,不知道函数调用关系是真实的还是推断的,不知道变量类型是确定的还是猜的。结果就是 LLM 会"幻觉"——不是因为它在编造,而是因为它把所有输入都当成了事实。
Graphify 的三级标注从源头上减少了这种幻觉的可能。LLM 看到 EXTRACTED 就知道这是事实,看到 INFERRED 就知道这是推断,看到 AMBIGUOUS 就知道这里不确定。信息的不确定性被显式传递给了下游消费者。
不用向量数据库,用 AST
Graphify 不用 embedding,不用向量数据库,不用相似度搜索。它用的是 AST(抽象语法树)。
工作流程:
- 解析:用 tree-sitter 解析源码,生成 AST。支持 Python、JavaScript、TypeScript、Go、Rust、Java 等 20+ 语言。
- 提取:从 AST 中提取节点(函数、类、变量)和边(调用、继承、导入、引用)。每条边标注 EXTRACTED / INFERRED / AMBIGUOUS。
- 序列化:把图谱序列化成紧凑的文本格式,喂给 LLM。
这个流程的 token 效率为什么高?因为 AST 提取的是结构信息,不是文本内容。一个 100 行的函数,AST 提取后可能只有 3-5 行的结构信息:函数名、参数、返回类型、调用了哪些函数。剩下的 95 行是实现细节,对理解"这个函数做什么"不是必需的。
向量数据库的思路是"找到最相关的代码片段",但"最相关"不等于"最必要"。一个 50 行的代码片段可能包含大量无关的细节,而 Graphify 的 3 行结构信息可能已经足够回答问题。
多模态:不只是代码
Graphify 不只解析代码。它还支持:
- PDF:提取文本和图表结构
- Markdown:提取标题层级和链接关系
- 截图:用 VLM 提取 UI 组件和交互流程
- 架构图:解析 Mermaid、PlantUML、draw.io
所有这些输入都被统一成同一种图结构。一个仓库的代码、文档、架构图、UI 截图,最终融合成一个统一的知识图谱,节点和边都有 EXTRACTED / INFERRED / AMBIGUOUS 标注。
这个多模态融合的思路解决了一个实际问题:仓库的理解不只靠代码。一个函数的名字和调用关系在代码里,但它的业务含义在 README 里,它的 UI 表现在截图里,它的部署关系在架构图里。只看代码会丢失大量上下文。
SHA256 缓存:增量更新
Graphify 对每个文件计算 SHA256 hash,只有 hash 变化的文件才重新解析。这意味着:
- 第一次解析一个 2000 行的仓库需要 30 秒
- 改了一个文件后重新解析只需要 2 秒(只解析那一个文件)
- 图谱的其余部分直接从缓存加载
这个设计让 Graphify 适合持续集成场景。每次代码提交后,Graphify 只需要增量更新图谱,不需要全量重建。大多数 CI 工具的代码理解步骤是全量的——每次都重新解析整个仓库,不管你改了一行还是一千行。
"诚实"作为设计原则
Graphify 的设计哲学可以总结成一句话:对"我是怎么知道的"保持诚实。
每条边都标注来源:是从 AST 直接提取的,还是推断的,还是无法确定的。这种诚实让下游消费者(LLM 或人类)能做出更好的判断:
- 看到 EXTRACTED 的调用关系,可以放心依赖
- 看到 INFERRED 的间接依赖,需要验证
- 看到 AMBIGUOUS 的动态分发,需要运行时确认
大多数代码理解工具不区分这三者。它们把所有信息都混在一起,标注为"从代码中提取"——但"提取"和"推断"是不同的认知行为,不应该混为一谈。
这个区分不只适用于代码理解。任何 AI 系统处理不确定信息时,都应该标注"我是怎么知道的":
- 知识图谱中的边是事实还是推断?
- 检索到的文档是原文还是摘要?
- 模型的回答是基于证据还是基于参数记忆?
信息的来源和确定性,应该和信息本身一起传递。这是 Graphify 给出的最重要的设计启示。
和 RAG 的根本区别
Graphify 不是"更好的 RAG",它和 RAG 是两条路线:
| 维度 | RAG | Graphify |
|---|---|---|
| 输入 | 文本片段 | 结构化图谱 |
| 检索 | 相似度 | 图遍历 |
| 确定性 | 不标注 | 三级标注 |
| token 效率 | 低(包含无关文本) | 高(只含结构信息) |
| 增量更新 | 难(需重新 embedding) | 易(SHA256 hash 比对) |
| 多模态 | 需要统一 embedding | 统一图结构 |
RAG 的优势是"语义匹配"——能找到"说了类似事情"的文档。Graphify 的优势是"结构精确"——能找到"有调用关系"的函数。两者不是替代关系,是互补关系。理解"这个函数做什么"用 Graphify 更高效,理解"有没有人讨论过这个问题"用 RAG 更合适。
适用场景
Graphify 最适合的场景:
- 代码审查:理解 PR 改动的影响范围,哪些函数会被间接影响
- 架构理解:新员工快速理解仓库结构,不需要读完所有代码
- 重构决策:找到所有调用某个函数的地方,包括间接调用
- 安全审计:追踪数据从输入到输出的完整路径
不太适合的场景:
- "这段代码的具体实现是什么"——Graphify 提取结构,不保留实现细节
- "有没有类似的代码"——这是 RAG 的领域
- "这个 bug 的原因是什么"——需要结合运行时信息
"Karpathy 的 /raw 文件夹"
README 里提到了一个有趣的参考:Andrej Karpathy 在 nanogpt 仓库里维护了一个 /raw 文件夹,存放原始的、未加工的代码理解数据。Graphify 的作者说这个文件夹是灵感来源之一。
Karpathy 的 /raw 是一种"透明"的姿态:不加工、不解释,原始数据就在这里,你自己看。Graphify 继承了这个姿态,但加了一层结构化——不是把原始代码丢给你,而是把代码的结构提取出来,同时告诉你"哪些是我提取的,哪些是我推断的"。
透明不是"给你看原始数据",是"告诉你我做了什么"。
GitHub: https://github.com/Graphify-Labs/graphify
许可证: MIT
文档: graphify-labs.github.io/graphify
讨论回复
加载中...正在加载回复...
智谱 GLM-5 已上线
我正在智谱大模型开放平台 BigModel.cn 上打造 AI 应用,智谱新一代旗舰模型 GLM-5 已上线,在推理、代码、智能体综合能力达到开源模型 SOTA 水平。