Agentic Search
像Claude Code、Codex、Cursor、OpenCode、Trae等编码Agent能够对我们的项目进行功能实现、代码重构、bugfix等操作的前提是:他需要读懂你的代码仓库。
通常来说用户输入自然语言提问:"请帮我查询一下下单流程是怎样的,怎么保证订单状态的一致性",这个时候Agent首先需要理解什么是下单流程,他会把这个提问query rewrite为对应的关键字,如:order|orderStatus|orderProcess,然后通过这些关键字去查找对应的代码片段:
- grep 关键词 -> read file -> grep 关键词 -> read file -> ...(loop) -> answer
通过多轮查询将碎片化的信息组织成有逻辑的上下文。

但是这种查询方式存在以下问题:
- AI 需要不断 grep 扩读原始仓库代码得到想要的结果,耗时和token消耗比较大
- 纯文本的代码片段是碎片化的,难以产生关联,比如函数的调用链路、页面与组件的关联关系等,AI 更容易关注到局部信息,而忽略掉与关键字无关的潜在内容
- 业务语义到实际代码是如何关联的?业务是由业务团队人为定义的,而代码是由开发人员的具体实现,同一个功能可能有不同的代码实现,反之同一个函数名称也可能承载不同的功能
CodeGraph
CodeGraph是一种通过静态分析(Tree-sitter等)把代码仓库转换成可检索、可遍历的代码知识图谱(由实体和关系组成),沉淀文件、函数、方法、类、调用关系、依赖关系、字段读写、状态流等上下文,提供相关API给调用方检索,让AI不再只靠关键词搜索,而是能够真正理解代码之间的关联关系。
以下是一些比较知名的代码知识图谱方案:
| 项目 | 一句话定位 | 核心技术 | 图如何设计 | 如何召回相关代码 | 更新方式 | 最突出的特点 |
|---|---|---|---|---|---|---|
| GitNexus | 功能全面的代码知识图谱与 Graph RAG 平台 | Tree-sitter + LadybugDB;支持浏览器 WASM | 文件、函数、类、调用关系,并预计算功能社区和执行流程 | BM25 关键词 + 向量语义检索 + RRF 融合,再结合调用链和功能社区 | 重新执行分析;增量能力仍在持续演进 | 检索、影响分析、流程分析和可视化比较完整 |
| code-review-graph | 面向代码审查和变更风险分析 | Tree-sitter + SQLite,可选向量模型 | 函数、类、导入、调用、继承、测试关系,并识别代码社区与执行流程 | 全文检索 + 可选语义向量 + 图遍历,重点寻找变更影响范围 | Watch、Git Hook 和增量更新 | 最适合 PR 审查、测试缺口和风险评分 |
| codebase-memory-mcp | 追求极致性能和语言覆盖的代码图后端 | Tree-sitter + Hybrid LSP + SQLite,静态二进制 | 除代码符号外,还建模 HTTP 路由、基础设施资源及跨服务关系 | 名称/正则搜索、图遍历、Cypher 查询和代码搜索 | 后台自动同步,也可共享压缩后的图数据库 | 语言覆盖广、查询快、依赖少 |
| CodeGraph | 为 AI 编程 Agent 提供始终最新的精准代码上下文 | Rust 原生解析内核 + Tree-sitter + SQLite/FTS5 | 以文件和代码符号为节点,以调用、导入、继承、实现和框架路由为关系 | 先用全文搜索定位入口,再沿调用关系扩展;一次返回源码、调用路径和影响范围 | 监听文件变化,只同步发生变化的部分 | 本地运行、自动保鲜,并把复杂查询收敛成一个 explore 工具 |
| Graphify | 将代码、文档、PDF、配置等统一生成可浏览知识图谱 | Tree-sitter;非代码内容可使用 LLM 提取 | 概念级图谱;每条边标记为"源码提取"或"推断";使用 Leiden 划分社区 | 不使用向量库,主要通过子图、邻居和最短路径召回 | 支持手动更新、Watch 和 Git Hook | 数据源最丰富,图关系可解释、便于可视化和团队共享 |
对比了业内多种方案,我们最终采取了CodeGraph这套方案,它包含完整的benchmark测试,并且产品化做得比较好,也符合我们在25年底前期探索的基于LocAgent的理论实践(在这之前我们已经基于这套理论实现了一版CodeGraph),而且是一套比较纯粹的、纯工程侧的基础能力。
它的核心流程可以概括为:FTS负责做精确符号和关键词定位,CodeGraph 负责沿调用关系、引用关系继续扩展上下文。两者结合后,召回结果可解释、确定性强。
- 解析代码 → 建立符号关系图 → 自动增量同步 → 为 Agent 一次性返回精准上下文
业务实践
为了增强前端语义,我们制定了 CodeGraph 图的标准:实体和边的设计
- 实体是构建图的基本单元,如文件、目录、函数等
- 边描述了实体与实体之间的关系,如包含、调用、继承等
实体类型
通用实体
通用实体用于描述代码库的基础结构和语言层面的符号关系,适用于不同语言
| 实体 | 含义 | 说明 |
|---|---|---|
| file | 文件 | 所有代码、配置、资源的承载单元 |
| directory | 目录 | 仓库结构基础实体 |
| function | 函数或 inline callback | 语言侧面的可调用逻辑单元 |
| method | 方法 | 类、对象或框架对象中的方法 |
| class | 类 | 语言侧面的类型与继承结构 |
| import | 导入定义 | 模块依赖和符号引用入口 |
| export | 导出定义 | 模块对外暴露的符号 |
框架实体(Vue/Mpx/React)
框架实体用于描述前端应用中由 Vue、Mpx、React 等框架或运行时约定产生的语义(前端特定语义)。这些实体通常不是纯语言 AST 能完整表达的,需要结合框架 parser、配置解析和约定识别。
| 实体 | 含义 | 说明 |
|---|---|---|
| app | 应用入口 | 应用启动、挂载和全局配置入口 |
| page | 页面入口 | 前端业务页面或路由页面 |
| component | UI 组件 | Vue/Mpx 组件或 React component |
| reactive_state | 局部响应式状态,例如 prop、data、ref、useState、computed | 组件或页面内部状态 |
| global_state | 全局状态,例如 store、model、全局 atom | 跨页面、跨组件共享状态 |
| event_channel | 事件通道,例如 emit/on、event bus | 组件事件、页面事件或全局事件通信 |
关系类型
通用边
通用边描述跨技术栈都成立的结构、依赖和调用关系。
| 边 | 含义 | 说明 |
|---|---|---|
| contains | 结构包含关系 | 目录、文件、类、方法、函数等层级关系 |
| invokes | 普通调用关系 | 函数、方法、callback 之间的调用 |
| imports | 模块依赖关系 | 文件或模块之间的导入依赖 |
| extends | 继承关系 | 子类继承父类 |
| resolves_to | 配置或符号解析到目标实体,例如 route 解析到 page | import/export、路由、配置等解析结果 |
| depends_on | 通用依赖关系,通常用于较弱或无法更具体归类的依赖 | 兜底依赖边,适合解析置信度较低的关系 |
框架边(Vue/Mpx/React)
框架边描述前端框架特有的 UI 组合、页面跳转、数据读写、事件副作用、服务调用和平台能力。
| 边 | 含义 | 说明 |
|---|---|---|
| navigates_to | 导航关系,例如页面跳转、路由跳转、参数跳转 | page、route 之间的跳转链路 |
| reads_data | 读取局部或全局状态 | 页面、组件、函数读取 reactive_state 或 global_state |
| writes_data | 写入局部或全局状态 | 页面、组件、函数写入 reactive_state 或 global_state |
| provides_to | provider 向 consumer 提供依赖 | 框架依赖注入或上下文提供关系 |
| injects_from | consumer 从 provider 注入依赖 | 框架依赖注入或上下文消费关系 |
基于实体和边的结构化表达,最终我们就获得了一张完整的、用于描述代码仓库结构与语义的一个完整关系图,他能清晰的表达不同职责的代码之间的关联关系。

