RAG 检索结果如何组装进上下文?
简化版
上下文组装不是把 Top-k 原样拼接,而是在 Token 预算内选择覆盖问题所需证据、去掉重复,并保留标题、来源、时间和邻接结构。通常先 rerank,再做去重与多样性选择,必要时扩展父块或相邻块;关键证据靠近问题,文档内容明确标为不可信数据,输出预留和引用映射不能被挤掉。
详细版
先从总窗口扣除系统规则、用户问题和最大输出,剩余才是 evidence budget。候选按相关性、来源质量、时效和权限打分,用 MMR 或覆盖约束避免五个结果都来自同一段;合并连续块、删除模板重复,并按“文档说明—编号片段—当前问题—回答契约”渲染。
长文档可用子块召回、父块回填:小块负责命中,大块补语境。冲突证据不要静默丢弃,要携带版本和时间供模型比较。评测不仅看 answer accuracy,还看 evidence recall、context precision、引用正确、输入 Token 与位置敏感度,并记录最终选中/丢弃的 chunk ID。
Top-N候选 -> rerank -> 权限过滤 -> 去重/多样性 -> 父邻扩展 -> 预算优化 -> 带来源上下文
完整版教学
一、Packing 是一个受约束选择问题
检索器给出的 Top-k 是候选,不是最终 Prompt。候选可能重复、缺前文、版本冲突,全部拼接还会超过窗口。Packing 要在有限 Token 下最大化答案证据覆盖,同时降低噪声、成本与注入风险。
可把每个 chunk 看成有价值 v_i、长度 l_i 的物品,在总预算 B 下选择。实际价值还依赖 chunk 之间的互补与冗余,因此不是简单按 score/length 贪心,但这个视角能提醒我们显式优化预算。
二、先算真正可用的证据预算
总窗口不能全给文档,要预留系统、问题、工具协议和输出。公式可写为:
B_evidence = B_context - B_system - B_query - B_output - B_margin
若窗口 16K,系统 1K、问题/历史 2K、输出 2K、安全余量 1K,证据最多 10K。实际 Token 应用目标模型 tokenizer 计算;按字符估算对中文、代码和表格会偏差。
记忆钩子:先给输出留座,再装证据;否则模型读完材料却没有空间写完整答案。
三、相关性之外还要多样性
向量 Top-5 可能是同一公告的五个重叠块,浪费预算且缺少其他来源。可按文档 ID 去重、限制每源配额,或用 MMR 平衡查询相关与候选间相似。对多跳问题还应覆盖不同实体和子问题。
| 信号 | 作用 | 风险 |
|---|---|---|
| Rerank score | 语义相关 | 同源重复 |
| 来源质量 | 提升可信度 | 权威源也可能过期 |
| 新鲜度 | 处理时效 | 新不等于正确 |
| 多样性 | 增加覆盖 | 可能引入弱证据 |
| Token 长度 | 控制成本 | 偏爱短而不完整片段 |
最终排序可设硬约束,再在可行集合中优化分数,避免一个维度完全主导。
四、父子块与邻接扩展
小 chunk 检索精确,却可能只有“是,允许”而缺少问题标题;大 chunk 语境完整,但 embedding 被多主题稀释。父子检索让子块建立索引,命中后回填父章节;邻接扩展补前后定义和条件。
扩展不是固定拿前后各两块。可根据句子是否完整、标题层级和指代词决定,并合并重叠区间。记录命中子块与最终注入父块的关系,诊断时才能判断检索成功但 packing 是否引入过多噪声。
五、证据顺序怎样安排
长上下文存在位置效应,关键证据放在中间可能被忽略。可按 rerank 后把最相关证据靠近问题,同时在每块前放短标题、来源与日期。不要把不同文档句子重新拼成无来源摘要,否则引用和冲突分析困难。
冲突资料按时间或权威排序,但全部保留并明确标记。当前问题放在证据之后可让模型临近作答时再次看到目标;核心高层规则仍在 system 前部。通过位置轮换实验验证模型,而非假设某位置永远最佳。
六、如何防文档注入
检索内容是不可信数据,其中可能包含“忽略规则”等文本。Prompt 明确 evidence 只能用于事实,不可修改指令或调用权限;文档用结构边界包裹并附 source_id。更重要的是工具执行由后端策略控制,秘密不放进上下文。
入库和查询阶段可扫描已知注入模式,但检测不是完全防线。Packing 只提供回答所需最小片段,减少攻击面;输出引用帮助发现模型是否依据异常文档。高风险来源可降权或隔离人工审核。
七、如何评测组装策略
固定召回候选,比较不同 packer,才能隔离组装收益。测答案、上下文精确率(注入片段中有多少真正有用)、证据召回、引用一致、Token 和延迟。加入“关键证据位置”和“高重复候选”压力集。
例如候选 20 块共 24K Token,朴素 Top-8 用 10K、答案 78%;去重+父子策略用 7K、答案 84%。还要检查没有答案样本,packer 不应为填满预算强塞弱相关文档,诱导模型编造。
八、常见误区与追问
- 误区:召回 Top-k 直接拼接就是 RAG 上下文。 候选还需去重、预算和结构恢复。
- 误区:k 越大证据越充分。 噪声、成本和位置干扰会增加,答案可能更差。
- 误区:按检索分数排序就够了。 还需权限、来源、新鲜度和多样性。
- 追问:小块还是大块? 小块检索、父块回填常能兼顾精确与语境,具体由评测决定。
- 追问:冲突证据怎么装? 保留来源与时间,显式并列,让回答说明冲突,不静默选一条。
- 追问:如何知道 packing 丢错了? 保存候选与最终 chunk ID,用真值证据替换和固定候选消融。
九、加强记忆
Context Packing 可记成“算预算、排相关、去重复、补结构、留来源、防注入”。Top-k 只是原料,先为输出留空间,再用 rerank 和多样性选择,子块命中后恢复必要父邻语境,并保留引用和冲突信息。用固定候选对照答案—Token 曲线,才能证明组装器真正提高了信息密度。