爆改RAG!用“上下文压缩”让你的AI检索系统又快又准 - 今日头条 摘要
文档概览
原文围绕一个很具体的工程问题展开:标准 RAG 通常是“先检索,再生成”,但检索召回的内容并不纯净,相关内容和无关内容会混在一起,最终把噪声也一并送入大模型。文章认为,这会直接带来三个后果:
- 有用信息被无关段落包围
- 上下文窗口被噪声占满
- 最终回答容易变得啰嗦、跑题,甚至答非所问
原文给出的解决方案是:在检索之后、生成之前增加一个“上下文压缩”步骤。这个步骤不是重新检索,而是针对已经召回的 chunk,再用大模型按当前问题做一次相关性筛选与内容浓缩,只把真正有用的部分留下来。
文章结构依次包括:
- 问题背景
- 上下文压缩 的定义
- 三种压缩流派
- 一套完整处理流程
- 伪代码框架
- 一个以《AI伦理白皮书.pdf》为知识源的案例对比
- 压缩效果表格
- 选型建议
- 自动评测与可视化的进阶思路
关键事实
标准 RAG 的问题背景
原文明确指出,标准 RAG 的典型问题不是“检索不到”,而是“检索到的内容太杂”。其具体表现包括:
- 检索结果中 Relevant(相关)与 Irrelevant(无关)内容混杂
- 真正有价值的信号只占一部分,其余内容会形成噪声
- 噪声会占用大模型的上下文窗口
- 结果上表现为回答啰嗦、偏题,严重时会答非所问
原文用一个提问示例说明这个问题:当用户问“AI决策的伦理问题有哪些?”时,召回段落里可能同时混入“AI 的历史”“AI 的优点”“AI 的缺点”等内容,而真正与伦理问题直接相关的部分可能只占三分之一。
对“上下文压缩”的界定
原文给出的定义很直接:
上下文压缩,就是在 RAG 检索后,用大模型把无关内容剪掉,只留下和问题最相关的部分。
这一定义包含几个边界:
- 发生时机是在检索后、生成前
- 作用对象是已召回的 chunk,而不是整个知识库
- 主要目标是删除无关内容,而不是改变检索机制
- 压缩后留下的是“与当前问题最相关的信息”,不是文档的全面摘要
原文总结了这样做的三项收益:
- 减少噪声,让模型只看到有用信息
- 提升准确率,让回答更聚焦、更靠谱
- 节省上下文窗口,从而支持更长文档并降低成本
三种压缩流派及差异
原文把 上下文压缩 分成三类:
1. Selective
- 含义:选择性保留与问题直接相关的句子或段落
- 特点:保留原文,不做改写
- 适用倾向:更强调覆盖面和原文保真
2. Summary
- 含义:把相关内容进一步压缩为简洁摘要
- 特点:信息密度更高,但会发生改写
- 适用倾向:更强调精炼、简明、节约上下文
3. Extraction
- 含义:从原文中抽取包含关键信息的句子
- 特点:输出以原文句子为主,通常比 Selective 更“短平快”
- 适用倾向:既要保留原文证据,又希望上下文比整段保留更短
原文对三者的概括选择规则是:
- 如果要“原汁原味”,选 Selective 或 Extraction
- 如果要“言简意赅”,选 Summary
完整流程整理
原文按顺序给出了一套 RAG 加压缩的完整流程。
1. 文档预处理
第一步是从 PDF 中抽取文本。原文提到可使用 PyMuPDF 等工具完成。随后进行分块。分块示例参数明确写出为:
- 每 1000 字一块
- 相邻块重叠 200 字
这里的重叠设计意味着切块不是完全独立的,目的是降低边界截断造成的信息丢失。
2. 向量化与检索
对分块后的文本做 Embedding,将每个 chunk 转成向量。原文提到可使用 OpenAI、bge 等模型。
在查询阶段:
- 先把用户问题也转成向量
- 再做相似度搜索
- 检索最相似的 Top-K 个 chunk
原文示例中给出的检索参数是:
- 检索 Top-10 chunk
3. 对每个检索结果做上下文压缩
这是原文强调的核心步骤。做法是:
- 对每个召回的 chunk 调用大模型
- 按指定压缩方式进行处理
- 压缩方式可以是 Selective、Summary 或 Extraction
- 目标是只保留与当前问题相关的内容
原文还特别提到可以“批量处理”多个 chunk,以提升整体效率。
4. 拼接压缩结果并生成答案
压缩后的 chunk 会被重新拼接成新的上下文,然后交给大模型生成最终答案。
这一步的关键不是直接拿原始检索结果生成,而是先把压缩结果作为生成上下文。
5. 必要时回退到原始 chunk
原文写明了一个重要例外:如果压缩后的内容太少,可以回退使用原始 chunk。
这意味着压缩不是绝对强制的;当压缩把信息删得过多、可能影响回答时,系统可以采用回退策略。
6. 评估与可视化
原文最后补充了工程化建议:应对不同压缩方式进行比较,关注的指标包括:
- 准确率
- 信息量
- 上下文长度
- 压缩比
同时还可以将原文和压缩后的内容进行可视化对比,直观看压缩后的“瘦身”效果。
伪代码框架整理
原文给出了一组伪代码,用来说明各函数的职责和整个调用链。虽然是示意代码,但结构相当明确。
文档处理相关函数
extract_text_from_pdf(pdf_path):从 PDF 中提取全文文本chunk_text(text, size=1000, overlap=200):按 1000 字切块并设置 200 字重叠create_embeddings(chunks):为文本块生成向量表示
向量检索相关步骤
原文用一个简单向量库示意:
- 创建
vector_store - 将每个
chunk与其 embedding 加入向量库 - 对用户问题调用
create_embeddings(query)生成查询向量 - 使用
similarity_search(query_emb, k=10)检索最相关的 10 个 chunk
压缩相关函数
compress_chunk(chunk, query, compression_type):对单个 chunk 做问题相关压缩- 该函数会根据
compression_type选择不同 system prompt - 返回值包括压缩后的文本和压缩比,即
compressed_chunk, compression_ratio
原文这里表达得很清楚:不同流派的核心差异,不是外层流程不同,而是 compress_chunk 使用的提示词和压缩目标不同。
答案生成相关函数
- 将多个压缩结果按分隔符拼接为
context - 调用
generate_response(query, context)生成最终答案
总体封装函数
原文最后又给出一个总入口式伪代码:
rag_with_compression(pdf_path, query, k=10, compression_type="summary")- 内部顺序为:文档处理 → 检索 → 批量压缩 → 生成答案
- 其中批量压缩使用
batch_compress_chunks(top_chunks, query, compression_type)
这说明作者建议把压缩视为标准 RAG 的一个可插拔中间层,而不是完全推翻原有流程。
案例与对比
案例设定
原文的实战案例使用:
- 知识源:《AI伦理白皮书.pdf》
- 用户问题:“AI在决策中的伦理问题有哪些?”
这个案例被用于对比“不压缩”和三种压缩方式的差异。
不压缩的标准 RAG
原文描述为:
- 先检索 10 个相关 chunk
- 直接拼接成上下文
- 得到的答案“很全”,但会有些啰嗦
- 偶尔还会夹带无关内容
这与文章前文对标准 RAG 痛点的描述保持一致:覆盖可能不错,但噪声没有在生成前被剔除。
Selective 压缩表现
原文描述:
- 只保留和伦理问题相关的句子或段落
- 答案更聚焦
- 废话减少
- 压缩比约 40%
Summary 压缩表现
原文描述:
- 把相关内容浓缩成摘要
- 结果最精炼
- 压缩比最高,约 64%
Extraction 压缩表现
原文描述:
- 只抽取原文中最关键的句子
- 信息密度高
- 压缩比约 54%
压缩效果数据
原文表格给出了三种方法与原始上下文长度的对照数据。这些数字是文章中最具体的量化信息之一:
| 技术流派 | 平均压缩比 | 压缩后上下文长度 | 原始长度 |
|---|---|---|---|
| Selective | 39.93% | 6025 | 10018 |
| Summary | 63.87% | 3631 | 10018 |
| Extraction | 54.41% | 4577 | 10018 |
从这些数据可以直接看出:
- 原始上下文长度是 10018
- Summary 压缩得最狠,压缩后长度仅 3631
- Extraction 居中,压缩后长度为 4577
- Selective 保留信息最多,因此压缩后长度也最长,为 6025
按文章的叙述逻辑,这也对应了三种方法的典型取舍:
- Selective:保留更多相关原文,压缩较温和
- Summary:最追求精炼,压缩比最高
- Extraction:介于两者之间,兼顾原文句子与长度控制
可视化示例中的重要细节
原文还给出一组“原始 chunk 与压缩后结果”的文本对比,用于说明压缩并不只是机械截断,而是围绕问题做相关性收缩。
原始 chunk 的主题内容
原始节选中包含多个伦理相关方向:
- 黑箱问题,即深度学习模型难以解释其决策过程