AI 改代码漏文件的根因,八成不在模型能力,而在检索方式:只喂关键词匹配的结果,智能体就只会改它”看见”的那几个文件。 Anthropic 在 Claude Code 里优先给的是 Grep 、 Glob 这类检索工具而不是把整个仓库塞进上下文;Sourcegraph 的实测更直接——纯关键词检索下智能体只改到 7 个受影响文件中的 2 个,换成结构化检索后 7 个全部命中。
为什么”把仓库塞进上下文”走不通
上下文窗口是最稀缺的资源。一次调试会话能轻松吃掉几万 token,而随着上下文接近上限,模型的表现会明显下滑:开始遗忘前面的指令、判断变粗糙。更麻烦的是成本——每次多塞十个无关文件,账单和延迟都在涨,收益却是负的,无关代码还会稀释模型对关键路径的注意力。
所以正确方向不是”塞得更多”,而是”找得更准,喂得更少”。
第一步:先建符号索引,别只靠关键词
关键词检索的失败模式很固定:搜 user 返回几百处匹配,智能体随手挑一个看起来像的,结果改到了测试桩或者同名工具类。符号级检索(定义、引用、类型归属)能把候选从几百个收敛到几个。
- 能上语言服务器就上:跳转定义、查找引用是符号检索的基础能力,比文本匹配可靠一个量级。
- 没有语言服务器时的退路:用带文件名与目录约束的正则把范围压到一层子目录,再让智能体逐个确认,别让它在大范围匹配里自由发挥。
- 把入口写进项目记忆文件:核心模块的职责、约定的目录含义,写一次就能让每次会话少走几轮检索。详见我们之前写过的项目记忆文件 CLAUDE.md 与 AGENTS.md 怎么写。
第二步:按依赖切片,而不是按目录切片
目录是人为了阅读方便划的,依赖才是改动真正会传播的路径。改一个函数签名,受影响的是所有调用方,而它们往往散落在三四个看似无关的目录里。切片时按”调用链 + 导入关系”取文件,而不是按”这个功能大概在 src/xxx 下”。
实操做法:先让智能体列出目标符号的全部引用点,再按引用点反查所属模块,最后只把这一批文件读进上下文。这一步是”改全”和”改漏”的分水岭。
第三步:上下文裁剪与外化
检索本身也会产生大量中间结果:读了二十个文件才找到答案,这二十个文件就永久占着上下文。 Anthropic 的做法是把检索任务丢给子智能体——它在自己的上下文里翻文档、搜代码,只把最终答案交回主智能体,主上下文因此保持干净。
这套”渐进式披露”思路同样适用于你自己的工作流:探索、规划、实现分成不同阶段,每阶段的中间产物不进下一阶段的上下文。
检索配置清单
| 配置项 | 建议 | 常见错误 |
|---|---|---|
| 符号检索能力 | 优先启用语言服务器 / 代码智能插件 | 只装了文本搜索,靠关键词硬凑 |
| 检索范围约束 | 先限定目录,再放宽 | 全仓正则,一次返回几百条 |
| 改动前确认 | 要求先输出受影响文件清单 | 直接开改,改完才发现漏文件 |
| 探索与实现 | 分成两个阶段,中间产物不外传 | 探索和写代码混在一次会话里 |
| 验证方式 | 给出可运行的测试或构建命令 | 以”看起来没问题”作为完成信号 |
检索做对了,还要防幻觉
检索质量提升能解决”改漏”,但解决不了”改错”——智能体依然可能引用一个不存在的函数、或者相信一个过时的接口定义。检索之后必须跟一道验证环节,我们在AI 编程幻觉怎么防里列了四类高频幻觉和对应的验证清单,可以和本文的三步法串起来用。
小项目也需要这套检索流程吗?
子智能体检索会不会更慢更贵?
怎么判断智能体检索得不准?
没有语言服务器的老项目怎么办?
参考来源与检索失败排查
本文事实依据:Anthropic 官方 Claude Code 文档与工程博客(上下文窗口管理、 Grep 工具的取舍、渐进式披露与子智能体隔离)、 Sourcegraph 关于检索方式对改动完整度的实测数据。
检索失败的排查顺序:① 确认检索工具是否真的执行了,而不是被模型跳过;② 检查范围约束是否过窄导致漏掉调用方;③ 检查是否只读了同名文件中的一个;④ 让智能体复述它读到的接口签名,看是否与你认知一致。









评论 (0)