AI 编程的上下文管理:大仓库里怎么把「对的代码」喂给模型

用一个百文件的大仓库试过 AI 编程的人都有同款挫败:模型改一个函数改得很漂亮,但它不知道仓库里还有三处在调用这个函数;或者它「自信地」重新发明了一个工具函数——仓库里明明就有。AI 编程的瓶颈往往不是模型的智力,而是上下文的喂法。怎么在几百万行的仓库里,把「此刻相关的代码」放进有限的上下文窗口(站内《Claude Code 实战工作流》讲的工具用法之外,本文讲上下文策略的通用原理)。

先算账:为什么不能全喂进去

一笔简单的账:一个中型仓库 50 万行代码约 500 万 token,而主流模型的上下文窗口是 10^5–10^6 token 量级——物理上装不下;就算装得下(长窗口模型),全量塞入还有两重代价:成本按 token 计费,以及「大海捞针」效应——超长上下文里的中间内容检索准确率会下降。所以上下文管理的本质是一道信息筛选题:从全仓库中挑出与当前任务相关的千分之几。

三层策略:从人工到自动

层一:人工指定(简单、可控、贵)

最朴素的做法:把相关文件手动加进对话。优点是精准、无歧义;缺点是你必须先知道哪些文件相关——在陌生仓库里这恰恰是办不到的。适合你熟自己代码库的场景,或作为自动检索失败后的兜底。

层二:仓库地图(Repo Map)——用大纲代替全文

Aider 的 repo map 是这一层的教科书实现,机制值得完整拆解:

  1. 符号抽取:用 tree-sitter 解析全仓库,提取每个文件的符号——类、函数、方法的定义与引用;
  2. 建引用图:把符号引用织成一张跨文件的图——A 文件调用了 B 文件的函数,就是一条边;
  3. 重要性排序:在图上跑 Personalized PageRank(个性化种子通常来自对话中已提到的文件),被核心代码引用多的定义排名高;
  4. 装填:在 token 预算内,把排名最高的定义签名(不含函数体)打包成一张「地图」,常驻上下文。

地图的精髓是用签名换语义:模型看不到函数体,但看得到「仓库里有什么、谁在用谁」——足以避免重复造轮子和破坏调用方,真要细看某个定义再展开。这是 O(仓库规模) 的压缩,让模型「知道全貌、局部展开」。

层三:智能体检索——让模型自己 grep

第三层把选择权交给模型自己:给 Coding Agent 一个 grep/文件读取工具,让它像人类工程师一样按需探索——先搜关键词,读两眼,再顺着 import 链往下挖。Claude Code 等智能体工具的核心机制正是这个(配合 CLAUDE.md 之类的项目记忆补足「常识」)。它的优势是按任务动态定位,地图是静态的而检索是活的;代价是多轮工具调用的延迟与 token 消耗,且检索质量取决于模型的搜索直觉。

三层的正确关系是互补而非互斥:地图提供常驻全貌,检索负责按需深挖,人工指定处理机器找不到的隐性约定(「这个函数别动,业务在等它」)。

实操守则:预算、防腐烂、验证

  • 给上下文分层定预算:以 200K 窗口为例的参考配比——系统提示与项目记忆 5%,仓库地图 10%,当前任务的相关代码 30–40%,对话与推理留余量。地图超预算时优先砍低 PageRank 的枝叶;
  • 警惕上下文腐烂:会话早期读入的代码,在模型多轮修改后可能已经过时——长会话里定期让 agent 重新读取被改过的文件,或干脆在任务切分时保证「读—改—验」闭环短小;
  • 改完验证调用方:无论上下文多充分,「改签名必查调用方」应该是硬流程——让 agent 跑 grep 确认引用、跑测试确认行为,上下文喂得再好也不能省这一步(评审与验证的完整话题见后续《AI 代码评审实战》);
  • 负面信息也是上下文:.aiderignore/.gitignore 之外,把「不要碰的目录」「过时的模块」写进项目说明,能省下模型误入歧途的大量 token。

结语

上下文工程的通用公式可以压缩成一句:全貌用地图,细节用检索,隐性知识用文档,信任用验证。模型窗口每代都在变大,但「全仓库装进上下文」永远不经济也不必要——筛选相关性的能力,才是 AI 编程工具真正的护城河,也是使用者的核心技能。

参考资料

← 返回资讯列表

读者留言

COMMENTS 暂无
仅本站原创文章开放留言 · 请勿留下手机号、邮箱等个人信息

还没有留言,来说第一句?