以下内容转载自 Anthropic 官方网站技术文章并通过 AI 翻译,完整原文请见:https://www.anthropic.com/engineering/contextual-retrieval
为了让 AI 模型在特定语境下发挥作用,它通常需要访问背景知识。例如,客户支持聊天机器人需要了解其服务的特定业务知识,而法律分析机器人则需要掌握大量的过往案例。
开发人员通常使用检索增强生成(RAG)来增强 AI 模型。RAG 是一种从知识库中检索相关信息并将其附加到用户提示词中的方法,能显著提升模型的响应质量。然而,传统 RAG 方案在对信息进行编码时会丢失语境,这往往导致系统无法从知识库中检索到最相关的信息。
在本文中,我们将介绍一种大幅提升 RAG 检索步骤的方法,称为“语境化检索(Contextual Retrieval)”。它结合了两种子技术:语境化嵌入(Contextual Embeddings)和语境化 BM25(Contextual BM25)。该方法可将检索失败率降低 49%,若结合重排序(Reranking)技术,降幅可达 67%。检索准确性的显著提升将直接转化为下游任务中更优质的表现。
您可以通过 我们的 Cookbook 轻松部署基于 Claude 的语境化检索方案。
关于直接使用长提示词的建议#
有时最简单的方案就是最好的。如果您的知识库小于 200,000 个 token(约 500 页材料),您可以直接将整个知识库放入提示词中,无需使用 RAG 或类似方法。
几周前,我们为 Claude 推出了 提示词缓存(Prompt Caching),使这种方法不仅更快而且更具成本效益。开发人员现在可以在 API 调用之间缓存常用提示词,从而缩短延迟 2 倍以上,并降低成本高达 90%(详情请参阅 提示词缓存 Cookbook)。
然而,随着知识库的增长,您将需要更具扩展性的方案。而这正是语境化检索的用武之地。
RAG 入门:扩展至大规模知识库#
对于无法放入上下文窗口的大型知识库,RAG 是典型的解决方案。RAG 的工作原理是通过以下步骤对知识库进行预处理:
- 将知识库(文档语料库)分解为较小的文本块(Chunk),通常不超过几百个 token;
- 使用嵌入模型(Embedding Model)将这些文本块转换为编码语义的向量嵌入;
- 将这些嵌入存储在向量数据库中,以便进行语义相似度搜索。
在运行时,当用户输入查询时,向量数据库会查找语义上与查询最相关的文本块。然后,这些最相关的文本块被添加到发送给生成模型的提示词中。
虽然嵌入模型擅长捕捉语义关系,但它们可能会遗漏关键的精确匹配。幸运的是,有一种较老的技术可以在这种情况下提供帮助。BM25(最佳匹配 25)是一种利用词法匹配查找精确词语或短语匹配的排序函数。对于包含唯一标识符或技术术语的查询,它尤其有效。
BM25 基于 TF-IDF(词频-逆文档频率)概念构建。TF-IDF 衡量一个词对集合中某个文档的重要性。BM25 通过考虑文档长度并对词频应用饱和函数进行了优化,这有助于防止常用词占据主导地位。
以下是 BM25 在语义嵌入失败时能够成功的原因:假设用户在技术支持数据库中查询“错误代码 TS-999”。嵌入模型可能会找到关于错误代码的一般内容,但可能错过精确的“TS-999”匹配。而 BM25 会寻找这个特定的字符串来识别相关文档。
通过结合嵌入技术和 BM25 技术,RAG 解决方案可以更准确地检索到最适用的文本块,步骤如下:
- 将知识库(文档语料库)分解为较小的文本块(通常不超过几百个 token);
- 为这些文本块创建 TF-IDF 编码和语义嵌入;
- 使用 BM25 根据精确匹配查找排名靠前的文本块;
- 使用嵌入根据语义相似度查找排名靠前的文本块;
- 使用排名融合(Rank Fusion)技术合并来自 (3) 和 (4) 的结果并去重;
- 将排名靠前的 K 个文本块添加到提示词以生成响应。
通过结合使用 BM25 和嵌入模型,传统的 RAG 系统可以提供更全面准确的结果,平衡了精确词项匹配与广泛的语义理解。

一个标准的检索增强生成(RAG)系统,结合使用嵌入和 BM25 来检索信息。
这种方法可以让您以高成本效益扩展到巨大规模的知识库,远超单个提示词所能容纳的范围。但这些传统的 RAG 系统有一个显著的技术局限:它们往往会破坏语境。
传统 RAG 中的语境困局#
在传统 RAG 中,为了提高检索效率,文档通常被切分为小块。虽然这种方法适用于许多应用,但当日语块缺乏足够的上下文语境时,就会产生问题。
例如,假设您的知识库中有财务信息(例如美国 SEC 文件),并且您收到了以下问题:“ACME Corp 在 2023 年第二季度的营收增长是多少?”
一个相关的文本块可能包含这样的文字:“公司营收较上一季度增长了 3%。” 然而,这个文本块本身并没有说明它指的是哪家公司或哪段时期,这使得检索正确信息或有效利用信息变得非常困难。
引入语境化检索(Contextual Retrieval)#
语境化检索通过在嵌入(“语境化嵌入”)和创建 BM25 索引(“语境化 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."值得注意的是,过去也曾提出过使用语境改善检索的其他方法,包括:为文本块添加通用文档摘要(我们实验后发现收益非常有限)、假设性文档嵌入以及基于摘要的索引(我们评估后发现性能较低)。这些方法与本文提出的方案有所不同。
实现语境化检索#
当然,手动为知识库中成千上万、甚至数百万个文本块添加注释的工作量太大了。为了实现语境化检索,我们寻求 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 索引之前,将其前置添加到文本块中。
以下是实际预处理流程的示意:

语境化检索是一种提升检索准确性的预处理技术。
如果您有兴趣使用语境化检索,可以参考 我们的 Cookbook 开始实践。
使用提示词缓存降低语境化检索成本#
得益于上文提到的特殊提示词缓存功能,使用 Claude 可以以极低成本实现语境化检索。通过提示词缓存,您无需为每个文本块重复传入参考文档。只需将文档加载到缓存中一次,随后参考已缓存的内容即可。假设文本块为 800 token,文档为 8k token,语境指令为 50 token,每个文本块生成的语境为 100 token,每百万文档 token 生成语境化文本块的一次性成本仅为 1.02 美元。


