前⾔
想⾃⼰实现⼀个 Agent 助⼿来回答关于代码的⼀些问题,但是代码仓库过⼤,都塞给⼤模型也不太现实... 想对仓库代码做分析,但还要考虑不同仓库不同分⽀的⽂件变化... 想识别函数的上下游依赖,使⼤模型更准确地理解代码,还要单独实现函数依赖的上下游能⼒...
增量语义化索引&检索你的代码仓库,召回相关的代码⽚段 增量⽣成代码⽚段&⽂件级别的代码摘要 根据函数声明&调⽤⽣成函数依赖关系图,可获取函数依赖的上下游函数
介绍
整体架构
建⽴索引:根据仓库及分⽀对代码建⽴语义化索引,并存储⽂件哈希值信息,⼆次索引可复⽤,实现增量索引。 查询索引进度:因索引过程中涉及⽂本模型及向量模型的调⽤,⼤型项⽬的索引时间较⻓,可通过该能⼒实时查询索引进度。 语义化检索:索引完成之后可通过⼀段语义化描述检索代码仓库中相关的代码⽚段及其语义化摘要。 查询⽂件摘要:可查询单个⽂件的语义化摘要,可⽤于 Codewiki 等应⽤。 查询函数声明:可查询⽂件中声明的函数⽚段。 查询函数 Deps:查询某个函数的上下游函数依赖,可⽤于 AI CR 等场景,辅助⼤模型判断代码变更是否合理。
部分细节解析
若 Class 内代码超出 chunk token 上限,会对内部的函数体省略,保持 Class 的整体代码结构完整 对 Class 内部的函数成员⼆次处理,单独进⾏ Chunk 拆分。
<document path="lib/utils.js"> <code start_line="0" end_line="2"> function formatDate(date) { return date.toISOString().split('T')[0]; } </code> <code start_line="3" end_line="5"> function validateEmail(email) { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); } </code></document>[ { "summary": "文件维度的代码摘要", "path": "文件路径", "chunks": [ { "start_line": "开始行号", "end_line": "结束行号", "summary": "代码片段级别的代码摘要" } ] }]Parser 适配层,所有语⾔的依赖图解析均通过拓展该层的⽅式实现,对外暴露 API ⼀致,内部采⽤ tree-sitter 对代码进⾏解析,分析其内部的函数依赖。 GraphDB 适配层,由于涉及到 SDK 与 openapi,故需要考虑本地与线上两种存储介质,所以对 KuzuDB 与 Postgres 数据库对外暴露接⼝标准化,⽆缝切换存储介质。
总结一下上面的时序图,SDK 内部会查询文件内部声明了哪些函数、函数内部有没有嵌套声明函数、函数内部调用了哪些函数、被调用的函数是来自内部声明还是外部引用。获取到这些信息之后可以合并为图数据结构存储在图数据库中。
Files:节点表,存储代码库中每个⽂件的基本信息。 Functions: 节点表,存储代码中定义的函数信息。 Contains: 关系表,表示⽂件与函数之间的包含关系 (Files -> Functions)。 FunctionCalls: 关系表,记录函数之间的调⽤关系 (Functions -> Functions)。 FileCalls: 关系表,记录⽂件直接调⽤函数的关系 (Files -> Functions)。 Imports: 关系表,表示⽂件之间的导⼊/导出关系 (Files -> Files)。 Exports: 关系表,表示⽂件导出函数的关系 (Files -> Functions)。 FunctionContains: 关系表,表示函数内部定义了其他函数的关系(嵌套函数),(Functions -> Functions)。
应⽤
总结
