在知识库问答等场景中,RAG已经成为当下最流行的LLM应用范式,为LLM提供又全又准的上下文信息是众多RAG技术努力的方向。在传统的 RAG 解决方案中,编码信息时往往会丢失上下文,这导致系统无法从知识库中检索到相关信息,如何能够更好地保留上下文信息成为了问题关键。Anthropic 研究团队提出了“Contextual Retrieval(上下文检索)”的创新方法在此领域取得了显著进展。近日,他们发表文章[1]可披露了这一技术的细节,他们通过上下文嵌入(Contextual Embeddings)和上下文 BM25(Contextual BM25)(文本检索)可以将检索失败率减少 49%,联合重排序(reranking),失败率可减少 67%。上下文检索的创新点
传统的 RAG 系统在分割文档时会破坏上下文,导致检索到的信息分块缺乏足够的背景信息。例如,假设你有一个包含财务信息的知识库,并收到以下问题:“ACME 公司在 2023 年第二季度的收入增长是多少?”一个相关的分块可能包含这样的文本:“公司的收入比上一季度增长了 3%。”然而,这个分块本身并没有指定是哪家公司或相关的时间段,导致难以检索到正确的信息或有效地使用这些信息。研究团队尝试过一些业内流行的改进措施,诸如:分块中添加文档摘要(adding generic document summaries to chunks)[2],假设文档嵌入(hypothetical document embedding)[3],以及索引摘要(summary-based indexing)[4],但都效果不佳。ingFang SC", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;">他们通过大量实验摸索,采用上下文检索时通过在嵌入前为每个分块添加特定的解释性上下文(Contextual Embeddings)和创建 BM25 索引(Contextual BM25)来解决这个问题。例如:原始分块 = "公司的收入比上一季度增长了3%。"
上下文化分块 = "这个分块来自ACME公司在2023年第二季度的SEC文件;上一季度的收入为3.14亿美元。公司的收入比上一季度增长了3%。"
ingFang SC", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;">这种方法显著提高了检索的准确性,特别是在处理包含特定标识符或技术术语的查询时。如何实现上下文检索
手动为知识库中的成千上万个分块添加上下文显然是不现实的。为此,研究团队使用了 Claude 模型,通过一个特定的提示生成每个分块的简洁上下文,生成的上下文通常为 50-100 个 token,然后在嵌入和创建 BM25 索引之前将其添加到分块中。ingFang SC", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;">这是官方 prompt 示例:<document>
{{WHOLE_DOCUMENT}}
</document>
Hereisthechunkwewanttosituatewithinthewholedocument
<chunk>
{{CHUNK_CONTENT}}
</chunk>
Pleasegiveashortsuccinctcontexttosituatethischunkwithintheoveralldocumentforthepurposesofimprovingsearchretrievalofthechunk.Answeronlywiththesuccinctcontextandnothingelse.

