为了让 AI 模型在特定环境中有用,它通常需要访问背景知识。如客服聊天机器人需要了解它所服务的特定业务,法律分析机器人则需要掌握大量的过往案例。
开发者通常通过 RAG扩展 AI 模型的知识。RAG 是一种从知识库中检索相关信息并将其附加到用户提示词中的方法,从而显著提升模型的回答能力。但传统的 RAG 解决方案在编码信息时会丢失上下文,导致系统无法从知识库中检索到相关信息。
本文介绍了一种显著提升 RAG 检索步骤的方法,称为“上下文检索”,它利用两个子技术:
该方法可将检索未命中率减少49%,结合重新排序后,甚至可减少67%。这些改进显著提高检索准确性,进而提升下游任务表现。
可通过操作指南轻松部署自己的上下文检索解决方案。
有时最简单的解决方案就是最好。如你的知识库小于 200,000 个 token(约 500 页材料),你可直接将整个知识库包含在给模型的提示词中,无需 RAG 或类似方法。
Claude 已发布提示词缓存,可显著加快并更实惠。开发者现可在 API 调用之间缓存常用提示词,减少超过 2 倍的延迟,降低高达 90% 的成本(阅读提示词缓存操作指南)。
然而,随知识库增长,你需要一个更具扩展性的解决方案。这时,上下文检索就派上用场。
对于无法放入上下文窗口的更大知识库,RAG 是典型的解决方案。RAG 通过以下步骤预处理知识库:
在运行时,当用户向模型输入查询时,向量数据库用于根据查询的语义相似性查找最相关的文本块。然后,将最相关的文本块添加到发送给生成模型的提示词中。
尽管嵌入模型擅长捕捉语义关系,但它们可能会错过重要的精确匹配。幸运的是,有一种较老的技术可以在这些情况下提供帮助。BM25(最佳匹配 25)是一种排名函数,使用词汇匹配来查找精确的单词或短语匹配。对于包含唯一标识符或技术术语的查询,它特别有效。
BM25 基于 TF-IDF(词频-逆文档频率)的概念。TF-IDF 衡量一个单词在文档集合中的重要性。BM25 通过考虑文档长度并对词频应用饱和函数来改进这一点,这有助于防止常见词主导结果。
以下是 BM25 在语义嵌入失败时的成功之处:假设用户查询“错误代码 TS-999”在技术支持数据库中的信息。嵌入模型可能会找到有关错误代码的内容,但可能会错过精确的“TS-999”匹配。而 BM25 则通过查找这个特定的文本字符串来识别相关文档。
通过结合嵌入和 BM25 技术,RAG 解决方案可以更准确地检索到最适用的文本块,以下是步骤:
通过利用 BM25 和嵌入模型,传统的 RAG 系统可以提供更全面和准确的结果,平衡精确术语匹配和广泛语义理解。
这种方法可以让你以低成本扩展到庞大的知识库,远超单个提示词所能容纳的范围。但传统 RAG 系统有一个显著的局限:它们往往破坏上下文。
在传统 RAG 中,文档通常被拆分为较小的块,以便于检索。尽管这种方法在许多应用中表现良好,但当单个文本块缺乏足够的上下文时,可能会导致问题。
例如,假设你的知识库中嵌入了一个财务信息集合(比如美国证券交易委员会的文件),你收到如下问题:“2023 年第二季度 ACME 公司收入增长了多少?”
一个相关的文本块可能包含:“公司收入比上一季度增长了 3%。”然而,这个块本身并未指明是哪家公司或哪个时间段,导致很难检索到正确的信息或有效使用这些信息。
上下文检索通过在嵌入前将块特定的解释性上下文添加到每个块中(“上下文嵌入”)以及创建 BM25 索引(“上下文 BM25”)来解决此问题。
让我们回到美国证券交易委员会文件的例子。以下是一个文本块的转换示例:
原始文本块 = “公司收入比上一季度增长了 3%。”
上下文化文本块 = “本块来自 ACME 公司 2023 年第二季度的证券交易委员会文件;上一季度的收入为 3.14 亿美元。公司收入比上一季度增长了 3%。”
值得注意的是,过去曾提出过其他使用上下文改进检索的方法。其他提案包括:为文本块添加通用文档摘要(我们实验后发现效果有限),使用假设文档嵌入(我们评估后发现效果不佳),以及基于摘要的索引(我们实验后表现不佳)。这些方法与本文提出的方案不同。
当然,手动为知识库中的成千上万个块注释上下文太费力。为实现上下文检索,我们转向了 Claude。我们编写了一个提示词,指示模型提供简洁、特定于块的上下文,使用整个文档的上下文来解释该块。我们使用了以下 Claude 3 Haiku 提示词为每个块生成上下文:
<document>
{{WHOLE_DOCUMENT}}
</document>
这是我们希望在整个文档中定位的块
<chunk>
{{CHUNK_CONTENT}}
</chunk>
请提供简短的上下文,以便在文档中更好地定位此块以改进搜索检索。只回答简短的上下文,别无其他。
生成的上下文文本通常为 50 到 100 个 token,将其附加到文本块之前进行嵌入并创建 BM25 索引。
实际预处理流程的示意图:
如果你有兴趣使用上下文检索,可通过我们的操作指南入手。
得益于 Claude 的特殊提示词缓存功能,上下文检索在低成本上具有独特优势。使用提示词缓存,你无需为每个块传入参考文档。你只需将文档一次性加载到缓存中,然后引用先前缓存的内容。假设每个块 800 个 token,文档 8,000 个 token,50 个 token 的上下文指令,以及每个块 100 个 token 的上下文,生成上下文化块的一次性成本为每百万文档 token 1.02 美元。
方法论
在各个知识领域(代码库、小说、ArXiv 论文、科学论文)、嵌入模型、检索策略和评估指标之间进行了实验。附录 II中提供了一些问题和答案的示例。
下图显示了在所有知识领域中使用最优嵌入配置(Gemini Text 004)并检索前 20 个块的平均表现。我们使用 1 减去 Recall@20 作为评估指标,它衡量前 20 个块中未能检索到相关文档的百分比。你可以在附录中看到完整结果——上下文化提高了我们评估的每种嵌入源组合的表现。
性能提升
实验表明:
实施考虑
在实施上下文检索时,需要考虑以下几点:
始终进行评估:通过传递上下文化的文本块并区分上下文和块内容,生成的响应可能会得到改进。
最后一步,我们可以结合上下文检索与另一种技术,以进一步提升性能。在传统 RAG 中,AI 系统会在其知识库中搜索潜在的相关信息块。当知识库很大时,这种初始检索往往会返回大量块——有时成百上千块,且相关性和重要性各不相同。
重新排序是一种常用的过滤技术,确保只有最相关的文本块被传递给模型。重新排序能提供更好的响应,并减少成本和延迟,因为模型处理的信息更少。关键步骤如下:
市场上有多种重新排序模型。我们使用 Cohere reranker 进行了测试。Voyage 也提供了重新排序器,但我们没有时间进行测试。我们的实验表明,跨多个领域,添加重新排序步骤进一步优化了检索。
具体而言,我们发现,重新排序后的上下文嵌入和上下文 BM25 将前 20 个块检索未命中率降低了 67%(5.7% → 1.9%)。
成本和延迟考虑
重新排序的一个重要考虑因素是对延迟和成本的影响,尤其是在对大量文本块进行重新排序时。因为重新排序在运行时增加了额外的步骤,必然会增加少量延迟,尽管重新排序器会并行对所有文本块进行评分。在检索更多文本块以提高性能与检索较少文本块以降低延迟和成本之间存在权衡。我们建议在你的具体用例上进行不同设置的实验,找到合适的平衡点。
大量测试比较上述所有技术(嵌入模型、BM25 的使用、上下文检索的使用、重新排序的使用,以及检索的前 K 个结果总数)的不同组合,跨各种数据集类型。以下是我们的发现摘要:
我们鼓励所有使用知识库的开发者通过我们的操作指南进行实验,以解锁新的性能水平。
以下是数据集、嵌入提供商、BM25 与嵌入结合使用、上下文检索的使用、重新排序的使用以及前 20 个检索结果的表现细分。
关于前 10 和前 5 个检索结果的细分以及每个数据集的示例问题和答案,请参见附录 II。
参考:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。