上下文工程实战:从提示词优化到信息架构的完整指南 1. 上下文工程到底在解决什么问题第一次听到“上下文工程”这个词很多人会下意识觉得它只是“提示词优化”换了个马甲。但真上手做过几个基于大模型的应用之后你会发现这两件事根本不在一个层面上。提示词优化关注的是“这一句话怎么写才让模型答得更好”而上下文工程关注的是“模型在生成这一句话之前它的脑子里到底被塞进了哪些信息、这些信息以什么顺序排列、哪些该留哪些该丢”。前者是遣词造句后者是信息架构。我打个生活化的比方。你去医院看病如果医生只看到你走进诊室那一秒的状态没有你的既往病史、没有最近的化验单、不知道你对什么药过敏他大概率只能给你开点缓解症状的药。但如果护士提前把你的病历、过敏史、最近三个月的用药记录整理好放在桌上医生一眼扫过去判断的准确率完全不是一个量级。上下文工程干的就是这个“整理病历”的活——它决定了模型在回答你之前手里握着多少有效信息。这件事之所以在最近被反复提起是因为大家逐渐意识到一个残酷的事实模型本身的能力上限在训练完成那一刻就基本锁死了。你能调的只有喂给它的上下文。同一个模型上下文组织得好它能像个资深专家组织得烂它就是个只会说车轱辘话的复读机。这个差距在实际项目里往往是“能用”和“不能用”的区别。那上下文工程具体适合谁来学我的判断是三类人。第一类是正在做AI应用开发的工程师你迟早会遇到“模型明明很强但回答就是不对”的场景这时候问题八成出在上下文上。第二类是产品经理和业务负责人你需要理解为什么有些AI功能做出来效果差不是模型不行而是信息没喂对。第三类是对AI有深度使用需求的个人比如用它做知识管理、做内容创作、做数据分析上下文工程能让你把同一个工具用出完全不同的效果。2. 上下文工程的核心构成与设计逻辑2.1 上下文不等于提示词它是一套信息编排系统很多人把上下文工程等同于“写一个好的prompt”这个理解偏差会导致你在实际项目中反复碰壁。提示词只是上下文的一个组成部分而且往往不是最重要的那部分。一个完整的上下文通常包含以下几个层次的信息系统指令层定义模型的角色、行为边界、输出格式要求。这部分是“宪法”一旦确定就不应该频繁变动。任务描述层当前这一轮对话要解决的具体问题。这部分是“案由”每轮都在变。背景知识层模型回答问题所需的事实性信息、领域知识、历史数据。这部分是“证据”决定了回答的质量上限。对话历史层之前几轮交互的内容。这部分是“庭审记录”需要策略性地保留或丢弃。示例层给模型看的输入输出范例。这部分是“判例”用得好能极大提升输出稳定性。这五层信息不是简单堆在一起就完事了。它们的排列顺序、详略程度、相互之间的引用关系都会影响最终输出。我见过太多项目背景知识写得非常详尽但系统指令里没有明确告诉模型“优先使用背景知识而不是你的训练数据”结果模型还是按自己的老一套回答背景知识等于白放。2.2 为什么信息越多反而效果越差这是上下文工程里最反直觉的一个点。新手最容易犯的错误就是“把所有能想到的信息都塞进去”觉得信息越全模型答得越好。但实际情况是当上下文超过一定长度后模型的表现会明显下降。这个现象在业内被称为“上下文稀释”。原因有两个层面。从技术层面看模型处理长上下文时注意力机制会被分散到大量无关信息上真正关键的那几条信息反而得不到足够的关注权重。从信息论层面看无关信息本身就是噪声噪声越多信噪比越低模型提取有效信号的难度就越大。我做过一个对比实验同一个问答任务一组上下文只放最相关的三段资料另一组放了二十段资料其中十七段是弱相关的。结果第一组的回答准确率是第二组的两倍多。这个差距在需要精确引用数据的场景下更加明显。所以上下文工程的核心不是“加信息”而是“做减法”。你要像一个严格的编辑每一段放进上下文的信息都要能回答一个问题“如果删掉它模型的回答会变差吗”如果答案是“不会”那就删掉。2.3 上下文的顺序为什么比内容还重要同样一组信息换个排列顺序模型的输出可能完全不同。这不是玄学而是有明确的机制在起作用。模型对上下文的开头和结尾部分关注度最高中间部分容易被忽略这个现象被称为“位置偏差”。基于这个特性上下文工程里有一条黄金法则最重要的信息放在开头或结尾次要信息放中间。具体来说系统指令和核心约束放最前面当前任务描述紧随其后然后是背景知识最后在结尾处再强调一次关键要求。这样模型在生成回答时开头和结尾的强信号能形成呼应中间即使有些信息被忽略也不影响核心任务的完成。还有一个实操技巧是“锚点重复”。如果你有一个绝对不能违反的约束比如“回答必须用中文”或者“不能编造数据”那就在系统指令里写一遍在任务描述里再提一次在结尾处再强调一次。三次重复听起来很啰嗦但实测下来模型遵守约束的概率会从六七成提升到九成以上。3. 上下文工程在实际项目中的落地方法3.1 从零搭建一套上下文模板的完整流程假设你现在要做一个基于大模型的客服问答系统需要处理用户关于产品使用的各种问题。下面是我在实际项目中总结出来的一套搭建流程你可以直接参考。第一步定义系统指令的骨架。这部分要回答三个问题模型扮演什么角色、必须遵守什么规则、输出格式是什么样。我通常会写成这样你是一个产品技术支持助手负责回答用户关于产品功能和使用方法的问题。 规则 1. 只基于提供的知识库内容回答不要使用你自己的训练数据 2. 如果知识库中没有相关信息直接告诉用户“这个问题我暂时没有找到答案”不要编造 3. 回答要简洁控制在200字以内 4. 如果用户的问题涉及多个方面分点回答 输出格式 - 先给出一句话的直接答案 - 如果需要详细说明另起一段展开第二步设计知识库的检索和注入逻辑。用户提问后你不能把整个知识库都塞进去而是要先做检索找出最相关的几条。检索策略我一般用“关键词匹配语义相似度”双路召回然后取交集或并集。具体来说先用关键词快速筛出一批候选再用向量相似度排序取Top 3到Top 5条注入上下文。第三步处理对话历史。多轮对话中历史记录不能无限累积。我的做法是保留最近三轮的完整对话更早的对话只保留用户问题的摘要。摘要用模型自己生成控制在50字以内。这样既保留了上下文连贯性又不会让历史记录占用太多空间。第四步设置兜底机制。无论上下文设计得多好总会有模型答不上来的时候。这时候要有一个明确的兜底回复并且记录下这些问题用于后续优化知识库。3.2 参数选择背后的计算逻辑上下文窗口的大小是有限的不同模型的窗口大小不一样从几千token到几十万token都有。但窗口大不代表你可以随便用因为token是要花钱的而且窗口越大推理越慢。我一般会按这个比例来分配token预算系统指令占10%任务描述占5%背景知识占60%对话历史占20%输出预留占5%。举个例子如果模型窗口是8000 token那背景知识大概能分到4800 token按中文平均1.5字/token算大概是7200字的知识内容。这个量级足够放三到五段详细的产品说明。如果你发现背景知识经常超预算有两个解决思路。一是优化检索精度只取最相关的两条而不是五条。二是对知识内容做预处理把长文档拆成短段落每段独立检索只注入最相关的段落而不是整篇文档。3.3 一个完整的上下文组装示例下面是我在一个知识问答项目中实际使用的上下文组装代码逻辑用伪代码展示def build_context(user_query, knowledge_base, chat_history): # 1. 系统指令 system_prompt 你是一个知识问答助手。规则 - 只基于下方提供的参考资料回答 - 参考资料中没有的内容回答“暂无相关信息” - 回答控制在150字以内 # 2. 检索相关知识 relevant_docs retrieve(knowledge_base, user_query, top_k3) knowledge_text \n---\n.join([doc.content for doc in relevant_docs]) # 3. 处理对话历史保留最近三轮 recent_history chat_history[-3:] history_text format_history(recent_history) # 4. 组装完整上下文 context f{system_prompt} 【参考资料】 {knowledge_text} 【对话历史】 {history_text} 【当前问题】 {user_query} 请基于以上参考资料回答当前问题。如果参考资料中没有相关信息请直接说明。 return context这个模板看起来简单但每一部分的顺序和措辞都是经过反复调试的。比如“参考资料”放在“对话历史”前面是因为参考资料更重要“当前问题”放在最后是因为模型对结尾部分的关注度最高把问题放在这里能提升回答的相关性。4. 上下文工程中最容易踩的坑与排查方法4.1 模型不按指令走的五种典型情况这是被问得最多的问题“我明明在系统指令里写了规则为什么模型就是不遵守”根据我的排查经验原因通常出在以下几个方面。第一种指令太抽象。“回答要专业”这种指令等于没写模型不知道什么叫专业。要改成“使用行业术语避免口语化表达每个回答至少包含一个具体数据或案例”。第二种指令之间有冲突。比如系统指令说“回答要详细”任务描述说“简洁回答”模型就会无所适从。排查方法是把所有指令列出来逐条检查有没有互相矛盾的。第三种指令被后续内容淹没。如果系统指令后面跟了很长的背景知识模型可能会“忘记”前面的指令。解决方法是在背景知识之后再重复一次关键指令。第四种指令格式不清晰。把规则混在一段话里模型容易漏掉。用编号列表把规则一条条列出来遵守率会明显提升。第五种模型能力确实不够。有些复杂约束小模型就是理解不了。这时候要么换更大的模型要么把复杂约束拆解成多个简单步骤。4.2 上下文长度超限的应急处理方案当你发现组装好的上下文超过了模型窗口限制不要慌按这个优先级来删减优先级处理对象处理方式影响程度1对话历史只保留最近一轮低2背景知识减少检索条数从5条减到2条中3背景知识对长文档做摘要压缩中4示例层删除所有示例中高5系统指令合并相似规则精简措辞高6任务描述无法删减极高核心原则是系统指令和任务描述是底线不能动对话历史和示例是可以牺牲的背景知识优先做压缩而不是删除。4.3 排查上下文问题的系统化方法当你遇到“模型回答不对”的问题时不要凭感觉猜按这个流程一步步排查打印完整上下文把实际发给模型的上下文原封不动打印出来肉眼检查有没有明显问题比如信息缺失、格式错乱、指令矛盾。做消融测试逐段删除上下文内容看模型回答的变化。如果删掉某段后回答变差了说明那段是有效的如果删掉后没变化说明那段是冗余的。换模型对比同一个上下文发给不同模型看是不是模型本身的问题。简化任务把复杂任务拆成多个简单任务每个任务单独设计上下文看问题出在哪一步。检查检索质量如果是RAG场景先确认检索出来的内容是不是真的相关。很多时候问题不在上下文组装而在检索环节就没找对资料。提示排查时一定要用固定的测试用例不要每次换不同的问题。固定用例才能对比出上下文改动带来的实际影响。4.4 几个反直觉的实操心得心得一少即是多。我做过一个实验把背景知识从五条减到两条回答准确率反而提升了15%。原因是剩下的两条是真正相关的模型不用在五条里分辨哪条有用。心得二格式比内容更容易被忽略。你精心准备的知识内容模型可能只用了七成但你规定的输出格式模型几乎百分百遵守。所以如果你对输出结构有要求一定要在系统指令里写清楚并且给一个格式示例。心得三否定指令不如肯定指令。“不要编造数据”不如“只使用参考资料中的数据”。模型对“不要做什么”的执行力远低于“要做什么”。心得四上下文工程是迭代出来的不是设计出来的。没有人能一次写出完美的上下文模板。我的做法是先写一个能用的版本然后收集bad case每遇到一个bad case就调整一次上下文迭代十几次之后才能达到稳定可用的状态。5. 上下文工程的能力边界与进阶方向5.1 什么情况下上下文工程救不了你上下文工程很重要但它不是万能的。有几种情况你再怎么优化上下文也无济于事。第一种是模型本身不具备某项能力。比如你让一个没有数学推理能力的模型做复杂计算上下文写得再好它也算不对。这时候需要换模型或者引入外部计算工具。第二种是信息本身就不存在。如果知识库里根本没有相关内容检索不出来上下文里自然就没有模型只能编造或者拒答。这时候要解决的是知识库覆盖度问题不是上下文工程问题。第三种是任务本身定义不清。如果连人都说不清楚这个任务要做什么那也没法给模型写清楚指令。这时候要先做任务拆解和定义再考虑上下文设计。认清这些边界很重要能让你在遇到问题时快速定位是哪个环节出了问题而不是在上下文工程这一棵树上吊死。5.2 从单轮上下文到多轮状态管理单轮问答的上下文相对简单但真实项目往往是多轮交互。多轮场景下上下文工程就升级成了“状态管理”问题。你需要跟踪用户在对话过程中透露的所有信息并在合适的时机把这些信息注入上下文。我常用的做法是维护一个“用户状态字典”记录用户已经提供的关键信息比如产品型号、使用场景、遇到的问题类型等。每一轮对话时把这个字典的内容作为背景知识的一部分注入。这样即使用户在第五轮才提到“我用的是专业版”模型也能结合前面几轮的信息给出针对性的回答。状态管理的难点在于“什么时候该更新状态”和“什么时候该清除状态”。我的经验是用户明确提供的新信息立即更新用户没有提到的信息保持不动对话主题发生明显切换时清除与旧主题相关的状态。5.3 上下文工程的自动化与工具化思路手动组装上下文在项目初期是可行的但当你的应用需要处理成百上千种不同场景时手动方式就不可持续了。这时候需要考虑自动化和工具化。一个可行的思路是建立“上下文模板库”把常见场景的上下文模板沉淀下来每个模板包含固定的系统指令和可变的背景知识占位符。运行时根据用户问题的类型自动匹配最合适的模板然后填充背景知识。更进一步的做法是引入“上下文编排引擎”用规则或模型来决定每一轮对话应该注入哪些信息、以什么顺序注入。这个引擎的输入是用户问题、对话历史、用户状态输出是组装好的完整上下文。这已经是一个独立的工程问题了需要专门的开发和调试。5.4 上下文工程的评估体系怎么建没有评估就没有优化。上下文工程的效果评估我一般从三个维度来做。准确性维度模型回答是否基于提供的上下文有没有编造信息。这个可以用人工抽检或者用另一个模型来做自动评估。相关性维度回答是否切题有没有答非所问。这个可以通过对比问题和回答的关键词重合度来粗略评估。一致性维度同一个问题在不同时间问回答是否一致。这个对于客服类应用特别重要回答忽左忽右会让用户失去信任。评估数据集要覆盖典型场景和边界场景每个场景至少准备二十个测试用例。每次调整上下文模板后跑一遍完整评估集对比各项指标的变化。这个过程很枯燥但它是把上下文工程从“手艺”变成“工程”的关键一步。6. 我个人在上下文工程实践中的几点体会做了这么多项目我最大的体会是上下文工程本质上是一种“信息策展”能力。你就像一个博物馆的策展人手里有一堆展品信息但展厅空间上下文窗口有限观众模型的注意力也有限。你的任务不是把所有展品都摆出来而是挑选最合适的几件放在最合适的位置配上最合适的说明文字让观众在最短时间内获得最好的体验。另一个体会是上下文工程没有“最优解”只有“当前场景下的最适解”。同一个任务换个模型、换个数据源、换个用户群体最优的上下文设计可能完全不同。所以不要迷信任何模板包括我上面写的那些。把模板当作起点根据实际效果不断调整才是正确的做法。最后分享一个我常用的调试技巧当你觉得上下文已经写得很好了但效果还是不理想时试着把上下文读给一个不了解这个项目的人听让他根据上下文回答用户的问题。如果他答不对那模型大概率也答不对。这个“人肉测试”能帮你快速发现上下文中的逻辑漏洞和信息缺失。上下文工程这个领域还在快速演进新的模型能力、新的工具、新的方法论层出不穷。但核心原则是不变的在正确的时间把正确的信息以正确的方式交给模型。把这句话刻在脑子里比记住任何具体技巧都管用。