ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

上下文工程实战:优化AI输入,让模型看到该看的信息

上下文工程实战:优化AI输入,让模型看到该看的信息

每次看到有人抱怨“同一个模型,为什么我用起来像个智障,别人用起来像个专家”,我都想提醒一句:问题多半不在模型,而在你喂给它看的东西。模型的能力边界在那儿摆着,你能控制的是它“看到什么”“先看到什么”“哪些东西不许看”。这就是上下文工程(Context Engineering),也是我这个标题想做的事:让 AI 看到该看的东西。

这事儿适合谁?两类人。一类是正在做 AI 应用的开发者,被幻觉、答非所问、输出不稳定折磨得头秃;另一类是重度使用 AI 助手的普通用户,发现自己永远在“调 prompt”,却不知道为什么时灵时不灵。上下文工程解决的就是同一个痛点:如何在不动模型参数、不重新训练的前提下,把输入侧的信息组织成模型最容易理解、最愿意遵循的形式。

1. 上下文工程到底在“工程”什么

先给个定义。上下文工程,说的是对整个上下文窗口(context window)里的信息做设计、裁剪、排序和格式化。它不是写一条好的指令那么简单,而是一整套关于“信息如何入场”的学问。

1.1 和 Prompt Engineering 的区别

很多人会问:这不就是 prompt engineering 换了个名字吗?真不是,区别挺大的。

Prompt engineering 的核心是“指令怎么写”——角色设定、语气控制、few-shot 示例、思维链引导,都发生在用户消息那一小段文本里。而上下文工程关心的是整个窗口中所有信息的布局:系统指令放哪、参考资料按什么顺序、用户问题插在哪、工具返回的结果怎么拼接、哪些历史对话该保留、哪些该丢弃。

用生活类比:prompt engineering 是教你怎么说话,上下文工程是教你怎么布置会议室。同样一拨人进来开会,桌椅摆成 U 型还是剧院式,白板上写没写议程,资料是每人一份还是扔在桌上自己拿,最终的会议质量完全不同。AI 对输入顺序、信息密度、格式结构的敏感程度,比一般人的想象高得多。

1.2 核心目标:信噪比管理

我做了大量实验后发现,上下文工程的所有技巧,最终都归结到一件事:信噪比。你给模型的信息里,有用的部分是“信号”,干扰它的、让它分心的、占用注意力的东西就是“噪声”。

一个常见的反面教材是:做文档问答时,直接把一份 200 页的 PDF 全文丢给模型,让它“根据文档回答问题”。结果模型频繁引用无关章节的内容,忽略了真正重要的条款,甚至把不同章节的内容混在一起编造。这就是信噪比太低——文档里大量与用户问题无关的信息,稀释了关键内容的影响力。

上下文工程要做的,就是提高信号强度、压低噪声干扰。手段可以是物理排除(只选相关片段)、语义加权(关键内容放大字体或强调标记)、结构引导(用 JSON/XML 分层)、位置安排(放开头或结尾)等等。整套方法论围绕“注意力分配”展开,模型关注什么,输出就靠近什么。

2. 上下文的“四层结构”与注意力分布规律

如果把一次完整的 AI 交互拆开看,上下文窗口里通常塞着四类信息。理解这四层的各自职责,是做好上下文工程的地基。

2.1 四层结构的组成

第一层是系统指令层。这里定义模型的身份、任务边界、输出格式、禁止事项。它的默认权重最高,相当于给整个对话“定调子”。我在实践中发现,系统指令写得越具体、越没有歧义,后续无论用户怎么乱问,模型都不容易跑偏。

第二层是背景资料层。包括文档片段、数据库检索结果、知识库条目。这一层是最容易失控的,因为它往往由外部系统动态注入,内容多、格式乱、甚至互相矛盾。上下文工程的大量精力都花在这里:清洗、排序、去重、裁剪。

第三层是示例层(few-shot)。给一两个高质量的输入-输出范例,比你在指令里写一百句“请遵循规范”有效得多。模型是预测下一个 token 的机器,给它看一个优秀答案的样板,它就会下意识模仿那个样板的结构和语气。

