跳转到内容

上下文工程

Context Engineering(Offload / Retrieve / Reduce / Isolate)


规则:上下文 = 模型在一次交互中”看得到”的全部信息。按来源分为 5 类,按生命周期分为 3 层。

[Requirement] 提交给 AI 的任何上下文,必须能明确归入下表中的某一类,禁止”凭感觉全贴”。

分类说明典型内容优先级
系统上下文 (System)不可变的全局约束角色设定、工程规范、输出格式P0
规范上下文 (Specification)当前任务的规格说明需求、验收标准、技术方案P0
代码上下文 (Code)相关源码与结构待修改文件、调用链、类型定义P1
数据上下文 (Data)运行时数据样例请求/响应样例、测试数据、日志P1
环境上下文 (Environment)运行与工具环境语言版本、框架、依赖清单P2
层级生命周期存放位置示例
持久层跨会话长期有效团队规范仓库、Agent System Prompt编码规范、架构决策
项目层单个项目内有效项目 README、docs/、配置文件项目目录结构、API 契约
会话层单次任务有效当前对话、临时挂载文件本次需求、相关代码片段

示例:

任务:为 FastAPI 项目新增一个"用户注册"接口
持久层:团队 Python 编码规范(已作为 System Prompt 注入)
项目层:README.md、openapi.yaml、现有的 user 模块代码
会话层:本次需求描述 + 验收标准 + 待修改的 user.py 片段

反模式:

  • 把整个项目所有文件一次性塞给模型(超出有效窗口,稀释关键信息)
  • 不区分层级,把临时调试日志和长期规范混在一起
  • 上下文来源不明,模型无法判断哪些是”必须遵守”、哪些是”仅供参考”

规则:Offload = 把信息从”对话上下文”转移到”外部存储”,用引用替代内联。核心是”能引用就不粘贴”。

[Requirement] 超过 200 行的代码文件,不得直接粘贴到对话中;必须通过文件路径或符号引用让 AI 读取。

[Standard] 反复使用的规范、模板、代码片段,必须沉淀到持久层(规范仓库 / System Prompt),不得每次手动粘贴。

[Default] 工具支持的场景下,优先使用”文件挂载 + 路径引用”,而非复制粘贴内容。

手段适用场景实现方式
文件挂载单次任务需查看多个文件IDE 插件挂载、@file 引用
符号引用只需要某个函数/类/类型定义@user.py#register_user、行号范围
链接引用外部文档、规范、Issue粘贴 URL(模型可联网时)或文档 ID

示例:

# 正确:用路径引用,不贴全文
请修改 src/services/user.py 中的 register_user 函数,
参考 src/schemas/user.py 中 UserCreate 模型的定义。
验收标准见 docs/requirements/user-registration.md 第 3 节。
# 错误:把三个文件全文粘贴到对话
[全文 300 行的 user.py]
[全文 150 行的 user.py schema]
[全文 80 行的需求文档]
请修改...

反模式:

  • 把 node_modules、dist/、生成产物贴进上下文
  • 明明工具支持文件读取,仍然手动复制大段代码
  • 规范内容散落在聊天记录里,每次重新粘贴一遍

规则:Retrieve = 在需要时精准拉取相关上下文,而非一次性塞入全部信息。核心是”按需检索、精准命中”。

[Requirement] 启动任务前,必须先明确”本次需要哪些上下文”,列清单后再逐一检索,禁止无目的全量加载。

[Standard] 检索遵循”先元数据、后内容”:先看文件树、函数签名、类型定义,再按需展开具体实现。

[Suggestion] 对大型仓库,先通过全局搜索(grep / 符号索引)定位相关代码,再读取命中文件。

1. 定位 → 通过文件名 / 符号名 / 调用关系找到候选文件
2. 筛选 → 读取文件头部、import、函数签名,判断是否相关
3. 展开 → 对相关文件读取具体实现段落(行号范围)
4. 验证 → 确认上下文是否足够回答问题,不足则回到步骤 1

示例:

任务:排查用户注册接口返回 500 的原因
1. 定位:搜索 "register" 命中 src/services/user.py、src/api/users.py
2. 筛选:读 user.py 的函数签名,发现 register_user 调用了 send_welcome_email
3. 展开:读取 register_user 第 40-80 行 + send_welcome_email 实现
4. 验证:发现 send_welcome_email 未捕获 SMTP 异常 → 根因明确

反模式:

  • 一上来就把整个 src/ 目录所有文件读一遍
  • 只靠文件名猜测相关性,不看内容就贴进来
  • 检索到第一个匹配就停止,遗漏调用链上下游

规则:Reduce = 对已加载的上下文做裁剪、压缩、结构化,只保留与当前任务直接相关的信息。核心是”去噪、提炼、聚焦”。

[Requirement] 提交给 AI 的代码片段,必须裁剪掉与任务无关的部分(无关函数、注释、空行、导入)。

[Standard] 超过 50 行的上下文,应先做结构化摘要(函数签名列表、关键数据流、约束条件),再附带必要的原始片段。

[Suggestion] 上下文总 token 数控制在模型窗口的 30% 以内,留出足够空间给思考和输出。

手法说明示例
行号裁剪只引用相关行范围user.py#L40-L80
签名提取只保留函数/类签名,去掉实现def register_user(data: UserCreate) -> User
依赖剥离去掉与任务无关的 import 和辅助代码只保留当前函数实际调用的依赖
摘要前置先给一句话摘要,再给细节“下面是注册流程,核心逻辑在第 3 步发邮件”

示例:

# 正确:裁剪后的上下文
相关代码:src/services/user.py
def register_user(data: UserCreate) -> User:
# L42-L48: 校验邮箱唯一性
if user_repo.exists(email=data.email):
raise EmailAlreadyExists()
# L50-L55: 创建用户
user = user_repo.create(data)
# L57-L60: 发送欢迎邮件(此处抛异常未捕获)
send_welcome_email(user.email)
return user
# 错误:把整个文件 300 行全贴进来,包含 5 个无关函数

反模式:

  • 把 git diff 的全部变更(含格式化、空白改动)塞进上下文
  • 不做任何摘要,直接丢一堆文件让 AI 自己找重点
  • 上下文里混入调试日志、临时变量、被注释掉的废弃代码

规则:Isolate = 把不同任务、不同模块、不同关注点的上下文隔离开,避免相互干扰。核心是”一次只做一件事,一个上下文只服务一个目标”。

[Requirement] 单个会话/任务只聚焦一个明确目标;多目标必须拆分为多个独立会话或子任务。

[Standard] 上下文按”职责”分块组织:需求归需求、代码归代码、测试归测试,不混在同一段文本里。

[Default] 不同模块的修改应通过不同的子任务/子 Agent 处理,每个子任务只加载本模块相关上下文。

维度隔离方式目的
任务隔离一个会话只做一个功能点避免多需求相互污染
模块隔离按模块/服务划分上下文边界避免无关代码干扰
角色隔离不同角色(编码/测试/评审)用不同上下文集避免角色越界

示例:

# 正确:分两个独立任务
任务 A(会话 1):实现用户注册接口
上下文:注册需求、user 模块代码、User schema
任务 B(会话 2):为注册接口补充单元测试
上下文:注册接口签名、测试框架规范、Mock 规范
# 错误:一个会话里同时做"实现接口 + 写测试 + 改前端页面"
上下文混乱,AI 输出互相矛盾

反模式:

  • 在同一个对话里既讨论架构设计又讨论具体 bug 修复
  • 后端接口开发和前端页面开发混在一个上下文里
  • 评审上下文(只读评论)和编码上下文(可修改代码)不区分