做 Coding Agent 搜代码:到底该选 RAG 还是 Grep?扒完 Claude Code 源码我顿悟了

大家好,我是不会喷火的小火龙。

很多团队自研 Coding Agent,第一步就是去搭向量数据库——Chroma、Qdrant、Weaviate 随便选一个,跑 Embedding,切片,建索引。看起来很"AI",很高大上。

但你有没有想过:Claude Code,目前公认最强的 AI 编程工具之一,它的代码检索底层,其实就是一个 50 年前的命令行工具——grep

如图 1 所示,这就是很多团队盲目上 RAG 之后经历的真实工程困局,和 Anthropic 自己走过的弯路。

image.png

这篇文章想帮你搞清楚三件事:代码检索场景下 RAG 为什么频繁翻车、Claude Code 的极简方案如何跑通、以及你自己的项目到底该怎么选。


一、为什么代码检索场景下,传统 RAG 频频翻车?

代码是符号系统,不是自然语言。这句话听起来像废话,但绝大多数 RAG 翻车的根源就在这里。

向量语义检索的逻辑是意思相近的文本在向量空间里彼此靠近,这在自然语言里成立,但在代码里会系统性失效。举个例子:createD1HttpClientbuildD1HttpClient 语义高度相近,向量距离极小,但它们在代码里是两个完全不同的函数;而同一条调用链里相互依赖的函数,语义可能毫无关联,向量检索根本找不到它们之间的联系。

如下表所示,代码符号场景下,语义向量召回和精确匹配之间的准确率差距相当触目:

代码精确符号 vs 语义向量召回偏差对比

查询类型示例查询向量检索结果精确匹配结果
函数名精确查找createD1HttpClient召回 buildD1HttpClient(相似但错误)精准命中,第 1 条结果
错误码定位ERR_DB_CONNECTION_TIMEOUT召回语义模糊的错误描述文本直接定位到常量定义行
调用链追踪handlePaymentCallback 的全部调用方召回支付相关的无关业务代码逐个匹配调用点,一个不漏
变量赋值查找MAX_RETRY_COUNT = 3 在哪里定义无法区分定义和引用精确定位定义行

RAG 在代码场景还有三个硬伤。

第一,Chunk 切片会破坏 AST。按字符数盲目切片,会把一个类或一个函数切成两半,上下文彻底断裂。第二,索引永远赶不上代码变化。代码是秒级变动的,向量索引构建慢、增量同步复杂,极易产生脏数据,让 LLM 基于过期上下文产生幻觉。第三,全量代码送第三方向量化,隐私泄露风险不可忽视;本地跑大型 Embedding 模型,GPU 成本直接劝退。


二、扒开 Claude Code 源码:极简的 Agentic Search 是怎么跑通的?

Anthropic 没有预先构建任何静态索引。Claude Code 的做法是把搜索变成 LLM 的"多轮自主探索循环"。

三大并发安全工具构成整个检索引擎:

  • GlobTool:按文件名模式快速扫描项目骨架,类似人类第一步看目录结构,确定大致位置。
  • GrepTool(底层是 ripgrep):毫秒级全文精确正则搜索,类似人类在 IDE 里按 Cmd+Shift+F 搜关键词。
  • ReadTool:按需读取具体行号范围,类似人类定位到文件后翻开那几十行上下文。

为什么选 ripgrep 而不是普通 grep?ripgrep 用 Rust 开发,内置 SIMD 硬件加速,万级文件的全文扫描仅需约 200ms,自动跳过 .gitignore 指定的目录,天然适配代码仓库。内置的 head_limit=250 截断保护,防止搜索结果把上下文窗口撑爆。

如图 2 所示,两者的底层架构存在根本性的范式转移:

图 2:静态 RAG 检索管线 vs Agentic Search 多轮自主探索流程

image.png

这个设计里最巧妙的地方:LLM 本身就是最顶级的动态 Reranker。每轮检索结束后,LLM 自己判断这个线索够不够、要不要继续顺藤摸瓜,完全替代了传统架构里那个静态的 Rerank 模型。


三、权威佐证:Anthropic 踩坑实录与亚马逊论文实锤

放弃 RAG 不是 Anthropic 拍脑袋的激进决定,是被真实实验数据逼出来的。