第四层是实时信息与工具结果层。比如调用搜索引擎返回的网页摘要、调用某个 API 返回的数据表、代码解释器算出的结果。这层的特点是“新鲜热乎”,但往往没有经过清洗,需要额外包装。我通常在工具返回后加一层格式化,把最关键的字段提取出来,并且标注来源编号,否则模型很容易被原始数据的噪声带偏。

2.2 注意力不是均匀分配的

这是上下文工程里最反直觉的一条规律。很多开发者误以为:我给了模型 128K 的上下文窗口,这 128K 内容模型都会“认真看”。实际上,大量实验和学术研究都指向同一个结论:模型对长文本不同位置的注意力权重是不均匀的。

我自己实测的体感是:开头的内容影响最大,结尾次之,中间最容易被忽略。学术界有个形象的说法叫“迷失在中间”(lost in the middle)。你辛辛苦苦放在第 5000 个 token 位置的关键规则,很可能模型读是读到了,但在回答时根本没想起来用。

所以我在组织上下文时的顺序策略是:

  • 最重要的系统规则、核心目标、禁止事项:放最前面,或者最后再强调一遍。
  • 需要精确引用的事实(比如数字、条款):尽量靠前,并且在后面引用时再次出现。
  • 大段参考材料:放在中部可以,但必须在指令层明确指示“材料在第几段有什么用”,否则模型会把它当成背景噪音。
  • 与当前任务最相关的即时信息:放在用户问题之前、紧挨着问题的位置。

有同行提出一个“边缘效应”的说法:把关键信息分布在上下文的头尾两端,变成两个“锚点”,比堆在中间效果好得多。我自己测试下来,把一条关键约束用不同表述在开头和结尾各写一遍,模型遵守的概率明显提升。这不是让你重复啰嗦,而是同一语义的两次编码,模型总能捕捉到至少一个强信号。

3. 上下文容量悖论:给得太多,反而看见得更少

上下文窗口越开越大,很多人的第一反应是“太好了,把什么都塞进去”。但我在实操中越来越确信一件事:上下文空间是一种稀缺资源,不是存储空间。每多一 token 无关信息,都会摊薄关键信息的注意力权重。

3.1 我踩过的“全量注入”的坑

有一次我在做某个指标提取任务,要处理一份业务报告。第一版方案是“全部塞进去”,心想上下文窗口够大,让模型自己找。结果输出惨不忍睹:提取出的关键指标漏了三个,而且把去年的数据和今年的数据混在一起。

后来我调整方案:先用规则脚本把报告里跟指标相关的段落截出来,剔掉大段的背景介绍和行业分析,再把每个指标的上下文按统一格式排列,最后在指令里明确“仅引用提供的指标卡片,不要自己推断”。同样的模型,没有任何参数调整,准确率从“没法用”直接变成“可用”。这个对比让我对上下文工程的价值有了直观体感。

把根因说透:模型的注意力机制本质上在做相似度匹配。它在生成 token 时,需要在上下文中找到最相关的信息来参考。如果上下文里有大段词句上和“指标”相关、语义上却不是真正目标的内容,模型很容易被带偏。给它干净的、直接对口的信息,它当然更容易命中。

3.2 信息密度与“适度模糊”

还有一层容易被忽略:不是所有任务都需要极度精确的上下文。有些任务是开放性创意任务,比如头脑风暴、文章框架设计,这时候上下文密度太高反而限制模型的发散能力。我做创意类任务时,会把背景信息压缩成几个关键词和约束条件而不是完整资料,让模型有足够的自由发挥空间。

这就是上下文工程里的一个权衡:你需要的是“精确检索”还是“开放性生成”?

  • 精确检索:上下文越干净、越结构化越好,最好精确到字段。
  • 开放性生成:保留必要的约束即可,不要塞入大量细节,否则模型会过度拘泥于给定材料,丧失发散能力。

理解这个二分法之后,你再看“上下文窗口多大才够用”这个问题,就会发现真正的答案不是“越大越好”,而是“刚好容纳关键信息 + 留一点余量”。超出余量的部分,宁可砍掉,也不要硬塞。

4. 实操演练:从零搭一个规范的上下文

前面讲了不少原理,现在上一个完整的实操案例。这个案例是我把上下文工程讲给团队新人时常用的,也是模拟项目 X(指标提取与风险评估Demo)的简化版本。任务是这样:给 AI 一段业务报告文本,让 AI 输出其中的风险项并排序。

