最强RAG技术?深入解析Anthropic的上下文检索与混合搜索

最强RAG技术?深入解析Anthropic的上下文检索与混合搜索

最强RAG技术?深入解析Anthropic的上下文检索与混合搜索

原创 程工  2024年10月20日 22:12 四川

RAG:融合传统与创新的信息检索技术

RAG(检索增强生成)技术正受到广泛关注,主要因为它能有效解决大语言模型的一些局限性。通过为模型(如ChatGPT)提供外部知识库的访问能力,RAG显著减少了模型生成的错误信息,同时为用户查询提供了更全面的背景信息。此外,RAG还能有效突破语言模型的上下文长度限制。

RAG的核心概念相对简单。以下是一个基本示例:

假设我们需要AI回答"李白的《静夜思》创作于何时?"我们可以按以下步骤实现:

1. 检索:从可靠来源(如百度百科)获取关于李白《静夜思》的信息。

2. 增强:将检索到的信息添加到提示中。

3. 生成:让AI模型基于增强后的提示生成回答。

这个简单的过程就构成了一个基本的RAG系统。

从架构上看,RAG系统主要包含两个核心组件:

1. 检索模块:负责从外部数据源获取相关信息。

2. 生成模块:利用检索到的信息生成最终的回答。

www.zeeklog.com  - 最强RAG技术?深入解析Anthropic的上下文检索与混合搜索

在RAG技术逐渐成为主流的过程中,人们经常过于简单化地将其等同于语义搜索或嵌入索引的构建。然而,检索技术的范畴远不止于此。事实上,信息检索的历史可以追溯到近百年前。在传统信息检索中,BM25算法是一个广泛使用的方法,以其简洁、高效著称。许多搜索引擎的核心仍然依赖于BM25等基于关键词的检索技术。

尽管RAG在提高AI模型输出质量方面展现出了显著优势,但它仍面临一些技术挑战。其中一个主要问题是,在将文档分割成小块进行检索时,容易丢失重要的上下文信息。针对这一问题,Anthropic公司提出了"上下文检索"(contextual retrieval)的概念,旨在在RAG框架内更好地保留文本的上下文信息。

上下文检索(contextual retrieval):提升RAG系统的检索精度

传统RAG系统通常将文档分割成较小的文本块以提高检索效率,但这种做法可能导致重要的上下文信息丢失。比如我们需要查询某公司的季度收入增长情况。一个相关的文本块可能是"该公司的收入比上一季度增长了3%"。这个信息虽然包含了增长百分比,但缺少公司名称和具体时间段等关键细节,可能会影响检索的准确性。

Anthropic公司最近发表的《Introducing Contextual Retrieval》论文提出了"上下文嵌入"(contextual retrieval)的创新概念。这种方法通过在嵌入过程前为每个文本块添加相关的上下文信息,有效地解决了上下文缺失的问题。

实现上下文检索可以利用大语言模型(LLM)。开发者可以设计特定的提示,指导LLM根据整个文档的内容,为每个文本块生成简洁而相关的上下文说明。如下就是一个典型的上下文检索提示词

www.zeeklog.com  - 最强RAG技术?深入解析Anthropic的上下文检索与混合搜索

提示词示例

这段提示词是用来指导AI模型(如Claude)为文档中的每个小块(chunk)生成简洁的上下文信息。让我们逐部分解析:

1. `{{WHOLE_DOCUMENT}}`:

这部分包含整个文档的内容。它为AI提供了完整的背景信息。

2. `Here is the chunk we want to situate within the whole document`:

这句话引出了需要处理的特定文本块。

3. `{{CHUNK_CONTENT}}`:

这里包含了需要添加上下文的具体文本块内容。

4. `Please give a short succinct context to situate this chunk within the overall document for the purposes of improving search retrieval of the chunk.`:

这是对AI的具体指令。它要求AI:

- 提供简短且精炼的上下文

- 将该文本块置于整个文档的语境中

- 目的是改善这个文本块在搜索中的可检索性

5. `Answer only with the succinct context and nothing else.`:

这是一个重要的限制条件,要求AI只输出上下文信息,不要添加任何其他内容。

这个提示词的目的是让AI生成一段简洁的说明,解释该文本块在整个文档中的位置和重要性。这种方法可以帮助检索系统更好地理解和定位每个文本块,从而提高检索的准确性。

通过以上提示词,我们可以将整个文档的每个文本块输入到LLM中,通过对原始文本块original_chunk的转化生成包含更多上下文信息的enhanced_chunk。

www.zeeklog.com  - 最强RAG技术?深入解析Anthropic的上下文检索与混合搜索

这个enhanced_chunk随后被送入嵌入(语义向量)模型(比如SentenceTransformers),生成更加丰富和精确的文本块嵌入(语义向量)表示。

这种方法能有效提高RAG系统的检索精度,使得系统能够更准确地找到与用户查询相关的信息。

混合搜索方法

