1. 引言:当提示词工程开始不够用,我们开始谈上下文工程
先抛一个我最近的真实感受:过去一年里,我用AI编码助手的习惯发生了根本性转变。早期我在意的是“怎么把prompt写得更精妙”,那段时期确实有效果,同样的任务换个措辞结果能好不少。但最近半年,我发现真正决定AI编码助手好不好用的,早就不是那一两句话的措辞,而是“模型到底能看见什么”。
这个“看见什么”就是上下文。一个AI编码助手拿到手的材料越准确、结构越清晰、和当前任务越相关,它的输出就越接近能直接落地的代码。反之,哪怕你提示词写得天花乱坠,只要模型看到的是一堆无关文件、缺失的依赖说明、含糊的需求描述,写出来的代码照样会跑偏。
现在行业里把这件事叫做上下文工程,也有团队开始叫agent上下文处理工程。它本质上是从提示词工程长出来的下一阶段,但思路完全不同:提示词工程关心的是“怎么问”,上下文工程关心的是“喂什么、喂多少、按什么顺序喂”。你甚至可以把它理解成给AI编码助手配菜——菜谱再重要,食材不新鲜、分量不对、摆放顺序乱了,端上桌也是一塌糊涂。
这篇文章我想把上下文工程落到一个具体的场景里:AI编码助手的配置。我把它拆成四层,从最贴近单次交互的会话层,到项目级的规则层,再到跨项目的全局层,最后是外部记忆层。每一层都有它的作用边界、配置方法和常见坑。我会把我在实际项目里的配置片段、参数选择理由、踩过的坑都整理出来,尽量说人话,保证看完能直接用。
2. 上下文工程是什么,它和提示词工程差在哪
先说清楚上下文工程这个概念的来龙去脉,不然后面讨论四层配置容易悬空。
2.1 从“怎么问”到“喂什么”的转变
提示词工程解决的是“给定同样的上下文,如何设计指令让模型输出更准确”。比如你要让AI写一个Python函数,你可以规定语言风格、要求写注释、指定错误处理方式。这些都是在“指令”层面做文章。
但AI编码助手和你对话时,真正决定输出的不仅是那句指令,还包括:它前面看到了哪些代码文件、读到了多少行日志、项目里有没有规范文档、它是否记得你上个月在这个仓库里约定过变量命名风格。
上下文工程处理的就是这些“指令之外”的信息。它研究的是:在模型上下文窗口有限的前提下,应该把哪些信息放进去,以什么样的结构组合,优先级怎么排,哪些信息需要被压缩、缓存或者丢弃,让模型在生成代码时有最充分的决策依据。
打个生活化的比方:提示词工程是教一个新人怎么读图纸,上下文工程是决定这个新人进工地之前应该先看哪张图纸、先看哪些照片、先了解哪些背景。图纸再多,塞不下也是白搭。
2.2 上下文窗口:工程约束的核心
为什么上下文工程会成为一个独立课题?根本原因是模型有上下文窗口限制。即便今天的模型已经把上下文窗口拉到百万token级别,看起来很大,但当你把它用在一个真实的大型代码仓库里,这点空间根本不够看。
一个中型项目的src目录下可能躺着几万到几十万个文件,把所有文件都塞进上下文显然不现实,就算塞得下,模型也会被大量无关信息干扰,出现“注意力稀释”的问题。我实测过一个场景:把一堆无关的工具类文件塞进上下文后,AI开始在所有生成的代码里导入这些无关模块,因为模型认为“这个项目里存在的东西应该被用到”。
所以上下文工程的核心任务不是“塞更多”,而是“塞得更聪明”。它在提示词工程之上增加了一个被大多数人忽视的维度:信息的筛选、组织与优先级排序。
2.3 agent 上下文处理工程的行业定位
最近“agent上下文处理工程”这个说法越来越热。我和几个做AI基建的朋友聊过,他们的共识是:当AI编码助手从简单的问答工具进化为能自主执行多步骤任务的agent时,上下文管理的难度会指数级上升。
因为一个agent在执行任务的过程中会产生大量中间状态:读取了文件A、生成了补丁B、执行了测试C、报错了D。这些中间信息既是后续步骤的依据,也是干扰源。你怎么决定哪个信息保留、哪个信息压缩、哪个信息过期?这不是简单的prompt设计问题,而是一个工程架构问题。
所以说上下文工程是提示词工程的延伸,但它已经远超提示词工程的范畴。提示词工程还可以靠个人经验取胜,上下文工程必须有方法论、有分层、有工具链支撑。这也是这篇文章要把AI编码助手的配置拆成四层来写的原因。
3. 四层上下文配置的整体框架
我第一次尝试系统化配置AI编码助手时,最大的困惑是不知道规范该写在哪。项目根目录需要什么文件,全局设置应该放什么,用户目录下要不要有配置,代码库里的README能不能被模型作为上下文读取?这些问题不搞清楚,配置就会很混乱。
后来我参考了几个团队的实践,自己也反复试错,最终把AI编码助手的上下文配置拆成了四层。每一层的职责边界很清晰,互不重叠:
第一层:会话级上下文,也就是你每次打开对话框、发起指令时临时携带的信息。
第二层:项目级上下文,包括rage文件、项目结构描述、目录树、关键代码索引、技术栈说明,作用是让AI理解“当前这个项目的基础设定”。
第三层:全局规则上下文,对应AI编码助手的全局设置、用户级别的规范文件,作用是让AI在跨项目协作时保持一致的行为习惯。
第四层:外部记忆与知识库,包括向量检索、历史对话记录、issue与任务系统接入,作用是为模型提供项目范围之外的补充信息,弥补上下文窗口有限的短板。
四层之间的关系可以理解为从微观到宏观的嵌套:会话层位于最内层,直接服务于当前任务;项目层包裹着会话层,提供项目背景;全局层再往外一层,提供用户级偏好;外部记忆层则像一个随时可以调取的扩展仓库,需要时拉取,不需要时不占空间。
我画了一张表格来对比这四层的边界,方便你对照理解:
| 层级 | 核心定位 | 典型载体 | 生命周期 | 更新频率 |
|---|---|---|---|---|
| 会话级 | 当前任务所需信息 | 指令、@文件、临时附加上下文 | 单次对话 | 每次对话 |
| 项目级 | 项目基础设定与约束 | rage、项目结构、规范文档 | 与项目同步 | 低频 |
| 全局级 | 个人/团队通用偏好 | 全局规则、用户配置 | 跨项目长期稳定 | 低频 |
| 外部记忆 | 超出窗口的知识扩展 | 向量库、issue、知识库 | 长效持久 | 动态更新 |
这个分层的价值在于:你在调优AI编码助手时,能快速定位问题出在哪一层。如果新助手在别的项目上表现正常,在当前项目上抽风,那大概率是项目级上下文出了问题;如果所有项目都表现异常,那先看全局层;如果单独某个对话不理想,那大概率是会话层没喂好。
4. 第一层:会话级上下文实战
会话级上下文是整个四层里最容易被忽视的一层,原因很朴素:它太常见了,常见到大家不觉得它需要被“工程化”。但你回头想想,同样用AI编码助手,有人能让它精准改一个bug,有人把整个文件贴进去结果越改越糟,差的往往就是对这一层的理解和控制。
4.1 明确交代任务的原子信息
会话级上下文的核心目标,是让模型在开启任务的那一刻就拥有足够且不冗余的信息。很多人的做法是把整个文件复制粘贴进去,然后说“帮我修复一个bug”。这样做模型确实能看到全部代码,但它的注意力被平均分散在每一行上,很难快速定位到你真正关心的那几行。
我现在的做法是:先告诉AI这个文件的作用,然后指定函数名或行号范围,再把关键代码块贴进去。举个例子:
文件 utils/date_parser.py 里有个 parse_date 函数, 它接收字符串参数,期望返回 datetime 对象, 但传 "2024-01-15 14:30" 这类格式时偶尔会抛 ValueError。 以下是函数核心代码: [粘贴代码块] 请分析可能的原因。这里的关键不是“写了多少”,而是“每一条信息都在帮模型收敛答案”。告诉AI文件作用,模型不需要扫描整个文件去猜;给出行号或函数名,注意力直接集中;贴出关键片段,避免token浪费。
4.2 善用@文件引用而不是全文粘贴
现在很多AI编码助手都支持在对话框里通过@符号引用项目文件。这个功能的设计本意就是让你不用手动复制粘贴,由工具自动把文件内容注入上下文。我强烈建议优先使用这个能力,它能保证AI拿到的代码是实时的,不会出现你贴的代码和磁盘上不一致的问题。
但@引用也要看场景。如果你的仓库里有一个几千行的文件,你自己都不确定问题在哪一块,那整个文件@进来既是浪费token,也是给模型制造噪音。更合理的做法是先用关键词搜索定位到具体函数,再针对性地引用那一段。
我试过在一个前端项目里直接@整个路由文件让AI找某个跳转逻辑的问题,结果AI在生成的代码里顺带“修复”了它认为的不规范之处,改了一堆无关的东西。后来我改成先通过编辑器定位到具体路由行,再把这个路由对应的处理函数单独@进来,效果就清爽多了。
4.3 临时给模型“补课”的策略
会话级上下文里还有一个常见需求:AI不熟悉某个SDK或某个内部工具的用法。这时候你没必要去改全局配置,也没必要立即写进项目级rage,直接在对话里附带一段精简的说明就行。
比如我接了一个用到了某个小众ORM的项目,第一天协作时我发现AI总是用SQLAlchemy的写法来写这个ORM的查询逻辑,于是我在每条指令前附加了一段话:
本项目使用的是 XXX ORM,它的查询语法与 SQLAlchemy 不同。 典型写法是: ModelName.query.filter_by(name="foo").first() 而不是 session.query(ModelName).filter(...).first() 请严格使用本项目的 ORM 写法,不要混用。这个操作的成本极低,但效果立竿见影。更关键的是,这类“临时补课”可以随用随弃,不需要沉淀到长期配置里,保持长期配置的精炼。
4.4 会话级上下文的三个常见反面案例
我把之前踩过的会话级上下文的坑整理成清单,都是真实发生过的场景:
第一,上下文重复注入。同一个项目的背景信息,每次开新对话都重新粘贴一遍,既浪费token,又可能在多次粘贴中产生信息误差。这类信息应该往项目级或全局级沉淀,而不是留在会话层。
第二,有用信息和噪音混杂。有些人习惯把一整个PR描述、贴了一大段会议记录、附带几个报错截图,然后说“帮我看看”。模型要从一大段无关信息里找出真正相关的部分,出错率直线上升。
第三,没有给出输出约束。会话级上下文里只说了“帮我改”,忘了说“不要动其他代码”“不要重构”“只修改指定函数”。AI很容易“好心办坏事”,因为它的默认倾向是帮你做到“最好”,而不是“最小改动”。
5. 第二层:项目级上下文实战
如果说会话级上下文决定了单次交互的质量,那么项目级上下文决定了AI在整个项目生命周期里的稳定性。这一层做得好,AI像是一个“进过这个项目”的开发者;做得不好,它每次都是从零开始的外包人员。
5.1 rage文件到底该写什么
rage(Rules for AI)文件是项目级上下文的核心载体。我见到最常见的错误是:要么不写,要么把它写成一本大而全的项目手册,事无巨细全往里面堆。结果模型真的会逐字逐句地读完——然后被里面的矛盾或冗余信息搞晕。
我的经验是,rage文件只写四类信息:
第一类是技术栈与命令约定。比如前端项目用pnpm还是npm,测试用vitest还是jest,后端语言版本是什么,有没有特殊的构建命令。这些信息AI光靠读代码不一定能完全推断出来,写清楚能少走很多弯路。
第二类是目录结构的核心约定。比如src下怎么分层、新增业务代码应该放在哪个目录、公共组件和页面组件的边界是什么。AI在生成新文件时,会根据这些约定选择正确的位置,而不是随便在根目录下新建一个文件草草了事。
第三类是编码风格与质量要求。比如变量命名用驼峰还是下划线、类型定义是否需要严格、错误处理的统一写法、是否需要编写单元测试。这些规则直接决定了AI输出代码能不能被code review顺利通过。
第四类是“禁忌清单”。这个最关键,也最容易被忽略。比如“不要在react组件里直接操作dom”“不允许使用any类型”“改动数据库schema前必须列出影响范围”。AI模型一般不会主动产生这些意识,但一旦在rage里明确出现,它会相当严格地遵守。
我不建议在rage里写太多关于项目业务背景的描述。比如“本系统是一个电商后台管理平台”这种话,写不写对代码生成的影响微乎其微。rage的定位是工程约束,不是业务说明书。
5.2 project定义:让助手认识整个仓库
现在不少AI编码助手支持在配置中指定当前项目使用的语言、技术栈和自定义规则文件路径。这个配置项英文常见为project定义,一般有两种补充方式:一种是在AI助手的设置界面里新建项目级配置,另一种是放在项目根目录下的配置文件中。
我给一个典型的前端项目配置示例:
{ "name": "my-web-app", "description": "基于 React 18 + TypeScript 的后台管理界面", "techStack": ["react", "typescript", "vite", "antd"], "rulesFile": ".ai/rules.md", "include": ["src/**/*"], "ignore": ["node_modules", "dist", "coverage", "mock"] }这个配置里最有价值的是include和ignore两项。include决定AI在浏览项目结构时优先关注哪些文件,ignore则明确告诉它不用管哪些目录。我强烈建议把node_modules、构建产物、生成文件、mock数据目录全部ignore掉。否则AI在回答问题时可能会引用这些不在核心代码内的文件,甚至从mock文件中学到错误的业务逻辑。
5.3 项目结构说明与目录树
另一个容易被AI编码助手困惑的点是缺少“全局视野”。你贴给它某个组件的代码,它能改好;你让它新增一个功能模块,它却不知道该把文件放在哪、要引用哪些现有的公共服务。
解决这个问题最笨但最有效的方法,是在项目级上下文里放一份精简的目录树。如果你用的AI编码助手支持读取目录树,只需在rage文件的开头引用一下根目录结构即可。如果不支持自动读取,就手动维护一份。
我维护目录树的原则是“只保留逻辑节点,不展示每个文件的细节”。展示到目录级别就够了,具体函数或组件名可以通过检索来补充。一个示例:
src/ api/ # 接口请求封装 components/ # 公共组件 hooks/ # 自定义hooks layouts/ # 页面布局 pages/ # 业务页面 types/ # 全局类型声明 utils/ # 工具函数这份目录树内容很短,但效果很明显。AI在生成代码时,会主动把新文件放到pages或components目录下,引用方式也会趋向于项目现有的相对路径风格。如果AI支持自动附带目录结构的能力,直接在项目配置里开启即可。
5.4 项目级上下文的分层细化方法
对于大型项目,一个rage文件往往不够用。我的做法是在项目根目录下创建一个.ai目录,把规则分散到多个文件里,然后通过主文件引用。例如:
.ai/ rules.md # 主文件,引用其他规则 style.md # 编码风格细节 stack.md # 技术栈与关键依赖 commands.md # 常用命令与脚本 conventions.md # 项目特有约定主文件rules.md里只写一个说明和对应的引用指令,其余细节都放进子文件。这样做的优势是:需要修改某类规则时,不需要在单个大文件里来回翻,也更方便按模块分享给其他成员。
有些AI工具会默认将项目根目录下的rage文件作为自动上下文,也有些支持在配置里手动指定具体文件路径。如果支持自动加载,直接把文件放在项目根目录即可;如果不支持自动加载,就通过项目级配置来显式Declare规则文件路径。
5.5 项目级上下文的维护节奏
项目级上下文最大的问题是“容易过期”。技术栈升级了但rage没更新,AI继续按旧规则生成代码;目录结构重构了但目录树没有同步,AI把新文件放进了已废弃的目录。这些问题不会立即暴露,但会随着项目迭代逐渐累积。
我现在给项目定了一个简单的维护节奏:每次大版本变更或目录调整后,花十分钟检查rage和目录树的同步情况;每个季度做一次全面review,把不再适用的规则删掉,把新形成的约定补进去。项目级上下文的价值在于“长期稳定”,但它必须跟着项目一起演变,否则稳定就会变成僵化。
6. 第三层:全局规则上下文实战
项目级上下文解决的是“这个项目怎么干”,全局级上下文解决的是“所有项目都要遵守什么”。这一层在单项目开发时容易被忽略,但一旦你同时维护多个项目,全局配置的价值就会立刻显现出来。
6.1 全局规则与项目规则的边界
很多人一开始会陷入一个纠结:规则到底放项目级还是全局级?我的判断标准很简单:这条规则换个项目还成立吗?如果成立,放全局;如果只对这个项目有意义,放项目级。
比如“代码中不允许出现硬编码的API地址”这种规则,在任何项目里都成立,放全局。再比如“本项目所有接口请求必须以/api开头并且走统一的request封装”,只在单一项目里成立,放项目级。
我把这个边界整理成一个简单的决策表:
| 规则特征 | 放置位置 | 示例 |
|---|---|---|
| 跨项目通用,面向个人/团队习惯 | 全局级 | 禁止使用console.log提交代码 |
| 跨项目通用,面向技术规范 | 全局级 | 所有异步操作必须明确错误处理 |
| 仅适用于某个项目 | 项目级 | 本项目使用XXX状态管理库 |
| 仅适用于某个模块/目录 | 项目级子文件 | 本模块禁止直接修改类型定义 |
这个区分做得好,能避免一个尴尬的场景:你在A项目里写的某些特殊约定,莫名其妙的跑到B项目里去影响了AI的生成行为。
6.2 全局配置文件的关键字段
不同AI编码助手的全局配置字段名不太一样,但核心逻辑都是一套:定义AI在回答问题时默认遵循的规则。我以常见的规则格式做一个示例:
rules: - id: coding_style description: "代码风格" rules: - "始终使用 TypeScript 严格模式" - "函数必须包含返回类型注解" - "不允许使用 any 类型" - id: security description: "安全约束" rules: - "禁止拼接 SQL 字符串" - "用户输入必须经过校验后再使用" - id: commit description: "提交规范" rules: - "代码提交信息遵循 Conventional Commits 格式"这种全局规则的应用范围是“所有会用到该编码助手的项目”。如果你是团队管理员,还能通过团队级别的共享配置把规范统一起来,新成员加入后拉取配置就能立刻获得和团队一致的编码助手行为。
6.3 全局配置导致的“跨项目污染”
全局配置有一类经典问题,我称之为“跨项目污染”。典型案例是:你在全局配置里写了“这是一个React项目,所有组件用React.FC定义”,结果你换到一个原生JavaScript项目里,AI依然不依不饶地生成React风格代码。你可能会疑惑全局配置为什么这么“顽固”,其实这就是因为它被设计成对所有项目生效的规则。
避免这个问题的核心原则是:全局只放“不会因为技术栈变化而失效”的规则。那些和特定框架、语言绑定的规则,应该下放到项目级。比如“所有组件必须用React.FC定义”这类规则,看起来是通用的,但它其实只适用于React项目,放全局就会造成污染。
我在实践中总结出来的经验是:把全局规则想象成“一个人的职业素养”,把项目级规则想象成“这个公司的规章制度”。职业素养是稳定的、跨公司通用的;公司规章制度则因公司而异。AI编码助手的配置也是同样的逻辑。
6.4 全局层的实际应用场景
全局层最常见的应用是统一代码提交规范和代码评审标准。我团队里的AI助手默认会生成符合Conventional Commits格式的提交信息,这一层配置只写一次,所有项目都能用。另一个高频场景是让AI默认使用相对路径而不是绝对路径进行模块导入,或者默认优先使用项目已有的公共组件而不是新建组件。
全局层还可以承载一些“行为偏好”,比如“当你不确定需求时,先列出你的假设,再继续生成代码”“生成的代码必须包含必要的注释,注释使用中文”“如果当前项目没有安装某依赖,不要在你的改动中引入该依赖”。这些都是非常好的跨项目规则,写进全局配置后,AI的行为会稳定很多。
7. 第四层:外部记忆与知识库接入
前两层解决的是“规则和约束”,第四层解决的是“知识来源”。一个代码仓库里的约定再多,AI也总有遇到未知领域的时候。框架文档更新了、某个内部包的接口改了、历史对话里的某个结论需要被复用……这些信息如果完全依赖人工解释,效率太低,所以要靠外部记忆来补齐。
7.1 为什么需要外部记忆层
即便AI编码助手的上下文窗口再大,也装不下一个团队所有的知识沉淀。代码库本身、设计文档、接口文档、历史issue、会议记录加在一起,token数量轻易就能超过上下文窗口的承载范围。即使全部塞得下,模型也会被大量信息严重稀释,生成质量反而下降。
外部记忆层解决这个问题的方式是“按需检索”——平时这些信息安静地躺在索引里,不占上下文空间;当模型遇到相关问题时,通过检索把最相关的内容提取出来注入上下文。它就像一个你身边随时带着的笔记库,需要用的时候翻一下,不用的时候完全不占脑力。
7.2 向量化文档库与代码索引
目前比较主流的实现方式是把团队知识库、API文档、历史决策记录等文档做向量化处理,存入向量数据库中。当AI编码助手回答问题时,工具负责把用户的问题转化成向量,在库里做相似度检索,把命中片段注入上下文。
这套方案的落地依赖具体工具链。一些成熟的AI编码助手已经内置了代码库索引能力,它会扫描项目代码建立符号索引和语义索引,在回答前自动把相关代码片段放进上下文。另外一些方案则需要手动接入知识库API。
我在实践中比较推荐的做法是:先优先使用编码助手自带的代码索引能力;再把团队的wiki或技术文档转成Markdown格式,接入向量检索;最后把历史issue和需求系统联动,这样AI能知道某个功能之前是怎么设计的。
7.3 记忆持久化:让AI不“失忆”
外部记忆的另外一个重要子方向是“历史记忆”。很多团队会发现AI编码助手总是在新对话里“失忆”,遇到同样的问题反复给出不一样的解决方案。这背后其实是上下文窗口的限制——它只会看到当前对话的内容,看不到过去三周的讨论记录。
设置外部记忆层最常见的做法有两种。一种是让编码助手持久化对话摘要,每次对话结束后把关键结论写入项目目录下的记忆文件。另一种是接入团队的任务系统,每次需求变更自动生成上下文片段供后续检索。
我自己采用了一种更轻量的方式:在每个项目的.ai目录下维护一个changelog.md文件,专门记录AI协作过程中的重要决策和修改背景。然后在rage文件里约定AI在新对话中优先查看这个文件。这种方式不需要额外搭建系统,几行配置就能让AI在不同会话之间保持一定程度的连续性。
7.4 召回质量比存储数量更重要
外部记忆层最常踩的坑是“只管存不管取”。团队把大量文档向量化入库之后,以为万事大吉,实际使用却发现AI经常会检索到无关的内容,导致回答质量下降。
我建议在接入外部记忆时,重点关注召回策略。核心原则包括:限制检索范围,不要把整个代码仓库的所有文档全部向量化,只选择与编码直接相关的文档;设置相似度阈值,宁可少召回也不召回不相关内容;对召回内容打上来源标签,让AI知道这条信息来自哪个文档,方便它判断权威性。
外部记忆层是一件“做了比不做好,做了还需要持续调优”的事情。它不像项目级规则那样写完就稳定,它需要根据实际使用效果,不断调整检索范围、文档切分策略和embedding模型参数。
8. 常见问题与排查技巧实录
四层配置落地之后,我遇到过不少妖魔鬼怪般的问题。把这些问题整理成一个速查表,能帮你少走很多弯路。
8.1 问题速查表
| 现象 | 大概率原因 | 排查位置 |
|---|---|---|
| AI生成代码风格与项目现有代码不一致 | 缺少项目级rage或rage不规范 | 项目级上下文 |
| AI在别的项目表现正常,当前项目表现明显变差 | 项目级配置过期或ignore配置不正确 | 项目级上下文 |
| 所有项目里的AI助手都表现不正常 | 全局规则里混入了某个项目专属规则 | 全局级上下文 |
| 同一问题反复问,每次答案都不一样 | 会话级上下文信息不足,或外部记忆未覆盖 | 会话级+外部记忆 |
| 单次对话中AI越改越乱 | 会话级上下文夹带过多无关信息 | 会话级上下文 |
| AI引用了不存在的API或过时的接口 | 外部记忆层召回到了过期文档 | 外部记忆层 |
8.2 一个从“抽风”到“正常”的调试案例
我印象最深的一次调试,是团队一个前端项目里AI突然开始疯狂生成样式内联代码,完全无视项目里正在使用的CSS Modules方案。当时第一反应是改rage,把“使用CSS Modules”写得更详细,但没有效果。后来排查到全局配置里,发现有人把“生成样式时优先使用内联样式”写进了全局规则,这样自然在所有项目生效,当然也包括这个用CSS Modules的项目。
这个案例给我最大的提醒是:当AI行为出现跨越多个文件的系统性偏差时,先查全局层,再查项目层,最后再回到会话层分析单次交互。如果每次都从会话层开始排查,很容易浪费时间。
8.3 上下文工程的三个常见“误解”
很多人会问我,上下文工程是不是等于写更多的提示词?完全不是。提示词关注的是“请求”,上下文工程关注的是“模型感知到的全部信息”。在真实使用中,项目结构、rage文件、文档索引这些“非提示词部分”对生成质量的影响往往比提示词本身更大。
也有人问,上下文工程是不是越“大”越好?我的答案是否定的。上下文越多,注意力稀释就越严重。我的经验是:能用一句话说清楚的约束,没必要写满一整段;能用rage里的一行规则解决,没必要在对话里重复三遍。
还有人误以为配置一次就一劳永逸。上下文工程是一个动态的系统,项目在变、规则在变、知识库在变,配置必须跟着变。如果你发现AI编码助手的表现越来越差,第一个念头不是“模型变笨了”,而应该是“我的上下文配置可能过期了”。
8.4 如何验证上下文配置是否有效
最后分享一个我用来快速验证配置效果的技巧:给AI布置一个跨文件的小任务,比如让它重构某个工具函数并同步修改所有调用点。如果AI在第一次尝试时就能准确识别所有调用位置并保持接口兼容,说明项目级上下文和代码索引是有效的。
其次,连续开几个新对话,用同样的问题去测。如果回答的稳定性和质量都保持稳定,说明外部记忆和rage配置在正常工作;如果每次都不同,那说明要么上下文信息不足,要么规则约束没有真正被模型采纳。
这些验证方法不复杂,但很值得定期做一遍。上下文工程本质上是一个持续调优的过程,你的项目在进化,AI编码助手也值得被持续调教。
9. 写在最后:回到实际项目里不断调
上下文工程不是一个可以一次性“配完”的东西。它更像你带新人:先给一份入职手册(全局规则),再带到具体项目里讲项目背景与约束(项目级rage),遇到具体任务时多交代几句(会话级上下文),等项目做久了再形成知识库沉淀(外部记忆)。
这个四层框架帮我解决了AI编码助手在使用过程中绝大多数“玄学问题”。现在我在新项目里启用AI编码助手,第一件事就是搭好项目级rage和目录结构说明,然后检查全局规则是否有会污染当前项目的条目,等项目稳定后再决定要不要接外部知识库。会话级上下文反而是最随意的部分,但每次开新对话时,我会刻意提醒自己:信息能不能再精简一点。
你也不用一上来就把四层全部铺满。先从第一层和第二层开始,建立好rage和项目配置,感受一下变化;等熟悉了,再逐步加入全局规则和外部记忆。上下文工程没有什么神秘的地方,就是一条朴素的道理:AI能给你的,取决于你给它看到的。