news 2026/10/11 13:57:37

MEX 代码图谱实现原理:Tree-sitter WASM + SQLite FTS5 如何构建确定性代码图

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MEX 代码图谱实现原理:Tree-sitter WASM + SQLite FTS5 如何构建确定性代码图

【免费下载链接】mex

Team memory for engineers and their AI agents. Lives in your repo. Shared through Git.

项目地址:https://gitcode.com/gh_mirrors/mex2/mex
点击查看免费下载

MEX 是一款面向工程师及其 AI Agent 的团队记忆工具,其核心能力之一是"代码图谱"(Code Graph):它用Tree-sitter WASM解析源码、把符号与调用关系写入SQLite FTS5全文索引,构建出一张确定性、可复现、不依赖任何 LLM的代码图,让mex graph query、mex impact这类命令能像数据库查询一样精确回答"谁调用了我""这个函数定义在哪"。本文带你拆解这套架构的五个关键设计。

为什么需要"确定性"代码图

很多代码理解工具把仓库内容直接丢给大模型,输出随提示词和随机性漂移;而传统 grep 只能做文本匹配,无法区分"同名的方法"还是"重载的函数"。

MEX 的图谱引擎在接口层面就明确了这一原则:build 是tree-sitter → SQLite,读取是纯 SQL,全流程没有 LLM 参与(见 src/graph/engine.ts)。这意味着:

  • 同一份代码,在任何机器上构建出的图字节级一致;
  • 读取路径是同步 SQL 查询,毫秒级返回;
  • 图谱本身成为一个可校验的数据契约,而不是"模型的印象"。

上图是 MEX Hub 中的 Graph 构建任务:从Discover → Stage → Parse → Resolve → Validate → Publish六个阶段逐段推进,任何一步失败都不会污染已发布的图谱——这是后文会讲的"候选进程 + 原子发布"机制的可视化体现。

第一步:Tree-sitter WASM 解析源码

