我最早意识到“上下文”是个工程问题是在一个跨语言文档问答项目里。同一个模型同一个接口系统提示词也一模一样可用户问“上个月报表里的异常波动是什么原因”它答得头头是道用户换个说法问同一个问题它就开始胡编。后来我把发送给模型的完整内容打印出来一条一条比对才发现问题根本不在模型能力而在于我们往上下文里塞了太多互相干扰的信息。那是我第一次认真看待“上下文工程”这件事。后来在好几个项目里反复验证我得出的结论是大模型应用能不能稳定落地七成功力都在上下文工程上。模型的权重和参数我们改不了但输入给模型的东西每一行都是我们可控的。这篇内容不扯抽象概念就讲清楚上下文工程为什么重要、它跟提示词工程差在哪里、实际项目怎么落地以及我踩过的几个坑。1. “上下文工程”到底在解决什么问题1.1 模型没有记忆每次调用都是陌生人对谈很多人刚接触大模型时默认它有“记忆力”。其实不是。模型在推理时只有一个无状态的函数调用你给它一段文本它根据文本预测后续内容。上一轮对话为什么“记得”是因为我们把之前的对话历史一并拼到了当前请求里。这个“拼进去”的动作就是上下文工程最基本的形态。打个比方。提示词工程像是教一个刚来的实习生怎么说话——你要交代清楚任务、格式、语气。上下文工程则是决定这个实习生上工前桌上应该摆哪些材料、材料按什么顺序放、哪些旧材料该撤走。你摆的材料质量直接决定他给出的结论质量。摆少了他瞎猜摆多了他分不清重点摆乱了他可能抓错线索。所以上下文工程的定义可以收敛成一句话系统性地设计、组织和管理每次请求中发送给模型的全部信息让模型在推理时具备完成任务所需的背景、约束和目标。1.2 上下文工程要解决三个核心问题选择性、组织性、时序性把上下文工程拆开看它本质上在做三件事信息选择性。模型的上下文窗口是有限的就算窗口大到能塞十几万字成本也会随着输入长度成倍上涨。你不可能把整个知识库都丢进去。上下文工程要决定哪些信息值得进、哪些不该进、哪些要压缩后再进。这在信息论里叫信道容量分配现实里就是我们常说的“这个片段要还是不要”。信息组织性。信息不是堆进窗口就完事。模型对上下文的感知不是均匀的——放在开头和结尾的内容模型记得更牢中间大段的内容容易被“遗忘”。所以系统指令、用户问题、检索到的外部知识、对话历史彼此之间的排列顺序和分层结构直接决定模型能不能抓准重点。这一点在后面的实操案例里会详细展开。信息时序性。多轮对话里上下文是动态的、持续增长的。上一轮用户说的需求、上一轮助手给出的结论、中途插入的外部检索结果它们的先后顺序和更新策略都需要管理。有些信息已经过时了如果不及时裁剪掉就会污染下一次推理。这三个问题单独拎出来哪一个都不算深奥。但它们组合在一起就构成了大模型应用从“能跑”到“跑得稳”的分水岭。1.3 为什么这件事值得单独拿出来讲提示词工程这几年讲得很多但大家慢慢发现提示词只是上下文里的一个组成部分。而且最难搞的往往不是那句system prompt怎么写而是异构信息的融合——一个请求里既有长指令、又有几段外部文档、还有几十轮对话历史、加上工具返回的结构化结果怎么让它们各司其职地协作。这个问题的复杂度已经超出“措辞优化”的范畴进入工程化设计的领域。所以业内开始用“上下文工程”这个词来概括这一整套方法论。理解了这层背景再看后面的内容就顺了。2. 上下文窗口是能力也是陷阱几个必须接受的物理约束2.1 看得见的窗口看不见的注意力偏差上下文工程之所以必要第一个原因是模型的注意力机制存在明显的偏好。有一段时间我专门做过对照实验把一段关键信息放在长文的正中间模型经常漏掉把它挪到开头或结尾模型的表现立刻好转。这个问题在自然语言处理领域有个形象的说法叫“Lost in the Middle”。这个现象对我们做应用是个大麻烦。现实中用户关心的信息往往恰好埋在长篇资料的中段。如果把整篇文档直接塞进上下文模型很可能会漏掉最关键的那段。上下文工程里的“结构编排”很大程度就是在对抗这种注意力偏差——要么把检索到的关键片段提到靠前的位置要么把长文档切得足够小保证每个片段都有机会被充分注意。2.2 每一个token都在花钱上下文不是免费的资源另一个现实约束是成本。模型按token计费输入侧的token单价虽然通常比输出侧便宜但架不住量大。一次请求塞5万token生成300字回答用不了多久费用就上去了。更麻烦的是这类费用是可累加的——多轮对话里每一轮都要重发完整的历史上下文一个用户聊20轮可能意味着几千甚至上万次token的重复消耗。我做项目时给团队定过一条原则上下文里的每一条内容都必须回答一个问题——“少了它模型给出的答案会不会显著变差”如果不会它就不该出现在上下文里。这个原则在执行时看起来很简单但实际项目中很多人会不自觉地把各种边角料往上下文里塞既费钱又拖慢速度。2.3 上下文组件拆解每一次请求里都有什么具体落地时我会把一次请求中的上下文拆成六个组件组件作用典型问题系统指令定义角色、任务边界、输出格式写得太长稀释重点示例Few-shot用给定样例约束输出模式样例太少不管用太多占空间外部知识检索到的文档、数据库结果内容过时、互相矛盾、噪声大对话历史维持多轮记忆早期信息污染当前意图工具定义描述可调用的函数或API描述与实际能力不匹配用户输入当前这轮的问题表述模糊、隐含需求多上下文工程做的所有事都可以归结为对这六个组件的分配、削剪和编排。理解了这个组件清单再去看市面上的“上下文管理系统”“对话记忆框架”你会发现它们本质上都是在帮你管理这六个组件的生命周期。3. 上下文工程和提示词工程的边界多走一步从优化措辞到管理系统3.1 一字之差的本质区别用一句话区分提示词工程优化的是“对模型说什么”上下文工程管理的是“模型能看到什么”。提示词工程的工作重心在指令本身——措辞、格式、角色设定、思维链引导。它默认模型能看到的信息集合是确定的、静态的你只需要把一句话写得更好。上下文工程则默认信息集合是动态的、多源的它关注的是如何在每个时刻构造出最合理的输入全集。举个例子。一个抽卡类问答系统提示词工程关心的是“请用简洁的中文回答用户问题并给出概率计算过程”上下文工程关心的是“用户最近提到过哪些卡牌组合当前卡池公告是哪一期哪些历史对话已经失效、要从上下文里裁掉”前者是话术优化后者是信息生命周期管理。3.2 提示词工程解决不了的三个场景把这两个概念切分开不是因为术语洁癖而是因为有些问题靠调提示词真的解决不了。动态检索场景。用户的问题不同需要的外部知识就不同。哪几段知识该进上下文取决于对当前问题的相关性排序。这个决策过程本身是代码逻辑不是提示词能替代的。长对话记忆场景。50轮对话之后历史内容已经超出窗口。是全部保留、滚动丢弃、还是压缩成摘要每一种选择都会改变模型的答复质量。这需要一套存储和更新策略而不是一句“记住前面的对话”能搞定的。多信息源冲突场景。检索结果之间互相矛盾时是让模型自己取舍还是在上下文层面就做好排序和标注我自己实测光靠提示词让模型“优先相信系统指令中的约定”效果不稳定更可靠的做法是在上下文里显式标注信息源和时间戳让模型可以依据这些元信息做判断。3.3 一个更完整的比喻提示词工程像是调水龙头的阀门把水温调准上下文工程是决定整栋楼的水管怎么铺、水箱容量多大、什么时候蓄水、什么时候排水。只调阀门解决不了水压不稳、水管堵塞的问题。这也是我从“什么都想靠写提示词解决”转向“认真做上下文管理”的根本原因——提示词能解决的往往只有最后一公里的表达问题而应用系统的稳定性取决于整条链路的信息质量。4. 一个跨语言文档问答项目的上下文工程落地全记录4.1 项目背景与设计约束有一次我们接了个跨语言文档问答需求。核心场景是企业内部有大量多语言技术文档用户用自然语言提问系统给出答案并标注引用来源。听起来不复杂但跑起来之后出现了很多跟模型能力无关的问题最后全部落到上下文工程头上。项目有几个硬约束。第一部分文档页数很长单篇超过上下文窗口的合理承载量。第二多轮对话是刚需用户会追着上一个答案继续深挖。第三成本敏感不能每轮都豪放地塞几万token。这三个约束决定了我们必须在上下文层面做管理。4.2 完整链路设计检索、拼装、压缩、裁剪我们最终跑的链路是四条线并行文档切分 → 相关检索 → 上下文拼装 → 动态裁剪。文档切分没有用固定字符数一刀切而是按语义段落切每块控制在500到800字之间。切太碎会让检索结果失去上下文切太大又容易超出窗口。这一步是上下文工程的地基很多后面解决不了的问题根源都在切分粒度上。检索阶段我们对候选片段做两轮筛选先用向量检索召回Top 20再用一个重排模型把相关度最高的Top 4到Top 6挑出来。为什么做两轮因为向量检索擅长找“语义相似”但常常把表面上相似、实际不解决用户问题的片段排到前面重排模型能结合用户问题的完整语义修正排序。上下文拼装阶段我们遵循固定模板系统指令在最前紧跟着是检索到的文档片段然后是对话历史最后是当前用户问题。这个顺序是有讲究的——文档片段紧跟在系统指令后面相当于让模型带着“任务说明”去看“参考资料”避免模型在历史对话里迷失。动态裁剪分两层。第一层是历史裁剪超出6轮之前的内容不再原文保留而是让模型生成一版摘要放进上下文。第二层是信息裁剪每次检索到的片段按重排得分取Top 4其余丢弃。这两层裁剪让单次请求的上下文长度稳定控制在3000到4000 token以内。4.3 实测中的三个问题与排查过程问题一检索到的片段互相矛盾。有一次用户问某功能的默认参数是多少系统答得含混不清还混进了两个不同版本的说明。排查下来是切分时把新旧两版文档切成相邻片段而检索阶段没有做版本过滤。最后加了元数据标过滤每个片段带着版本号和时间戳进上下文检索时只允许同一个版本生效。问题二历史对话污染当前问题。用户先问“A产品的部署步骤”然后又问“那安全配置呢”模型把“那”理解成了A产品的部署里的安全配置答非所问。事实是用户在问B产品的安全配置。我们最后在拼装对话历史时给早期轮次加了显式的角色标记和时间线同时压缩掉与当前问题关键词重叠度低的历史轮次。问题三窗口溢出导致的截断。长文档问答时如果检索出的片段特别多加上历史对话窗口就超了。早期我们图省事直接用模型自带的截断策略结果总是把末尾的用户问题截掉。这个问题最危险——模型以为自己看得到问题实际看不到。后来我们改成自己控制的“优先丢弃策略”先丢最早的历史轮次再丢弃相关度最低的检索片段保证当前问题永远完整。4.4 这个案例带来了什么做完这个项目一个直观的认知是同一个底层模型在上下文工程做得粗糙和做得精细两种状态下表现差距大得令人惊讶。粗糙时只配当个玩具Demo精细时才能作为稳定输出交付给真实用户。这也是为什么我在任何技术分享里都坚持把上下文工程放在比模型选型更优先的位置。5. 上下文工程的设计准则与高频误区5.1 五条可复用的设计准则经过几个项目沉淀我给自己整理了五条上下文工程准则每次设计上下文管理方案时都会对照检查。准则一最小必要原则。上下文里的每条信息必须证明自己有存在价值。判断方法是做一个“裁剪测试”把这条信息删掉看模型输出是否显著变差。没变差就删了。准则二位置即权重。关键信息放首尾次要信息放中间。系统指令和当前问题是最重要的两端外部知识次之过时历史再一次。在模板里固定这个顺序而不是每次临时拼。准则三动态保鲜。对话是动态的上下文绝不能是静态的。每一轮结束后主动评估哪些信息已过时、哪些可以压缩成摘要、哪些必须削减。让上下文管理跑在业务逻辑里而不是请求前临时抱佛脚。准则四显式胜过隐式。如果你希望模型优先相信某个信息不要指望它自动从语料里领悟直接在上下文里标注“以下信息来自正式文档优先级最高”。我测试过很多次显式标注的效果远好于隐式暗示。准则五可观测可回放。每次请求的上下文要能完整记录和回放。线上出问题时第一件事就是把那条请求的上下文拉出来看。没有这个能力排错基本靠猜。5.2 高频误区逐个拆解误区一把上下文窗口当垃圾桶什么都往里塞。窗口大不代表可以滥用。注意力会被稀释成本会飙升延迟也上去了。我见过有人把窗口从4K换成128K后反而把系统提示词、旧文档、日志一股脑塞进去结果答案质量没提升费用先爆炸了。误区二上下文越短越好。这是另一个极端。有些人为了省token把场景背景砍到只剩一句话结果模型缺背景信息只能靠猜。上下文工程追求的是“不多不少”而不是“能短则短”。省token最该下手的是冗余历史不是必要背景。误区三只调系统指令不调数据质量。很多团队拿到一个效果不佳的案例第一反应是改prompt第二反应是换模型很少去检查检索上来的文档片段本身是不是答非所问。我经手的项目里至少一半的“模型答错”问题根子在检索端或切分端不在提示词。误区四忽略对话历史的优先级。历史对话和当前问题冲突时模型往往会参考离得最近的对话内容做判断如果中间夹着一大段检索结果“当前问题”的注意力就被稀释了。所以要刻意把当前问题放最后并且在上下文里显式分成不同区块而不是一股脑端平。误区五上下文一次性拼好就完事。这是最普遍的问题。上下文工程是个持续过程用户每提一个新问题上下文的构成都要重新计算。一个环节的缓存策略、摘要更新、历史裁剪处理不好都会让系统在多轮交互中逐渐走下坡路。5.3 验证上下文是否有效的几个小技巧我实测下来验证上下文工程做得对不对有几个很便宜的方法。第一换序测试。把同一个关键信息从中间挪到开头看模型能否答对。能说明模型本身知道答案只是你没给它足够好的位置不能说明问题更可能在指令或知识本身。第二反转提问。构造一个与原文相反的问题看模型是无脑顺着上下文答还是能结合约束给出正确判断。这个方法尤其适合检查系统指令是否把边界讲清楚了。第三批量A/B测试。不要拿单个case判断上下文方案好坏。准备几十个典型问题两个方案各跑一遍比较关键指标答案正确率、引用命中率、关键信息遗漏率用数据说话。上下文工程里的很多改动单看一两个case会觉得“差不多”批量跑完差别才明显。6. 上下文审计我建议每个人都建立的日常习惯最后分享一个实操层面的个人心得。上下文工程不是搭完一套链路就一劳永逸的事它需要持续迭代。而迭代的前提是能看到系统里真实流动的上下文内容。我在团队里立了一条规矩每一条用户反馈“答得不好”的case必须把当时的完整上下文dump出来逐条检查六个组件里哪个出了问题。这个动作叫“上下文审计”。做了三个星期后我们形成了自己的问题分类清单背景缺失、指令模糊、检索噪声、历史污染、位置不佳、信息过时。绝大多数线上问题都能归入其中。这个小习惯带来的直接收益是团队不再靠玄学调参而是照着审计结论做定向优化。有一次用户反馈某个新功能总是答得前后矛盾一查上下文发现旧的系统指令在代码里被另一条新指令覆盖了模型手里同时握着两套相互冲突的任务说明。这种问题不看上下文根本找不到。建议你的项目甚至个人实验里也建立这个习惯把每次请求的上下文落盘存下来没有落盘能力的至少打日志。它会让上下文工程的优化从“灵光一现”变成“按图索骥”。上下文工程重要不只是因为它决定模型表现更因为它是一套可测量、可迭代、可沉淀的工程方法。只要你在做大模型应用这件事就绕不开。