核验日期:2026-07-08
内容来源:Anthropic Engineering 官方技术博客。本文先作为 Claude Code 专区后台草稿入库,发布前应由内容人员复核标题、摘要、图片、来源链接与是否需要补充本站实践说明。
Contextual Retrieval 介绍
要让 AI 模型在特定语境中真正有用,它通常需要访问背景知识。
来源:https://www.anthropic.com/engineering/contextual-retrieval
发布日期:2024-09-19
要让 AI 模型在特定语境中真正有用,它通常需要访问背景知识。比如,客服聊天机器人需要了解它所服务的具体业务,而法律分析机器人则需要掌握大量过往案例。
开发者通常使用检索增强生成(Retrieval-Augmented Generation,RAG)来增强 AI 模型的知识。RAG 会从知识库中检索相关信息,并将其附加到用户提示词中,从而显著提升模型回答的质量。问题在于,传统 RAG 方案在编码信息时会移除上下文,这往往导致系统无法从知识库中检索到相关信息。
在本文中,我们会介绍一种能显著改进 RAG 检索步骤的方法。这个方法叫做「Contextual Retrieval」(上下文检索),包含两项子技术:Contextual Embeddings(上下文化嵌入)和 Contextual BM25(上下文化 BM25)。该方法可以将检索失败数量减少 49%;如果再结合重排序,减少幅度可达 67%。这些都是检索准确率上的显著提升,会直接转化为下游任务中更好的表现。
你可以参考我们的 cookbook,轻松用 Claude 部署自己的 Contextual Retrieval 方案。
关于直接使用更长提示词的说明
有时候,最简单的方案就是最好的方案。如果你的知识库小于 200,000 个 token(约 500 页材料),你完全可以把整个知识库直接放进给模型的提示词中,而不需要 RAG 或类似方法。
几周前,我们为 Claude 发布了提示词缓存,让这种做法显著更快,也更具成本效益。开发者现在可以在多次 API 调用之间缓存常用提示词,将延迟减少一半以上,并将成本最多降低 90%(可以阅读我们的提示词缓存 cookbook了解其工作方式)。
不过,随着知识库规模增长,你会需要更可扩展的解决方案。这正是 Contextual Retrieval 的用武之地。
RAG 入门:扩展到更大的知识库
对于无法放入上下文窗口的大型知识库,RAG 是典型解决方案。RAG 会按照以下步骤预处理知识库:
- 将知识库(文档「语料库」)拆分成更小的文本块,通常每块不超过几百个 token;
- 使用嵌入模型将这些文本块转换成编码语义的向量嵌入;
- 将这些嵌入存入向量数据库,以支持按语义相似度搜索。
运行时,当用户向模型输入查询时,系统会使用向量数据库,根据与查询的语义相似度找出最相关的文本块。随后,最相关的文本块会被加入发送给生成模型的提示词中。
嵌入模型擅长捕捉语义关系,但可能漏掉关键的精确匹配。幸运的是,有一种更早出现的技术可以在这些场景中提供帮助。BM25(Best Matching 25)是一种排序函数,它使用词法匹配来寻找精确的单词或短语匹配。它对包含唯一标识符或技术术语的查询尤其有效。
BM25 建立在 TF-IDF(Term Frequency-Inverse Document Frequency,词频-逆文档频率)概念之上。TF-IDF 衡量一个词对某个文档集合中的某篇文档有多重要。BM25 在此基础上进行了改进:它考虑文档长度,并对词频应用饱和函数,从而帮助避免常见词主导结果。
下面这个例子展示了 BM25 如何在语义嵌入失败的地方成功:假设用户在技术支持数据库中查询 "Error code TS-999"。嵌入模型可能会找到关于错误代码的一般性内容,却可能漏掉精确的 "TS-999" 匹配。BM25 会查找这个具体文本字符串,从而定位相关文档。
RAG 方案可以通过结合嵌入与 BM25 技术,更准确地检索最适用的文本块,步骤如下:
- 将知识库(文档「语料库」)拆分成更小的文本块,通常每块不超过几百个 token;
- 为这些文本块创建 TF-IDF 编码和语义嵌入;
- 使用 BM25 根据精确匹配找到排名靠前的文本块;
- 使用嵌入根据语义相似度找到排名靠前的文本块;
- 使用排序融合技术合并并去重来自第 (3) 步和第 (4) 步的结果;
- 将 top-K 文本块加入提示词以生成回答。
通过同时利用 BM25 和嵌入模型,传统 RAG 系统能够提供更全面、更准确的结果,在精确术语匹配与更宽泛的语义理解之间取得平衡。