解析层的核心是 src/graph/extraction/grammars.ts,它封装了web-tree-sitter——一个运行在WASM 上的 tree-sitter 运行时。选 WASM 而不是原生模块,有三个直接收益:

  1. 免编译安装:.wasm文件随包分发(见 src/graph/wasm/ 下的 TypeScript、JavaScript、Python、Rust、C# 等语法文件),无需 node-gyp 构建;
  2. 按需懒加载:只有项目中真实出现的语言才会加载对应 grammar,大型仓库不会白白占用 WASM 堆;
  3. 跨平台一致:同一份 WASM 字节在任何操作系统上产出同一棵语法树。

文件扩展名到语言的映射(.ts、.tsx、.py、.rs、.cs等)是唯一的事实来源,定义在 grammars.ts 第 56-72 行;parse()函数则是语法树进入提取器的唯一边界,提取器永远不直接触碰 web-tree-sitter。

一个容易忽视的细节在 第 164-166 行:解析出的树分配在 Emscripten 堆上,不会被 JavaScript GC 回收,因此每个文件解析完必须显式disposeTree()释放——这是图谱引擎能在巨型仓库上不泄漏内存的关键之一。

第二步:行无关节点 ID,确定性身份的基石

"确定性"最脆弱的地方是身份标识。如果节点 ID 里包含行号,那么上方任意一行代码的增删都会让 ID 变化,所有引用它的锚点(grounding)会静默失效。

MEX 的解法在 src/graph/extraction/node-id.ts:

节点 ID = `${kind}:` + sha256(`${file_path}:${kind}:${name}`…).前 32 位

注意哈希输入里没有行号——注释、格式化、上方代码增删都不会改变 ID。这个"Tier-1 身份"故意保持粗粒度:重命名(name 变化)或移动文件(path 变化)仍会表现为"删除 + 新增",而这正是下一层指纹机制要接管的事。

两阶段管线:先单文件提取,再全局解析

图谱构建采用extract → resolve两阶段设计:

  • 提取阶段:每个文件独立、纯函数式地解析,产出符号节点和"未解析引用"(unresolved_refs)。提取器禁止跨文件查询、禁止读文件系统,保证单文件结果可缓存、可复用;
  • 解析阶段:全量索引完成后,统一把引用绑定成边(edges)。框架级知识由可插拔的FrameworkResolver补齐——目前覆盖 Express、Next.js App Router、FastAPI、Flask、NestJS(见 docs/code-graph-support.md 的支持矩阵)。

绑定不上的引用不会被丢弃,而是诚实保留在unresolved_refs表中——图谱对自己的盲区是可见的,mex graph query who-calls会明确标注这类降级证据。

第三步:SQLite + FTS5 存储与全文检索

存储层直接复用 Node.js 内置的node:sqlite(要求 Node ≥ 22.5),它编译进了完整的WAL + FTS5 + mmap能力,无需任何原生依赖(见 src/graph/db/sqlite.ts)。MEX 甚至在启动时探测 FTS5 是否可用,缺失时给出可操作的报错而不是生硬的no such module: fts5。

数据契约是一份"冻结"的 schema(src/graph/schema.sql),核心表职责清晰:

表职责
nodes代码符号(函数/类/方法…),带body_hash漂移检测列
edges符号关系:calls、imports、extends、references…
files文件内容哈希与解析健康度,驱动增量筛选
unresolved_refs解析失败的引用(图谱的已知盲区)
node_fingerprints/lsh_bucketsMinHash 指纹与 LSH 倒排(重命名对账)

全文检索由两张FTS5 虚拟表承担:

  • nodes_fts(schema.sql 第 214-222 行):索引符号的 name、qualified_name、docstring、signature,通过触发器与nodes表自动同步;
  • source_chunks_fts(第 202-209 行):contentless 模式索引源码分块的标识符与注释词,命中时源码永远从磁盘重读,索引只存坐标。

查询侧用BM25 加权排序(src/graph/db/store.ts 第 957-960 行:name 权重 20、docstring 权重 5、signature 权重 1),配合 src/graph/retrieval/query.ts 里的查询规划器——它会剥离停用词、把BudgetLedger拆成budget/ledger词元、对configuration做保守词干变体(→config),让"用自然语言问代码"也能命中结构化符号:

第四步:MinHash + LSH,让图谱在重命名后"认得人"

Tier-1 ID 能扛住行号漂移,但扛不住重命名。MEX 为此设计了Tier-2 指纹(src/graph/fingerprint.ts):

  1. 对节点归一化 AST 三元组(丢弃标识符拼写,只保留语法骨架)做MinHash,K=64;
  2. 指纹连同 caller/callee邻域签名一起存入node_fingerprints;
  3. 用LSH 分带索引(32 bands × 2 rows)加速候选查找:分带哈希存入lsh_buckets,两指纹只要任一带哈希相同就进入候选集;
  4. 对账器(src/graph/reconcile.ts)在 Tier-1 未命中时给出三选一裁决:MOVED(静默重绑)、GONE(报错)、AMBIGUOUS(交给人或 Agent 确认)。

这套机制让 Wiki 中"某段说明指向某函数"的锚点,在函数改名或挪文件后依然能自动找回——而不是静默断链。

第五步:增量更新与原子发布

日常开发中mex graph refresh不会全量重建:files表的内容哈希先筛出变更文件,file_extraction_cache复用过期的提取结果,file_row_digests记录每个文件的派生行摘要,只重写过掉文件的行。

更重的 rebuild 则在一次性候选进程中完成(Hub 侧见上文的 Jobs 管线):子进程崩溃、超时、取消都只影响临时工作区,父进程校验通过后才原子改名发布新库;读者永远只打开"最后一次成功发布"的不可变快照(升级规则见 docs/design/graph-v4-compatibility.md)。任何失败都不会让坏数据成为可信图谱。

最终效果:在 Code 页面查看任意符号,Callers/Callees/Impact 都是对 SQLite 索引的确定性查询结果。

上手:三条命令验证你的代码图

mex graph status # 图谱新鲜度与解析健康度 mex graph query who-calls requireSession # 精确的调用关系查询 mex graph scope "trace the authentication flow" # 按任务取有界证据集

如果mex check提示某个 Wiki 断言的 grounding 漂移,说明对应节点的body_hash变了——这就是nodes表里那个"demo 没有、MEX 独有"的列在做的事(schema.sql 第 80-86 行):

核心文件索引

  • 语法加载与语言检测:src/graph/extraction/grammars.ts
  • 行无关节点 ID:src/graph/extraction/node-id.ts
  • SQLite 数据契约(FTS5 虚拟表):src/graph/schema.sql
  • node:sqlite 适配与 FTS5 探测:src/graph/db/sqlite.ts
  • 存储与 BM25 查询:src/graph/db/store.ts
  • MinHash 指纹与 LSH 分带:src/graph/fingerprint.ts
  • 重命名/移动对账契约:src/graph/reconcile.ts
  • 引擎接口(build/sync/search):src/graph/engine.ts
  • 查询规划(停用词、词干、标识符拆分):src/graph/retrieval/query.ts
  • 语言与框架支持矩阵:docs/code-graph-support.md

一句话总结:MEX 的代码图谱 = WASM 化的确定性解析(Tree-sitter)+ 冻结的 SQLite 契约(FTS5 + 指纹)+ 行无关 ID 与原子发布,三者共同把"问代码"从概率问题变成了数据库问题。

【免费下载链接】mex

Team memory for engineers and their AI agents. Lives in your repo. Shared through Git.

项目地址:https://gitcode.com/gh_mirrors/mex2/mex
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/11 13:55:43

rea实战:用脚本自动化浏览器重复操作,打造高效流程

首先要跟看到这个标题的朋友解释一下:我平时写自动化脚本,经常要给临时项目起个随手能打的代号,rea就是从里面蹦出来的三个字母。它的全称被我私下写成 Repeat Everything Automatically——听起来有点中二,实际上做的事情特别接地…

作者头像 李华
网站建设 2026/10/11 13:54:48

Unity系统字体动态加载:TextMeshPro生僻字与多语言渲染方案

简介:UnityNativeOSFont 是一套面向 Unity 开发者的开源工具,用于在运行时获取操作系统本地字体并接入 TextMeshPro 动态字体渲染,解决 TMP 默认字体库无法覆盖各平台系统字体、需手动导入字体文件的问题。它通过 C# 脚本读取系统字体列表并转…

作者头像 李华
网站建设 2026/10/11 13:54:30

企业年会大屏互动系统实战:WebSocket高并发弹幕与摇一摇

简介:这是一套面向企业年会策划人员、活动执行团队及现场技术支持的LED大屏互动解决方案,针对年会现场气氛调动难、互动形式单一的问题,整合了抽奖、游戏与签到等环节。压缩包共约2000个文件,整体255.57MB,以png图片素…

作者头像 李华
网站建设 2026/10/11 13:51:42

WOA-CNN在通信辐射源识别中的超参数优化实践

简介:本资源面向通信工程、信号处理及人工智能方向的科研人员与高年级本科生,提供一种基于鲸鱼优化算法(WOA)提升卷积神经网络(CNN)分类性能的完整MATLAB实现方案,聚焦通信辐射源个体识别这一典…

作者头像 李华
网站建设 2026/10/11 13:47:55

YOLOv5摔倒检测落地实战:从高分模型到养老院真实部署

简介:本资源是一套基于YOLOv5实现的摔倒检测与跌倒识别高分项目,面向深度学习初学者及计算机视觉实践者,聚焦于老年人看护、智能监控等实际安防场景中的行为异常识别需求。压缩包共193个文件,含75张标注图像(jpg/jpeg&…

作者头像 李华