为什么 AI 读代码比向量检索更准?聊聊代码知识库的设计取舍
做 AI 知识库的人都知道 RAG——把文档切成 chunk,向量化,用户提问时找相似 chunk,喂给大模型生成答案。
文档库这样做没问题。但代码库这样做,会出大问题。
比如你问:"修改 parseInput() 会影响哪些测试?"
向量检索能找到语义相近的代码片段,但找不到调用关系。它知道哪些代码和 parseInput "像",但不知道谁调用了它。
再比如:"这个奇怪的边界判断是为什么加的?"
向量检索完全无能为力——这个信息只存在于半年前那个 commit message 里。
这篇文章聊聊我对代码知识库的理解,以及我在做一个 IDEA 插件时做出的设计取舍。
代码知识不是平的,是四层的
代码库的知识不是一个平面,而是四个层次,每层需要不同的理解方式:
层次 4:业务意图层 —— "为什么这样设计?"
↑ Git 历史、Commit Message、Issue 关联
层次 3:架构层 —— "谁调用了谁?"
↑ 调用图、依赖关系、模块边界
层次 2:语义层 —— "这段代码做什么?"
↑ AI 理解、代码注释、函数命名
层次 1:语法层 —— "这个文件有什么?"
↑ 目录结构、类定义、函数签名
传统方案是混合多种工具来覆盖每一层:
| 方案 | 语法层 | 语义层 | 架构层 | 意图层 |
|---|---|---|---|---|
| grep / ripgrep | 擅长 | 不支持 | 不支持 | 不支持 |
| 向量化检索 | 有限 | 擅长 | 不支持 | 有限 |
| AST 符号索引 | 擅长 | 有限 | 有限 | 不支持 |
| 调用图 / 依赖图 | 有限 | 有限 | 擅长 | 不支持 |
| Git 历史索引 | 不支持 | 有限 | 不支持 | 擅长 |
没有任何单一方案能覆盖全部四个层次。
但我在做知识归档插件时,发现了一个有趣的事情——
AI 读代码时,同时在理解四个层次
当 AI 读到 WoHdrServiceImpl.java 这个文件时,它同时在做四件事:
语法层:这是一个 Service 实现类,有 validate、create、update 三个公开方法,依赖 WoHdrDao 和 WoModelService。
语义层:这是工单头表的核心服务,负责工单的创建、校验和更新逻辑。validate 方法检查工单日期不能早于当前日期,create 方法自动生成工单编号。
架构层:它被 WoHdrController 调用,通过 WoHdrDao 访问数据库,依赖 WoModelService 做工单模型转换。
意图层:从 commit 历史看,validate 方法上个月刚重构过,原因是合并了两种工单类型,原来分开校验现在统一了。
一次阅读,四层理解。 这就是 AI 和传统工具的本质区别——AI 不需要你为每一层单独建索引。
向量检索只能做到语义层的"这段代码和工单创建相关",但 AI 能告诉你"这是工单头表的核心服务,被 Controller 调用,上个月刚因为合并工单类型重构过"。
我的设计取舍
基于这个认知,我在做 Knowledge Archiver 插件时,做了一个核心决策:不让工具分别处理每一层,而是让 AI 作为统一理解引擎,配合结构化文档做长期记忆。
取舍 1:文件即记忆,而不是向量数据库
大多数 AI 工具用向量数据库存知识。我反其道而行——AI 的分析结果直接写入 Markdown 文件。
.knowledge/
├── drafts/ # AI 生成的草稿
│ └── 2026-08-10_模块-wo-management.md
docs/
├── core/ # 升格后的正式文档
│ └── wo-management.md
└── INDEX.md # 文档索引
为什么不用向量数据库?
因为知识文档的读者是人,不是机器。Markdown 文件可以:
- 被 Git 版本控制,追踪知识的演进历史
- 被人直接打开编辑,补充 AI 遗漏的内容
- 零成本迁移,不依赖任何服务
- 在代码审查时一起 review
向量数据库里的 embedding 人看不了。你的知识被锁在一个二进制索引里,离开了这个系统就什么都不是。
取舍 2:AI 一站式理解,而不是多层工具组合
传统方案需要 AST 解析器 + 向量检索引擎 + 调用图生成器 + Git 索引器,四套工具组合起来才能覆盖四个层次。
我的方案:让 AI 直接读源码,一次性完成语义层和意图层的理解。
传统方案:
代码 → AST 解析器 → 语法索引
代码 → Embedding → 向量库 → 语义检索
代码 → 调用图生成器 → 依赖图 → 架构查询
Git → Commit 索引器 → 历史检索
四套管道,各自维护
我的方案:
代码 + Git 历史 → AI 一次性理解 → 结构化 Markdown 文档
一套管道,AI 做统一理解
代价是每次调用消耗 Token。收益是不需要维护复杂的索引管道,而且 AI 的理解能力远超任何单一工具。
实测对比:让 AI 读 45 个源文件后生成的工单管理模块文档,包含了完整的业务流程图、状态机、异常处理路径。同样的信息,用向量检索 + 调用图的方案,你需要先建索引、再写查询、再拼接结果——还不一定能拼出完整的业务流程。
取舍 3:多视角文档结构,而不是扁平 chunk
RAG 把文档切成等大的 chunk,丢失了结构信息。AI 拿到一个 chunk 时,不知道这是"开发视角的业务流程"还是"测试视角的验收标准"。
我的文档按 7 个视角组织章节:
| 视角 | 内容 | AI 能自动填充? |
|---|---|---|
| 开发视角 | 业务流程、状态机、核心实现 | 擅长 |
| 测试视角 | 验收标准、边界场景 | 部分 |
| 运维视角 | 日志监控、常见故障 | 部分 |
| 实施视角 | 配置项、接口协议 | 部分 |
| 产品视角 | 需求背景、业务痛点 | 人工补充 |
| 客户视角 | 操作流程、功能入口 | 人工补充 |
| 销售视角 | 价值主张、核心优势 | 人工补充 |
AI 读取文档时,知道当前章节是什么视角,生成内容时不会混淆。检索时也能精准加载——用户问"验收标准是什么",只需要加载测试视角章节,不用把整个文档都塞进上下文。
取舍 4:四层记忆体系,各层解决不同问题
L1 元数据索引 → 毫秒级定位模块(语法层的轻量替代)
L2 内容层 → Markdown 存储完整文档(语义层 + 架构层)
L3 检索层 → 本地优先 + AI 兜底(控制 Token 成本)
L4 输出标签 → 自动发现跨模块依赖(架构层补充)
意图层由 Git Commit 自动归档覆盖——每次提交自动提取变更意图,写入文档的变更记录章节。不需要单独的 Git 索引器,因为 AI 在归档时就已经理解了变更的业务含义。
这个方案不擅长什么?
公平地说,AI 驱动的方案也有短板:
语法层查询不是强项。 如果你需要"找到所有调用 parseInput() 的地方",IDE 自带的 Find Usages 比任何知识库都快、都准。知识库的目标不是替代 IDE 的代码导航功能。
架构层依赖 AI 判断。 没有精确的调用图,模块间的依赖关系是 AI 从 import 语句和代码结构中推导出来的,可能有遗漏。但对于业务知识文档来说,"工单模块依赖库存模块"这种粒度的信息已经够用了。
Token 成本可控但不为零。 每次 Commit 归档约 5K-15K Token,深化分析每轮约 85K-190K Token。用国产模型(DeepSeek、智谱等)成本很低,但如果项目很大、提交很频繁,需要合理规划。
总结
代码知识库不是"给代码做 RAG"那么简单。代码有结构、有层次、有历史,需要不同的理解方式。
传统方案是堆工具——每一层一个工具,然后组合。我的方案是让 AI 做统一理解引擎,用结构化文档做长期记忆。
| 维度 | 传统 RAG 方案 | AI 驱动方案 |
|---|---|---|
| 理解引擎 | 向量相似度 | AI 一次性理解 |
| 存储格式 | 向量数据库 | Markdown 文件 |
| 覆盖层次 | 语义层强,其他层需补工具 | 语义层 + 意图层强 |
| 可维护性 | 需要维护多套索引管道 | 文件即记忆,零维护 |
| 可读性 | embedding 不可读 | 人可直接阅读编辑 |
| 精确查询 | 语法层精确 | 架构层可能遗漏 |
两种路线各有取舍。但对于"让业务知识沉淀"这个目标来说,AI 驱动的方案更简单、更可控、更贴近人的阅读习惯。
毕竟,知识库最终是给人看的,不是给机器查的。
欢迎试用和反馈。