上下文工程实战:AI编码助手四层配置框架拆解
提示词工程最近被讨论得很多但圈里真正热起来的词已经换成了上下文工程。我是在把 AI 编码助手从玩具用成结对老手的过程中才真正意识到这个转变有多重要爆肝提示词带来的收益远不如把模型眼前的材料整理好来得大。这篇文章要拆解的就是过去半年我在真实项目里落地的一套四层配置框架——把 AI 编码助手要面对的世界分成全局规则层、仓库索引层、会话任务层、反馈闭环层一层一层调。文章里会给出每一层的配置原理、可复现的模板和踩过的坑能直接抄作业的部分我都尽量写成了可编辑的版本。1. 为什么上下文工程成了比提示词工程更值得研究的命题1.1 提示词工程解决怎么说上下文工程解决模型看见什么行业里已经形成一句共识性表述上下文工程是提示词工程的升级版。这话初听有点像术语换皮真刀真枪用下来你会发现它确实不是简单的改名。我把一个编码助手从偶尔惊艳调到稳定可用最大的转折点不是把提示词写得更花哨而是开始认真思考一个问题模型在生成代码之前到底看到了哪些材料提示词工程关心的是你用什么话引导模型上下文工程关心的是模型在决策时手里握着哪些事实。这两件事在普通聊天机器人上还分不太开但在编码助手场景里差异巨大。你让 AI 改一个订单超时状态流转的 bug如果不把相关的状态机文件、数据库 schema、调用入口放进上下文那不管你把指令写得多么清晰它也只能靠猜猜出来的方案自然偏离业务实际。我更要强调一个反直觉的点上下文窗口大不等于上下文质量高。窗口从几千 token 一路卷到百万级看着很美好可一旦与任务无关的材料塞得太多模型会出现两种副作用——一是注意力被无关内容稀释抓不住真正重要的约束二是产生一种我已经看过足够多材料的假自信幻觉反而更隐蔽。上下文工程要做的是用正确材料填满窗口而不是单纯把窗口撑大。1.2 Agent 上下文处理工程与编码助手的特殊性最近 agent 上下文处理工程这个概念也频繁出现在技术社区。它比静态的上下文工程多了一个维度动态调度。agent 不是一次性回答一个问题就结束而是自己决定下一步要读哪个文件、跑哪条命令、看哪段报错每一步动作都会产生新的上下文旧的上下文还需要有选择地保留或者丢弃。这已经远远超出了提示词怎么写的范畴本质上是一套系统设计。AI 编码助手恰好是 agent 场景里最典型也最苛刻的一种。它拥有代码库的读取权限、终端命令的执行权限、文件系统的修改权限一旦上下文管理出问题后果会直接落到代码质量上改错文件、破坏模块边界、在无关目录里留下调试代码。同一个模型版本有的人用起来像靠谱的结对工程师有的人用起来像不懂事还爱乱动手的实习生差的不在模型本身而在于谁更会做上下文调度。所以我的立场很明确与其等着每个新模型带来能力跃迁不如先搭建一套稳定的上下文工程框架。后面四层拆解就是顺着这个思路展开的。2. 第一层全局规则层给 AI 立性格与底线2.1 规则文件到底该放什么内容第一层是全局规则层载体通常是项目根目录下的AGENTS.md、CLAUDE.md、.cursorrules这类规则文件。它们有两个共同特点一是对项目范围内的所有 AI 会话生效二是优先级非常高。你可以把它理解成给 AI 看的入职手册但它不是 README 那种项目介绍而是行为约束 项目知识速查。我在真实项目里一般只放五类内容。第一类是技术栈摘要包括语言版本、构建工具、核心框架、依赖管理方式第二类是代码风格和架构约束比如命名习惯、目录划分、模块边界我通常明确写UI 层禁止直接调用数据库查询这种硬边界第三类是明确禁止的事情比如不要删除看似无用的代码、不要擅自安装依赖、不要重构与当前任务无关的文件第四类是流程约定比如要求先写测试再补实现或者修改后必须运行类型检查第五类是给 AI 的偏好设置比如注释用中文还是英文、日志风格、错误处理习惯。很多人低估了不要动与任务无关的文件这条规则的价值。我经历过不止一次AI 接到一个小需求做完之后顺手把周边几处代码也重构了生成的 diff 里夹带大量无关修改评审成本直接翻倍。规则层存在的意义与其说是让 AI 变强不如说是让 AI 变安全——先不捣乱再谈干活。2.2 规则文件的体量与写法控制规则文件写多少合适我踩过两个极端写过只有三行的规则也见过一版两千多行的项目规则。三行等于没写模型的自由度太高行为漂移得厉害两千行则是另一种灾难模型在长文本里会出现规则过载读到后面忘了前面最终只记得开头和结尾的几句话中间的全被当成填充物。我的经验是单项目的常驻规则文件控制在 300 到 800 个 token 之间。超过 1200 个 token 就必须做信息分层。所谓分层就是把必须遵守的硬性规则和仅供参考的背景知识分开。硬性规则放常驻区域背景知识放进 docs 目录在规则里只写一句遇到 XX 问题时先阅读 docs/architecture.md让模型在需要时再触发翻阅而不是一股脑塞进每次请求。下面是我常用的模板可以直接复制到项目根目录的AGENTS.md里# 项目规则AGENTS.md ## 硬性规则 - 语言TypeScript严格模式开启注释使用中文。 - 架构UI 层禁止直接调用数据库所有数据访问走 repository。 - 变更纪律只修改与当前任务直接相关的文件禁止顺带重构。 - 命令修改后必须运行 npm run lint 与 npm run typecheck。 ## 背景信息 - 此项目为微服务架构业务核心在 services/order 目录。 - 测试使用 Vitest新功能必须附带对应测试文件。这个写法的核心在于把不强制的背景知识放到按需调用的位置把强约束放进常驻上下文。AI 每开一次会话都会重新读到这套规则所以它必须精简、高信噪比。你不可能像带人类实习生一样培训一次就放心它每次都是新入职你只能把精华浓缩到它第一眼就能看到的地方。2.3 我踩过的一个坑规则写得越多 AI 越乖巧但越不干活有一个阶段我为了让 AI 严格遵守规范在规则文件里堆了大量否定句不能这样做、不允许那样说、禁止自作主张。效果很快显现但它不是往好的方向——AI 变得异常保守遇到任何问题都先回复我建议您确认一下……或者给出一大段绕来绕去的风险提示却迟迟不出实际代码。复盘之后我找到了原因否定性规则过多会让模型学到的不再是边界而是风险。它把大量推理资源用在了自检上生怕自己违规结果就是过度防御、不敢行动。这和人一样一个满脑子都是这不能碰那不能碰的新人是很难放开手脚把活干漂亮的。我现在写规则遵循三个原则。第一正向表达优先请把数据访问集中在 repository 层优于禁止直接调用数据库第二每条规则必须能对应到可检查的产物比如一条能运行的命令、一种可见的目录结构而不是模糊的保持优雅第三写完每条规则都问一句如果这条不成立最坏会怎样答不上来的就不值得占规则层的 token。这个校准思路后来变成了我所有项目的基线。3. 第二层仓库索引层决定 AI 对整个代码库的知识面3.1 代码索引与检索增强的基本原理第二层是仓库索引层它的存在方式不像规则层那样常驻而是按需检索。几乎所有主流 AI 编码助手在后端做的工作都类似一套针对代码库的 RAG检索增强生成先对仓库的符号、文件结构、语义片段建立索引当用户提问或触发补全时从索引里召回最相关的代码片段拼接到上下文中交给模型。术语叫代码语义检索也叫符号级索引它直接决定 AI 是不是真的懂你的项目。很多新用户会以为AI 能在三万个文件里精准找到目标函数是因为模型读完了整个仓库。真实情况不是这样它只是通过索引找回了候选片段。这个认知差异极其重要上下文工程的目标不是让模型读全仓库而是让模型读对片段。类比一下就是搜索引擎不会把整个互联网塞进一页结果给你它只把最相关的十条链接放在前面。编码助手背后的工程逻辑完全一致。理解了这一点你就能明白为什么某些项目里 AI 表现得很笨。要么是索引覆盖错了范围召回的全是第三方库里的同名函数要么是代码结构太乱语义检索根本抓不住业务关键词。这些不是模型问题是索引层没调好。3.2 可配置的索引范围与排除项现在的编码助手多数把索引范围做成可视化配置或配置文件。项目一变大索引噪音会非常致命。node_modules、dist、build、.git、vendor这类目录一旦进入索引模型就像一个在堆满杂物的仓库里找螺丝钉的人召回结果全是第三方库里的近似命名真正属于你业务代码的片段反而排到后面。不同工具的入口不一样Cursor 可以在项目设置里配置 ignore 内容基于 LSP 的插件通常遵守.ignore/.gitignoreCLI 型 agent 一般在启动参数或配置文件里指定 exclude。第一步操作基本都是排除这些目录。我常用的排除清单长这样node_modules/ dist/ build/ coverage/ .git/ tmp/ *.lock除了排除目录还要考虑索引的广度和深度。对超大仓库优先索引入口文件、路由表、数据模型、测试夹具这些结构性文件对业务密集的目录再开更细粒度的语义索引。衡量标准只有一个召回结果的 top-k 是否精准而不是数量够不够多。3.3 要想检索结果好代码本身先要可被搜索这一节讲一个很多教程不会提的经验RAG 的召回质量不仅取决于检索算法还取决于代码本身是不是一张容易被检索的脸。我遇到过一个典型的反面案例某项目所有接口的响应处理器都叫handle函数名只有一两个单词AI 经常召回错文件在 A 模块的修改里套用 B 模块的实现。后来把handleResubmitOrder、handleRefundCallback这类带业务语义的名字替换上去同样的问题召回准确率立刻上来了。想让索引层长期保持良好状态我建议把四件事纳入日常维护函数、类、变量的命名要携带业务语义尽量避免handle、get、set这种过于通用的命名一个文件尽量只承担一个职责大文件在索引时会被切碎语义连续性受损核心模块加简明注释领域词汇对检索召回有正向帮助定期看一眼索引统计信息如果工具有提供确认核心目录确实进入了索引。很多人舍得花钱换更强模型却不肯花时间把代码库整理得可被检索。实际上这部分免费改动的收益往往比换模型还明显它属于典型的低成本高杠杆。4. 第三层会话任务层决定 AI 的临场判断4.1 哪些信息会自动进入会话上下文第三层是离用户最近的一层也是感知最强的一层会话任务层。AI 编码助手在对话中会自动把当前打开文件的内容、光标附近的代码、编辑器可见的错误诊断、最近几次操作记录下来作为这次回答的上下文。这就是为什么你把光标放到某个函数里问这里为什么报错它立刻知道你在说哪个函数——它靠的可不是读心术而是编辑器状态快照。CLI 型的 agent 还会多带一层自动上下文git diff 结果、最近提交记录、当前分支信息。这些自动信息绝大部分是合理的但它们也会带来一个问题打开的文件越多历史越乱AI 就越容易分不清你到底要处理哪个目标。我自己开新任务前有个习惯就是先做会话整理关掉无关标签页、只保留和问题相关的文件、清掉上一轮遗留的对话必要的时候直接开一个新会话给这项任务用。这一步几乎不花什么成本但对准确率的提升非常稳定。4.2 人工补上下文引用路径、符号与伪代码即便有自动上下文真正可靠的理解仍然来自用户在对话里主动给出的信息。我总结了一套任务描述三段式在团队里推广之后配合度的提升非常明显目标一句话说清你想要的结果输入材料指出相关文件路径、关键函数或数据结构的名称约束条件明确不改动的部分、兼容性要求、验收标准。给你看一个正面的例子目标修复订单超时后状态没有自动流转的问题。 输入材料services/order/statusMachine.ts 中的 transition() 函数 订单表结构在 db/schema.prisma。 约束不要改支付模块改动后需要补充针对超时场景的单元测试。为什么不能只写帮我修一下这个问题因为你省掉的每个字模型都会靠猜测来填。上下文工程的本质就是尽可能压缩模型需要猜测的空间。任务越复杂这个原则越重要。当你要做一个稍微大一点的改动时我会先在对话里写下一段伪代码级别的思路让 AI 跟着你的设计走而不是让它自由发挥一套新架构。我实测下来的感受是补全和改写的准确率会随着你提供伪代码的完整度线性上升。4.3 对会话历史做剪枝用新鲜会话换准确率会话层最容易失控的是历史信息。长对话里累积了大量早期决定、被否决的方案、错误的尝试这些东西如果全部留在上下文里会在关键时刻干扰判断。我连续调试一个复杂 bug 超过四十分钟以后经常遇到模型突然忘记最初需求——它不是我以为的记性差而是上下文里塞满了调试碎片注意力分布变得太稀疏。应对方案有两类。一类是显式剪枝当对话明显走岔时我会手动把关键信息重新写一遍然后明确告诉它以上讨论作废现在只按这段描述执行。另一类是主动开新会话只要第一个可验证的里程碑已经达成就开新会话继续下一阶段新会话里只带入上一阶段的结论而不是完整流水账。会话层的核心原则可以浓缩成一句话留结论不留过程。模型带着干净的目标进下一个任务比带着沉重历史进下一个任务稳定性高出一大截。5. 第四层反馈闭环层决定 AI 的自我修正5.1 编辑器、终端、测试输出就是 AI 的眼睛四层之中最容易忽略但收益最明显的是第四层反馈闭环层。很多 AI 编码助手第一次输出的代码都带小毛病类型不匹配、lint 不通过、单元测试崩溃。模型本身并不会实时感知这些它只有看到报错才有机会改对。谁来把报错喂给它以前靠人工复制粘贴现在靠工作流自动回灌。这一层配置的本质是给 AI 装上一双实时反馈的眼睛。具体到不同形态的工具实现方式不同编辑器插件会把 TypeScript / ESLint 的诊断信息直接拼进下一次请求agent 模式会在修改文件后自动运行测试命令把失败输出作为下一轮的上下文工作区级别的 Copilot 类功能则在后台持续收集编译错误和静态检查结果。如果你的 AI 经常改完代码后拍着胸脯说应该没问题了实际一跑就挂那基本可以断定是反馈层没有配对。5.2 把反馈接到工作流里自动化检查与重试闭环要让反馈闭环真正生效我建议至少做三件事。第一开启保存时自动执行格式化 静态检查让 lint / typecheck 的错误在 AI 下一次运算前就进入上下文。这一步不仅省掉人工复制粘贴还能让模型在还处于当前任务时就把问题修掉。第二在规则层里明确告诉 AI修改完成后请运行pnpm test -- --changedSinceHEAD根据失败信息继续修复直到通过。不要以为它默认会这么做你不写在规则里它经常改完就停。第三对 agent 类工具不要急着点接受全部代码让它把验证步骤也写进执行计划。换句话说你要让 AI 自己承诺改完就跑验证而不是把验证全推给人类。我做过一条真实路径的对比测试关闭自动验证时AI 完成一个小型 bug 修复平均需要 3 轮人工反馈开启自动跑测试 把失败信息回灌后同类问题平均 1.2 轮就能收敛。差的这 1.8 轮就是反馈层带来的真实效率。它的本质是让错误这件事本身也变成上下文的一部分而不是让错误停留在模型的视野之外。5.3 哪些反馈是强信号哪些其实是噪音不是所有报错都值得进入上下文。反馈信息如果不筛选模型会像人一样被海量告警吓到反而不敢动手改代码。我按信号强度给反馈分了一个级信号级别内容类型处理方式强信号编译错误、类型错误、测试失败、安全告警必须进入上下文中信号lint 风格告警、废弃 API 提示作为次级参考弱信号第三方依赖警告、编辑器格式提示、无业务影响的日志过滤掉不进上下文一个实操技巧是在自动验证脚本里只保留会改变正确性判断的检查即tsc、testlint 视情况决定是否以 fail 模式接入弱信号输出重定向到日志文件而不是回灌给模型。这样模型拿到的是高质量的失败信息不会陷入噪音。反馈层配置得越干净自我修正的能力才会越强。6. 一套可以直接抄的四层配置模板6.1 四层剖面总览前四节讲的是原理这一节给落地剖面你可以对照着检查自己手头的项目配置。我做出来的四层模型大概长这样层级配置载体生命周期主要目标全局规则层AGENTS.md / CLAUDE.md / .cursorrules每次会话常驻让 AI 守规矩仓库索引层索引配置、exclude 清单、目录结构设计建索引时一次性代码变更后增量更新让 AI 找对文件会话任务层对话内容、打开文件、任务描述模板单个会话内让 AI 理解当前任务反馈闭环层保存自动检查、agent 自动跑测试、报错回灌每次修改后循环让 AI 自我修正这张表反过来用就是一张排错表AI 出了问题先判断问题出在哪一层再动对应层而不是盲目重写提示词。我观察到的真实情况是大多数这模型好蠢的抱怨最后定位下来都是某一层上下文没接好。6.2 规则文件模板与索引排除示例下面是我最常用的最小模板直接放在项目根目录的AGENTS.md即可。它刻意保持精简只保留真正能约束行为的条目。# AGENTS.md ## 项目定位 - 后端服务Node.js TypeScript Fastify - 数据库PostgreSQLORM 使用 Prisma - 测试Vitest ## 硬性规则 1. 只修改与当前任务有关的文件禁止顺手重构、格式化无关代码。 2. 数据访问必须走 services/repository 层禁止在路由处理函数中直接操作数据库。 3. 每次代码变更后运行 pnpm typecheck 和 pnpm lint:changed有问题先修复再继续。 4. 使用中文注释变量和函数命名使用英文并携带业务含义。 ## 常用命令 - 启动开发pnpm dev - 跑测试pnpm test - 类型检查pnpm typecheck索引排除示例放在.cursorignore或你所用工具的对应配置文件里node_modules/ dist/ build/ coverage/ .git/ tmp/ *.lock如果你的工具支持自定义检索优先级还可以额外维护一个强相关目录名单比如把src/domain、src/features设为优先检索对象把配置文件、图标资源这类低相关度内容后置。这样做在大型项目里效果尤其明显。6.3 让配置稳定落地的四步启动流程新项目接入这套配置建议按顺序做不要一次性把四层全改完否则效果波动时根本不知道是哪一层的变化引起的。我一般走这四步先写规则层然后用一个简单任务验证它是否生效——故意让它修改一个文件名带禁止修改标记的文件看它会不会拒绝配置索引排除项清理掉node_modules、dist等再通过索引页面或日志确认仓库里已经没有第三方代码被收录开始第一个真实任务用任务描述三段式写指令观察 AI 的输出是否聚焦、是否只动了应该动的文件开启自动检查和反馈回灌在第一次跑挂时看报错有没有回到上下文第二轮修复是否指向正确的文件。每一步都记录一次前/后对比。我自己的统计是80% 的AI 变强发生在规则层和反馈层索引层和会话层更多是放大器。先保证规矩和反馈再优化检索与对话这个顺序的投产比最高。7. 调了几个月后的踩坑记录与校准方法论7.1 定位问题先从层入手把 AI 编码助手当作日常生产力工具几个月以后我养成了一种排查习惯问题出现时不先怪模型而是先问一句它到底缺了什么上下文。我总结了一个底层判断框架很粗糙但非常管用方案在结构上完全跑偏连模块边界都不对大概率是规则层缺失它不知道项目边界找错了文件改错了目录大概率是索引层召回质量问题任务听懂了但实现细节不对大概率是会话层输入信息不足或者任务描述里缺少约束条件改完之后仍然反复报同样的错大概率是反馈层没有把报错传回去。有了这个框架调模型就从玄学变成了一项工程化的工作。我建议你也把它抄到项目文档里每次遇到 AI 行为反常先逐条对照而不是立刻改提示词。7.2 三个最常见的上下文事故复盘分享几个我真实踩过的案例每个都是某一层配置失败的典型。第一个是规则层过载。我在一个大型老项目里写过一版特别长的规则大约 3000 个 token结果 AI 频繁漏掉第一条只修改相关文件代码 diff 越来越大。原因不是它不听话而是信息过载淹没了关键规则。最后的解法不是删规则而是把一半知识挪到 docs 目录规则文件里只留遇到 XX 问题先读哪个文档的引导。第二个是索引层选错了范围。项目里有五万个文件某次助手每次检索都把编译产物里的同名模块当成第一候选导致所有改动都落在dist目录里。我在代码仓库里看到那些被改动的文件时整个人是懵的。排查后才发现是索引配置没有排除dist重建索引后问题立刻消失。很多时候我们以为模型蠢其实是配置里没把核心代码范围锁死。第三个是会话历史污染。在一次重构任务里我连续和 AI 聊了好几轮旧方案后来在同一个会话里提出了新需求结果 AI 把新旧两套设计合并成了一套缝合怪架构既不符合旧方案也不符合新需求。踢掉这个会话、新建一个会话、只把结论带进去问题当场消失。这三个事故有个共同点不是模型能力问题而是上下文管理问题。它们让我对上下文工程这件事有了切身的信任感。7.3 我的校验清单与收尾建议如果你只带走一样东西我希望是对每次请求的上下文到底包含什么保持敏感。大多数编码工具都提供了查看一次请求携带了多少 token、哪些文件被作为参考、哪些规则被激活的入口。遇到奇怪的输出先打开这块面板看一眼通常一眼就能定位到问题层。现在我每次接手新项目都会用这么一张清单过一遍规则文件是否控制在 800 token 以内硬性规则是否都有可执行的验证命令索引是否排除了所有依赖和构建产物核心业务目录是否明确任务描述是否包含目标、输入材料、约束三要素自动验证是否开启强信号反馈是否一定会回到对话上下文里四层不是配完一次就一劳永逸的。代码库在增长技术栈在更换每一层都需要定期回归。把这个过程当成和依赖升级一样的常态维护工作AI 编码助手才会从偶尔灵光一现的工具慢慢变成一个真正懂你项目的团队成员。最后说句实在的我这几个月在四层配置上的收益并不比换一个更强模型的收益小而且前者完全掌握在自己手里。这一点大概也是上下文工程最让我着迷的地方。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →