1. 为什么 Prompt 写了一大堆模型还是听不懂人话1.1 一次让人抓狂的“长指令”实验先讲一个我亲眼见过的场景估计很多人也遇到过。当时某个内部工具项目组要做“客户资料清洗”把不同渠道的零散对话整理成标准表格。同事A为了保险给模型写了一套“两页纸”的Prompt先解释这个行业里客户说的是什么意思然后列了十条注意事项再写上“请认真分析”“不要遗漏字段”这种话。结果呢模型反而开始自由发挥该填的字段漏掉备注格式每次都不一样甚至把一些模棱两可的信息直接当事实写进去。后来我接手把两页纸砍成了三行背景加两个“输入-输出”示例准确率反而上来了。原因说起来很简单大语言模型在接收上下文时不是“一条一条读指令”的它像一个在暗房里猜你意图的人。你给的信息越多、越杂乱它越不知道该以哪条为准。这件事给我的触动很大——原来“让 Prompt 更好用”的重点根本不是把话说得更满而是把上下文安排得更聪明。1.2 模型不是“读”指令而是“在上下文中猜”要搞清楚上下文工程先得接受一个底层现实主流大语言模型的本质是“根据已有的全部输入预测下一个该出现的词”。它没有专门理解“这条是命令、那条是背景”的独立模块。系统设定、用户消息、参考资料、历史对话在模型眼里都是同一串字符流的一部分。这意味着什么意味着模型的输出质量取决于整个上下文的信息密度、信息一致性和信息位置而不是某一句“咒语”写得多精妙。你告诉它“不要胡说八道”但如果参考资料的几段话里本身就矛盾百出模型大概率会选择其中之一当作事实。你要求它“务必简洁”但示例里的每个回答都是三百字起跳它也会很自然地学着绕。这就是为什么很多人抱怨“我明明写得清清楚楚它就是不听话”——你的指令可能真的很清楚但你放进上下文的那些其他内容把信号冲淡了。我用一个生活类比解释你让一个刚入职的新人去做一份报表给他一个装着三十页流程手册的资料夹和给他“这是你要统计的字段、这是两个已经做好的例子、这是数据源”这样一套精简材料哪个更容易上手显然是后者。Prompt 只是指令上下文才是他工作的全部环境。1.3 从 Prompt 到上下文工程称呼变化的背后最近业内越来越多人在讨论“上下文工程”而不是单纯说“写好 Prompt”。我觉得这个转变很自然。Prompt 时代大家更关注“怎么组织一句话”上下文工程则把视野放大到“怎么组织一次完整输入”。它关心的是四件事放什么信息信息放在哪一层信息以什么形式出现信息按什么顺序排列。上下文工程之所以重要是因为现在大模型应用早就不是“问一个问题拿一个答案”那么简单了。做客服助手、写代码辅助工具、跑文档分析每次调用都要往模型里塞一大包东西。谁把这一包东西塞得合理谁就能把模型能力压榨到极限。接下来几节我会从最基本的上下文成分讲起最后落到一套可以直接抄走的模板和调优方法。2. 上下文工程的基本盘搞清楚每次请求里到底塞了什么2.1 上下文里到底可以放什么很多人以为上下文就是“对话里说过的所有话”其实不是。一次请求的上下文通常由五种成分组成系统设定、当前指令、参考资料、示例、对话历史。它们是可拆开的只是很多人在使用时把它们混在了一起。成分典型内容放错位置的常见后果系统设定角色定位、全局规则、语气要求模型把它当成需要执行的任务反而忽略当前真实需求当前指令本次任务、目标、约束条件如果夹在资料里模型会认为它只是参考信息参考资料文档原文、知识片段、背景事实内容过于冗余模型注意力被分散关键信息被淹没示例输入输出对、判断示范示例质量差会把整体行为带偏对话历史前几轮的问答、用户偏好历史里的错误答案被继续模仿错误滚雪球我在实际拆解中最大的感受是大多数人并没有“分层”意识。他们会把系统设定写成一大段小作文把当前指令塞在资料中间又随手丢两个示例。结果就是模型看什么都有用于是什么都信一点、什么又都没执行到位。2.2 每一种上下文成分的正确姿势和翻车现场先说系统设定。它应该是整个上下文里最稳定的部分适合放那些“每次请求都成立”的全局规则比如“你是客服助手”“不要编造事实”“回答控制在300字以内”。它不适合放临时任务因为临时任务一变这里的旧内容就会形成干扰。我见过一个项目把“本次要统计的数据范围”写进了系统设定结果下一轮任务已经换了主题模型还在按旧范围回答。当前指令则是每一次请求真正想干的事。它应该短、具体、动作明确比如“从下面资料里找出所有售后条款并按时间排序”。翻车现场通常是这样的指令里同时出现“先总结背景”“再给出建议”“不要总结背景只要建议”自相矛盾模型只能随缘执行。参考资料是最容易失控的部分。许多人习惯把整篇文档原封不动丢进去觉得“多给一点总没错”。但模型不是无限吸收的海绵它更像一个注意力有限的学生资料里 90% 都是无关内容时那 10% 的关键信息就会漏掉。对待参考资料的正确做法是先问自己模型回答这个问题到底需要哪几段事实只留下这些其他删掉。示例的问题则在于质量。一个坏示例比没有示例更可怕。比如你的任务是要模型判断“这段对话是否包含售后诉求”结果示例里给了一个模糊案例模型就会学着模糊判断。后面我会专门讲示例怎么选。2.3 先给上下文做结构分层这里我给一个简单实用的思路别把上下文当作文来写把它当成给模型的一张“信息结构图”。系统设定是导航栏告诉模型“你是谁、边界在哪”当前指令是任务单告诉模型“这一轮要干什么”参考资料是资料卡示例是案例集对话历史是操作记录。每一块都有自己的功能不要混着写。我在实际构建时会用明确的标签把块分段比如“【系统设定】”“【当前任务】”“【提供资料】”。这样做有两个好处一是在人工阅读和调整时更清晰二是模型在训练阶段就见过大量带标签的结构化文本它更容易理解“标签后面的内容属于特定职责”。这不算是玄学更像是信息编排上的“界面设计”。当你把上下文拆成了清楚的分层后面遇到问题也会好查很多。输出偏了你能一眼看出是哪个块出了问题而不是对着一段大杂烩无从下嘴。下一节我会给出一套完整的模板你可以在自己的项目里直接改着用。3. 手把手搭一套能复用的上下文工程模板3.1 一个可以直接抄的模板结构下面是我现在构建上下文时最常用的模板结构已经用了很久。它不复杂但每一块都有明确作用。【系统设定】 你是XXX负责XXX。 回答问题遵循以下规则 1. ... 2. ... 【背景信息】 - 当前场景... - 目标用户... - 需要满足的特殊约束... 【当前任务】 一句话写清楚要模型做什么。 【提供资料】 - 资料1... - 资料2... 【输出要求】 - 输出格式... - 内容范围... - 引用方式... 【示例】 输入... 输出...别小看这些方括号标签。它们等于在给模型划“工作区域”让它能快速定位每一段文字的角色。相比你把所有内容堆成几大段标签式的结构会明显降低误读概率尤其是当上下文很长时。3.2 实战案例做一个资料问答助手拿最常见的“文档问答”来演示。假设你要做的是一个产品说明手册问答助手目标是让用户提问题模型根据手册内容回答。系统设定我会写成【系统设定】 你是某产品线的客服知识助手。 你只能根据【提供资料】中的内容回答用户问题。 资料中没有提到的信息必须明确回答“手册中未找到相关内容”禁止自行推测。背景信息写什么写用户最常见的提问场景帮助模型理解提问角度比如“用户可能是刚收到产品的新手也可能是有一定经验的老用户问题可能涉及安装、配置、售后”。当前任务则可以每次请求动态生成比如“请根据手册内容回答用户关于设备无法联网的问题”。提供资料这里不能把整本手册都扔进去。我会提前把和“联网设置”相关的章节提取出来只放这一部分。输出要求写“先给出结论再给出操作步骤每条操作前标注手册页码总字数不超过300字”。最后放两个示例。一个给出良好回答一个给出生硬照搬资料的反面回答。这样模型就同时知道“应该怎么回答”和“不应该怎么回答”。整体构建好之后你会发现模型的稳定性比单纯写“请你仔细根据手册回答”要好得多。3.3 模板字段的填写要点和常见错误有几个字段特别容易填错我挑重点说。系统设定不要写成长篇角色故事。“你是温柔耐心的客服语气亲切会站在用户角度思考……”这种话不是没用但优先级远低于“必须根据资料回答”。系统设定更像是规则宪法三五句足矣说多了反而稀释重点。当前任务必须独立成块。不要把它藏到背景信息或者资料里。模型需要快速识别这一轮的真正指令如果你把任务写成背景说明的一部分它会以为你只是在提供语境而不是在要求它干活。输出要求要尽量可验证。与其写“请认真回答”“保证质量”不如写“结论在前、步骤在后”“每条信息必须对应资料中的原文页码”“不要输出表格”。能被自动检查的要求才是好要求。示例放在最后挨着用户输入的位置。原因是示例离问题越近影响越直接。如果你把示例提到最前面模型会把它当成背景的一部分行为约束力会下降。我见过最普遍的错误是系统设定和当前任务重复。系统设定已经写了“必须使用资料回答”当前任务又写一遍“请务必根据资料回答不要自己编”结果模型把重复信息当成了两条不同规则行为反而变得忽左忽右。记住上下文里的相同意思只保留一处重复不是强调而是制造矛盾。4. 塞不下的内容怎么处理长上下文的压缩与分层策略4.1 上下文窗口是资源不是仓库很多模型有越来越大的上下文窗口于是大家的思路变成了“反正装得下就全塞进去”。这个思路很危险。上下文窗口更像电脑内存而不是硬盘。你塞进去的内容每次请求都会参与计算所以会带来三个直接后果费用随 token 上涨响应速度变慢信息一旦过多模型的注意力会被噪声分散关键信息反而更容易被忽略。我自己做过一次对比同一个文档问答任务完整文档塞进去的效果居然不如只塞一个“精简摘要关键结论”。完整文档里有大量相互矛盾的解释和冗余背景模型在判断时反而拿不准。所以上下文工程的一个重要原则是能少给就少给够用就好。4.2 先压缩再塞把资料做成三级摘要面对长文档我的做法是把资料整理成三级摘要再决定往上下文里放哪一级。第一级是核心结论只留事实判断和最终结论第二级是支撑论据保留关键数据、对比、因果关系第三级才是原始原文或全文。多数问答任务只需要放第一级加第二级只有需要逐字核对时才把第三级放进去。具体操作上你可以先让模型自己完成压缩把一篇长文档丢给它让它提取要点、整理成结构化摘要再把这个摘要放到正式任务的上文里。这相当于用一次小成本调用换取后续多次请求的大幅瘦身。我实测下来三份产品手册压缩成摘要后效果不降token 开销却少了一半还多。当然压缩不是万能药。如果任务要求模型必须引用原文页码或者逐字比对条款摘要就不够用了。这时候要反过来做根据当前问题先定位相关章节只把对应章节原样放进上下文而不是把整本书都塞进去。这种“先检索后放资料”的方式是长文档场景里最有效的省上下文方法。4.3 对话历史的裁剪和摘要聊天类应用还有一个大头对话历史。如果不处理几十轮对话之后上下文会被旧内容占满。我的经验是对话历史要分三层处理。第一层是滑动窗口只保留最近几轮完整对话。因为用户最终的问题通常只依赖最近两三轮的信息。第二层是滚动摘要每几个回合之后把早期对话里的重要事实提炼成一段话放到上下文顶部。第三层是关键信息抽取把用户在这段对话里流露出的固定偏好单独记下来比如“用户喜欢简洁答案”“用户上次要求过用表格格式”。实际执行时我常用一种很轻量的做法给对话加一个“进程卡”字段。每轮交互以后模型先把新的关键信息同步到进程卡里然后下一轮请求带着“进程卡 最近几轮完整消息”一起送进去。这样既不会弄丢重要信息又可以随时把旧对话丢掉。长会话跑下来上下文体积能控制得非常稳定。5. 用示例做“隐形规则”少样本示例的选择与排布5.1 示例是给模型看的“标准答案示范”还是“推理范式”很多人以为示例就是“给正确答案让模型照着写”这其实只说对了一半。高质量示例真正起作用的是它暴露了从输入到输出之间“应该怎么做判断”的思考过程。举个例子。你让模型判断客服对话里有没有售后诉求。如果示例只写“输入用户说我充电器坏了。输出有售后诉求”模型学到的只是这一个具体案例。但如果示例写成“输入用户说我充电器坏了。输出有售后诉求因为用户提到了产品损坏且期望解决符合售后诉求的定义”模型就有机会学会你的判断标准。它能把“充电器坏了”这个具体内容泛化到“任何产品损坏抱怨”上。所以我在写示例时特别强调“输出里要能看到判断依据”而不是只给一个干巴巴的答案。判断依据不是要求模型每次都输出一大段解释而是借由示例内容把推理路径固定下来。5.2 示例怎么选、写几个、放哪里选示例要守住三条标准。第一和当前任务同分布你处理的是客服对话示例就放客服对话不要放新闻摘要。第二覆盖边界情况挑选那些容易混淆、容易踩坑的类型。第三好坏成对出现一个好示例配上一个典型坏示例模型会更快学会“不能那样做”。数量方面我常用的区间是 2 到 5 个。给太少模型找不到规律给太多边际收益明显下降反而占用上下文并增加模仿表面格式的风险。你很可能经历过这种情况给了模型一堆示例后它的输出开始机械地套用示例里的句式哪怕内容根本不相干。示例越多这种“格式锁死”就越严重。位置方面示例要放在当前提问之前作为最后一块铺垫。如果资源允许它还应该紧贴在输入下方中间不要夹一堆无关内容。因为离得越近对当前输出的约束力越强。5.3 位置效应模型对上下文不同位置的“偏心”现象位置效应是上下文工程里比较隐蔽、但非常影响结果的因素。模型在阅读长上下文时对开头和结尾的信息关注更高中间部分容易被“一带而过”。所以你在中间放一条重要规则很可能它是被看到了但没被足够重视。根据这个特性我会做三件事。第一最重要的规则放开头和结尾比如系统设定开头放“只能根据资料回答”输出要求结尾放“没有资料依据时明确说不知道”。第二参考资料这种密度高、但不算核心指令的内容放到中间区域。第三关键约束如果很重要可以在结尾用不同措辞再强调一次但绝不和开头原句完全一样。这样能做到“规则一致且重点被覆盖在容易被注意到的位置”。6. 上下文调优的验证闭环别靠感觉调参6.1 建立一个最小评测集上下文工程最大的坑是“感觉改了以后变好了”。一次两次对话看不出什么必须用固定输入集反复验证。我建议你建一个最小评测集不需要多二十到三十条典型输入就够。里面要包含正常问题、边界问题、容易误导模型的问题最好还有几条你已经踩过坑的真实案例。跑评测时我会给每条输出打三个维度内容是否正确、格式是否合规、是否有多余废话。三个维度都过才算这条合格。然后统计通过率。之后无论我怎么调整上下文都用同一套评测集跑前后对比才有意义。6.2 一次调优的完整流程示例调优的纪律是一次只改一个变量。假设我把评测集跑完发现一个问题当用户连续追问时模型会忘记最开始指定的输出格式。这时候我会做一个假设可能是系统设定里的规则被中间大量对话稀释了。于是我把格式要求同时追加到了当前任务的结尾保持其他内容完全不变重新跑评测集。看到结果后再判断这个改动是否有效。如果有效就留下来如果无效就换一个假设。这样一步步积累上下文会越改越稳。我特别提醒不要同时改系统设定、资料位置和示例内容然后看“整体效果好像变好了”。这种改进你根本不知道是哪一步起的作用下次调优时没有依据。6.3 最后分享一些我摔过跤的地方讲几句我自己的真实体会。第一上下文越长出错概率越高能用两百个 token 解决的问题就不要用八百个。第二把同一条规则换措辞写三遍不等于强调模型可能理解成三条不同的规则带来不稳定行为。第三示例是双刃剑复杂示例会诱导模型去模仿形式忘记你的核心任务。第四参考资料别偷懒直接贴原文压缩后再放效果通常更好。第五每次调整记一笔变更理由不然三天后你再看到那段上下文根本想不起来当时为什么要这么写。上下文工程没有一套包打天下的完美模板但它确实是有方法论的把信息拆成清楚的角色把重要规则放在容易被注意到的位置用示例演示判断路径再用一套固定评测集反复验证。做到这几步你会发现自己调 Prompt 不再是碰运气而是真正能把一个不听话的模型一点一点矫正到稳定状态。希望这篇手记能帮你省下一些试错的时间。