一个标准的检索增强生成(RAG)系统,同时使用嵌入和 Best Match 25(BM25)来检索信息。TF-IDF(词频-逆文档频率)衡量词语重要性,并构成 BM25 的基础。
这种方法让你能够以较低成本扩展到极大的知识库,远远超出单个提示词所能容纳的范围。但这些传统 RAG 系统有一个显著限制:它们往往会破坏上下文。
传统 RAG 中的上下文难题
在传统 RAG 中,文档通常会被切分成更小的文本块,以便高效检索。虽然这种方法适用于很多应用,但当单个文本块缺少足够上下文时,就会带来问题。
例如,假设你的知识库中嵌入了一组财务信息(比如美国 SEC 文件),并且你收到如下问题:"What was the revenue growth for ACME Corp in Q2 2023?"
一个相关文本块可能包含这样的文字:"The company's revenue grew by 3% over the previous quarter." 但是,这个文本块本身没有说明它指的是哪家公司,也没有说明相关时间段,因此很难检索到正确的信息,也很难有效使用这些信息。
Contextual Retrieval 介绍
Contextual Retrieval 通过在每个文本块嵌入之前、以及创建 BM25 索引之前,为每个文本块前置一段特定于该文本块的解释性上下文,来解决这个问题。这两个环节分别称为「Contextual Embeddings」和「Contextual BM25」。
让我们回到 SEC 文件集合的例子。下面展示一个文本块可能如何被转换:
original_chunk = "The company's revenue grew by 3% over the previous quarter."
contextualized_chunk = "This chunk is from an SEC filing on ACME corp's performance in Q2 2023; the previous quarter's revenue was $314 million. The company's revenue grew by 3% over the previous quarter."
复制
值得注意的是,过去也有人提出过其他利用上下文改进检索的方法。其他方案包括:为文本块添加通用文档摘要(我们做过实验,收益非常有限)、假设性文档嵌入,以及基于摘要的索引(我们评估过,表现较低)。这些方法不同于本文提出的方法。
实现 Contextual Retrieval
当然,手动为知识库中的成千上万甚至数百万个文本块做标注,工作量会大得不可接受。为了实现 Contextual Retrieval,我们转向 Claude。我们写了一个提示词,指示模型利用整篇文档的上下文,为文本块提供简洁、特定于文本块的上下文说明。我们使用以下 Claude 3 Haiku 提示词为每个文本块生成上下文:
<document>
{{WHOLE_DOCUMENT}}
</document>
Here is the chunk we want to situate within the whole document
<chunk>
{{CHUNK_CONTENT}}
</chunk>
Please give a short succinct context to situate this chunk within the overall document for the purposes of improving search retrieval of the chunk. Answer only with the succinct context and nothing else.
复制
生成的上下文文本通常为 50-100 个 token,会在嵌入文本块之前、以及创建 BM25 索引之前,被前置到文本块中。
下面是实践中的预处理流程:

Contextual Retrieval 是一种提升检索准确率的预处理技术。
如果你有兴趣使用 Contextual Retrieval,可以从我们的 cookbook开始。
使用 Prompt Caching 降低 Contextual Retrieval 的成本
得益于前面提到的特殊提示词缓存功能,Contextual Retrieval 可以以较低成本在 Claude 上实现。使用提示词缓存时,你不需要为每个文本块都传入参考文档。你只需要把文档加载进缓存一次,之后引用此前缓存的内容即可。假设文本块为 800 个 token、文档为 8k token、上下文指令为 50 个 token,并且每个文本块生成 100 个 token 的上下文,生成上下文化文本块的一次性成本为每百万文档 token 1.02 美元。
方法
我们在多个知识领域(代码库、小说、ArXiv 论文、科学论文)、嵌入模型、检索策略和评估指标上进行了实验。我们在附录 II中列出了一些各领域所用问题和答案的示例。
下方图表展示了所有知识领域的平均表现,配置为表现最好的嵌入设置(Gemini Text 004),并检索 top-20 文本块。我们使用 1 minus recall@20 作为评估指标,它衡量的是相关文档未能在前 20 个文本块中被检索出来的比例。完整结果可见附录;在我们评估的每一种嵌入-来源组合中,上下文化都改善了表现。
性能提升
我们的实验显示:
- Contextual Embeddings 将 top-20 文本块的检索失败率降低了 35%(5.7% → 3.7%)。
- 结合 Contextual Embeddings 和 Contextual BM25 将 top-20 文本块的检索失败率降低了 49%(5.7% → 2.9%)。