上下文嵌入技术显著改善了传统RAG系统的检索性能,但结合上下文BM25的混合方法可以取得更好的效果。

在这种方法中,我们不仅将特定块的上下文信息用于嵌入,还将其应用于BM25索引的创建。这种双管齐下的策略进一步提升了整体的检索准确性。

BM25算法

BM25是一种先进的信息检索算法,它解决了TF-IDF(词频-逆文档频率)方法的一些缺点。具体来说,BM25主要改进了两个方面:

1. 词项饱和度问题:

BM25通过引入一种特殊的计算方法来解决TF-IDF中词频无限增长的问题。在TF-IDF中,词频与文档相关性的关系是简单的线性关系,也就是说,一个词出现的次数越多,文档的相关性就越高。然而,这种关系在现实中并不总是成立。

BM25采用了一种更加合理的方法。它认为,当一个词的出现次数达到一定程度后,继续增加并不会显著提高文档的相关性。这就像是吃饭一样,开始时你会感到很饿,每吃一口都能明显感到饱腹感增加。但随着你继续吃,即使又吃了很多,你的饱腹感增加得也不那么明显了。

举例说明:

假设我们有两篇关于"苹果公司"的文章:

- 文章A中"苹果"出现了5次

- 文章B中"苹果"出现了50次

在传统的TF-IDF方法中,文章B的相关度会比文章A高出很多,可能是10倍。但在BM25中,尽管文章B中"苹果"出现的次数是文章A的10倍,但它的得分并没有显著提高。BM25认为,当"苹果"这个词出现了5次之后,再多出现几次对文档相关性的贡献就不那么大了。这更符合我们的直觉和实际情况。

2. 文档长度问题:

BM25通过考虑文档长度来解决TF-IDF偏向于长文档的问题。在TF-IDF中,长文档往往会得到更高的分数,因为它们通常包含更多的词和更高的词频。但这并不总是合理的,因为一篇长文档并不一定比一篇短文档更相关。

BM25的做法就像是给长文档一个"惩罚"。它会考虑每个文档的长度,并将其与所有文档的平均长度进行比较。如果一个文档比平均长度长,那么它的词频得分就会被适当地降低。反之,如果一个文档比平均长度短,那么它的词频得分就会被适当地提高。

举例说明:

假设我们有两篇关于"人工智能"的文章:

- 文章C是一篇500词的短文,其中"人工智能"出现了5次

- 文章D是一篇2000词的长文,其中"人工智能"出现了15次

在传统的TF-IDF方法中,文章D可能会得到更高的分数,因为它包含了更多的"人工智能"一词。但在BM25中,情况就不一样了。BM25会考虑到文章D的长度是文章C的4倍,因此会对文章D的得分进行一定程度的降低。这样一来,尽管文章D中"人工智能"出现的次数是文章C的3倍,但在BM25中,它的最终得分可能并不会比文章C高出太多。

通过这些改进,BM25能够更准确地评估文档相关性,不仅考虑了词频,还考虑了词频的饱和效应和文档长度的影响,因此在实际应用中往往能够取得比TF-IDF更好的效果。这种方法更符合我们对文档相关性的直觉理解,也能够在搜索结果中提供更加公平和准确的排序。

尽管传统的关键词匹配检索方法效果显著,但它可能无法准确把握文本的深层含义,因此有时会遗漏重要的相关文档。这时,语义化检索技术就能弥补这一不足。

语义向量检索(又称深度语义检索)

这种技术将文本转换为语义向量,简单来说就是用一组数值来表示文字(甚至图像、声音)的语义信息。语义向量的目标是保留原始内容的核心语义特征。在执行搜索时,系统会将查询内容转换为同一向量空间中的向量,然后通过计算向量间的距离来识别与查询最相关的文本段落或文档。

余弦相似度是语义向量检索中常用的相似度计算方法,它通过计算两个向量之间夹角的余弦值来衡量它们的语义相似程度。余弦相似度越接近1,表示两个向量在语义上的重合度越高,也就意味着它们所代表的内容含义越接近。

比如,"春天来了,花儿开了"这句话的语义向量应该与"秋高气爽,树叶变黄"的相似度要高于"量子计算机的发展前景",因为前两句在描述自然季节变化这一语义主题上更为接近。

在实际应用中,向量搜索通常通过最近邻搜索来实现。给定一个查询,目标是找出k个最相似的向量。k-最近邻(k-NN)算法是一种直接的方法:

首先,计算查询嵌入向量与所有存储向量之间的相似度得分,通常采用余弦相似度。

然后,根据相似度得分对这些向量进行排序。

最后,选择得分最高的前k个向量。

融合搜索:上下文增强的BM25与上下文嵌入相结合

Anthropic提出了一种创新的融合搜索方法,巧妙地结合了上下文增强的BM25技术和上下文语义嵌入。这种方法利用倒数排名融合(Reciprocal Rank Fusion)算法来整合两种检索结果,从而得出最终的相关性排序。

www.zeeklog.com  - 最强RAG技术?深入解析Anthropic的上下文检索与混合搜索

