Context-Compression-RAG

相关段太多,拼进窗口后注意力被噪声稀释,且 token 费用上升。根因是证据包超过有效上下文。本方法在预算内压缩或抽取。金标准 span 被删会直接掉 Faithfulness,必须报压缩保真率。

本文属于 RAG 工程框架中的「3 重排与证据组装」环节,聚焦「Context Compression(上下文压缩)」方法。

定位

维度 内容
角色 证据包的预算装箱
输入 → 输出 排序后的 chunks → 不超过预算的 span 包
默认组合 LLMLingua-2;LangChain ContextualCompressionRetriever
何时不用 证据已短于预算

核心机制

$$
\max \sum_i r(s_i,q)\quad\mathrm{s.t.}\quad \sum_i |s_i|\le B
$$

并报 $\mathrm{Keep}=|S_{\mathrm{gold}}\cap S_{\mathrm{out}}|/|S_{\mathrm{gold}}|$。

实现路径与心智:把候选切成句/span,按与 $q$ 的相关打分,在 token 预算里做装箱,丢掉低分噪声。底层心智:窗口是背包,多塞进去的 token 会抢注意力。压缩保真率必须和压缩比一起看。

优缺点

  • 优点:降 token、降噪声。
  • 缺点:可能删掉剂量/时程。

契约与走通样例

输入

1
{"budget": 80, "chunks": ["20 nM siRNA GAPDH for 48 h before RNA extraction. Actin loading control. Review of glycolysis."]}

中间量

保留「20 nM…48 h」,丢掉 review。$\mathrm{Keep}=1$,$\mathrm{token}{out}/\mathrm{token}{in}=0.45$。若预算 20,48 h 被删,$\mathrm{Keep}=0$。

输出

1
{"spans": ["Treat HEK293T with 20 nM siRNA targeting GAPDH for 48 h before RNA extraction."], "keep": 1.0}

社区实现

LLMLingua-2。风险:压缩模型不认识基因符号当停用词删掉。

工程落地

最小可运行示例

复制为 .py 后直接运行(仅标准库)。生产句级打分可换 LLMLingua-2 / ContextualCompressionRetriever

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
"""在 token 预算内按与 query 的重叠装箱;先切句,禁止整段硬截。"""
from __future__ import annotations

import re


def sentence_split(chunks: list[str]) -> list[str]:
"""句级 span。生产可用 NLTK/spaCy;不要用词级以免删单位。"""
spans = []
for chunk in chunks:
spans.extend(s.strip() for s in re.split(r"(?<=[。.!])\s*", chunk) if s.strip())
return spans


def overlap_score(query: str, span: str) -> float:
q, s = set(query.lower().split()), set(span.lower().split())
return len(q & s) / max(len(q), 1)


def compress_for_prompt(query: str, ranked_chunks: list[str], budget_tokens: int) -> list[str]:
"""输入已排序 chunk;输出不超过预算的 span 列表。"""
packed, used = [], 0
for span in sorted(sentence_split(ranked_chunks), key=lambda x: -overlap_score(query, x)):
cost = max(1, len(span) // 4)
if used + cost <= budget_tokens:
packed.append(span)
used += cost
return packed


if __name__ == "__main__":
chunks = [
"Treat HEK293T with 20 nM siRNA targeting GAPDH for 48 h. Cells were maintained in DMEM.",
"Statistical tests used GraphPad Prism.",
]
print(compress_for_prompt("GAPDH siRNA 48 h", chunks, budget_tokens=20))

参数

参数 起点 影响
budget_tokens 模型窗的 30%~50% 给证据 过小必伤 Keep
粒度 句级 词级更容易删约束

失效—信号—螺丝

  • Keep 掉、Faithfulness 掉:螺丝:加大预算或保护数字/单位。
  • 本来就短:螺丝:关掉压缩。
  • 符号被删:螺丝:领域词保护列表。

规模(100 篇生物学 PDF)

压缩模型 GPU 8–14 GB。在线每问 +200–800 ms

-------------本文结束感谢您的阅读-------------