大模型Context Mode实战:从客服问答翻车到上下文管理落地
我真正开始认真研究 Context Mode不是从技术文档里而是从一次尴尬的演示翻车开始的。当时我做了一个基于大模型的客服问答原型客户在演示现场上传了一本 60 页的售后政策手册然后连续问了三个问题。系统确实接住了但它的回答每一句都像第一次看到这份手册第一个问题答了第二个问题又开始重新自我解释第三个问题直接忘了用户一开始说的订单信息。客户很客气地问了一句你们这个不是有上下文模式吗这一问让我意识到Context Mode 不是一个勾上就能用的开关而是一整套关于模型如何接收、整理、取舍信息的设计。它横跨提示词、检索、记忆管理和成本控制。这篇文章不聊概念名词就聊我怎么从翻车到跑通以及你现在可以照着做的落地方法。适合正在做 AI 应用、尤其是文档问答和客服场景的开发者与产品负责人。1. 先搞明白Context Mode 到底在解决什么问题1.1 一次对话为什么会断片先还原那段让我破防的对话很多人看完会觉得似曾相识用户退换货流程是什么AI请提供订单号我来帮您查询。用户订单号是 A12345退换货需要几个工作日AI根据售后政策退货需在签收后 7 天内申请。请问您的订单号是用户我刚刚说了A12345……AI抱歉我没有查询到该订单的信息。这种断片太典型了。它的根因不是模型记忆力差而是我的提示词没有帮助模型建立上下文优先级用户刚刚给出的订单号应该在本轮合并为新事实售后政策文档应该作为引用来源这两类信息不应该被平等对待。Context Mode 本质上要做的是把系统设定、外部资料、历史消息、当前提问四类文本按照明确的优先级组装进模型输入。如果只是简单地把所有内容拼在一起模型虽然都看到了但它不知道谁是主角、谁是背景、谁已经过期。于是它在回答时就会随机挑一个视角。明白了这一点后面所有工程手段都围绕同一个目标让模型在每一轮生成前拿到一份结构清晰、主次分明的上下文。1.2 用后厨备餐台理解 Context Mode这个概念不用讲得太玄。你可以把大模型想成一位后厨系统提示词是贴在他工位上的规矩本店不放香菜出餐前检查订单号文档资料是备菜台上的食材有的是主菜原料有的是摆设对话历史是前面做过的菜和顾客反馈新订单来了要参考前面做了什么当前提问是刚进来的最新订单后厨必须优先响应。没有 Context Mode后厨把所有食材、旧单据、新订单混在一起时间长了必然抓瞎。有了这套模式主厨才知道当前这份订单要优先用哪个冰箱的原料哪些旧订单可以忽略哪些规矩必须守住。每次向产品同事解释时用这个类比对方基本立刻就能理解后面聊预算和需求也顺畅得多。1.3 三个经常被搞混的词很多讨论里的错位是因为没分清三个概念。这里我直接列一张表概念含义关键特征上下文窗口模型单次输入的最大 token 上限硬边界超出部分无法送入模型对话历史多轮问答中保留的用户/助手消息序列可变可裁剪、可压缩Context Mode把资料、历史、提问按优先级组装成输入的策略可设计是应用层能力我见过不少团队在上下文窗口不够用上死磕反复换更大窗口的模型但效果依然差。因为他们真正缺的不是窗口大小而是没有建立什么信息值得进上下文、什么信息不值得进的筛选机制。窗口大只是容量变大并不等于里面的每句话都有效。2. 落地 Context Mode 的两条路线先提示词再工程2.1 提示词层面的显式 Context Mode最早我用的方法很朴素在系统提示词里明确告诉模型你现在处于 Context Mode。虽然听起来像玄学但实测确实有效原因在于模型在预训练阶段见过大量指令 资料 问答的文本结构如果你给出像协议一样的声明它更容易进入对应的工作状态。我的模板长这样你现在处于 Context Mode。 1. 用户可能会粘贴长文本、代码、日志或对话记录这些都属于需要分析的资料。 2. 收到资料后先整理内部摘要再结合用户的问题作答。 3. 如果资料中没有答案直接说资料中没有相关内容不要臆测。 4. 每轮回答都必须基于对话中已经出现的事实尤其是用户主动提供的编号、日期、状态。这套提示词解决了我前文说的断片问题因为它明确告诉模型用户刚给的订单号等于新证据必须带到下一轮。但它也有明显局限如果业务文档超过上下文窗口、或者历史对话特别长光靠提示词撑不住。所以提示词是下限工程方法才是上限。2.2 工程层面RAG 检索增强的上下文组装当资料大到塞不进单次窗口时必须走 RAG 路线。我一直把它理解为给后厨装一个食材管理系统不需要把所有食材堆在案板上而是根据订单去冷库取对应的那一份。标准流程是清洗文档去掉页眉页脚、水印、无效符号按章节或固定长度切块通常每块 500~800 token块与块之间保留 50~100 token 的重叠防止关键信息被切断把每个块做向量化存入向量库用户提问后先做向量召回取 TopK 个候选块如果候选块太多再加一层重排用轻量模型或分数融合选出最相关的 3~5 块最后把选中的块拼进上下文。第 5 步非常关键我一开始跳过它结果召回质量波动很大加了一层重排之后输出明显稳定了。RAG 属于 Context Mode 的资料层工程化它解决的不是模型能力问题而是让模型真正读到该读的段落。2.3 对话太长滑窗 摘要记忆另一个容易翻车的地方是多轮对话。用户聊了 20 轮之后前 5 轮的细节可能占了几千 token如果全部保留后面的上下文窗口放不下如果粗暴丢弃用户的关键信息又丢了。我现在用的方案是两层记忆滑动窗口只保留最近 N 轮完整消息通常 N 取 5~8保证近期意图不丢摘要记忆把窗口之前的内容定期压缩成一段 200~300 token 的会话摘要放在系统层。比如把用户问过退换货流程订单号 A12345已确认 7 天内可退提炼成结构化摘要这样旧信息以高密度形式存活又不占用太多窗口。这个方案很像人做会议纪要太久远的细节不记原话但结论和关键数据写进纪要。我靠这套结构把单次请求的 token 消耗稳定控制了近 40%长对话的连贯性反而更好。3. 手把手5 步搭一个带 Context Mode 的问答助手3.1 明确场景约束先定义清楚需求。以我最近一个客服项目为例输入资料一本 50 页的售后政策文档单次回答长度要求不超过 300 字模型上下文窗口8K token并发压力中等需控制单次请求成本。这些约束决定了下游所有参数。很多人一上来就写代码结果做到一半发现文档太长、预算超标返工成本很高。我建议先花半小时把资料量、窗口上限、回答长度、预算四件事写清楚。3.2 把静态文档拆成可检索片段这一步决定了后面回答质量的底线。我采用标题优先 固定长度兜底的切块策略优先按 Markdown 标题或 Word 大纲切分让每个片段自带语义边界遇到没有标题的长段落按 600 token 切重叠 100 token切完后给每个片段记录来源页码和更新时间。比如售后政策里退货时限和退款方式如果落进同一个块会弱化各自的聚焦度按标题切分后检索退款多久到账时召回器能精准定位到退款方式章节而不是拿着整章文档去做模糊匹配。3.3 组装三层上下文确定检索到的片段之后组装顺序很讲究。我用固定三层结构顺序如下第1层系统提示词规则、输出格式、Context Mode 声明 第2层检索到的资料片段带编号和来源 第3层最近的对话历史 当前问题注意顺序不是随意排的。模型对开头的文本注意力权重更高所以规则必须放最前面资料放中间作为证据区最新问题放最后让模型带着刚读完的资料直接生成回答。如果反过来把历史对话放在资料前面模型容易被聊天语气带偏削弱对资料的引用。3.4 触发条件与优先级规则不是每个问题都需要检索也不是每段资料都同等重要。我加了一层轻量判断逻辑规则很简单问题超过 20 个字或者包含政策、流程、多久、多少、能否等业务词强制走检索用户提供了新的编号、日期、订单状态优先更新会话摘要记忆不进资料层资料片段之间冲突时优先采用更新时间最新的片段并在回答中注明来源。这个优先级规则是防断片的关键。我最初踩的坑是把用户临时输入和静态资料混在一起导致模型分不清哪句是刚发生的事实哪句是旧文档内容。拆开之后模型基本不会再用文档口径去否定用户刚说的话。3.5 Token 与成本估算落地前必须算清 token 账。我给出一个可以直接套用的估算公式单次请求总 Token ≈ 系统提示词 Token 检索片段数 × 平均片段 Token 历史窗口条数 × 平均历史 Token 当前问题 Token用一个真实数据算一遍系统提示词约 350 token检索召回 4 个片段每段平均 600 token2400 token历史窗口保留 5 条对话每条约 100 token500 token当前问题约 80 token合计3330 token。如果模型窗口是 8K那么留给输出的余量是 8000 - 3330 4670 token非常充裕。但如果你把召回片段提到 8 个、历史提到 20 条总 token 会迅速涨到 7000 以上不仅成本翻倍还会把输出空间挤得很小。我自己的经验是检索片段宁可少而准不要多而杂出了问题时优先砍片段数量而不是盲目开更大的窗口。3.6 固定输出格式 完整日志最后一个容易被忽略但特别重要的步骤是让模型以固定格式输出同时把每次请求的上下文组成记进日志。我的输出格式强制要求包含两个字段引用来源编号和结论置信度。结论回答正文 来源[文档-03第 12 页更新时间 2025-06-01] 置信度高/中/低日志则记录本轮用了哪几个片段、命中路径是什么、总 Token 用了多少、最终回答是什么。别小看这些日志它是我排查问题最依赖的工具。模型回答不对时第一件事不是调提示词而是把日志打开看看检索到底召回了什么。往往答案就在日志里要么召回了过时版本要么召回了完全不相关的章节。4. 现场排障Context Mode 最常见的 6 个翻车点4.1 答非所问先查检索到了什么它怎么答到外太空去了是最常见的反馈。大多数时候问题不在模型而在检索层。我排查的第一步永远是看日志里的片段列表确认召回的片段跟问题是否真的相关。如果片段列表里混入了类似关键词但不相关的内容就降低召回数量或者加强重排环节如果召回结果空荡荡就检查切块大小和向量化方式。4.2 资料自相矛盾谁来裁决文档大了以后必然出现版本冲突有的章节说退货 7 天内可申请另一个表格写按批次最长 30 天。模型遇到矛盾时会随机选一个或给出含糊回答。我的解法是在每个片段上记录更新时间并在系统提示词里明确写当资料冲突时优先参考更新时间最新的片段并如实说明存在版本差异。至少保证模型不编造面子上也说得过去。4.3 上下文越长回答越飘有些开发者以为把资料全部塞进上下文就能提高准确率结果发现问题越多回答越飘。原因很简单模型在注意力计算时会被大量无关 token 分散注意力垃圾进、垃圾出。这是一个典型的上下文窗口很大但有效信息密度低的问题。我的经验是强制限制资料层最多 4~6 个片段宁可让模型说资料中没有相关内容也不要给它一堆云里雾里的干扰项。4.4 长对话开头被遗忘长对话超过窗口后如果粗暴滑窗早期用户说过的重要信息会丢失。比如用户在第 2 轮报了订单号第 18 轮再提退换货时模型可能不知道这个订单号的存在。这就是我前面说的摘要记忆的用武之地在滑窗前把关键事实提炼成结构化摘要固定放在系统层。相当于给模型一张长期记忆卡即使原始对话已经被裁掉结论还在。4.5 成本像坐过山车Context Mode 做得越复杂每次请求拼进上下文的内容越多成本越容易失控。我见过一个项目因为把整本手册每次都塞进系统提示词单次调用成本直接翻了 5 倍。控制成本有三板斧限制检索片段数量、限制历史窗口条数、对历史做摘要压缩。每个季度我还会拉一次 Token 使用报表看哪些请求超出预期再针对性调参。4.6 格式飘忽不定解析困难模型偶尔会在该输出结构化格式时突然自由发挥把来源编号写成一句话或者漏掉置信度这会影响下游解析。解法是在系统提示词里放一两个固定示例同时把输出格式要求从请按格式输出改成只输出以下 JSON 结构不要输出任何额外内容。示例比任何描述都管用这是我在实际调试中反复确认过的一句话。4.7 翻车点速查表最后把常见问题整理成一张速查表方便你在现场快速定位现象可能原因优先排查动作回答与用户刚给的事实矛盾事实未进入历史摘要检查摘要记忆更新逻辑回答与文档资料不一致检索到过时/冲突片段看日志片段列表更新提示词裁决规则答非所问召回结果不相关降召回数量加重排上下文越长效果越差有效信息密度不足限制资料层片段数量长对话忘掉开头滑窗切掉早期关键事实启用摘要记忆输出格式不稳定描述太抽象增加输出示例限定 JSON5. 做 Context Mode 大半年我最后想说的几句实话把 Context Mode 从概念落到生产环境之后我最大的体会是它不是某个模型自带的魔法按钮而是一套应用层策略。每次救场的不是更贵的模型而是让模型看到的东西更干净、更有序这个朴素原则。我现在接到新需求第一句话会先问产品你说的上下文到底指哪几个信息来源这个问题想清楚了方案基本就成了一半。也分享一个最近还在用的习惯每次发布新版本前我会把三组比较刁钻的测试问题跑一遍——一组考验长对话记忆一组考验资料引用一组考验新旧信息冲突。三组都过了我才敢往线上推。这套方法让我的迭代回归成本低了很多也不用每天盯着线上日志看用户吐槽。Context Mode 这条路上没有一劳永逸的捷径但它值得你把每一步都做扎实。