重排序Reranking

在传统的 RAG 中,AI 系统会搜索其知识库以查找潜在相关的信息块。对于大型知识库,此初始检索通常会返回大量(有时是数百个)具有不同相关性和重要性的块。

重新排序是一种常用的过滤技术,可确保仅将最相关的块传递给模型。重新排序可提供更好的响应并降低成本和延迟,因为模型处理的信息更少。关键步骤如下:

执行初步检索以获取前几个可能相关的块;

将前 N 个块连同用户的查询一起传递到重新排名模型;

使用重新排序模型,根据每个块与提示的相关性和重要性为其赋予分数然后选择前 K 个块;

将前 K 个块作为上下文传递到模型中以生成最终结果。

权重分配

这种融合式方法的效果在很大程度上取决于在倒数排序过程中,语义检索和BM25检索结果各自被赋予的相对权重。通过调整这些相对权重,我们可以控制每种检索方式对最终排序的影响程度。

如果我们为语义检索分配较高的权重,而为BM25分配较低的权重,那么在语义检索中表现出色的文本片段(由于其权重更高)很可能在最终结果中获得更高的排名。

举个例子,假设我们将BM25的权重设为0.2,而将嵌入式检索的权重设为0.8。在这种情况下,嵌入式检索中排名第20位的项目对最终得分的贡献,将等同于BM25检索中排名第5位的项目。

www.zeeklog.com  - 最强RAG技术?深入解析Anthropic的上下文检索与混合搜索

检索流程

进行语义搜索

进行BM25搜索

使用指定的权重来合并这两种搜索的结果

使用倒数排名融合(Reciprocal Rank Fusion)方法来计算最终得分

这种混合方法的核心在于充分利用了BM25在精确匹配方面的优势和语义嵌入在捕捉语义关系方面的长处。通过上下文增强,两种方法都得到了显著改进,重新排序的上下文嵌入和上下文 BM25 融合搜索将前 20 个块检索失败率降低了 67%(5.7% → 1.9%)

www.zeeklog.com  - 最强RAG技术?深入解析Anthropic的上下文检索与混合搜索

结论

Anthropic提出的上下文检索和混合搜索技术为RAG系统带来了新的突破。通过巧妙地结合上下文BM25和上下文嵌入,这种方法不仅提高了检索的准确性,还增强了系统对上下文的理解能力。这种混合方法的优势在于它能够同时利用关键词匹配和语义相关性,从而在各种查询场景中都能表现出色。通过调整BM25和语义搜索的权重,我们可以灵活地适应不同类型的问题和数据集,实现检索效果的最优化。

参考及附图来源:

1.https://www.anthropic.com/news/contextual-retrieval

2.https://github.com/anthropics/anthropic-cookbook/blob/main/skills/contextual-embeddings/guide.ipynb

Read more

深入理解 Proxy 和 Object.defineProperty

在JavaScript中,对象是一种核心的数据结构,而对对象的操作也是开发中经常遇到的任务。在这个过程中,我们经常会使用到两个重要的特性:Proxy和Object.defineProperty。这两者都允许我们在对象上进行拦截和自定义操作,但它们在实现方式、应用场景和灵活性等方面存在一些显著的区别。本文将深入比较Proxy和Object.defineProperty,包括它们的基本概念、使用示例以及适用场景,以帮助读者更好地理解和运用这两个特性。 1. Object.defineProperty 1.1 基本概念 Object.defineProperty 是 ECMAScript 5 引入的一个方法,用于直接在对象上定义新属性或修改已有属性。它的基本语法如下: javascript 代码解读复制代码Object.defineProperty(obj, prop, descriptor); 其中,obj是目标对象,prop是要定义或修改的属性名,descriptor是一个描述符对象,用于定义属性的特性。 1.2 使用示例 javascript 代码解读复制代码//

By Ne0inhk

Proxy 和 Object.defineProperty 的区别

Proxy 和 Object.defineProperty 是 JavaScript 中两个不同的特性,它们的作用也不完全相同。 Object.defineProperty 允许你在一个对象上定义一个新属性或者修改一个已有属性。通过这个方法你可以精确地定义属性的特征,比如它是否可写、可枚举、可配置等。该方法的使用场景通常是需要在一个对象上创建一个属性,然后控制这个属性的行为。 Proxy 也可以用来代理一个对象,但是相比于 Object.defineProperty,它提供了更加强大的功能。使用 Proxy 可以截获并重定义对象的基本操作,比如访问属性、赋值、函数调用等等。在这些操作被执行之前,可以通过拦截器函数对这些操作进行拦截和修改。因此,通过 Proxy,你可以完全重写一个对象的默认行为。该方法的使用场景通常是需要对一个对象的行为进行定制化,或者需要在对象上添加额外的功能。 对比 以下是 Proxy 和 Object.defineProperty 的一些区别对比: 方面ProxyObject.defineProperty语法使用 new Proxy(target,

By Ne0inhk