4.1 第一版:完全裸奔

我直接把报告原文复制进对话框,问:“请帮我看看这个报告里有哪些风险?”

模型输出了一堆正确的废话:“可能会影响项目进度、需要关注资金压力……”原因很明显:没有角色定义、没有输出格式约束、没有判断标准,模型的“默认模式”是生成一段四平八稳的泛泛总结。

4.2 第二版:加角色和格式

于是我加了系统指令:

你是资深风险管理分析师。请阅读用户提供的报告,输出 JSON 格式的风险列表。每个风险项包含:severity(高/中/低)、likelihood(高/中/低)、description(一句话)、evidence(原文摘录)。

这版好多了,输出结构化了,JSON 也能解析。但我很快发现一个问题:模型会自己脑补一些报告里根本没提的风险。比如报告只说“研发周期紧”,模型就脑补成“研发进度严重超期的风险”,甚至给了一个高严重度。这就是典型的“意图漂移”——你给了格式,没给边界。

4.3 第三版:加入判断标准和否定指令

关键的转折在于我给了一组“什么算风险”的判据,并且明确“没有证据就不要列”。

系统指令: 你是风险管理分析师。只能基于用户提供的报告原文提取风险,不得推测报告未明示的风险。 “风险”定义为以下三类之一:a) 报告明确指出的负面事项;b) 报告中两个事实组合可能导致的负面结果;c) 报告中的数据异常。 判定严重度时综合考虑影响范围和发生概率;证据栏必须引用报告原文中的短语,禁止改写或编造。 如果某事项不满足上述定义,不要输出。

这版的输出终于像专业分析师的产物了。风险项的理由都有原文依据,改写的证据变少了。从中我能清楚看到:模型不会自动知道“该做什么标准”,上下文工程的一部分工作就是把评估标准显式化。

4.4 第四版:用 few-shot 巩固行为模式

我最后加了一个示例。因为这种任务里“什么样的风险值得报、什么程度算高严重度”特别微妙,文字描述说不清楚,一个样例顶过千言万语。

我构造了一个模拟的风险条目,显示给模型“我希望的高质量输出长什么样”。

示例里的风险项刻意包含了:一个严重度高但影响范围小的、一个严重度中但发生概率高的、一个原文暗示但未明说的(配合证据短语)。模型看完之后,输出风格基本定住了,后续测试多条报告,结构稳定率从 70% 提升到了 90% 以上。

这个四步演进的过程,每一步都在做“让 AI 看到该看的东西”:第一不裸奔,第二给框架,第三给边界,第四给样板。最终你发现,真正费工夫的不是“写 prompt”,而是“整理任务知识”——你需要把脑海里模糊知道的评估标准、边界条件、典型样例全部显式化,变成模型能读懂的文本。

5. 上下文组织的高级技巧:压缩、分层、动态组装

处理长文档和复杂任务时,光靠“把关键段落挑出来”还不够。下面三个技巧是我长期在用的,按推荐程度排序展示。

5.1 结构化重构:把原始文本变成“卡片”

很多源文档的原始结构并不适合直接投喂。比如 PDF 导出后的文本,标题和正文混在一起,表格变成一行行的乱码。我的做法是:先写一段预处理脚本,把文档按语义切块,每一块变成一个“信息卡片”。

每个卡片包含三要素:ID、来源位置标签、正文内容。

卡片 ID: R-034 来源: 第三章 第2节 表格3-1 内容: 2024年毛利率 42.3%,同比下滑 6.1个百分点

投喂给模型时,系统指令里明确写:“引用信息时使用卡片 ID 加 [卡片引用] 标记”。这会让模型的引用行为变得非常可控,直接解决幻觉式引用问题。模型不再说“据报告显示”,而是说“R-034 卡片显示”。这种把自由文本变成结构化单位的方式,是我见过性价比最高的上下文工程手段。

5.2 动态组装:不是所有内容都要进上下文

上下文工程的另一大块是“决定什么不进去”。我常用一个两阶段方案。

第一阶段,用廉价的、快速的模型(甚至可以用规则脚本)对检索到的候选片段打分,选出与当前问题最相关的 Top N。第二阶段,把选出的片段按相关度重新排序,最相关的放最靠近用户问题的位置,依次向窗口头部回退排列。

