
1. 从“会问问题”到“会造上下文”Context Engineering到底在解决什么过去两年我花了不少时间帮团队搭建 AI 辅助开发的内部工具从最早的“把提示词写长一点”到后来折磨人的“为什么换个说法效果就崩了”再到真正开始系统性地设计 Prompt 的输入结构这中间踩过的坑几乎都能归结为一件事我们从来没把“上下文”当成一个正经的工程对象来管理。很多人以为 Context Engineering上下文工程只是提示工程换了个唬人的名字实际上差别挺大。提示工程的核心是“怎么写好一句话”上下文工程的核心是“怎么构造一小块完整的信息环境”。打个比方提示工程是教你怎么跟一个记忆力只有几分钟的实习生说清楚任务而上下文工程是决定给他一张什么样的便签、便签上写哪些内容、按什么顺序写、哪些内容绝不能写。同样一个人拿一张写满废话的便签和拿一张精准的结构化便签干出来的活完全是两个水平。我真正意识到这件事的价值是在一次客服场景的改造里。原先我们做了一套售后问答机器人提示词反复调效果始终不稳定。用户问“订单什么时候到”机器人有时候能答出来有时候却开始东拉西扯。后来我们把改造重心从“改提示词”挪到“重组上下文”把订单状态、物流接口、售后政策、历史对话摘要分区块地塞进 Prompt再给模型一个明确的阅读顺序和输出格式。效果立刻稳定下来准确率肉眼可见地提升。从那以后我越来越确信在模型能力基本固定的前提下上下文构造得好不好才是决定系统上限的关键。这篇文章就是围绕 Context Engineering 这套方法论来写的它到底是什么、核心操作有哪些、在真实项目里怎么落地、常见的坑长什么样。适合正在做大模型应用开发、做 AI Agent 或者被 Prompt 调优折磨得头疼的工程师。就算你不是技术背景看完也能理解为什么同样一个大模型不同的人用出来差别会那么大。2. 上下文工程的底层逻辑模型不是在“理解”而是在“回忆”2.1 大模型对上下文的处理方式更像“即时联想”要说清楚 Context Engineering 为什么有效得先理解大模型处理输入时的真实机制。很多人以为模型是在“读懂”Prompt实际上更准确地说模型是在做一种受上下文约束的联想生成。你给它什么内容它就在这个内容的范围内做最大概率的延续。这不是严格意义上的逻辑推理更像是一个人被提醒了某些信息之后顺着思路往下走。这个理解对工程实践极其重要。既然模型是“被上下文唤醒”的那么唤醒哪些信息、唤醒到什么程度、信息之间怎么排列就直接决定了输出的方向和质量。你不把关键信息塞到上下文里它就只能靠自己训练时留下的记忆来联想结果当然不可控。举个例子你问模型“帮我看看这段代码有没有问题”如果上下文中只贴了那段代码它多半只能给出泛泛而谈的建议。但如果你在上下文里写上“这段代码运行在嵌入式设备上RAM 只有 2KB主频 48MHz采用 C99 标准”模型的注意力会立刻被牵引到资源占用、内存分配、语法兼容这些具体问题上。同样一个请求上下文里的“触发器”不同输出完全两样。2.2 上下文工程的三个核心维度选择性、结构化、动态性把上下文当成工程对象来管理至少要关注三个维度这也是整个方法论的骨架。第一是选择性。上下文长度再大也是有限的模型能有效利用的信息更是远小于窗口上限。你塞进去 10 万字真正被模型“认真对待”的可能只有开头和结尾附近的几千字中间部分经常被稀释。所以上下文工程的第一个动作永远是做减法哪些信息必须进哪些可以压缩哪些干脆不要。第二是结构化。同样一段信息用一坨散文写在 Prompt 末尾和用清晰的区块、标签、格式说明组织好效果差距巨大。模型对结构的敏感度远超大多数人的直觉。结构化不只是为了好看而是在帮模型降低“找信息”的成本。第三是动态性。上下文不是静态的定稿而应该随着对话轮次、任务阶段、实时数据不断更新。比如客服场景里用户补了一句“其实我买的是另一款”那么之前填入的产品信息就必须被替换或标记为失效否则模型会继续基于错误信息作答。上下文工程本质上是给模型的每一次推理“重写便签”而不是写一张便签用到底。这三件事听起来不复杂做起来全是细节。后面我会拿真实场景一步步拆给你看。3. 先做架构再写内容上下文布局的标准步骤3.1 明确任务类型确定上下文清单我在实际项目里总结了一套流程第一步永远是问自己这个模型要完成的到底是一件什么性质的任务是分类、抽取、生成、总结还是做多轮决策任务类型决定了上下文的“信息需求清单”。比如做分类任务你需要的是类型定义、判断标准、示例对做抽取任务你需要的是目标字段说明、原文范围、边界约定做生成任务你需要的是风格参考、受众描述、禁忌列表做 Agent 决策任务你需要的是工具清单、可用动作、环境状态、历史轨迹。把这些清单列出来再逐项对比自己手里有什么数据就能发现上下文里缺什么、哪些是多余的。我为客服机器人列过一张典型的信息需求表信息区块用途说明必须包含用户当前问题触发模型响应的直接输入是用户历史摘要识别重复提问和前后矛盾视情况订单/商品数据提供个性化回答的事实依据是售后政策条款保证回答合规、有边界是对话输出格式规定回复结构是全量对话原文完整信息但噪声大否这张表不是一次性定死的每个项目都要根据自己的数据情况调整。但思路是一致的先把“模型要做什么”翻译成“模型要知道什么”再做筛选。3.2 上下文区块的排列顺序直接影响注意力分布确定了清单之后下一件重要的事是排序。大模型对 Prompt 不同位置的注意力权重是不一样的简单说就是“开头和结尾最容易被记住中间区域容易被忽视”。这个现象在长上下文场景里尤其明显业界常说的“lost in the middle”就是指中间信息容易被模型遗漏。所以我的布局习惯是把最关键的任务指令和当前问题放在最前面把需要严格遵守的输出格式放在最后面中间放支撑性的事实材料。这样一个 Prompt 的基本骨架就是“任务 材料 格式”。如果中间材料太多我还会在开头加一句“注意材料区包含不相关信息请依据任务相关性自行筛选”这句话能明显降低无关信息的干扰。另外每个区块之间最好用清晰的分隔标识。我常用的做法是-- 任务定义 -- 你是售后支持助手... -- 当前问题 -- 用户我的订单状态显示已签收但我没收到货 -- 订单信息 -- 订单号... ... -- 回答约束 -- 1. 语气友好不超过100字 2. 如果存在物流异常优先给出解决方案用这种显式的标签把不同信息分块模型就不用在杂乱的文本里自己找边界了。你不会把调度指令和现场报告混在一张纸上递给同事吧对模型也一样。3.3 用“上下文协议”统一多轮对话的状态管理单轮的 Prompt 设计只是基础真正体现 Context Engineering 价值的是多轮对话。每一轮用户输入之后上一轮的模型回答、用户新补充的信息、外部系统的返回结果都变成了下一轮的上下文素材。如果不做管理上下文会越来越臃肿模型会渐渐记不清最初的任务目标。我在项目中习惯定义一个“上下文协议”它是一个结构化的状态对象每次对话轮次结束后被更新下一轮开始前被序列化进 Prompt。比如一个简单的客服场景协议包含这些字段{ task_state: awaiting_shipping_info, user_intent: query_order_status, known_facts: { order_id: 20241001-8823, product: 无线降噪耳机 Pro, current_status: signed, user_claim: 未收到货 }, unresolved: [物流签收人与用户是否一致], history_summary: 用户前两轮提供了订单号并坚持未收到包裹, policy_hits: [已签收但未收到货时可申请物流核查] }然后把这个协议用固定模板渲染到下一轮的 Prompt 里。这比直接把对话原文全部堆进去干净得多模型每次只见它真正需要的“记忆碎片”而不是一段冗长的聊天记录。这套思路本质上就是在给模型做“工作记忆管理”跟人脑用一个便签本而不是靠背书来记事的逻辑是一样的。4. 实操复盘一个客服机器人的上下文重构全过程4.1 改造前的失败样本问题出在哪里前面提到的客服机器人我先还原一下改造前的 Prompt 长什么样。当时的做法是把所有资料一股脑写在系统提示里包括产品手册全文、售后政策原文、甚至公司简介然后让模型自由发挥。结果就是开头提到的不稳定回答的情感基调对但事实经常出错要么引用过期的政策要么忽略用户已经提供过的信息。这就是典型的“上下文没有工程化”的三个症状信息无分区、事实无更新、状态无管理。模型每次都像是在一个塞满文件的办公室里找东西找不到就自己编一个合理的答案。我们当时做了一个简单的小实验把同样的问题分别喂给三个不同版本的 Prompt——完整版、精简版、结构化分区版。完整版大约 2 万字精简版 3000 字分区版 3000 字但用了明确的区块标签。测试结果是完整版准确率最低精简版略好但依然不够分区版准确率最高而且回复风格更稳定。这个实验给了我一个很深刻的教训上下文不是越多越好信息的相关性和组织度才是关键。4.2 重构后的上下文模板可以直接抄作业下面这份是我后来整理出的通用客服上下文模板结构上可以直接套用到很多类似场景-- 角色定义 -- 你是XX品牌的售后客服助手名称小助。你的任务是在政策范围内解决用户问题。 -- 核心政策只许引用不许编造 -- 1. 未收到货先核实物流签收信息如果显示签收但用户未收到可发起物流核查。 2. 质量问题用户在签收后7天内可申请换货或退货。 每条政策都带编号方便在回答中引用 -- 用户当前问题 -- {用户最新输入} -- 已知事实来自历史/系统 -- 订单号{order_id} 商品{product_name} 状态{status} 用户备注{notes} -- 当前状态 -- 上一轮是否给出了承诺{yes/no} 是否有待办事项{todo|无} -- 回答要求 -- - 先判断问题所属的政策类别再回答 - 如果信息不足只问最必要的一个问题 - 回答不超过100字不编造政策这个模板里最关键的一点是“核心政策只许引用不许编造”。等于给模型划了一条硬边界虽然它本质上是概率生成但有了这样一条指令加上政策用编号标注模型在输出时就更倾向于从给定内容里摘取而不是自由发挥。实践下来编造条款的比例明显下降。4.3 动态更新别让“过期事实”留在上下文里上下文工程还有一个容易被忽略的点同一段信息在不同时间点可能有效也可能失效必须设计更新机制。我们的做法是给每个事实字段加一个置信度和时间戳在每次对话轮次结束后重新评估。比如用户一开始说“我买了黑色款”下一轮又说“查了一下其实我买的是白色款”那上下文里绝不能同时出现两条冲突信息。我们的协议更新逻辑会把旧的“黑色款”替换成“白色款”并在 known_facts 里加一条备注“用户自述颜色已更正以白色为准”。如果没有这个机制模型在多轮对话里就会陷入事实混乱有时候甚至自己跟自己打架。动态更新做起来不复杂关键是得有这个意识。很多人做 Agent 应用上下文的更新逻辑完全靠着 Prompt 里一句“请记住用户刚才说的内容”来实现这在小规模场景下勉强可用但一旦对话变长、事实变多模型根本记不住。用外部代码维护一份准确的状态再序列化进 Prompt才是可靠的做法。5. 信息过载、上下文冲突真实项目里的高频故障5.1 故障一中间内容被模型“遗忘”怎么处理我在 3.1 节提过 lost in the middle 现象这在实际使用中会带来很隐蔽的错误。一段重要的售后政策如果恰好排在 Prompt 中间模型很可能在你问它细则的时候答得模模糊糊。处理办法有几个。最直接的是把关键信息挪到开头或结尾。其次是压缩中间区块只保留精简摘要把完整细节放到外部检索器里按需提取。再就是显式提示模型“材料中可能存在不相关内容”让它主动过滤。我自己的建议是不要过度依赖模型对长上下文的归纳能力。能塞进开头结尾的关键内容尽量都放进去中间区域留给辅助性材料。如果上下文实在长到非用中间区域不可就要接受模型在某些边缘细节上可能丢分的现实然后通过评测来确认这个损失是否可接受。5.2 故障二事实冲突时模型“和稀泥”当上下文里同时出现两条互相矛盾的信息模型的常见反应不是判断对错而是“和稀泥”——试图把两条都圆过去。这在工程上是灾难因为输出会变得不可信。解决办法是在上下文里提前声明信息的优先级。比如加一句“如 [已知事实] 与 [用户自述] 冲突以 [已知事实] 为准并在回答中说明可能存在的误会”。这样做等于帮模型预判了矛盾你不用指望它自己具备事理推断能力但你可以通过上下文把决策规则给定下来。还有一种情况是模型输出里引用了过期的政策条款解决方案是在上下文协议里维护一个“已废弃政策”清单明确告诉模型这些内容不能用。很多人忽略这个反向约束只想着把正确的东西塞进去忘了错误的东西也得明确排掉。5.3 故障三多轮对话中模型“跑偏”如何用状态锁住多轮对话做到十几轮以后模型经常会开始忘记最初的任务目标。用户明明在问 A 产品的售后聊着聊着模型却开始推荐 B 产品。这就是状态管理失效的表现。我的经验是在 Prompt 中持续注入“当前任务锚点”。每一轮都在显眼位置保留一句“当前任务处理订单 20241001-8823 的未收货问题不允许转移话题”。这个锚点看起来朴素但在长对话里的效果出奇地好。配合外部状态协议能有效抑制模型跑偏。如果模型还是容易走神可以试试在回答要求里加一条“如果用户问题与当前任务无关回复该问题需要转接人工处理”给模型一条清晰的退出路径它就不会自主地越界去答不该答的问题。6. 方法论进阶从 Prompt 到完整外部上下文系统6.1 上下文工程不等于提示工程工具链和接口的配合走到这一步你应该能理解为什么我说 Context Engineering 不等于提示工程了。它更像一个分布式的信息管理系统一部分逻辑靠 Prompt 表达另一部分靠代码在外部维护状态还有一部分靠检索系统按需获取外部知识。在一个完整的落地架构里上下文工程的角色其实是一个编排层。它接收来自用户的输入、来自业务系统的数据、来自知识库的检索结果然后把这些信息按任务意图组装成模型友好的结构。架构上并不复杂但难点在于组装规则的设计——什么信息优先、什么信息省略、什么信息必须标记为冲突这些规则需要不断迭代调优。我现在做新项目的时候通常会把上下文构造逻辑写成一个独立的模块不跟业务代码混在一起。这样既方便测试也方便在模型升级时单独调整。我见过很多人把 Prompt 拼在业务逻辑里写着写着就失控了维护成本非常高。6.2 上下文工程的评估方法不能只靠“感觉变好了”方法论的最后一环是评估。没有评估上下文工程就退化成了玄学。我建议至少从三个层面来测事实准确率、格式符合率、行为约束遵守率。事实准确率看的是模型回答中的事实性信息是否与给定上下文一致格式符合率看的是输出是否符合你的结构化要求行为约束遵守率看的是它有没有违反“不许编造”“不许转移话题”这类规则。每改一次上下文结构都跑同一套评测集来对比才能判断改动是正向还是负向。我踩过一个很典型的坑调整了 Prompt 顺序之后凭感觉觉得效果变好了后来跑评测才发现只是个别测试用例表现变好整体准确率反而降了。从这以后我养成了一个习惯任何上下文改动都必须有评测数据支撑。拿数据说话这件事在 AI 应用开发里怎么强调都不为过。7. 再补充几个我自己常用的实战小技巧讲了不少宏观层面的东西最后分享几个在实际项目里反复验证过的小技巧。第一个技巧是给模型提供“反例”。很多人只知道给正例比如“回答要友好”不如再补一句“不要这样直接让用户自己联系快递公司”。反例能更精确地缩小模型的行为空间这种约束效果比正例强得多。第二个技巧是善用“信息数量提示”。在 Prompt 里明确告诉模型“以下是 5 条当前有效政策”模型就倾向于从中挑选而不是去训练记忆里翻找。这是利用模型对上下文里列举项的计数能力实测能降低它编造新规则的概率。第三个技巧是设立回答的“边界回调词”。我经常在 Prompt 里加一句“如果无法回答回复抱歉我暂时无法确认已为您转接人工”给模型一条安全输出的底线。别指望模型诚实地承认自己不会你得给它一个不会时的固定动作。第四个技巧是定期回看历史 Prompt 版本。上下文工程是个反复迭代的过程每一版 Prompt 背后都对应一个当时的问题假设。定期把旧版本翻出来对比往往能发现当初某个看似正确的设定其实早已不适用。版本管理不要嫌麻烦这是省下后期排查时间最划算的投资。Context Engineering 这类方法论的价值不在于提供一个标准答案而在于帮我们建立一套系统性的思考框架。当你再看那些“换个 Prompt 效果天差地别”的案例时就会意识到背后其实是上下文构造逻辑的差别。我自己的体会是大模型应用开发越往后做越像在打磨一套信息流管线输入侧的信息筛选与组织、推理路径的约束与锚定、输出侧的结构与边界缺了哪一个系统都会变成那个“平时还行关键时刻掉链子”的玩具。希望这套方法能让你少走几步我走过的弯路。