值得建图的那一类问题
代码检索有两个层次:找字符串,和找依赖关系。前者用 grep 或向量检索就够了,后者只要涉及"跨文件的影响面",文本检索就会失效。把调用关系落成图,换来的是可查询、可复用的结构事实——同一次导入,既能服务 AI,也能服务人。
为什么线性文本无法还原立体架构?
代码本质上不是线性文章,而是由函数调用、接口实现、继承与事件监听构成的复杂网状结构。纯文本搜索很难回答诸如“修改这个函数会间接影响哪些上游服务”之类的问题。
0. 先把 Neo4j 跑起来
本地验证用 Docker 最省事:
docker run -d --name neo4j \
-p 7474:7474 -p 7687:7687 \
-e NEO4J_AUTH=neo4j/change_me \
neo4j:5
7474 是浏览器端口,7687 是 Bolt 端口。启动后用 cypher-shell 连上,执行 RETURN 1; 能出结果即说明实例可用;生产环境务必改掉默认账号密码,并限制监听网卡。
1. 构建代码图谱
利用解析器提取代码中的实体(Entity: Function, Class, File)与关系(Relationship: CALLS, IMPORTS, IMPLEMENTS),导入 Neo4j 数据库。
落地时有三条经验:
- 解析器选型:语法解析可用 tree-sitter 一类的通用解析库;如果团队已经在用 LSIF/SCIP 之类的索引产物,直接从索引转图比自己写解析更省力。
- 属性先定死:每个节点至少带
name、file,关系带repo与commit。没有commit,图就无法与代码版本对应,几次迭代之后没人知道这份数据属于哪个版本。 - 入图后建索引:按查询里用到的等值条件建索引,否则影响面查询会退化成全表扫描。
CREATE INDEX function_name IF NOT EXISTS FOR (f:Function) ON (f.name);
CREATE INDEX class_name IF NOT EXISTS FOR (c:Class) ON (c.name);
2. 封装 Cypher 查询 MCP 工具
编写 MCP Server 暴露 find_impact_radius(function_name) 工具:
MATCH (target:Function {name: $function_name})<-[:CALLS*1..3]-(caller:Function)
RETURN caller.name, caller.file
当开发者计划对底层通用工具函数进行入参重构时,AI 能够通过该图谱工具精确定位出所有 1 到 3 层的间接调用方,主动提醒并协助完成全量适配。
封装这一层有三条纪律:只允许只读查询,工具内部拒绝非 MATCH 语句;变长路径深度写死在模板里,不要让模型自由填 *1..n,否则一次深度失控就能拖垮实例;结果带 LIMIT 并按 file 去重,避免同名函数把上下文塞满重复行。
3. 让查询能力覆盖常见的架构提问
单一的影响面查询价值有限,把下面几个问题做成工具,图谱才真正能用:
| 提问 | 查询形态 |
|---|---|
| 谁调用了它 | <-[:CALLS*1..3]- |
| 它依赖了谁 | -[:CALLS|IMPORTS*1..2]-> |
| 两个模块是否间接相连 | 最短路径查询,限制最大跳数 |
| 哪些函数是改动高危点 | 按入度排序取 Top-N |
最后一项对 AI 特别有用:把"入度最高的工具函数"作为提示词的一部分喂进去,模型在提重构方案时会主动避开这些位置。
怎么验证图谱是对的
不要只看节点总数,用两个交叉验证:
- 挑一个自己熟悉的函数,把图给出的调用方与
grep -rn的结果对比,两边差异应当只来自动态调用与别名。 - 故意制造一个已知引用(新增一次调用后重新导入),确认它出现在图里;这一步同时验证了解析覆盖率与导入流水线。
动态派发、反射、依赖注入产生的调用边大概率缺失,这属于图方法的固有盲区,结论里要显式说明。
常见故障速查
| 现象 | 原因 | 处理 |
|---|---|---|
| 查询很慢 | 属性无索引,或变长深度过大 | 建索引、把深度固定在 3 层内 |
| 同名函数结果混淆 | name 不唯一 | 用 file + name 复合条件定位 |
| 调用方为空 | 解析器未覆盖该语言特性 | 抽查该文件的解析产物再补规则 |
| 图与代码不同步 | 增量导入未接 CI | 把导入挂到流水线并记录 commit |
| MCP 工具报鉴权失败 | Bolt 账号或地址错 | 先用 cypher-shell 单独验证连通 |
小结
值不值得建图,可以用一个问题判断:你最近的架构提问里,有多少需要跨文件跳 2 步以上。这个比例高,图谱的收益会立刻显现;比例低,混合检索加 AST 索引就够用了,不必为少数问题维护一套导入流水线。