以下是详细的实现步骤:
ingFang SC", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;">首先,研究团队使用 Claude 为每个分块生成上下文。通过设计一个特定的提示,Claude 可以为每个分块生成简洁而有意义的上下文。ingFang SC", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;">例如,假设我们有一个分块:“公司的收入比上一季度增长了3%。”
ingFang SC", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;">我们可以设计一个提示,让 Claude 生成上下文:“请为以下分块生成一个简洁的上下文:‘公司的收入比上一季度增长了3%。’”
ingFang SC", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;">Claude 可能会生成以下上下文:“这个分块来自ACME公司在2023年第二季度的SEC文件;上一季度的收入为3.14亿美元。公司的收入比上一季度增长了3%。”
ingFang SC", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;">生成上下文后,将其添加到原始分块中。这样,每个分块都包含了足够的背景信息,便于后续的检索和使用。上下文化分块 = "这个分块来自ACME公司在2023年第二季度的SEC文件;上一季度的收入为3.14亿美元。公司的收入比上一季度增长了3%。"
ingFang SC", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;">接下来,使用嵌入模型将上下文化分块转换为向量嵌入。向量嵌入是高维空间中的点,表示文本的语义含义。常用的嵌入模型包括 Voyage 和 Gemini,它们在实验中表现出色。嵌入向量 = 嵌入模型(上下文化分块)
ingFang SC", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;">除了生成嵌入,还需要为上下文化分块创建 BM25 索引。BM25 是一种基于词频和逆文档频率的检索算法,能够有效地衡量文本分块与查询之间的相关性。BM25索引 = BM25模型(上下文化分块)
将生成的嵌入向量和 BM25 索引存储在向量数据库和 BM25 索引库中。这样,当用户输入查询时,系统可以同时使用嵌入向量和 BM25 索引进行检索,从而找到最相关的上下文化分块。
向量数据库.存储(嵌入向量)
BM25索引库.存储(BM25索引)
在检索到相关分块后,使用重排序技术对分块进行过滤和排序,确保只有最相关的分块被传递给生成模型。重排序可以显著提高检索的准确性和相关性。
相关分块 = 向量数据库.检索(查询)
重排序分块 = 重排序模型(相关分块)
在实现上下文检索时,研究团队特别指出需要考虑以下几点:
- 分块策略:考虑如何将文档分割成分块。分块大小、边界和重叠的选择会影响检索性能。
- 嵌入模型:选择合适的嵌入模型,对提高上下文检索性能帮助更大, Gemini[5] 和Voyage[6]在测试中表现更好。
- 自定义上下文提示:虽然通用提示效果良好,但仍然可能需要针对一些场景定制提示来获得更好的结果。
- 分块的数量:将更多的块添加到上下文窗口中,增加了包含相关信息的可能性。然而,过多的信息可能会使模型分心,因此存在一个限制。研究团队尝试了提供 5、10 和 20 块,发现使用 20 块在这三个选项中表现最佳,但仍然在一些具体场景中进行实验选择。
- 持续评估:通过将上下文化的语块传递给响应生成器,并区分上下文和语块,可以改进响应生成。
效果如何
研究团队的实验结果显示:
- 上下文嵌入将前 20 个分块的检索失败率减少了 35%(从 5.7%降至 3.7%)。
- 结合上下文嵌入和上下文 BM25 将前 20 个分块的检索失败率减少了 49%(从 5.7%降至 2.9%)。

同时,利用提示缓存技术降低了使用成本。通过提示缓存,您不需要为每一块都传递参考文档。您只需将文档加载到缓存中一次,然后引用之前缓存的内容即可。假设每块有 800 个 token,8k 个 token 的文档,50 个 token 的上下文指令,以及每块 100 个 token 的上下文,生成上下文化块的一次性成本为每百万文档 token1.02 美元。
联合重排序进一步提升性能

在传统 RAG 中,AI 系统会从知识库中检索到大量潜在相关的信息分块。对于大型知识库,这一初始检索往往会返回大量分块,有时多达数百个,且相关性和重要性各不相同。重排序是一种常用的过滤技术,确保只有最相关的分块被传递给模型。实验结果显示,重排序后的上下文嵌入和上下文 BM25 将前 20 个分块的检索失败率减少了 67%(从 5.7%降至 1.9%)。

同时注意,由于重排序在运行时增加了额外的步骤,即使所有分块都是并行评分,也必然会增加一小部分延迟,在重排序大量分块时表现更加明显。重排序在使用更多分块以获得更好性能与更少分块以降低延迟和成本之间存在取舍,这需要在具体的场景下尝试不同的设置,以找到合适的平衡点。
总结
研究团队通过大量的实验,为大家指出了一个新的提升 RAG 性能的方法,为开发者指出了实践新方向。
同时,研究团队基于大量实验的结果,给出了一些关键的经验总结:
- 嵌入+BM25 比单独使用嵌入效果更好(向量检索与文本检索相结合);
- Voyage 和 Gemini 是测试中效果最好的嵌入模型;
- 将前 20 个分块传递给模型比仅传递前 10 个或前 5 个分块更有效;
- 所有这些改进措施可以叠加:结合上下文嵌入(Voyage 或 Gemini)、上下文 BM25 和重排序步骤,并将前 20 个分块添加到提示中,可以最大化性能提升。
对于该方法感兴趣的读者,可以在cookbook[7]指导下上手体验。