恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
上下文工程实战:从信息筛选到动态裁剪,提升大模型输出质量
首页
资讯中心
/
上下文工程实战:从信息筛选到动态裁剪,提升大模型输出质量
上下文工程实战:从信息筛选到动态裁剪,提升大模型输出质量
发布时间:2026/10/13 21:02:23
1. 为什么“喂给AI什么”比“用什么模型”更值得花时间很多人第一次接触大模型应用开发时注意力几乎全在模型选型上——参数多大、上下文窗口多长、推理速度多快。但真正做过几个落地项目之后你会发现同一个模型换一种上下文组织方式输出质量能差出好几个档次。这就是“上下文工程”要解决的问题不是让模型变得更聪明而是让它在每一次调用时恰好看到该看的东西。我最初做的一个内部知识问答工具用的是当时能力相当不错的通用模型但回答质量一直不稳定。用户问“上季度的报销流程有没有变化”模型要么答成通用财务常识要么把三年前已经废止的旧规定翻出来。排查了很久才发现问题不在模型而在我把整个知识库的摘要一股脑塞进了系统提示里真正相关的那份流程变更说明反而被淹没在几千字的无关内容中。后来我把上下文从“全量摘要”改成“按问题动态检索结构化裁剪”同样的模型准确率肉眼可见地往上走。这件事让我意识到上下文工程的核心不是“塞更多”而是“筛更准”。它涉及几个层面的判断哪些信息是当前任务真正需要的、以什么形式呈现给模型最容易被理解、信息之间的顺序和优先级怎么安排、当信息量超出窗口时如何取舍。这些判断做得好小模型也能干出漂亮的活做得差再大的窗口也只是浪费。这篇文章适合两类人看一类是正在做AI应用、发现输出质量忽高忽低但找不到原因的开发者另一类是对提示词有一定了解、但还没系统思考过“上下文”这个维度的人。我会从实际项目出发把上下文工程拆成几个可操作的环节包括信息筛选、结构组织、动态裁剪、顺序编排和验证方法尽量给出能直接抄的配置和思路。2. 上下文工程到底在工程什么从“提示词”到“信息环境”的认知升级2.1 提示词工程的局限它只管“怎么说”不管“给什么”提示词工程在过去两年被讨论得很多核心关注的是指令的措辞、格式、角色设定这些表达层面的东西。比如“你是一个资深财务专家”比“你是一个助手”更能让模型进入状态“请分三步回答”比“请回答”更能得到结构化的输出。这些技巧确实有用但它们有一个共同前提模型已经拥有了回答问题所需的信息。现实情况是大多数应用场景里模型本身并不具备领域知识。你问它某家公司内部的报销标准它不可能知道。这时候再怎么优化措辞模型也只能编。提示词工程解决的是“表达效率”问题而上下文工程解决的是“信息供给”问题。两者是互补的但后者往往被忽视因为它不像写一句漂亮的指令那样有即时反馈。我见过不少团队在提示词上反复打磨把系统提示写了上千字却对检索回来的文档不做任何筛选和排序直接把Top-K结果拼接进去。结果就是系统提示很精致但模型看到的是一堆噪声输出自然好不了。这就像你给一个新人写了非常详细的岗位说明书但给他的参考资料全是过期的和无关的他照样干不好。2.2 上下文的四个层次系统层、任务层、知识层、对话层要把上下文工程做扎实先得把“上下文”这个东西拆开看。在实际项目中我习惯把它分成四个层次每个层次的职责和优化重点都不一样。系统层是模型的角色设定和全局约束比如“你是一个只基于给定资料回答的助手不知道就说不知道”。这一层相对稳定不随每次请求变化但它决定了模型对待后续信息的态度。系统层写得好能大幅降低模型“自由发挥”的概率。任务层是当前这次请求的具体指令比如“根据以下文档回答用户关于报销流程的问题”。它告诉模型这次要干什么通常和用户问题一起出现。任务层的关键是明确边界允许模型做什么、不允许做什么、输出格式是什么。知识层是检索或筛选出来的参考资料也是上下文工程里变量最多、最需要精细处理的部分。同样一批文档不同的裁剪方式、不同的排列顺序、不同的标注方法模型的使用效果差异很大。这一层是本文重点讨论的对象。对话层是多轮交互中积累的历史消息。很多人会忽略这一层把全部对话历史都带上导致上下文越来越长、越来越贵而且早期无关的闲聊会干扰当前任务。对话层需要做摘要或选择性保留而不是无脑追加。把这四层分开管理之后你会发现优化有了抓手系统层调措辞任务层调边界知识层调筛选和结构对话层调保留策略。每一层都可以独立迭代而不是混在一起凭感觉改。2.3 一个反直觉的结论上下文不是越多越好大窗口模型出现后很多人第一反应是“终于可以把所有东西都塞进去了”。但实际测试下来信息量和输出质量并不是线性关系。当上下文里包含大量与当前问题弱相关的内容时模型反而更容易抓错重点甚至被无关信息带偏。我做过一组对比测试同一个问题分别给模型提供3份高度相关的文档、10份相关但夹杂无关的文档、以及全部30份文档。结果是3份那组准确率最高10份那组开始出现混淆30份那组虽然也能答对但响应时间明显变长而且偶尔会引用不相关的条款来佐证。这说明模型在长上下文中分配注意力的能力是有限的冗余信息会稀释关键信息的权重。所以上下文工程的一个基本原则是在满足任务需求的前提下上下文越精简越好。精简不是删减必要信息而是去掉那些“有它不多、没它不少”的内容。判断标准很简单如果删掉这段内容模型还能不能正确回答如果能就删。3. 信息筛选怎么判断哪些内容该进上下文3.1 相关性判断不能只靠向量相似度做检索增强生成时最常见的做法是用向量数据库做相似度搜索取Top-K个片段拼进上下文。这个方法简单有效但它的判断标准是“语义相似”而不是“任务相关”。这两者经常不一致。举个例子用户问“报销需要哪些材料”向量检索可能会返回一段讲“报销材料提交方式”的文档语义上很相似但用户真正需要的是材料清单而不是提交渠道。再比如用户问“出差住宿标准”检索可能返回一段讲“出差审批流程”的内容因为都包含“出差”这个词但实际不相关。更靠谱的做法是在向量相似度之外加一层基于元数据的过滤。比如给每个文档片段打上类型标签政策、流程、FAQ、模板、时效标签现行、已废止、适用范围标签全公司、某部门。检索时先用元数据缩小范围再用向量相似度排序。这样能过滤掉大量“语义相似但实际无关”的内容。我在一个项目里就是这么做的知识库文档入库时除了生成向量还提取了文档的标题、章节、生效日期、适用部门这些结构化字段。检索时先按用户所属部门和当前日期过滤再取相似度最高的几条。准确率比纯向量检索提升了不少而且响应更稳定。3.2 用“问题类型”反推需要什么信息不同类型的用户问题需要的信息类型是不一样的。把问题分类然后针对每类问题设计不同的检索策略比一套策略打天下要有效得多。问题类型典型问法需要的信息检索策略事实查询“年假有多少天”具体数值、条款精确匹配条款定位流程咨询“怎么申请调休”步骤、条件、入口流程文档操作指引对比判断“A方案和B方案哪个好”双方优缺点、适用场景多文档对比结构化呈现故障排查“提交失败怎么办”错误原因、解决步骤FAQ排查清单开放建议“怎么优化这个流程”背景、约束、最佳实践多源综合案例参考这张表不是理论分类而是从实际用户提问日志里归纳出来的。有了这个分类检索时就可以根据问题类型走不同的管道。比如事实查询优先走精确匹配流程咨询优先走步骤类文档对比判断则需要同时拉取多个来源并做结构化整理。3.3 时效性和权威性容易被忽略的筛选维度在知识密集型场景里信息的时效性和权威性往往比语义相关性更重要。一份三年前的流程文档即使语义上和当前问题高度匹配也可能已经失效。一份来自非官方渠道的解读即使说得头头是道也不如官方原文可靠。我的做法是在文档入库时就标注两个字段生效日期和来源等级。检索时如果用户没有特别说明要历史版本就默认只检索现行有效的文档如果多个来源都相关优先取来源等级高的。来源等级可以简单分为三级官方原文、官方解读、用户整理。官方原文优先级最高用户整理只在没有前两者时才使用。这个策略在合规、财务、人事这类场景里尤其重要。模型本身没有判断信息时效性的能力你给它什么它就信什么。如果上下文里混入了过期条款它很可能一本正经地给出错误答案而且语气还很自信。注意时效性过滤不是简单按日期排序。有些文档虽然旧但仍然是现行有效的比如多年未修订的基础制度。关键是看“是否被新文档替代”而不是“发布时间早晚”。实现上可以用一个“替代关系”字段来标记文档之间的版本关系。4. 结构组织同样的信息换个排法效果差很多4.1 给上下文加“路标”用结构化标记替代纯文本拼接很多人把检索到的文档片段直接拼接成一个长字符串塞进提示里片段之间没有任何分隔或标注。这种做法对模型很不友好因为模型需要自己判断“哪里是一段新内容”“这段内容来自哪个文档”“哪些是标题哪些是正文”。当片段多了之后模型很容易混淆来源把A文档的内容说成是B文档的。更好的做法是给每个片段加上明确的结构化标记。比如用XML风格的标签包裹每个片段并在标签属性里标注来源、类型、日期document source员工手册-2024版 typepolicy date2024-03-01 title差旅报销标准/title content 国内出差住宿标准一线城市不超过500元/晚 二线城市不超过400元/晚其他城市不超过300元/晚。 /content /document这种标记方式有几个好处模型能清楚知道每段内容的边界和来源当需要引用时可以准确说出“根据员工手册2024版”如果不同文档有冲突模型也能识别出来并提示用户。实测下来加了结构化标记之后模型引用错误来源的概率明显下降。4.2 顺序编排把最重要的放在开头还是结尾上下文里信息的排列顺序会影响模型的注意力分配。一般来说模型对开头和结尾的内容记得更牢中间部分容易被忽略。这个现象在长上下文里尤其明显。基于这个特点我在编排上下文时遵循一个原则最相关的放开头次相关的放结尾弱相关的放中间。如果只有少量片段就把最相关的放开头如果片段较多可以把最相关的放开头和结尾各一份如果内容允许重复中间放补充材料。另一个技巧是把“指令”放在最后。很多人习惯把系统提示放在最前面然后跟一堆文档最后才是用户问题。但实际测试中把关键指令比如“请只基于以上文档回答不要编造”放在文档之后、用户问题之前模型遵循指令的比例更高。因为模型在读完所有材料后紧接着看到指令更容易把指令和材料关联起来。4.3 用“摘要原文”两级结构控制信息密度当检索到的文档片段较长时直接全文塞进去会占用大量窗口而且很多细节对当前问题并不重要。这时候可以用“摘要原文”的两级结构先给一段简短的摘要让模型快速判断这段内容是否相关如果相关再提供原文细节。具体做法是在文档入库时同时生成摘要和原文两个版本。检索时先返回摘要模型根据摘要判断是否需要深入。如果需要再发起一次检索获取原文。这样既能控制单次上下文长度又能在需要时提供完整信息。不过这个方案会增加交互轮次适合对准确性要求高、对延迟不敏感的场景。如果追求单次响应速度可以简化为检索时直接返回原文但在原文前面加一句摘要作为“导读”帮助模型快速定位重点。5. 动态裁剪当信息量超出窗口时怎么取舍5.1 先算一笔账你的上下文预算花在哪了在动手裁剪之前先要清楚上下文窗口的“预算”是怎么分配的。以一次典型的问答请求为例上下文里通常包含这几部分系统提示、对话历史、检索文档、用户问题、输出预留。每一部分都占token加起来不能超过模型窗口上限。我习惯在项目里做一个简单的预算表每次请求前算一下各部分占了多少组成部分典型占比可压缩性系统提示5%-10%低但可以精简措辞对话历史10%-30%高可以摘要或截断检索文档40%-70%高可以筛选和裁剪用户问题1%-5%低输出预留10%-20%根据任务调整从这张表能看出来检索文档和对话历史是压缩空间最大的两块。系统提示虽然占比不高但如果写得过于冗长也可以精简。输出预留要根据任务类型调整如果是简短问答留10%就够如果是长文生成可能要留30%以上。5.2 对话历史的压缩摘要关键实体保留多轮对话里早期消息对当前任务的价值通常很低但完全丢弃又可能丢失重要背景。我的做法是保留最近N轮完整对话更早的对话压缩成一段摘要同时把对话中出现的关键实体人名、项目名、日期、数字单独提取出来保留。摘要的生成可以在对话轮次达到阈值时触发用模型自己来总结。摘要提示可以这样写“请用三句话总结以上对话的核心内容保留所有提到的具体名称、数字和结论。”这样得到的摘要既简短又保留了关键信息。关键实体提取可以用规则模型结合的方式。规则负责抓取明显的日期、金额、编号模型负责识别项目名、人名这类需要语义理解的内容。提取出来的实体以列表形式附在摘要后面确保模型不会因为摘要而丢失细节。5.3 文档裁剪的优先级规则从“必须保留”到“可以丢弃”当检索文档总量超出预算时需要按优先级裁剪。我通常按以下顺序决定取舍必须保留直接回答用户问题的核心条款或数据。这部分无论如何不能删。优先保留与核心内容直接相关的上下文比如条款的适用条件、例外情况。可以压缩背景介绍、历史沿革、相关但不直接的内容可以只保留摘要。可以丢弃与当前问题无关的章节、重复内容、格式说明。实现上可以给每个文档片段打一个“重要性分数”分数由检索相似度、来源等级、时效性加权计算。裁剪时从低分开始删直到总量回到预算内。如果删到“必须保留”级别仍然超预算那就说明单次请求装不下需要考虑分步处理先回答一部分再追问补充。提示裁剪时要注意保留文档的“边界信息”比如条款编号、章节标题。这些信息占不了几个token但能帮助模型理解内容的结构和来源。不要为了省token把标题都删了那样模型会失去判断依据。6. 验证与迭代怎么知道上下文工程做得好不好6.1 建立一个小型评测集20个问题就能看出问题上下文工程的优化不能凭感觉需要有一个可重复的评测方法。不需要一开始就搞几百条测试用例先准备20个左右有代表性的问题覆盖不同问题类型和难度就能发现大部分问题。评测集的构建可以从真实用户提问里采样也可以自己设计。每个问题标注好“期望答案要点”比如应该包含哪些关键信息、不应该包含哪些错误信息。然后每次调整上下文策略后跑一遍评测集对比准确率、引用正确率、响应时间这几个指标。我自己的评测集里有一类“陷阱题”特别有用问题本身有歧义或者知识库里有多个相似但不同的条款。这类问题最能检验上下文筛选是否精准。如果模型能正确区分并给出针对性回答说明筛选策略是有效的。6.2 看模型的“引用行为”判断上下文质量除了看最终答案对不对还可以观察模型在回答中如何引用上下文。如果模型频繁引用不相关的文档或者把多个文档的内容混在一起说说明上下文组织有问题。如果模型能准确说出“根据XX文档第X条”说明结构化标记起了作用。具体可以统计几个指标引用来源的准确率模型说的来源和实际来源是否一致、引用覆盖率该引用的地方有没有引用、混淆率是否把不同文档的内容搞混。这些指标比单纯的答案准确率更能反映上下文工程的质量。6.3 迭代节奏每次只改一个变量上下文工程涉及的因素很多筛选策略、排序方式、标记格式、裁剪规则任何一个改动都可能影响效果。如果一次改多个地方出了问题很难定位原因。我的习惯是每次只改一个变量跑完评测集确认效果后再改下一个。比如这一轮只调整文档排序方式其他都不动下一轮只调整摘要长度其他不动。这样虽然慢一点但每一步的效果都清晰可归因。积累下来你会对自己场景下“什么策略有效”有非常具体的认知而不是停留在模糊的感觉上。7. 几个实际项目里踩过的坑和对应解法7.1 坑一检索回来的文档“看起来相关”但答非所问早期做知识问答时经常遇到检索结果语义相似度很高但模型就是答不到点子上。排查后发现问题出在文档切分粒度上。当时按固定长度切分文档导致一个完整的条款被切成两半检索到的片段只有前半句缺少关键条件。解法是改用语义切分按文档的自然结构章节、条款、段落切分保证每个片段是一个完整的意思单元。如果某个段落太长再按句子边界切分但绝不从中间切断。切分后给每个片段加上所属章节的标题作为“上下文头”这样即使片段本身不完整模型也能通过标题理解它的位置和含义。7.2 坑二多轮对话里模型“忘记”了早期设定的约束在多轮对话场景中用户在第一轮说了“只考虑国内航班”但聊到第五轮时模型开始推荐国际航班。这是因为早期对话被压缩或截断后约束条件丢失了。解法是在对话层维护一个“活跃约束”列表把用户明确提出的限制条件范围、格式、偏好单独记录下来每轮都附加在上下文里。这个列表不参与摘要压缩始终完整保留。同时当用户提出新约束时更新这个列表当用户明确取消某个约束时从列表中移除。这样模型每轮都能看到当前生效的所有约束不会因为对话变长而遗忘。7.3 坑三上下文里的“噪声”导致模型过度保守有一段时间我在上下文里加了大量“安全提示”比如“如果不确定请说不知道”“不要编造信息”。本意是减少幻觉但实际效果是模型变得过于保守明明文档里有明确答案它也说“根据现有信息无法确定”。后来我把这些全局性的安全提示从系统层移到了任务层并且改成更具体的表述“如果以下文档中包含答案请直接引用如果文档中确实没有再说明无法确定。”这样模型会先尝试从文档中找答案而不是一上来就进入防御模式。同时把安全提示放在文档之后而不是之前也减少了它对模型阅读文档的干扰。7.4 坑四不同来源的文档格式差异导致解析混乱知识库里的文档来源多样有Markdown、PDF转换的文本、网页抓取的内容格式各不相同。直接拼接后模型经常把不同格式的标记搞混比如把PDF的页眉页脚当成正文。解法是在入库阶段做统一的格式清洗去掉页眉页脚、统一标题层级标记、把表格转换成Markdown表格、把列表统一成无序列表。清洗后再做切分和向量化。这一步虽然繁琐但一次做好后续所有检索都受益。格式统一之后模型对内容结构的理解明显更准确引用也更规范。8. 写在最后上下文工程是一种“信息策展”思维做了几个项目之后我越来越觉得上下文工程本质上是一种“策展”工作。你不是在简单地传递信息而是在为模型策划一场信息体验哪些内容先出现、哪些内容重点标注、哪些内容需要对比呈现、哪些内容可以略过。好的策展能让观众模型在有限的时间里获得最有效的认知差的策展则是把一堆东西堆在面前让观众自己挑。这个思维转变之后很多决策就变得清晰了。每次构建上下文时我会问自己如果我是模型看到这些内容能不能在第一时间找到回答问题的关键有没有什么信息会让我分心来源和时效性我能不能判断把这些问题的答案落实到具体的筛选、排序、标记、裁剪操作上上下文质量自然就上去了。最后分享一个我一直在用的小技巧在上下文的最末尾加一句“请基于以上内容回答如果以上内容不足以回答请明确指出缺少什么信息”。这句话有两个作用一是提醒模型聚焦当前材料二是当材料确实不足时模型会告诉你缺什么而不是硬编一个答案。这个反馈对后续优化检索策略非常有价值。