RAG还是AST图谱?把30万行仓库建成可查询图谱的真实代价 本文摘要纯向量 RAG 做仓库级问答时跨文件调用链检索经常拼错且不易察觉。用 AST 图谱把定义与调用建为带来源标注的边可直接遍历回答调用链。但动态导入等静态盲区仍需人工验证不能只信确定性。一、问题与结论在 Claude Code 里问一个跨文件问题比如requests 的Session.send在哪定义它在调用链上还会调到哪些模块的方法“纯向量 RAG 按函数切片入库检索只能返回包含def send的若干代码块——embedding 相似度不理解谁调用谁”import 链一断Agent 只能靠推理拼接拼错时还看起来很自信。结论先行AST 图谱把定义、调用、引用建模为带来源标注的边跨文件调用链由边遍历直接回答不依赖 LLM 多轮拼接。但确定性只覆盖静态可分析的部分动态导入、配置驱动的加载会让图谱看起来有边、实际断裂这类错误比 RAG 漏检更难被发现。30 万行仓库全量建图之前先用三条grep判断静态盲区大小再决定建图范围。二、排查与选择依据建图前先回答一个问题你的仓库有多大比例是静态分析覆盖不到的。在目标仓库根目录执行# 动态导入 / 反射grep-rnimportlib\|__import__\|import_module--include*.py|wc-l# 字符串拼接的模块路径grep-rnimport_module(f--include*.py|wc-l# 配置文件中的代码引用grep-rnhandler\|plugin\|moduleconfig.yaml config.json settings.py2/dev/null|wc-l三条结果中任意一条非零图谱在该仓库上就存在已知盲区。另外统计自动生成代码占比protobuf 生成的_pb2.py、.pb.go等AST 会解析出大量有边无语义的节点图谱体积膨胀但查询价值接近零。替代方案与取舍方案选择条件代价与边界纯 RAG切片向量快速搭建问题以为什么类文档问答为主跨文件调用链断链切片粒度直接影响召回LSP Agent 封装已有 IDE 语言服务器基础设施需逐语言配置不产出图谱SQL/配置文件不可查混合AST 定位 RAG 解释需同时回答在哪和为什么两套基础设施的维护成本自建代码属性图如 Joern需要深度安全审计学习曲线陡大仓库构建可能达小时级不该用 AST 图谱的三种情况仓库以动态语言 插件架构为主且上面的grep结果很大主要问题是这段逻辑的业务含义是什么AST 只给结构语义在文档里团队里没人能读懂图查询结果、也没有预算做查询模板沉淀。三、关键原理两个机制决定图谱能回答什么、不能回答什么。边的来源分两类。显式函数调用Session.send→HTTPAdapter.send由 AST 直接建边解释明确到行号。跨类型边则不同——SQL 表名连接到 ORM 模型类、config 键连接到 Python 模块这类边依赖字符串匹配或启发式推断。“每条边都有解释是质量下限的承诺不是正确性的承诺拼写不一致会静默生成孤岛节点Agent 看到的是有边”边指向的却不是真实代码。确定性的边界在运行时。importlib.import_module(fplugins.{name})这一行 AST 解析得了但运行时实际加载哪些模块静态不可知。图谱要么缺出边要么近似成一个通配节点——后者意味着 Agent 查询load_plugin 会调用哪些 handler时拿到的是形式完整、实质不精确的答案而确定性这个卖点会让人放松验证。四、可运行示例环境macOS/LinuxClaude Code已启用 skill 机制Python 3.11。# 1. 准备目标仓库示例用开源仓库实际建议换成你维护的仓库gitclone--depth1https://github.com/psf/requests /tmp/target-repo# 2. 盲区自检cd/tmp/target-repogrep-rnimportlib\|__import__--include*.py|head-5# 3. 安装 graphify skill 到 Claude Code 的 skill 目录# 路径与命令以仓库 README 为准此处不编造然后在 Claude Code 中执行命令拼写以 README 为准/graphify init /tmp/target-repo /graphify query Session.send 定义在哪列出调用链上其他模块的方法。对照组把同一批代码切片灌入向量库用同样的问题检索。预期输出基于机制推断未验证图谱查询返回Session.send的精确文件与行号并通过边遍历列出调用目标RAG 返回若干包含send的代码块调用链需要 LLM 推理拼接import 链处容易断。实际输出以上结果必须在你自己的仓库上跑过才算数。核对两点——调用链是否完整对照grep -rn def send手动追踪 import 链每条返回的边是否标注了来源文件和行号。五、验证结果与边界最危险的失败场景插件架构导致图谱说安全、运行时崩溃。若第二节的grep命中Agent 可能基于图谱判断删除某个plugins/billing_handler.py没有引用——而它实际由config.yaml在运行时动态加载。修复方法为每个动态加载点维护一份显式运行时依赖清单注释或文档均可建图后让 Agent 结合清单二次确认不单独依赖图谱出边做删除决策。版本层面的边界Claude Code 的 skill 机制经历过目录结构变更升级 Agent 后 skill 可能静默失效Graphify 自身的具体版本、语言覆盖清单、构建耗时在已验证来源中均无数据接入前先在 5 万行以内的子仓库跑通检查孤立节点和无语义边的占比再决定是否扩展到全量仓库。思考你的仓库里动态加载和插件机制占比多高时AST 图谱的确定性优势反而会变成误导性的安全感团队更需要精确回答在哪的问题还是能容忍概率性的为什么——这个判断应该由谁来做参考资料Graphify-Labs/graphify