
先说一个我观察到的现象用 AI 编程助手的人经常会遇到同一个工具一会儿像大神一会儿像傻子的情况。前十分钟它还能快速生成一整个模块后十分钟你问它改一个变量名它都能给你改出一堆莫名其妙的报错。很多人把锅甩给模型说是模型不行。但我在真实项目里折腾大半年之后得出来的结论很不一样问题多半出在上下文上更准确地说是你根本没搞清楚 context-mode 的正确打开方式。Context Mode直译是上下文模式现在几乎成了各类 AI 编码工具的标配功能。它的核心职责只有一个决定大模型在动手写代码之前到底看哪些文件、读哪些内容、遵守哪些约定。听起来很简单但实际用起来里面的门道非常多。这篇文章我打算把自己的完整思路、具体操作、以及踩过的坑都摊开来讲希望给那些在项目里重度依赖 AI 编程助手的开发者一些参考也帮刚入门的朋友少走几个月的弯路。1. AI 编程助手失忆症的根源上下文窗口的分区逻辑1.1 每次对话其实都是从零开始首先要破除一个误解很多人以为 AI 编程助手记住了你整个项目的代码它在回答时是翻遍了全项目之后才给出答案。实际上绝大多数情况下模型看到的东西极其有限。我在本地项目上做过一个简单实验仓库里有 800 多个文件我什么上下文都不加直接让它帮我重构一下 utils 目录下的日期处理函数结果它给出的代码引用了好几个根本不存在的依赖还把另一个模块里的旧函数名当成了现状。原因很简单——它没看见实际代码只能靠训练阶段学到的通用知识去猜。所以 AI 编程助手并不是失忆而是它默认状态下几乎什么都没记住。每次请求发送时模型能使用的窗口是有限的这个窗口由几个分区构成系统提示工具预设的行为指令比如你是一个资深工程师。任务描述你刚才敲进去的那段话。参考材料被检索或指定加入的代码文件、文档内容。对话历史此前几轮的问答记录。输出预留模型写回复和代码的空间。如果参考材料这块是空的模型就只能靠常识干活。这就是失忆症的真相。1.2 Context Mode 的本质给模型划定你去哪看资料Context Mode 这个功能本质上就是一种指派阅读范围的机制。你告诉模型这次任务你的重点检查对象是 A 文件、B 目录项目约定看 C 文档别的东西不用管。这个机制的价值类比一下就非常清楚你让一个新来的同事帮你改代码。如果你只说帮我把某个页面改得好看一点他大概率会从首页开始逐个翻翻到一半就开始瞎改。如果你说先看src/pages/profile.tsx样式问题都集中在styles/里设计规范在docs/design.md他的效率就会高得多。Context Mode 做的就是这个事只是把口头交代变成了结构化的、模型能真正读取的输入。1.3 上下文窗口不等于长期记忆还有一个必须强调的点上下文窗口再大也不是长期记忆。它更像一块临时便签。项目里真正长期、稳定的信息应该沉淀在文档、注释、配置规则里而不是指望每次靠模型自己想起来或者窗口自动带入。我见过不少团队明明写好了项目规范文档却不在每次提问时把文档链接或内容放进去结果 AI 生成的代码风格跟项目规范完全不一致。这不是工具的锅是使用方式有问题。2. 三种主流的 Context Mode 形态与选择策略2.1 自动检索模式适合探索不适合攻坚现在的编辑器插件基本都有自动检索能力。你的问题发出去以后工具会在本地仓库里做一次语义搜索挑出最相关的文件片段自动塞进上下文。这种模式的好处是省事不用你手动指定文件。我在处理一个自己不太熟悉的模块时会用这种方式先问一遍让 AI 大致告诉我这块业务的代码分布。但它有个非常明显的问题检索的相关度是基于向量相似度算出来的和解决问题真正需要的信息不是一回事。举个例子我在一个微服务项目里问订单超时未支付后库存为什么没释放自动检索找出来的是大量订单状态枚举定义和几个 Controller 文件但真正扣库存的逻辑在消息队列的消费者模块里检索结果完全没覆盖到。那次白折腾了二十分钟最后手动指定文件后一轮就定位到了。所以我的原则是自动检索模式只用来问路别用来走迷宫。一旦涉及跨模块、跨服务的逻辑修改就必须切到手动指定模式。2.2 手动指定模式最可控也最看功力手动指定是指通过符号或拖拽的方式明确把某个文件、某个目录、某段代码加入上下文。这种方式下模型看到的范围完全由你掌控不会跑偏。它的核心技巧在于指定哪些、指定多少。我在实际项目中一般遵循三个原则入口文件必给比如你要改一个 API 接口就必须把路由定义、Controller、Service 这三层文件全部放入上下文。数据模型必给涉及数据库操作时把对应的实体类、表结构定义放进去否则模型很容易把字段名写错。样式或风格锚点可给可不给如果任务是新增页面我会放一个已有的、风格类似的页面作为风格锚点让模型参考着写出来的代码风格会统一得多。手动指定模式的上限很高但非常考验对项目结构的熟悉程度。如果你自己都没搞明白问题出在哪个文件里那 AI 很难帮你搞清楚。2.3 全库扫描模式最后的选择不是最优选择现在不少 AI 编码助手支持Agent 模式或全仓库模式也就是让模型自己遍历仓库目录结构自主读取相关文件然后完成任务。这个模式看起来很智能但在真实项目里代价非常大。首先大仓库文件极多模型如果全部读一遍上下文会被迅速撑爆其次模型在自主遍历时同样可能被看起来相关的文件带偏遇到文件少的小项目还好文件一多就会开始犯糊涂。我测试过一个中型项目用全库扫描模式让它给某个模块加日志结果它先把整个 README 和一些无关的测试数据读进去了然后回答得非常散。所以我把全库扫描当作兜底方案只有在完全不熟悉项目、手头又没有文档、且问题范围特别宽泛的时候才会用。一旦定位到具体位置立刻转向手动指定。2.4 三种模式的搭配思路模式优点缺点我推荐的使用时机自动检索省事、无需了解项目结构容易漏关键文件、相关性不稳定快速了解陌生模块、全局搜索线索手动指定精确、可控、质量最稳依赖使用者的项目熟悉度明确知道问题所在文件、或已经定位到模块全库扫描覆盖面大、适合极陌生环境上下文消耗大、容易被无关文件带偏完全没有头绪时的第一轮探测三种模式不是互斥的。我自己最常用的是先自动检索问路再手动指定攻坚的组合打法。这样既节省了摸索时间又保证了生成质量。3. 上下文喂养的具体方法从提问到交付的完整链路3.1 需求描述用三段式别当聊天爱好者很多人在用 AI 编程助手时对话风格像在跟朋友聊天帮我看看这个为啥不行。这句话丢给模型它确实会去看但看什么、怎么看完全取决于工具默认行为——实际上就是相当于什么都没给。我在实践里总结了一个需求描述模板三段式背景当前是在什么项目、什么模块里工作涉及哪些技术栈。目标期望 AI 产出什么是一段代码、一份解释还是一个重构方案。约束不能动哪些文件、必须遵循哪条规范、性能上有什么要求。举一个我实际用过的例子这是给一个促销后台添加导出功能的提示词背景项目是 Vue 3 TypeScript 的后台管理系统列表页在src/views/promotion/list.vue导出请求的封装在src/api/request.ts后端导出接口返回的是二进制流。目标在列表页新增一个导出按钮点击后调用接口并下载文件。约束不要修改request.ts里的公共逻辑下载后要提示用户成功文件命名带上当天日期。这段描述里没有任何废话模型拿到之后动作非常快第一次生成的代码就基本能跑。对比一下你平时可能发的帮我加个导出功能差距一目了然。3.2 先读后写策略让模型先复述再动手我后期使用 context-mode 最重要的一条心得是不要上来就让模型直接改代码先让它证明它读懂了上下文。操作方法很简单在任务描述末尾加上一句在动手之前先总结一下你从上述文件里理解到的现状包括关键函数、变量命名、以及你觉得需要注意的地方。 然后等它输出总结你确认总结准确以后再接着输出第二段话总结没问题现在开始修改。这个习惯的价值在于它能提前暴露模型读错文件或者模型理解偏差的问题而不至于在生成一大坨代码以后才发现方向错了。我在处理一段复杂的权限校验逻辑时让模型先复述了一遍才发现它把管理员可写、普通用户只读理解成了所有人只读。如果直接让它改整片代码全废了。3.3 用规则文件把项目约定写进上下文Context Mode 的另一种重要用法是把项目级规则当成隐性上下文自动注入。很多 AI 编码工具支持项目根目录放置规则文件比如.cursorrules、AGENTS.md、CLAUDE.md这类文件里的内容会在每次对话时作为系统提示的一部分自动添加到上下文中。我在项目里维护了一个AGENTS.md内容大概包括技术栈与目录结构的简要说明。代码风格约定比如组件命名用 PascalCase、工具函数放src/utils/、禁止在组件里直接写网络请求。常用依赖的注意事项比如 UI 库的按钮组件必须用typeprimary时才有蓝色样式。有了这个文件之后AI 输出的代码质量有了肉眼可见的提升。最明显的是组件命名风格统一了不会出现一半user-card、一半UserCard的情况。要注意的是规则文件不是写得越多越好。写得过杂模型反而抓不住重点。我建议只写三类内容一定会被频繁遵守的约定、最容易写错的细节、以及不允许触碰的禁区。3.4 会话太长了怎么办重置会话与信息搬运长对话是上下文质量的最大杀手。对话越久历史记录占的空间越多真正重要的参考材料反而可能被挤出有效范围。我自己的经验是一个会话解决一个问题超过五轮对话还没解决果断开新会话。开新会话时不需要把一整段对话都搬过去那样只会复制垃圾。要做的是信息搬运——把以下三项搬到新会话问题的最初描述三段式那段。已经排查出的关键结论比如已经定位到某文件的某一行。尝试过但失败的方法加一句不要再这么做。这样新会话一开始AI 就能站在一个清晰的起点上继续干活而不必消化前面那堆试错记录。4. 上下文窗口不是越大越好Token 预算与注意力陷阱4.1 Lost in the Middle中间内容容易被忽略模型处理超长上下文时有一个被广泛验证的现象它对开头和结尾的内容注意力最强中间部分的信息会被明显弱化。这意味着你把一百个文件塞进上下文模型真正看清楚的可能只有最前面几个和最后面几个。这直接导致了两个常见问题一是你辛辛苦苦选进上下文的某个关键文件正好落在被忽略的中间地带模型根本没好好看二是上下文里信息太多模型在生成时不知道该以哪一份为准回答会变得很平均缺少针对性。所以我严格控制单次上下文里的文件数量。一次任务参考文件尽量控制在 5 个以内最多不超过 10 个。如果确实有大量文件需要模型理解我会分步骤来先让它读完文件 A 和 B总结出方案再把方案作为上下文的一部分和文件 C、D 一起继续下一个任务。这样每一轮的上下文都精炼且高效。4.2 动手估算一次请求的成本很多人对上下文消耗没概念等到月账单出来才发现费用飙高。我提供一个非常粗略但够用的估算方法中文文本1 个汉字大约对应 0.6 到 1 个 token。代码文本平均每行代码大约 10 到 15 个 token取决于缩进和符号密度。一次请求的总消耗约等于系统提示 全部上下文文件内容 全部对话历史 本次输入 模型输出。举个具体例子你让模型阅读 10 个文件每个文件平均 400 行代码那就大约有 4000 行代码换算成 token 就是 4 万到 5 万左右。如果对话又持续了十几轮每次回传整个历史记录总消耗会非常可观。想控制成本最有效的办法就是上面说的减少参考文件数量、控制会话长度、及时重置。另外还有一个细节如果你的工具支持仅将选中的代码块加入上下文而不是整个文件加入尽量用前者。很多时候我只需要某个文件里的一个函数没必要让模型读完整份 1000 行的文件。4.3 上下文不够时的降级策略架构说明文件碰到超大项目时想让模型理解整个系统是不现实的。我的做法是维护一份精简的架构说明文件几百字到一千字即可把系统分几个模块、每个模块的职责、模块之间的调用关系说清楚。这份文件不是为了给人看的是为了喂给 AI 的。当任务跨模块时我把这份说明放入上下文再配合相关的关键文件。模型虽然不会亲眼看到全部代码但靠着这份地图它能在正确的方向上工作。说白了上下文不够时我们给它的是指路牌而不是全程实景导航。5. 真实项目中的 Context Mode 翻车现场与修复过程5.1 检索到过时文件把以前的方案当成了现状有次我在重构一个老模块自动检索把一份已经废弃的设计稿 markdown 文件当成参考放进了上下文。模型基于那份文档生成了一套早已不存在的接口调用代码。我第一眼看到就觉得不对但没立刻怀疑是上下文的问题还以为是业务改了需求。排查的时候我点开工具里的上下文面板逐个检查这次请求到底读了哪些文件这才发现那份废弃文档混在里面。去掉之后把当前正在用的 Service 层代码手动加入第二次生成的代码就对了。教训是AI 工具给出的相关文件并不能保证时效性尤其在有大量历史文档的仓库里过时文档的相似度可能比现行代码更高。以后我凡是用到自动检索出来的内容都会留个心眼先确认文件有没有标记已废弃。5.2 手动指定范围太窄局部看多了丢了全局约束跟上面相反的情况也经常遇到。我手动指定了三个关键文件让模型去改一个功能结果模型把所有校验逻辑都写死了完全没有复用项目里已有的全局异常处理机制。原因是我没把全局的异常处理规范这类全局约束放进上下文。模型只看到局部三个文件自然会认为错误处理就在本地做。后来我把项目的AGENTS.md更新了一下明确写了业务异常统一抛BizException由全局拦截器处理同样的问题再也没出现过。这个案例说明手动指定模式不能只关注跟任务直接相关的文件还要考虑跟任务有约束关系的全局文件。至少要把错误处理、鉴权、日志规范这些横切关注点覆盖到。5.3 规则文件内容互相矛盾上下文变成了一堆吵架的声音还有一次我同时维护了.cursorrules和AGENTS.md两份文件里对组件命名风格的描述不一致。一份说用PascalCase另一份说用kebab-case。模型每次读取到的规则都可能不一样生成的代码风格也随之摇摆不定。这个问题的排查比较简单我发现在同一类问题上模型给出完全相反的处理方式时就会去检查规则文件有没有冲突。从那以后我把项目里的规则文件收敛成一份主文件其他文件只引用它不再各自宣言。单一事实来源是给模型喂规则时最重要的原则。5.4 全文翻译型任务把无关内容全塞了进来有一类任务特别容易把上下文撑爆让人工智能通读全文后总结。如果你给一个 AI 工具挂上整个仓库让它总结它会真的把所有文件都读一遍。总结倒是生成了但下一次正经写代码时这段历史里的海量内容还在上下文里占着位置。我在处理完这种大检索任务之后会立刻开启新会话绝不让上一轮的全量阅读污染下一轮的精简操作。这个习惯帮我省了很多 token也让后续任务的质量稳得住。6. 团队里把 Context Mode 变成共同基础设施6.1 一份 CONTEXT.md让新人和 AI 站在同一起点个人用 context-mode 和团队用完全是两种玩法。个人可以靠习惯和记忆团队必须靠文件沉淀。我在团队里推行的一个方案是在项目根目录维护一份CONTEXT.md结构与内容大概是# 项目上下文速览 ## 技术栈 - 前端: React 18 TypeScript Vite - 后端: Node.js Express Prisma - 数据库: PostgreSQL 15 ## 目录结构 - src/pages: 页面级组件一个路由对应一个文件 - src/components: 通用业务组件禁止写页面逻辑 - src/api: 接口请求封装统一走 request.js - src/utils: 纯函数工具集 ## 关键约定 - 所有异步错误必须用 try/catch 包裹并在 UI 层给出提示 - 日期统一使用 dayjs 格式化格式 YYYY-MM-DD HH:mm:ss - 新增页面必须接入路由懒加载 ## 数据模型 - 用户表: users - 订单表: orders - 关联关系: 一个用户可拥有多个订单 ## 常用命令 - 启动: npm run dev - 测试: npm run test - 生成迁移: npm run migrate:create --name xxx这份文件别小看它同时服务两个对象人类新成员快速了解项目AI 工具作为上下文反复读取。每次有新任务我都会让模型先读CONTEXT.md再结合具体文件干活。团队里几个新人上手项目的速度明显比上一批没这份文档的人快了一大截。6.2 任务模板化把喂上下文变成流水线团队协作里还有一个大问题每个人给 AI 描述需求的口吻、详略差异巨大。有人写得像写作文有人只写一两个字。为了让大家的产出质量对齐我在团队内推广了一个简单的任务模板本次要改的功能是什么改动涉及哪些文件必须列出来运行/验证方式是什么不能影响哪些现有功能写完这个模板再配合CONTEXT.md整个团队用 AI 编程助手的效率下限就被托起来了。至少不会出现某人花了一下午都没让 AI 生成正确代码的情况。6.3 代码评审场景下的上下文裁剪最后聊聊评审。我以前试过让 AI 直接对整个 PR 做 review效果很一般它会输出一堆这个函数可以拆分建议增加注释之类的废话真正的问题一个没抓到。后来我调整了做法把 PR 的核心改动文件手动选进上下文再附带一句只关注逻辑正确性、边界条件和安全隐患不用提代码风格建议。这样 AI 的评审质量立刻上了一个台阶。这个场景本质上还是 context-mode 的典型应用你不裁剪上下文AI 就给你泛泛之谈你裁剪得越精准它输出的信息密度就越高。我自己在实际项目里最深的一个体会是context-mode 不是用不用的问题而是怎么用的问题。它决定了 AI 是在帮你还是在替你添乱。一个优秀的开发者不应该把 AI 编程助手当自动补全工具使而应该把它当作一个需要合理授权阅读范围的协作者。每当你觉得 AI 变笨的时候不妨先检查一下自己喂给它的上下文是不是真的精准。试试把本文提到的那几个习惯落地到项目里你会发现同样的模型、同样的提示词生成质量完全不一样。