这个方案背后是对注意力分布的利用:既然模型在结尾附近(用户问题前)的注意力最强,那就把最强的位置留给最相关的材料。很多人做 RAG 时直接把检索出的 Top-K 按原始得分从高到低拼接,根本不管它们在窗口里的位置,效果自然打折。

5.3 压缩:让模型帮你浓缩信息

当原始材料太长,连塞进窗口都困难时,我的折中方案是“摘要链 + 层次压缩”。

先把长文档切块,让模型对每一块生成一段包含所有关键数字和结论的摘要。再把摘要拼起来,做一个更上层的摘要。最后只把最上层的摘要和与当前问题直接相关的某一层摘要放进上下文。代价是有信息损失,但大多数任务中收益远大于损失——关键是模型在真正回答问题时,参考的是高密度摘要而不是稀薄原文,回答质量反而提升。

很多人在这一步会担心:丢了细节怎么办?我的经验是:给摘要链加一个“按需回溯”机制。系统指令里告诉模型:“上下文只有摘要,但如果回答中需要某个摘要里的具体细节,请指出需要的卡片 ID,我会在下一轮提供。”这在多轮交互场景里非常好用,既控制上下文体积,又不牺牲信息完整性。

6. 常见问题排查与避坑实录

做久了上下文工程,你会发现大多数“AI 不听话”都能归因到几个固定模式上。下面这几张速查表是我自己整理出来的,拿来即用。

6.1 常见输出问题的上下文侧诊断

现象大概率原因上下文侧解法
回答太泛、太模板缺角色定义和判断标准加系统指令,输出格式约束
忽略某一关键规则该规则被放在长上下文中部移到底部或反复强调,靠近用户问题
引用不存在的内容上下文里的材料结构混乱,模型分不清哪些可引用用卡片 ID 标记,明确“只能引用卡片”
答非所问上下文塞满了与问题无关的附加材料做裁剪,只保留高相关片段
多轮对话越聊越偏历史消息没有压缩,早期无关对话还在窗口里定期清理/摘要历史,限制窗口范围
相同输入不同输出,方差大上下文里存在语义冲突的信息检查是否有矛盾内容,统一口径

6.2 我亲测有效的三个排除法步骤

第一,做减法。出现问题时,先把上下文砍到只剩“系统指令 + 用户问题”,看模型表现是否恢复。恢复了,说明是附加材料里有什么东西干扰了它的判断,再把材料一点点加回来,找到那个“万恶之源”。

第二,换位置。如果模型忽略了一条重要的约束,别急着换措辞。先把这条约束挪到最靠近用户问题的地方(也就是窗口末尾),通常问题就解决了。位置权重在很多模型模型中表现极其显著,成本为零。

第三,换格式。如果同一含义的文本规则模型“看见了但没执行”,把它改写成一个列表、一个表格或一段 JSON。格式变化会改变 token 序列的分布规律,有时候就是这一点变化让模型从“模糊理解”变成“遵循指令”。

6.3 高阶避坑:上下文工程不是万能的

必须诚实地说一句:上下文工程有边界。当任务本身超出模型能力上限,比如需要复杂的多步推理、数学计算或因果推断时,再优秀的上下文组织也只能小幅度改善,不能质变。我的判断标准是:如果经过三轮上下文优化,输出仍然达不到要求,那大概率要换更大的模型,或者把任务拆解成多个子任务,而不是继续在 prompt 里挖。

还有一类任务是上下文工程无能为力的:需要私有知识的问题。如果这个知识模型训练时没见过,你也没在上下文里给它,它只能编。不要用上下文工程对抗知识缺失,该接检索接检索,该建知识库建知识库。上下文工程负责“组织信息”,不负责“创造信息”。

末尾再补两句

做上下文工程这几年,我最大的体会是:别把它想成一种“取巧”,这实际上是在逼迫自己把任务想清楚。你要让 AI 看到该看的东西,首先你得知道“什么对该任务是重要的”。这个梳理过程,受益的不只是 AI,还有你自己对业务的理解。再分享一个小技巧:每次只改一个变量。不要同时调整角色、裁剪材料、加示例、改格式,那样你永远不知道是哪一步起效的。一次一动,用 A/B 的思路慢慢逼近最优,实测下来这是最稳、最省时间的迭代方式。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进