微信扫码
与创始人交个朋友
我要投稿
为了让 AI 模型在特定情境中发挥作用,它通常需要访问背景知识。比如,客户支持聊天机器人需要了解它们所应用的特定企业的信息,而法律分析机器人则需要掌握大量过往的知识。
开发者通常使用检索增强生成(RAG)方法来增强AI模型的知识。RAG 是一种从知识库中检索相关信息并将其附加到用户提示中的方法,这大大提升了模型的响应能力。然而,传统的 RAG 解决方案在编码信息时往往会失上下文,这常常导致系统无法从知识库中检索到相关信息。
在这篇文章中,我们将介绍一种能显著改进 RAG 中检索步骤的方法。这个方法被称为“上下文检索”,它使用了两种子技术:上下文嵌入和上下文 BM25。通过这种方法,可以将检索失败的次数减少49%,如果结合重排序技术,甚至可减少67%。这些都是检索准确率上的重大提升,直接提高了后续任务的表现。
您可以通过Claude的操作指南,轻松地使用 Claude 部署自己的上下文检索解决方案。
有时候,最简单的解决方案就是最好的。如果您的知识库少于 200,000 个标记(大约500 页的材料),您可以直接将整个知识库包含在提供给模型的提示中,而无需使用 RAG 或类似方法。
几周前, Claude 推出了提示缓存功能[1],这使得这种方法显著更快且更具成本效益。开发者现在可以在 API 调用之间缓存常用的提示,从而将延迟减少超过 2 倍,并将成本降低多达 90%(您可以通过阅读我们的提示缓存操作指南[2]来了解其工作原理)。
然而,随着知识库的增长,您将需要一个更具扩展性的解决方案。这就是上下文检索的用武之地。
对于无法在上下文窗口内容纳的大型知识库,RAG 是一种典型的解决方案。RAG 通过以下步骤预处理知识库:
1. 将知识库(文档的“语料库”)拆分成较小的文本块,通常不超过几百个标记;
2. 使用嵌入模型将这些文本块转换为向量嵌入,以编码其语义;
3. 将这些嵌入存储在一个向量数据库中,以便通过语义相似度进行搜索。
在运行时,当用户向模型输入查询时,向量数据库会根据查询的语义相似度找到最相关的文本块。然后,这些最相关的文本块会被添加到发送给生成模型的提示中。
尽管嵌入模型在捕捉语义关系方面表现出色,但它们可能会错过关键的精确匹配。幸运的是,有一种较老的方法可以在这些情况下提供帮助。BM25(最佳匹配25)是一种使用词汇匹配来找到精确词语或短语匹配的排名函数。对于包含唯一标识符或技术术语的查询,它尤其有效。
BM25 的工作原理基于 TF-IDF(词频-逆文档频率)的概念。TF-IDF 衡量一个词在文档集合中的重要性。BM25 通过考虑文档长度并将饱和函数应用于词频来完善这一点,这有助于防止常用词主导结果。
BM25 在语义嵌入失效之处的成功之处在于:假设用户在技术支持数据库中查询“错误代码 TS-999”。嵌入模型可能会找到有关错误代码的一般内容,但可能会错过“TS-999”的精确匹配。BM25 则会寻找这个特定的文本字符串来识别相关文档。
通过结合嵌入和 BM25 技术,RAG 解决方案可以更准确地检索到最适用的文本块,具体步骤如下:
1. 将知识库(文档的“语料库”)拆分成较小的文本块,通常不超过几百个标记;
2. 为这些文本块创建 TF-IDF 编码和语义嵌入;
3. 使用 BM25 查找基于精确匹配的顶级文本块;
4. 使用嵌入模型查找基于语义相似度的顶级文本块;
5. 使用排序融合技术合并和去重步骤 (3) 和 (4) 的结果;
6. 将 Top-K 的文本块添加到提示中以生成响应。
通过同时利用 BM25 和嵌入模型,传统的 RAG 系统能够提供更全面和准确的结果,既平衡了精确术语匹配,又兼顾了更广泛的语义理解。
一个标准的检索增强生成(RAG)系统结合了嵌入和最佳匹配25(BM25)技术来检索信息。TF-IDF(词频-逆文档频率)用于衡量词语的重要性,并构成了 BM25 的基础。
这种方法使您能够以经济高效的方式扩展到巨大的知识库,远远超出单个提示可以容纳的范围。但这些传统的 RAG 系统存在一个显著限制:它们常常破坏上下文。
在传统的 RAG 系统中,通常将文档拆分成较小的文本块以便于高效检索。虽然这种方法在许多应用中效果良好,但当单个文本块缺乏足够的上下文时,可能会导致问题。
例如,假设您的知识库中嵌入了一系列财务信息(比如,美国 SEC 文件),并且您收到以下问题:“2023 年第二季度 ACME 公司的收入增长是多少?”
一个相关的文本块可能包含这样的内容:“公司收入比上一季度增长了 3%。”然而,这个文本块本身并未具体说明它指的是哪家公司或相关的时间段,这使得很难检索到正确的信息或有效地使用这些信息。
上下文检索通过在嵌入之前为每个文本块添加特定的解释性上下文(“上下文嵌入”)以及创建 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 个标记)添加到文本块的前面,然后进行嵌入和创建 BM25 索引之前的处理。
这一预处理步骤确保了在生成嵌入和 BM25 索引时,文本块中包含了足够的上下文信息,从而提高了检索的准确性和相关性。通过这种方式,信息的语义和词汇匹配能力都能得到有效的提升。
在实际操作中,预处理流程看起来是这样的:
如果你对使用上下文检感兴趣,可以从我们的指南开始[3]。
由于我们之前提到的特殊提示缓存功能,使用Claude进行上下文检索可以以低成本实现。通过提示缓存功能,你不需要为每个数据块传递参考文档。只需将文档加载到缓存中一次,然后引用之前缓存的内容即可。假设每个数据块包含800个标记,文档包含8000个标记,50个标记用于上下文指令,每个数据块包含100个上下文标记,那么生成上下文化数据块的一次性成本仅为每百万文档标记1.02美元。
我们在不同的知识领域(代码库、小说、ArXiv论文、科学论文)、嵌入模型、检索策略和评估指标上进行了实验。在附录II[4]中,我们列出了每个领域中使用的一些问题和答案示例。
下方的图表展示了在所有知识领域中使用表现最佳的嵌入配置(Gemini Text 004)和检索前20个数据块时的平均表现。我们使用1减去召回率@20作为评估指标,该指标衡量在前20个数据块中未能检索到的相关文档的百分比。完整结果见附录——上下文化我们评估的每种嵌入来源组合中都提升了性能。
我们的实验表明:
• 上下文嵌入将前20个数据块的检索失败率降低了35%(从5.7%降至3.7%)。
• 结合上下文嵌入和上下文BM25,将前20个数据块的检索失败率降低了49%(从5.7%降至2.9%)。
在实施上下文检索时,有几个方面需要注意:
1. 数据块边界:考虑如何将文档划分为数据块。数据块的大小、边界和重叠选择会影响检索性能。
2. 嵌入模型:虽然上下文检索提升了我们测试的所有嵌入模型的性能,但某些模型可能受益更多。我们发现Gemini和Voyage嵌入特别有效。
3. 定制化的上下文提示:虽然我们提供的通用提示效果良好,但针对特定领域或用例定制化的提示可能带来更好的效果(例如,包括在知识库其他文档中定义的关键术语的词汇表)。
4. 数据块数量:在上下文窗口中添加更多数据块可以增加包含相关信息的几率。然而,信息过多可能会分散模型的注意力,因此这方面存在限制。我们尝试了传递5、10和20个数据块,发现使用20个数据块时表现最佳(参见附录中的比较),但在具体应用中值得进行实验。
始终运行评估:通过传递上下文化的数据块并区分上下文和数据块内容,可能改善响应生成。
在最后一步中,我们可以将上下文检索与另一种技术结合,以获得更大的性能提升。在传统的RAG中,AI系统搜索其知识库以找到潜在相关的信息块。在大型知识库中,初始检索通常会返回大量数据块——有时多达数百个,相关性和重要性各不相同。
重排序是一种常用的过滤技术,确保只有最相关的数据块传递给模型。重排序提供更好的响应,同时减少成本和延迟,因为模型处理的信息更少。关键步骤包括:
1. 执行初始检索以获取潜在相关的顶级数据块(我们使用了前150个);
2. 将前N个数据块与用户查询一起传递给重排序模型;
3. 使用重排序模型,根据数据块与提示的相关性和重要性为每个数据块打分,然后选择前K个数据块(我们使用了前20个);
4. 将前K个数据块作为上下文传递给模型以生成最终结果。
市场上有多个重新排序模型。在我们的中,我们使用了Cohere的重新排序器。Voyage也提供了一种重新排序器,但我们没有时间测试它。我们的实验表明不同领域中,加入重新排序步骤可以进一步优化信息检索。
具体来说,我们发现使用重新排序的上下文嵌入和上下文BM25,使前20个块的检索失败率降低了67%(从5.7%降至1.9%)。
在重新排序时,一个重要的考虑因素是其对延迟和成本的影响,特别是在对大量块进行重新排序时。由于重新排序在运行时增加了一个额外的步骤,即使重新排序器可以并行评分所有块,也不可避免地会增加少量的延迟。这里存在一个固有的权衡:更好的性能重新排序更多的块,还是为了更低的延迟和而重新排序更少的块。我们建议在您的特定用例中尝试不同的设置,以找到最佳衡。
我们进行了大量测试,比较了以上提到的各种技术组合(嵌入模型、BM25的使用、上下文检索的使用、重新排序器的使用和检索的总前K个结果),涵盖了各种不同的数据集类型。以下是我们的发现总结:
• 嵌入+BM25优于单独使用嵌入;
• 在我们测试的嵌入中,Voyage和Gemini表现最佳;
• 向模型提供前20个块比仅提供前10或前5个块更有效;
• 为块添加上下文可以显著提高检索准确性;
• 重新排序优于不进行重新排序;
• 所有这些优势是可以叠加的:为最大化性能提升,可以结合使用上下文嵌入(来自Voyage或Gemini)和上下文BM25,再加上重新排序步骤,并在提示中加入20个块。
以下是跨数据集、嵌入提供商、在嵌入之外使用BM25、使用上下文检索和在前20个检索中使用重新排序的结果分析。
请参阅附录II,了解前10和前5个检索的结果分析以及每个数据集的示例问题和答案。
53AI,企业落地应用大模型首选服务商
产品:大模型应用平台+智能体定制开发+落地咨询服务
承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业
2024-11-22
如何使用 RAG 提高 LLM 成绩
2024-11-21
提升RAG性能的全攻略:优化检索增强生成系统的策略大揭秘 | 深度好文
2024-11-20
FastGraphRAG 如何做到高达 20%优化检索增强生成(RAG)性能优化
2024-11-20
为裸奔的大模型穿上"防护服":企业AI安全护栏设计指南
2024-11-20
RAG-Fusion技术在产品咨询中的实践与分析
2024-11-19
构建高性能RAG:文本分割核心技术详解
2024-11-19
【RAG竞赛获奖方案】CCF第七届AIOps国际挑战赛季军方案分享EasyRAG:一个面向AIOps的简洁RAG框架
2024-11-19
企业RAG构建中,如何用“行级别权限管控”避免数据泄露
2024-07-18
2024-05-05
2024-07-09
2024-07-09
2024-05-19
2024-06-20
2024-07-07
2024-07-07
2024-07-08
2024-07-09
2024-11-06
2024-11-06
2024-11-05
2024-11-04
2024-10-27
2024-10-25
2024-10-21
2024-10-21