视图分层
为了更好的对仓库进行理解,我们做了视图抽象:可以通过视图分层聚焦到某一块的内容进行查看,这一块儿的分层是基于Vue/Mpx/React等前端框架来设计的,主要分为四层:

以下示例基于开源项目vue-admin-better进行分析生成:
- L1:BaseGraph层,最基础、最底层的、基于前端项目的全实体graph,如下图(基于GitNexus渲染)

- L2:PageGraph层,只展示页面语义单元,描述了整个CodeGraph中有多少个Page实体,这些实体之间有什么路由关联关系,可以由那些普通实体进行跳转(也就是包含了路由graph)

- L3:Page层,只展示对应页面下的组件语义单元,一个页面可以包含多个组件,并且页面自身也有一些额外的逻辑,比如页面自身的方法、data数据、props等

- L4:Component层,基于某个组件(Component)展开之后的完整的子图,包含该组件内部的函数、方法、Hook、Store 访问、副作用、数据流、状态流等真实关系


覆盖场景
公共场景(跨语言)
| 场景 | 说明 |
|---|---|
| 结构导航 | 浏览目录、文件、类、方法、函数层级 |
| 调用链分析 | 追踪函数和方法之间的调用路径 |
| 依赖分析 | 分析文件级 import 关系和模块依赖 |
| 符号定位 | 根据文件名、函数名、方法名、类名定位代码位置 |
前端场景(Vue/Mpx/React)
前端上下文召回:为 AI Coding 找到相关页面、组件、状态、跳转链和接口链路
| 场景 | 说明 |
|---|---|
| 页面跳转分析 | 追踪页面跳转和参数传递 |
| 组件使用分析 | 分析页面和组件之间的渲染关系 |
| 数据流向分析 | 分析局部状态和全局状态的读取、写入和副作用 |
应用到开源CodeGraph,适配内部技术项目
Benchmark
为验证前端语义增强的实际收益,我们选取了乘车码、乘客小程序、tianji-sale-car、VS Code 和 Excalidraw 共 5 个项目、17 个真实代码理解问题进行测试。每个 Case 分别执行 4 次 Agent 任务(claude code + deepseek-v4-flash),并采用四轮中位数进行统计。
测试包含三组:
- Without:不使用 CodeGraph。
- Main :使用Github主干版本
codegraph 1.0.1。 - CodeGraph :使用加入 Page、Component、Service 等前端语义增强后的候选版本
codegraph 1.0.3(内网版本)。
测试模型为 deepseek-v4-flash。
| 指标 | Without | Main | CodeGraph | CodeGraph vs Main | CodeGraph vs Without |
|---|---|---|---|---|---|
| 总耗时 | 2119.6s | 1672.4s | 1430.6s | -14.5% | -32.5% |
| 总成本 | ¥22.735 | ¥16.302 | ¥13.097 | -19.7% | -42.4% |
| Total Tokens | 57.45M | 33.18M | 27.39M | -17.4% | -52.3% |
| 工具调用 | 764.5 | 320.0 | 321.5 | +0.5% | -57.9% |
具体的数据见:

