进阶收官

Contextual Retrieval:更好的 RAG

RAG 的核心假设是「检索到正确的 Chunk 就能给出正确的答案」。但实践中发现了一个根本性问题:切 Chunk 的过程本身就会丢失关键信息。Contextual Retrieval 正是为了解决这个问题。

传统 RAG 的核心问题

传统 RAG 的工作流程是:把文档切成小块(Chunk),对每个 Chunk 做向量化,用户提问时检索最相似的 Chunk,然后把 Chunk 喂给 LLM 生成答案。这个流程有一个致命缺陷:

Chunk 脱离上下文后变得模糊不清

文档被切成 Chunk 后,每个 Chunk 失去了它在原文中的位置信息。一段在原文中意义清晰的文本,单独拿出来可能完全无法理解。
典型案例
"The company's Q2 revenue increased by 3% over the previous quarter."
哪个公司?哪一年?Q1 的基准是多少?这个增长率在行业中算好还是差?所有这些关键上下文,都在切 Chunk 时丢失了。向量检索可能找到了这个 Chunk,但它本身携带的信息严重不足。
完整文档
切成 Chunks
上下文丢失
检索模糊
Contextual Retrieval 的核心思路

在 Embedding 前,用 LLM 给每个 Chunk 加上上下文前缀

思路非常直观:在对 Chunk 做向量化之前,先用 LLM 阅读整篇文档,然后为每个 Chunk 生成一段简短的上下文描述作为前缀。这样每个 Chunk 在被检索时都自带了必要的语境信息。
BEFORE -- 裸 Chunk
"The company's Q2 revenue increased by 3% over the previous quarter."
谁?什么时候?无从得知。
AFTER -- 带上下文的 Chunk
"This chunk is from the company's 2024 Annual Report, specifically the Financial Performance section. The company's Q2 revenue increased by 3% over the previous quarter."
LLM 生成的前缀自动补充了来源、时间、章节。
三层递进优化
LAYER 01
Contextual Embeddings
给每个 Chunk 加上下文前缀后再做向量化。前缀包含文档标题、章节位置、关键实体等信息。向量检索时,Chunk 自带语境,语义匹配更精准。
LAYER 02
Contextual BM25
传统的 BM25 关键词检索也加上上下文前缀。前缀中的关键词(如公司名、年份)让 BM25 能匹配到原本因缺少语境而无法命中的 Chunk。向量检索 + BM25 双路召回,互补盲区。
LAYER 03
Reranking
检索后,用 Reranker 模型对候选 Chunk 重新排序。Reranker 能更精确地判断 Chunk 与查询的相关性,把最相关的结果排到前面。三层叠加效果最佳。
效果数据

检索失败率降低幅度

仅 Contextual Embeddings
49%
Contextual Embeddings + BM25 + Reranking
67%
67% 的检索失败率降低意味着什么?假设之前每 100 次检索有 30 次找不到正确的 Chunk(失败率 30%),优化后失败率降到约 10%,三分之二的检索错误被消除了。对于依赖 RAG 的生产系统来说,这是质的飞跃。
成本权衡

没有免费的午餐

预处理成本增加:每个 Chunk 都需要一次额外的 LLM 调用来生成上下文前缀。对于大规模文档库,这个预处理成本不可忽视。
Prompt Caching 可以降低成本:同一篇文档的不同 Chunk 共享相同的文档级上下文。利用 Prompt Caching,可以避免重复发送整篇文档内容。
适合高准确率场景:如果你的 RAG 系统对准确率要求极高(如法律文档检索、医疗知识问答、金融合规查询),额外的预处理成本是值得的。对于容错率高的场景(如闲聊推荐),可能不划算。
RAG 不是切 Chunk 加向量检索就够了,每个 Chunk 要自带上下文。Contextual Retrieval 的核心洞察:检索的质量瓶颈在 Chunk 本身的信息完整性,换更强的向量模型帮助有限。给 Chunk 补上丢失的语境,检索失败率可以降低三分之二。