代码库理解:索引、符号与语义检索
一句话定义
AI 通过三条路径「看见」代码库——显式上下文(你贴的文件)、自动检索(索引与语义搜索)、结构信息(符号与调用关系)——理解三条路径的机理才能诊断「它怎么又找不到这个函数」。
为什么重要
同一份代码库,AI 表现可以天差地别,差异大多不在模型而在「检索路径是否通畅」。当你理解了 AI 的取材方式,就能预测它会在哪里失败(巨型文件、重复命名、生成代码、索引过期),并主动设计上下文(kp-008)与探索策略(kp-010),而不是凭感觉反复重试。
前置知识
kp-004(上下文窗口与注意力预算)。
核心概念
- 显式上下文:你直接贴入窗口的内容。最可控,成本是你手动挑选。
- 关键词检索:grep/精确符号匹配。确定性高,但对「意思相近名字不同」无效。
- 语义检索(semantic search):把代码切块(chunk)算成向量(embedding),按含义相似度召回。能找到「改名前的逻辑」,但对精确符号反而可能漏。
- 符号与结构信息:LSP/语言服务提供的定义、引用、类型层级,是代理层「跳转」能力的来源。
- 索引新鲜度:索引在文件改动后需要重建,过期索引是「AI 引用旧代码」的常见根因。
原理与机制
语义检索的召回质量取决于切块策略(按函数还是按行)与嵌入模型对代码的理解。切块过大→单块内混入多主题,相关度被稀释;切块过小→上下文断裂,召回的片段缺调用方。混合检索(关键词+语义)通常优于单一来源:关键词保精确性,语义保召回率。代理层在检索到候选后还会「打开文件读上下文」做二次确认——这是它比纯聊天助手强的原因之一,也是它消耗更多时间与 token 的原因。
实例或案例
操作步骤(判断你的仓库对 AI 是否友好):
- 检查单文件体量:>1000 行的文件会被切块,考虑补全时拆分焦点。
- 检查命名唯一性:同名工具函数散落多目录时,明确写「用 utils/http.py 的 retry」。
- 检查生成代码目录(build/dist/lock 文件)是否被排除在索引外,否则污染召回。
- 大仓库先验证索引状态:改完代码等索引更新,或手动触发重建。
排错清单(AI 找不到函数/引用旧实现时):
- 符号确实存在吗 → 用 grep 确认,排除拼错。
- 是不是重名 → 告诉 AI 全限定路径。
- 索引是否过期 → 重建索引后重试。
- 是否在生成目录/被忽略路径里 → 移到索引可见处或直接贴代码。
- 仍找不到 → 退回显式上下文:手动贴定义与调用点。
公式或模型
本节不适用:检索质量由工程实现决定,无通用闭式公式。
图示
你的任务
├─ 显式上下文(你贴) → 100% 可控
├─ 关键词检索(grep 类) → 精确但字面
├─ 语义检索(向量索引) → 会意但可漂移
└─ 符号结构(LSP/跳转) → 代理层的导航能力
四路汇合 → 窗口 → 生成直观类比
三条路径像查资料的三种方式:你递纸条(显式)、图书馆按书名查(关键词)、管理员听你描述大意帮你找(语义)。描述得越准、馆内目录越新,找得越快。
常见误区
- 「AI 应该自动知道我的代码」:没有检索材料就没有理解,检索失败是工程问题不是智力问题。
- 语义检索万能:对精确符号匹配常不如 grep,两者互补。
- 忽略索引新鲜度:改完代码立刻问,得到的可能基于旧快照。
与其他知识点的关系
kp-010 把本节机理变成探索操作序列;kp-008 决定何时绕过检索直接投喂显式上下文。
自测题
要点:显式上下文(人挑漏)、关键词检索(字面不达意)、语义检索(漂移/索引过期)。
要点:索引过期引用旧快照;重名/生成目录污染导致召回错位。
- 三条取材路径分别是什么?各有什么失效模式?
- AI 引用了「不存在的函数」最可能的两个工程原因?
延伸阅读
本节不适用:语义检索经典文献多面向通用 NLP,与本库编程技能主线关联弱,建议直接在自家仓库做第 1 节的实践验证。