跳转到内容

Introducing Contextual Retrieval

这是一篇 Anthropic 于 2024-09-19 发布的工程文章。它聚焦的不是生成阶段,而是 RAG 的检索阶段,提出了 Contextual Retrieval:在 embedding 和 BM25 建索引之前,先给每个 chunk 自动补一段简短的 chunk-specific context,以降低传统分块检索丢失上下文的问题。

  • 文章先指出传统 RAG 的核心缺陷:文档被切成小块后,很多 chunk 在脱离原文时会失去“它在讲谁、什么时间、什么场景”的关键信息。
  • Anthropic 提出的 Contextual Retrieval 由两个子技术组成:Contextual EmbeddingsContextual BM25
  • 具体做法是:让 Claude 读取整篇文档和单个 chunk,为该 chunk 生成一段通常 50-100 token 的简短解释性上下文,再把这段上下文 prepend 到 chunk 前面,用于 embedding 和 BM25 建索引。
  • 它的关键思想不是改查询,而是在预处理阶段把“原本会在 chunking 时丢掉的文档语境”补回去。
  • 文章把它和传统 Embeddings + BM25 混合检索明确区分开来:不是只做 semantic similarity 或 lexical match,而是先 contextualize,再做这两类召回。
  • 文中也明确提到一个更简单的边界条件:如果知识库小于 200,000 tokens,很多时候根本不需要 RAG,直接整库塞进 prompt 反而更简单,尤其配合 prompt caching。
  • 成本方面,这篇强调 Claude 的 prompt caching 让 contextualization 预处理变得可行,因为同一文档不需要为每个 chunk 重复传整篇内容。
  • 评测上,文中使用 1 - recall@20 作为检索失败率指标,结果显示:
  • Contextual Embeddings 将 top-20 retrieval failure rate 从 5.7% 降到 3.7%,约 35% 改善。
  • Contextual Embeddings + Contextual BM25 将失败率从 5.7% 降到 2.9%,约 49% 改善。
  • 再叠加 reranking 后,失败率进一步降到 1.9%,即约 67% 改善。
  • 文章最终给出的 recipe 很明确:Embeddings + BM25 + contextualization + reranking + top-20 chunks,这些收益可以叠加。
  • 它还提醒了几个 implementation knobs:chunk 边界、embedding model、contextualizer prompt 定制、以及最终送入模型的 chunk 数量,都需要在具体业务里自己 eval。

ℹ️ Conflict:

  • 这篇虽然大幅改善召回,但它解决的是“检索前处理”问题,不等于自动解决生成质量;文章自己也强调最终回答效果仍需要端到端 eval。
  • 它默认 chunk 需要额外上下文,但如果知识库很小、文档高度结构化,或者直接整库进 prompt 已经足够好,那么 RAG 本身可能就不是最优默认。
  • contextualization 会引入额外预处理成本和索引膨胀,因此它更像“用更多离线计算换更稳检索”,而不是无条件免费收益。
  • Anthropic, “Introducing Contextual Retrieval”, 2024-09-19.
  • 原文摘录:[llm-wiki/raw/anthropic/Introducing Contextual Retrieval](/raw/anthropic/Introducing Contextual Retrieval.md)