结合 Contextual Embedding 和 Contextual BM25,可将 top-20 文本块的检索失败率降低 49%。
实现注意事项
实现 Contextual Retrieval 时,需要注意以下几点:
- **文本块边界:**考虑如何将文档拆分成文本块。文本块大小、文本块边界和文本块重叠的选择都会影响检索表现 1。
- **嵌入模型:**虽然 Contextual Retrieval 能提升我们测试过的所有嵌入模型的表现,但某些模型的收益可能更大。我们发现 Gemini 和 Voyage 的嵌入尤其有效。
- **自定义上下文化提示词:**虽然我们提供的通用提示词效果不错,但如果针对你的具体领域或用例定制提示词,可能取得更好的结果(例如,加入关键术语表,因为某些术语可能只在知识库中的其他文档里定义)。
- **文本块数量:**向上下文窗口加入更多文本块,会提高包含相关信息的概率。不过,更多信息也可能分散模型注意力,因此这里存在上限。我们尝试传入 5、10 和 20 个文本块,发现 20 个在这些选项中表现最好(对比见附录),但仍值得根据你的用例进行实验。
**始终运行评估:**将上下文化文本块传给模型,并区分哪些内容是上下文、哪些内容是原文本块,可能会改善回答生成。
通过重排序进一步提升性能
最后一步,我们可以将 Contextual Retrieval 与另一项技术结合,获得更大的性能提升。在传统 RAG 中,AI 系统会搜索知识库,找出可能相关的信息文本块。对于大型知识库,这种初始检索往往会返回很多文本块,有时多达数百个,而且相关性和重要性各不相同。
重排序是一种常用过滤技术,用于确保只有最相关的文本块被传给模型。重排序能带来更好的回答,并降低成本和延迟,因为模型需要处理的信息更少。关键步骤如下:
- 执行初始检索,获取排名靠前、可能相关的文本块(我们使用 top 150);
- 将 top-N 文本块连同用户查询一起传入重排序模型;
- 使用重排序模型,根据每个文本块与提示词的相关性和重要性给它打分,然后选择 top-K 文本块(我们使用 top 20);
- 将 top-K 文本块作为上下文传入模型,以生成最终结果。

结合 Contextual Retrieval 和重排序,以最大化检索准确率。
性能提升
市面上有多种重排序模型。我们使用 Cohere reranker 进行了测试。Voyage 也提供重排序器,但我们没有时间测试。实验显示,在多个领域中,加入重排序步骤可以进一步优化检索。
具体而言,我们发现,经过重排序的 Contextual Embedding 和 Contextual BM25 将 top-20 文本块的检索失败率降低了 67%(5.7% → 1.9%)。

经过重排序的 Contextual Embedding 和 Contextual BM25,可将 top-20 文本块的检索失败率降低 67%。
成本与延迟注意事项
重排序有一个重要考量:它会影响延迟和成本,尤其是在对大量文本块进行重排序时。由于重排序会在运行时增加一个额外步骤,即使重排序器会并行给所有文本块打分,它仍不可避免地会增加少量延迟。因此,在「重排序更多文本块以获得更好性能」与「重排序更少文本块以降低延迟和成本」之间存在天然权衡。我们建议根据你的具体用例尝试不同设置,找到合适平衡。
结论
我们做了大量测试,比较了上文所述各种技术的不同组合(嵌入模型、是否使用 BM25、是否使用上下文检索、是否使用重排序器,以及检索得到的 top-K 结果总数),并覆盖了多种不同类型的数据集。下面是我们的发现摘要:
- Embeddings+BM25 优于单独使用 embeddings;
- 在我们测试的嵌入模型中,Voyage 和 Gemini 表现最好;
- 向模型传入 top-20 文本块,比只传入 top-10 或 top-5 更有效;
- 为文本块添加上下文会显著提升检索准确率;
- 使用重排序优于不使用重排序;
- 所有这些收益可以叠加:为了最大化性能提升,我们可以将(来自 Voyage 或 Gemini 的)上下文化嵌入与 Contextual BM25 相结合,再加上重排序步骤,并把 20 个文本块加入提示词。
我们鼓励所有使用知识库的开发者使用我们的 cookbook来实验这些方法,从而释放新的性能水平。
附录 I
下面按数据集、嵌入提供方、是否在嵌入之外使用 BM25、是否使用上下文检索,以及是否为 Retrievals @ 20 使用重排序,拆解展示结果。
参见附录 II,了解 Retrievals @ 10 和 @ 5 的拆解,以及每个数据集的问题和答案示例。

不同数据集和嵌入提供方上的 1 minus recall @ 20 结果。
致谢
研究和写作:Daniel Ford。感谢 Orowa Sikder、Gautam Mittal 和 Kenneth Lien 提供关键反馈,感谢 Samuel Flamini 实现 cookbooks,感谢 Lauren Polansky 进行项目协调,也感谢 Alex Albert、Susan Payne、Stuart Ritchie 和 Brad Abrams 共同打磨这篇博客文章。