Boris Cherny(Claude Code 技术负责人)在 2025 年 5 月的 Latent Space 播客里说过:Claude Code 早期确实搭建过基于 Voyage Embedding 的向量 RAG 检索系统,效果"还行"。但在实测用 Glob + Grep + Read 构成的 Agentic Search 之后,他的原话是:

"outperformed everything, by a lot. You avoid all the problems with security, staleness, and indexing."

安全问题没了,索引过期没了,增量同步也不用维护了。

学界的数据同样说明问题。亚马逊科学团队在 AAAI 2026 发表的论文《Keyword search is all you need》(arXiv:2602.23368)严格对比了标准向量 RAG 和纯关键词检索的 Agent 系统,结论是:关键词搜索在综合性能上达到 RAG 的 90% 以上,在代码等高度结构化的符号系统中,精确匹配的表现还显著优于向量语义检索。

从工程实践到学术实验,两份证据指向同一个结论:代码这个特殊领域里,精确性比语义相似性更重要。

如图 3 所示,代码搜索工具链使用图:

image.png


四、反方视角:Cursor 为什么坚持重仓向量?

读到这里,你可能会问:Cursor 呢?它也是 AI 编程工具里的顶流,技术路线和 Claude Code 截然不同,难道走错了?

没有。两者的架构选择,背后是产品形态的差异。

Claude Code 是轻量 CLI 工具,面对频繁切换的项目,零冷启动是第一要务。每次打开一个新项目,没有时间也没有必要预建索引,Glob + Grep 随开随用,几毫秒就能工作。

Cursor 是 IDE 插件,常驻用户系统,面对的往往是几十万文件的超大 Monorepo。在这个规模下,每次查询都做全量 ripgrep 扫盘,性能会出现瓶颈。

如图 4 所示,Cursor 并没有抛弃 grep,而是构建了一套双轨混合系统:

图 4:Cursor 混合检索双轨架构

image.png

Cursor 工程团队在官方博客(Instant Grep & Codebase Indexing)里直说:纯语义搜索在精确标识符、错误码、函数名上表现太差,所以他们自研了基于三元组(trigram)倒排索引的"Instant Grep"来弥补。两套系统并联,精确归精确,语义归语义,用 Merkle Tree 实现分钟级增量同步保持索引新鲜。

Cursor 的一个典型场景是:用户说"微信支付退款重试逻辑在哪里",记不住具体函数名,这时候语义向量检索才真的有用。


五、实战选型指南:自研 Coding Agent 到底怎么选?

扔掉非黑即白的架构争论。正确的问题是:你的产品形态和业务场景是什么?

我把这套选型逻辑整理成了一张清晰的决策树,如图 5 所示:

图 5:Coding Agent 代码检索技术选型决策树

image.png

三个场景的核心判断:

模式 1,极简优先,适合 90% 的个人开发者和轻量 CLI 工具。零依赖、零维护,直接用 ripgrep + Glob + Read 先把产品跑起来,有实际用户反馈再说向量的事。

模式 2,混合检索,适合 IDE 插件和常驻大型 Monorepo 的服务。精确符号归 trigram 倒排,模糊语义归轻量向量,两者并联。不要上重型托管向量数据库,自研 trigram 索引成本比你想象的低得多。

模式 3,LSP 语法感知,有明确跨文件引用追踪需求时接入 Language Server Protocol,获取符号定义和引用关系图。这才是"语义理解"真正应该发生的地方。


结语

Anthropic 用 50 年前的 grep 打败了自己搭的向量 RAG,这不是反智,这是工程上的诚实:代码是精确的符号系统,grep 是精确的符号匹配工具,用对了工具比堆技术栈更管用。

希望这篇文章能帮你在自研 Coding Agent 的路上少走一段弯路。

如果你对这类技术拆解感兴趣,欢迎关注公众号「小火龙AI 手记 」。

这里持续挖掘 GitHub 等开源社区里真正好用、能打的高价值项目,拆解它们背后的工程逻辑;同时也记录我自己用 AI 搓工具、做产品、踩坑填坑的全过程实录。都是有一点技术基础就能看懂的干货,跟你一起把 AI 驯化成真正趁手的生产力工具。


参考资料:

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
不会喷火的小火龙
下载 APP