上下文工程实战:6个核心问题玩转Token预算与上下文管理

发布时间:2026/10/20 5:19:27
上下文工程实战:6个核心问题玩转Token预算与上下文管理
做提示工程这几年我有个越来越深的体会真正拉开AI应用体验差距的往往不是模型选型而是上下文怎么填、怎么管、怎么省。上下文工程Context Engineering这个说法出现得比提示工程晚但它是提示工程真正走向工程化的关键一跃——你写的每一条指令最终都要放进一段有限的上下文窗口里去跟模型交互。窗口就那么大放什么、不放什么、以什么顺序放几乎决定了应用的上限。所以这篇内容我想把上下文工程里最值得反复琢磨的6个核心问题摊开聊聊。它们不是零散的技巧而是我在多个实际项目里反复踩过坑之后沉淀下来的思考框架token预算的取舍、信息结构的优先级、多轮记忆的压缩策略、静态与动态内容的边界、上下文的体检方法、以及成本压力下的可复现设计。适合正在做复杂AI应用、智能体或RAG系统的提示工程架构师、技术负责人阅读也适合被“上下文不够用”困扰的开发者参考。文章不会给一堆花哨模板尽量把底层逻辑讲透。1. 窗口大小不是护身符token预算的“够用”与“好用”之辨1.1 容量幻觉塞得进去不等于用得好很多人拿到一个超大上下文窗口的模型第一反应是“太好了全塞进去”。我见过一个团队把几十页产品文档一股脑丢进上下文结果模型回答的准确性反而不如只给关键几段。这个现象背后是注意力机制的物理规律窗口再大模型在一次前向传播里能“专注”的信息总量依然是有限的信息之间会互相干扰、彼此淹没。这里有一个特别反直觉的结论更大的窗口并不天然等于更强的上下文能力。中间部分的内容被模型“看”到的权重明显偏低学术界把这个现象叫做“迷失在中间”Lost in the Middle。你可以把它理解成一个开会场景会议刚开始的议题和最后总结的结论大家都记得清楚中间那几个小时的讨论细节往往一片模糊。模型也一样它对上下文开头和末尾的内容最敏感对中间的依赖度要弱得多。我在实际项目中见过最典型的失败案例是把所有历史聊天记录不分轻重地拼进系统提示词后面再追加一句“请基于以上信息回答”。结果模型要么抓住了最开头几轮对话的内容要么只记得最新一条消息中段那些真正包含用户偏好的信息反而成了摆设。这不是模型笨而是上下文工程没做对。1.2 预算分配的三条实用原则既然容量不是护身符我们就得学会“预算思维”。一个合格的上下文窗口分配通常遵循三个原则原则一按功能域划分预算。把窗口想象成一个项目的经费不同模块需要单独的预算账号。我的习惯是核心任务指令占40%左右、当前输入和关键资料占30%左右、历史摘要占20%左右、输出格式和示例占10%左右。这个比例不是铁律但能避免某一类内容无限膨胀。原则二必须留白。不要试图把窗口用到99%你至少要留下15%到20%的缓冲空间给模型的输出、中间推理过程和临时插入的信息。有一次我把系统提示词压到刚好卡在模型的最大输入限制边缘结果模型在生成回答时直接截断因为连输出的token都没地方放了。原则三按价值排序而非按时间排序。很多人在组织上下文时默认“最新的放最后、最早的放最前”这种时间序逻辑在真实业务里并不总是最优的。更有价值的做法是按信息对当前任务的重要性排序最核心的约束条件放开头最需要模型精确执行的指令放结尾中间放需要参考但不要求逐字记忆的材料。预算分配不是算数游戏而是对“模型注意力的定向投资”。2. 信息也有优先级上下文架构中的金字塔分层与注意力保护2.1 为什么你的指令会被“稀释”咱们继续聊“迷失在中间”这个坑。当你把用户需求、背景资料、历史对话、系统约束全都塞进同一段上下文时它们是在“平等竞争”注意力吗不是。模型实际上会根据位置、格式、与当前问题的相关性来动态分配注意力。那些跟当前输入离得远、而且被大量无关内容包裹的关键指令最容易被稀释。我做过一个实验同一个任务把关键约束放在第200token处和第2000token处后者出现的信息被模型遵循的概率下降了接近三成。这个数据在多个模型上都稳定复现。这就是为什么上下文工程的第一课不是“怎么写提示词”而是“怎么安排信息的位置和层级”。生活化地讲上下文架构就像给模型准备一个文件柜。如果你把所有文件都杂乱地堆在柜子里需要的时候谁都能找到吗找不到。正确做法是分抽屉抽屉A放“你是谁、要做什么”抽屉B放“这条指令的特殊要求”抽屉C放“参考资料”。模型每次只需要打开最相关的抽屉而不是在一堆文件中翻找。2.2 可复用的三层金字塔结构基于以上逻辑我沉淀出一个比较通用的上下文金字塔结构分为三层系统层System Layer放角色设定、任务目标、通用规则、输出格式。这一层是“宪法”每次请求都应该在场最好放在开头让模型一眼看到自己的身份和总目标。任务层Task Layer放用户当前输入、本次请求的特殊要求、必要的补充说明。这一层是“临时工”只在本次对话中有效紧跟用户输入最合理。资料层Knowledge Layer放参考文档、检索结果、历史摘要。这一层是“图书馆”数量最大但优先级最低要克制地按需装载并且要明确告诉模型“资料只是辅助如果与系统层冲突以系统层为准”。一个典型的结构化组织方式大概是这样的[系统层] 你是一个专业的金融数据分析助手。你的任务是围绕用户提供的财报信息回答问题。 约束只基于给定资料作答不确定时明确说“资料不足”不要编造数字。 [任务层] 当前用户问题这家公司三季度毛利率为什么下滑 [资料层] 引用资料12024年三季度财报节选 引用资料2管理层电话会议记录节选 引用资料3行业分析师报告节选 [输出要求] 先给出结论再分条说明依据最后注明引用了哪份资料。这种结构的直接好处是模型在生成时能快速定位“我是谁”“用户要什么”“依据是什么”。我甚至会让资料层里的每条内容都加上编号索引要求模型在回答中标注使用了几号资料一下子把可追溯性也解决了。2.3 开头与结尾两个黄金位置前面说过模型对上下文首尾的内容记忆最牢那这两个黄金位置应该放什么以我的经验开头位置放最不容妥协的硬约束。比如“不要编造数据”“如果信息不足就直接说不知道”“严禁输出违法内容”。这些规则是底线必须放在模型最“清醒”的位置。结尾位置放本次任务最需要被执行的指令。例如“请先用三句话总结然后分点回答”在上下文的尾部再次强调输出形式模型落实的概率会明显提升。中间位置放参考资料、历史对话摘要等“备用信息”并明确其“仅供参考”的属性。理解了注意力保护这件事你再去翻自己之前写的系统提示词会发现很多问题都不是措辞问题而是布局问题。同样的内容换个位置效果可能完全不同。3. 遗忘是一门手艺多轮状态压缩与记忆持久化策略3.1 多轮对话里的“失忆”现场做过客服机器人和个人助理类应用的朋友肯定遇到过这个场景用户第10轮提问时突然说“我刚才不是说了嘛我要蓝色的那款”而你的模型已经完全不记得了。原因很简单——你把历史记录截掉了。窗口有限要么保留原始对话要么舍弃。很多人的第一反应是用滑动窗口只保留最近N轮对话。这是个急刹车方案虽然简单但问题明显用户的长期偏好、前面已经确认过的关键事实全都被一刀切掉了。还有一种做法是把所有对话原文一直拼接下去直到接近窗口上限结果就是前面的分析——信息过载模型什么都记住不好。3.2 分层记忆短期、工作、长期各司其职真正可持续的多轮记忆方案不是靠上下文窗口硬扛而是建立分层记忆架构短期记忆保留最近2到3轮完整的原始对话。这部分的语义细节最丰富适合承载需要精确引用用户原话的场景。工作记忆记录当前任务的状态变量比如“用户在填写表单第二步”“正在确认收货地址”。这部分通常是结构化的键值对放在上下文里占用的token很少但能让模型知道现在进行到哪一步了。长期记忆存储跨会话的用户画像、稳定偏好、历史关键事实。长期记忆通常放在外部向量数据库或键值存储里按需检索写入上下文而不是常驻窗口。打个比方短期记忆是桌面上的草稿纸工作记忆是显示器上的任务清单长期记忆是书架上的档案盒。草稿纸用完就扔任务清单随时跟踪档案盒按需调取。三层各司其职才不会把桌面堆得乱七八糟。3.3 摘要压缩从“逐字背诵”到“提取要点”压缩是上下文工程里绕不开的技术动作。最好的做法不是让模型逐条总结“用户说了什么”而是提炼“哪些信息对后续对话仍然重要”。我常用的三级摘要策略是增量摘要每一轮结束后把该轮产生的关键事实、用户偏好、待办事项追加到一个滚动摘要里。注意只追加增量不做全量重写降低token消耗。滚动摘要当上下文快满时让模型基于旧的滚动摘要和最近几轮新内容生成一份更精简的新摘要。关键事实抽取每轮对话结束后额外用一次轻量抽取判断“有没有值得长期保存的事实”。比如用户所在城市、预算上限、产品偏好。判断为空就什么都不写不为抽取而抽取。下面是一个我常用的摘要指令模板可以直接抄作业请对以下对话进行状态压缩生成一份JSON格式的会话摘要。要求 1. facts本轮出现的不随时间变化的事实如用户身份、偏好、约束 2. progress当前任务进行到哪一步 3. pending明确待办或需要下次提醒的事项 4. 如果某一项没有任何内容返回空数组。 请忽略寒暄和与任务无关的内容。这个模板用格式化输出避免了摘要信息散乱的问题后续无论是人工检查还是程序读取都很方便。实测下来一段10轮对话的原始内容大约2000 token用这个方法压缩后能控制到120 token以内信息留存率反而更高因为丢掉的全是寒暄和重复表达。4. 动静分离的上下文固定基座与动态注入的边界设计4.1 静态基座系统提示词里的“稳定域”上下文里并不是所有内容都需要每次重新计算。那些在长时间内保持稳定的部分——角色设定、公司背景、产品定位、安全红线——都属于“静态基座”。把它们放在系统提示词的开头每次请求原样带上即可。电商导购机器人就是一个典型例子。它的静态基座包括“你叫小助手”“你的服务范围是官方旗舰店”“你必须遵守七天无理由退货规则”这些内容不会因为用户换了个人就改变。静态基座的好处是稳定、可维护、不容易出错。但代价是它占据了固定的token开销所以必须精炼到极致。我有一个习惯静态基座里的每一句话都要经过“删除测试”。删掉这句话模型的整体表现会不会明显变差如果不会说明它不够核心就该删。经过几轮删减原本500 token的系统提示词常常能被压到200 token以内而效果反而更清晰。4.2 动态注入按需装载的“弹性区间”与静态基座对应的是动态注入——每次请求都可能变化的部分。典型包括用户当前输入、检索出的相关文档片段、当前时间/天气、用户的地理位置、实时的库存信息等。动态注入的核心原则只有一个按需装载。东西再多也只拿与当前任务最为相关的部分进上下文。做RAG的同学对这一点应该不陌生。一篇5万字的公司制度文档你不可能整篇塞进上下文让模型回答“年假怎么休”你需要先把文档切成小块、向量化再通过语义检索召回最相关的三四块内容作为资料层注入。这就是“动静分离”思想在检索增强场景下的落地。判断一个信息该不该放进来我有一个简单的两步过滤法第一步它跟当前用户问题有关吗第二步它对生成正确答案是必要条件还是锦上添花前者必须放后者一律不放。这一步想清楚了你的上下文会立刻清爽很多。4.3 上下文污染不同任务的互相干扰动静分离还有一个被很多人忽略的作用——避免上下文污染。我见过一个团队把“翻译助手”和“代码解释器”两个功能写进同一个系统提示词结果用户问代码问题时模型时不时会蹦出几句英文翻译反过来也一样。这就是静态基座里塞了相互冲突的任务指令导致的。更合理的做法是给不同任务建立独立的上下文入口。可以在路由层判断用户意图然后分别加载各自专属的系统提示词不让无关信息进入彼此的上下文。这样既能精简长度又能避免指令打架。上下文隔离不是性能优化而是质量底线。5. 给上下文做体检质量指标、评估流程与常见病根5.1 从“感觉不对”到“数据说话”上下文质量低时最直观的表现就是模型回答“好像哪里不对”。但“好像”是不足以指导优化的。我们需要一套可量化的体检指标。结合实践我认为以下五个指标最值得跟踪指标含义参考阈值上下文利用率实际填充token / 窗口上限一般不应超过80%有效信息密度完成任务真正需要的信息token / 总token越高越好基准50%以上首响应延迟从发送请求到收到首个token的时间随模型和场景不同趋势要稳定关键事实召回率评测集里的关键信息是否被正确使用核心业务上应逼近100%任务成功率端到端完成用户目标的占比视场景而定需要持续对比我自己在一次客服机器人项目里把上下文里的产品资料从8段砍到3段上下文利用率从95%降到62%关键事实召回率反而从71%涨到89%。这就是典型的“做得少反而做得好”。5.2 单轮体检法看一眼模型真正“看见”了什么想要诊断上下文问题最直接的办法不是反复修改提示词碰运气而是做一次单轮体检。操作方法分三步选一个有代表性的用户问题构造一份完整的上下文输入在调试环境里关闭知识库干扰只保留你要检查的那份上下文让模型输出答案的同时强制它标注“我回答中使用了上下文的哪些部分”。第二步里的“标注依据”是体检的核心动作。如果模型引用了上下文里并不存在的“事实”说明上下文里有误导项如果模型对关键资料视而不见说明资料位置太靠后或者被无关内容淹没了。调优一次做一次体检形成闭环。5.3 四个常见病根与排查顺序根据过往经验上下文质量差的根源通常落在以下四个位置建议按顺序排查病根一过载。资料太多、历史太长、指令太啰嗦。对应症状是回答平庸、缺失细节。解决方案是做减法、做摘要。病根二位置错放。关键指令被埋在中间参考信息抢占了开头。对应症状是答非所问、规则执行不严格。解决方案是重新布局。病根三指令冲突。系统提示词里自相矛盾比如先说“回答要简洁”又要求“输出完整分析报告”。对应症状是模型行为飘忽。解决方案是统一口径、删除冗余约束。病根四事实漂移。资料层里的信息过时或有误模型却把它当成权威依据。对应症状是“一本正经地胡说八道”。解决方案是在资料层标注时间、版本、可信度并在指令中提醒模型必要时质疑资料。排查时记住一条原则一次只动一个变量。改完重测保留日志。上下文优化是个累积迭代的过程最怕的就是一次性改五处出了问题也不知道是哪儿引入的。6. token经济学成本约束下的可复现上下文设计6.1 每一次调用都在烧钱成本公式拆解聊完质量再来算一笔账。很多团队在上下文工程上的优化只盯着效果忽略了成本等到账单出来才吓一跳。其实每次API调用的费用可以简单拆成输入token成本 输出token成本 缓存token成本。在大多数场景里最大的开销是输入token——也就是上下文本身。假设你的上下文平均是6000 token用户每次提问都携带这6000 token。一天10万次调用就是6亿token的输入消耗。哪怕单价很便宜乘以30天也不是小数目。更扎心的是这6000 token里有相当一部分是用户根本不看的系统说明和重复历史。换句话说压缩上下文不只是技术洁癖而是真金白银。6.2 三类成本优化手法缓存、压缩、按需成本优化不是牺牲质量换便宜。我常用的手法有三类提示词缓存把静态基座和那些不经常变化的内容放在请求的固定前缀位置很多厂商对命中缓存的token有折扣。前提是设计上下文时就要有意识地把静态内容和动态内容分开“动静分离”在这里再次发挥作用。语义摘要压缩章节三里的滚动摘要方法不只是为了效果也是为了省钱。长期对话场景下把5000 token的历史压成300 token每次调用直接省下4700 token的输入费用。按需装载不要预先在上下文里堆资料用检索或路由的方式只装载当前需要的部分。这既是个效果策略也是个成本策略。我见过某项目在这些措施全量上线后单次调用的平均输入token从8000降到了2400任务成功率还提升了5个百分点。这说明质量和成本从来不是对立面冗余才是它们共同的敌人。6.3 上下文配方让好设计可以被复刻光自己会做还不够上下文工程必须沉淀成团队资产。我的习惯是把每类场景的上下文设计做成“配方”用结构化配置管理起来。一个配方通常包含四个槽位base_prompt静态基座团队内共享版本化管理dynamic_loader动态注入逻辑定义哪些外部数据需要被检索history_policy历史记忆的压缩策略比如“保留最近2轮滚动摘要”output_formatter输出格式约束与示例。配方的意义在于可复现新成员接手项目时不用靠“前辈的玄学经验”来试错做A/B测试时可以很方便地对比不同配方的效果差异当模型升级或业务调整时也能逐个槽位替换快速迭代。我这几年越来越觉得上下文工程到了一定阶段拼的不是灵光一现的灵感而是能不能把一次“答得好”变成次次“答得好”的体系。最后再聊一点个人心得。上下文工程是一个典型的“非线性收益”领域你砍掉一半冗余效果可能提升80%你再砍掉剩下的一半效果不一定继续提升反而可能崩。所以别把“减少token”本身当成目标目标永远是“在有限预算内获得最高质量的任务完成度”。我每做一个新项目都会在前期花大量时间做上下文设计评审这个时间绝对值得——它是在给后面所有的调用次数省成本、给所有用户的问题回答提质量。如果你正被“模型好像理解不了我的业务”困扰不妨先别急着换模型仔细看看自己喂给它的上下文是不是真的把最重要的信息放在了对的位置。