先记住这个答案
已知函数名、错误码、路由片段或配置键时,grep 或 ripgrep 能直接定位实际文本,结果容易核对,也不依赖向量索引更新。只有自然语言行为描述、代码命名与需求用词差异较大时,语义检索可以帮助找到概念相关候选,但相似度不证明调用关系或当前实现正确。两者可以组合:先用精确线索缩小范围,缺少线索时语义召回,再读取真实文件并追踪定义与引用。无论从哪种方式得到结果,修改前都要确认仓库、分支、版本和文件现状。
- 符号和错误文本适合精确查找,模糊意图适合语义召回
- 命中内容不等于证明运行路径或符号关系
- 索引结果必须回到当前原文件核对
精确搜索擅长回答内容在哪里
用户给出错误码 AUTH_EXPIRED,先在目标源码目录固定字符串查找,通常比把整段问题转换成向量更直接。rg 的 -F 让搜索词按字面匹配,避免点号或括号被当成正则语法;-n 提供行号,便于继续读取上下文。
命中结果仍可能来自测试、旧实现或未使用导出。下面限制 TypeScript 文件并分别查看文件清单和错误码位置。真实排查还要确认忽略规则、隐藏文件与生成目录是否符合任务范围,零命中不等于整个系统不存在相关行为。
rg --files src -g '*.ts' -g '*.tsx'
rg -n -F 'AUTH_EXPIRED' src -g '*.ts' -g '*.tsx'第一条列出所选源码文件,第二条查找字面错误码。命令不会判断哪个分支实际运行,也不会自动追踪同名符号;必要时结合语言服务、引用查询和调用方代码继续验证。
语义召回适合命名未知的业务问题
如果问题是“关闭弹窗后旧请求仍覆盖新页面”,仓库可能使用 epoch、requestToken 或 disposed 等词,未必出现用户描述中的关键词。语义检索可以把这些概念相关片段放进候选集,再由 Agent 对照异步流程判断是否有关。
它也可能把其他模块里类似的取消逻辑排得很高,或者只召回注释和文档。分数表示当前检索模型的相关程度,不是代码正确性的概率。应保留路径、范围与版本信息,避免脱离上下文把一个看起来相似的片段直接当成修改目标。
混合检索最后仍要落到当前代码证据
可以并行收集文本命中和语义候选,去重后按任务相关性、目录归属和调用关系继续缩小。两种分数通常不能直接相加,排名融合是一种可选方式,但是否有效需要用真实仓库问题评估,不能只看检索列表更长。
向量索引可能落后于当前分支,文本搜索也可能读取到随后被修改的文件。准备补丁前重新读取目标范围并检查版本,必要时更新索引或放弃过期候选。涉及符号重命名时还应使用语法与引用工具,普通文本匹配无法可靠区分所有同名符号。
容易答错的地方
- 语义搜索排名第一的文件就是问题根源
- 相似度只提供候选,真正根因需要结合调用链、状态变化和复现证据确认;相关实现不一定在故障路径上。
- rg 没找到就证明代码不存在
- 搜索目录、扩展名、忽略规则和词形都可能限制结果,动态生成与依赖包也可能不在范围内;应先检查搜索前提再下结论。
面试官还会怎么问?
已经知道函数名还要跑向量检索吗?
通常先查精确符号更直接。只有定义分散、需要发现替代实现或相关业务概念时,再增加语义召回作为补充。
向量索引应该按整文件还是函数切块?
要兼顾语义完整和上下文成本。函数块方便定位,但可能缺少类型与周围约定;检索结果应能扩展到相邻定义,并保留原文件位置。
搜索结果可以直接作为补丁输入吗?
应先重新读取当前文件,确认内容没有截断或过期。检索片段是发现入口,不能替代应用补丁时需要的真实上下文和版本前提。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。