检索模块返回的是一组相关文档片段,但这些片段不能直接“塞”给大语言模型。上下文窗口有限,片段之间可能存在重复、冲突或冗余,组织不当会浪费宝贵的 token、降低回答质量,甚至引入误导信息。上下文组织策略要解决的核心问题是:如何将检索到的零散片段,整理成一段紧凑、有序、便于模型正确理解与引用的输入文本。
9.2.1 片段排序:让重要信息先被看到
语言模型对上下文存在“位置偏见”,往往更重视开头和结尾的内容,对中间部分关注相对较弱。因此,片段的前后顺序会直接影响生成结果。
实用排序准则:
- 相关性优先:检索时已经得到相似度评分,可按分数降序排列,最相关的片段放在最前面。
- 信息互补优先:如果多个片段描述同一主题的不同侧面,将最核心的定义、结论放在前面,细节、示例放后面。
- 时效性优先:当知识库中存在同一主题的多个版本时,优先展示最新更新时间的片段,旧版本可排后或干脆丢弃。
- 避免开头全是相似内容:如果 top-3 片段说的几乎一样,可以将差异性更强的那一个提前,防止模型陷入“重复赘述”。
真实做法:在代码中维护一个简单的排序函数,综合检索分数、文档日期、片段类型(如“定义”优先于“案例”)进行加权排序,而不是单纯依赖向量相似度。
9.2.2 去重与合并:别让模型看三遍同一件事
检索容易召回多个内容高度重叠的片段,比如同一文档中相邻的几个 chunk,或者同一信息的略微改写版本。直接保留全部会造成上下文臃肿、信息冗余,甚至让模型困惑“到底以哪个为准”。
处理策略:
- 文本相似度去重:计算候选片段之间的 Jaccard 相似度或向量相似度,设定阈值(如 0.85),高于阈值的只保留第一个或内容最完整的一个。
- 长片段优先保留:如果两个片段高度重复,优先保留包含更完整上下文(如更长的 chunk 或未截断语义)的那个。
- 来源合并:对于重复内容,可保留不同来源的片段以便交叉印证,但此时要控制数量,一般最多保留两个差异来源。
真实体验:在医疗产品说明书场景中,同一个药品的“用法用量”可能在不同文档中出现多次。去重后,模型给出的回答更精炼,不再反复强调同一内容,节省的 token 可用于容纳更多样化的信息。
9.2.3 上下文压缩与截断:好钢用在刀刃上
即使经过排序和去重,总长度仍可能超出模型上下文限制。这时需要对每个片段或整体进行压缩,保证信息密度的同时遵守长度约束。
常见方法:
- 保留关键句:对每个片段使用简单规则(如保留包含数字、日期、专有名词的句子)或轻量模型(如 small cross-encoder)打分,只保留得分最高的若干句。
- 摘要式压缩:调用一个专门的小模型,将片段压缩为一到两句的摘要后再放入上下文,适合描述性、背景性内容。
- 丢弃低相关信息:如果某些片段的相关性分数明显偏低,且排序后处于末尾,可以直接舍弃,无需压缩。
- 动态分配 token:根据问题长度,预留一定 token 给生成,剩余空间按片段重要度分配最大长度。
实用建议:不要盲目追求最大化上下文填充量。实验表明,保留 3~5 个最相关、信息密度最高的片段,效果往往优于塞满窗口但含大量冗余信息。质量远胜数量。
9.2.4 提示模板与引用格式:让模型“知道该怎么用”
上下文组织不仅是把片段堆在一起,还包括用固定格式告知模型这些片段的身份和用法。良好的模板能显著提升回答的结构化程度与可溯源性。
模板设计要点:
- 明确角色:例如使用“请仅根据以下【参考资料】回答问题。如果资料不足以回答,请直接说明‘资料中未找到相关信息’。”
- 片段标记:为每个片段赋予编号、来源标题、日期等元数据。例如:
【参考资料1:产品手册v2.3(2024‑11)】
内容...
【参考资料2:常见问题FAQ(2025‑01)】
内容...
- 引用指令:要求模型在回答中注明引用片段的编号,例如“据【参考资料1】,X200 型笔记本仅支持 45W 充电。”
- 处理冲突:当不同片段包含矛盾信息时,可额外指令:“如果参考资料之间存在冲突,请指出矛盾并说明各来源的说法,不要自行判断哪一个是正确的。”
真实案例:某政府部门的知识库系统,要求模型所有回答末尾必须附“依据条款”,提示词中固定加上“请在回答的‘依据’部分,列出你引用过的所有参考资料编号”。这样操作后,审核人员可以直接对照片段检查,极大减少了核对时间。
9.2.5 多轮对话中的上下文管理
在聊天场景下,历史对话也是上下文的一部分,需要与检索片段共同管理。
实用策略:
- 滑动窗口历史:只保留最近 N 轮对话的摘要或原始文本,避免无限增长。
- 片段与历史分离:将检索片段放在 prompt 的最上方(或紧跟系统指令之后),历史对话放在片段之后、当前问题之前。这样可以确保模型先接收最重要的参考资料,再结合对话脉络作答。
- 替换而非叠加:如果用户追问时仍然复用上一次的检索结果,不要将两次检索到的所有片段都堆积在一起。应根据当前问题重新检索,只保留最新的高质量片段,避免历史片段干扰当下判断。
一个真实的组装顺序示例:
系统指令
↓
【参考资料】 (本次检索到的片段,经过排序、去重、压缩)
↓
【对话历史】 (最近3轮)
↓
【当前用户问题】
这种结构让模型在“阅读”时先建立知识基础,再理解对话背景,最后聚焦当前问题,回答的准确性和连贯性都更好。
高效的上下文组织并非一次性设计到位,而是需要结合具体业务持续迭代。通过观察哪些片段被模型频繁引用、哪些片段从未被使用、模型是否出现“忽略资料”等行为,可以反推组织策略的不足并进行调整。说到底,检索负责“找得到”,而上下文组织负责“用得好”,两者同等重要。