改进后的CodeGraph VS without

改进后的CodeGraph VS 原始的CodeGraph VS without
总的来说,前端语义增强取得了明确的正向收益。相较 Main(原始的upstream),CodeGraph 在工具调用量基本持平的情况下,总耗时下降 14.5%、成本下降 19.7%、Token 消耗下降 17.4%。这说明收益并非简单来自减少工具调用,而是语义图帮助 Agent 更快定位页面、组件、状态和服务之间的关系,减少了无效代码阅读和上下文扩张。
相较完全不使用 CodeGraph,语义增强版本的耗时下降 32.5%、成本下降 42.4%、Token 消耗下降 52.3%、工具调用下降 57.9%,说明图召回对于大型代码仓库中的 Agent 代码理解具有显著价值。
存在的问题
CodeGraph提供的是高效查询、组织代码上下文、提供给AI Agent的能力,它是一个由工程侧产生的确定性的结果,在绝大部分场景下,他是由Agent自主调用的(cli命令、mcp、skill等)、不影响最终产出结果准确性的工具(只会影响耗时、Token消耗等)。

但是在我们的实际应用场景中,决定查询质量的第一步往往是用户输入的query:
- 如果这个query是一个比较确定symbol,比如函数、组件、页面的名字等,那么这种查询是非常高效的。

- 如果这个query 是一个比较抽象的业务场景,比如某个功能的流程是怎样的、涉及到多个业务语义场景,那么在很大程度上取决于Agent的query rewrite 能力,如果Agent对用户query做到很好的理解,基于query拆分出来symbol是精确的、那么最终组织生成的代码上下文是比较可靠的,反之Agent则可能因为拿不到精确的内容而退化到使用find、glob、grep等工具进行文本扩读,按照AI自己的理解去组织代码上下文,得到对应的结果。

因此我们最近在尝试构造Business Knowledge System,它是一个面向业务领域的知识库,是一个描述各业务实体之间的关联关系的拓扑结构。
我们前后端可以基于这个拓扑结构生成关于代码仓库的知识图谱,如LLM Wiki生成的一些关于代码仓库的业务解释性的md文件,通过解析这些文件,得到对应的业务语义与代码symbol(如页面、组件、函数的地址等)的一个关联关系(索引)。建立业务语义与相关代码子图之间的关系,使同一组关系支持双向查询:
- 业务 -> 代码(Top-down):从 Stage、Page 等业务语义定位前端代码入口;
- 代码 -> 业务(Bottom-up):从 symbol、组件、文件、模块或 API 反查业务归属和影响场景。
这就是业务语义与代码的双向可追溯关系。
这个 BKS 是跨仓库、技术栈的,比如前端后端在同一个PRD里,针对同一个业务场景有不同的具体代码实现。在抽象层,业务语义其实是一样的,而在具体的代码查询(CodeGraph)则可以根据对应的团队技术栈进行优化实现。这样我们不仅能够回答某个功能对应到哪些代码、也能反过来回答当前的代码是归属于哪些业务的,这样修改一个功能,我们就能反推会影响哪些业务模块儿。理论上讲这能解决所有场景:Coding、issue定位、bugfix、知识问答等。