ToB企服应用市场:ToB评测及商务社交产业平台

标题: 向量+稀疏向量+全文搜刮+张量 = 最佳 RAG 搭配 ? [打印本页]

作者: 守听    时间: 2024-9-19 13:54
标题: 向量+稀疏向量+全文搜刮+张量 = 最佳 RAG 搭配 ?
开源 AI 原生数据库 Infinity 0.2 release 正式发布,提供了 2 种新数据类型:稀疏向量 Sparse Vector 和 张量 Tensor,在此前的全文搜刮和向量搜刮之外, Infinity 提供了更多的召回本领,如下图所示,用户可以采用恣意 N 路召回(N ≥ 2)举行肴杂搜刮,这是目前功能最强大的 RAG 专用数据库。

为什么需要肴杂搜刮(多路召回)?
我们知道,仅仅依靠向量搜刮(默认情况下,它用来特指稠密向量)并不总能提供令人满意的结果。当用户标题中的特定关键词与存储的数据禁绝确匹配时,这种标题尤为明显。这是因为向量本身不具备精确语义表征能力:一个词,一句话,以致一篇文章,都可以只用一个向量来表示,这时向量本质上表达的是这段笔墨的“语义”,也就是这段笔墨跟其他笔墨在一个上下文窗口内共同出现概率的压缩表示 ,因此向量天然无法表示精确的查询。例如如果用户扣问“2024年3月我们公司财务计划包含哪些组合”,那么很可能得到的结果是其他时间段的数据,或者得到运营计划,营销管理等其他类型的数据。
因此,在一种好的解决方案是,利用基于关键词的全文搜刮提供精确查询,它跟向量搜刮共同工作,这就是全文搜刮 + 向量搜刮 的 2 路召回,又被称为肴杂搜刮(hybrid search)。
多路召回,在 RAG 的使用场景中,有时间还被解释为其他选择:
一种是仍然用向量搜刮,但是采用多种方式将改写查询,然后归并多个查询的返回结果,这实在解决的仍然是向量本身语义表征粒度难以控制的标题,并不能解决向量无法举行精确查询的标题。
另一种就是引入稀疏向量,跟稠密向量组合到一起提供肴杂搜刮(hybrid search)。稀疏向量跟稠密向量并不是一回事,它并没有稠密向量那种针对语义的压缩表示,而是试图针对全文搜刮的一种替代,它解决的是全文搜刮过程中如何针对倒排索引的词典进一步对关键词举行裁剪、扩展和界说权重。这样,一篇原始文档,就可以用这些裁剪后的关键词构成的稀疏向量来表征。例如下边的例子,上边是稠密向量,下边则是稀疏向量,它的维度一般要远高于稠密向量,例如会有3万维,由于大多数维度并没有值,因此可以采用 (位置,值)的情势表达向量中每个存在权重的维度。
  1. [0.2, 0.3, 0.5, 0.7,......]
  2. [{331: 0.5}, {14136: 0.7}]
复制代码
把文本转为稀疏向量最着名和有代表性的工作就是 SPLADE (参考文献[1]),它利用一个标准的预训练数据,将文档中的冗余词删除,而且增加扩展词,从而形成一个标准的 3 万维的稀疏向量输出。这里的冗余词删除,实在就类似传统搜刮引擎中分词过程中的“去停用词”(在构建索引的过程中,将英文中的the、a、等频率很高但信息密度很低的词跳过,这并不影响团体召回的结果,中文也同样的道理);增加相应扩展,也类似传统搜刮引擎的查询同义词等扩展技能。站在使用的角度,它可以把任何文档都表征为一个 3 万维的稀疏向量,向量每个维度表征这个单词的权重。在典范的信息检索( Information Retrieval) 评测使命中,采用 SPLADE 稀疏向量取得了比传统搜刮引擎基于 BM25 排序方式更好的体现。而利用稀疏向量 + 稠密向量的肴杂搜刮,其结果在近期的一篇采用 BGE M3 embedding 模子的论文中也得到了验证(参考文献[2]),在典范评测中,取得了比 BM25 要好许多的结果:

那么看起来,好像稠密向量 + 稀疏向量就是更好的多路召回方案,采用全文搜刮 + 稠密向量,好像没有须要?


为什么需要三路召回?
我们知道, RAG 在技能上总是会遇到许多挑战,只管信息检索理论为 RAG 提供了许多支撑,包括信息检索的评测等,但在实际中仍然会遇到许多标题。稀疏向量通过预训练模子删除了许多无用词,并增加了许多用来做查询扩展的词,这在通用查询使命上必然会体现更好,然而在实际使用中,依然有大量用户提问的关键词,并不在天生稀疏向量的预训练模子中,例如各种呆板型号,说明书,专用词汇等等,用 3 万维表达全部关键词,还是多语言,依然会有诸多信息丧失,此外另有各类业务所必须的短语查询等等,这些都是必须采用全文搜刮才能实现的功能。因此,近期 IBM 的研究文章(参考文献[3])对比了各种召回方式的组合,包括 BM25,稠密向量,BM25 + 稠密向量, 稠密向量 + 稀疏向量,以及 BM25 + 稠密向量 + 稀疏向量,最终得出结论:采用 3 路召回是全部组合中最适合 RAG 的选择,而 Infinity 已经完全内置了这种肴杂搜刮功能。


3 路召回体现好非常容易理解,因为稠密向量可以表征语义, 稀疏向量可以在训练数据类似的场景下提供更好的精确召回,而关键词全文搜刮则在各种场景下提供更加鲁棒的精确召回选择。3种查询选择,一种都不能少,这使得 RAG 的方案计划更加复杂化,如果这些查询方式不能在一个数据库内完成,就需要用户组合多个数据库的 pipeline 来完成这一个功能,从而引入更多的工程 tricks 和复杂度,也影响了 RAG 技能的推广。例如:采用向量数据库提供稠密向量搜刮和稀疏向量搜刮,采用 Elasticsearch 提供关键词全文搜刮,因此确保两者的数据同步就带来了技能挑战,如果一个文档在一个存储中存在,但在另一个存储中却不存在,就会带来一些错误的查询结果,以是可能需要一些其他 workaround :例如再引入一个 OLTP 数据库如 PostgreSQL 用来存放元数据,然后用一些对象存储来存放原始的文档数据,两者结合向量数据库和 Elasticsearch 来提供最终的数据同步,这是一个非常复杂的后端架构。 而如果采用 Infinity ,就无需依赖这种复杂架构,3 种格式的存储,连同原始数据一起,一次全部插入且保证数据 ACID ,3 路召回的肴杂搜刮,一条语句就可以完成,方便且高效。


如何排序?
三路召回完成后,一个直接的标题就是如何举行融合排序。Infinity 内置了多种融合排序算法:
Infinity 提供了强大的排序组合机制,给用户提供多样化选择,如下图的2个例子:

第一种是3路召回的结果直接用 RRF 融合排序后返回。使用方式极其简单:
  1. res = table_obj.output(['*'])
  2.                .match_vector('vec', [3.0, 2.8, 2.7, 3.1], 'float', 'ip', 1)
  3.                .match_sparse('sparse_vec', {"indices": [0, 10, 20], "values": [0.1, 0.2, 0.3]}, 'float', 'ip', 1)
  4.                .match_text('title, body', 'hello world', 'topn=10')
  5.                .fusion('rrf')
  6.                .to_pl()
复制代码
第二种向量搜刮用ColBERT重排序,然后结果跟关键词全文搜刮做权重叠加再返回。
  1. res = table_obj.output(['*'])
  2.                .match_vector('vec', [3.0, 2.8, 2.7, 3.1], 'float', 'ip', 1)
  3.                .match_sparse('sparse_vec', {"indices": [0, 10, 20], "values": [0.1, 0.2, 0.3]}, 'float', 'ip', 1)
  4.                .fusion('match_tensor','column_name=t;search_tensor=[[0.0, -10.0, 0.0, 0.7], [9.2, 45.6, -55.8, 3.5]];tensor_data_type=float;match_method=MaxSim;topn=2')
  5.                .match_text('title, body', 'hello world', 'topn=10')                .fusion('weighted_sum', 'weights=0.8, 0.2')
  6.                .to_pl()
复制代码
这些召回和融合排序本领,使得 Infinity 可以为 RAG 提供最强大易用的多路召回能力。在多路召回之外,Infinity 0.2 release 还引入了 引入了一种全新的数据类型——Tensor,在计算机科学中,Tensor 可以用来表达多个向量,多维数组,或者一个矩阵,为什么要支持这种类型呢?这要从 ColBERT 谈起。 ColBERT(参考文献[4])是一种排序模子,隔断本日已经有四年了,是信息检索领域比年来引用次数非常多的着名论文。目前排序模子的架构有这样几类范式: 






下图从性能和排序质量上,分别对以上排序模子举行对比,而且也包含了全文搜刮。图中的 Dense Encoder 既为双编码器,代表普通的向量搜刮,它既可以做 Retriever,也可以做 Reranker。 由于 ColBERT 的延迟交互机制,它既满意了对排序过程中查询和文档之间复杂交互的捕获,也能实现较快的排序性能,雷同数据规模下, ColBERT 的效率可达 Cross Encoder 的 100 倍以上,分身了性能与结果,因此 ColBERT 是一种非常有远景的排序模子。

只管如此,在使用上,ColBERT 仍然面临2个标题:
基于以上原因, Infinity 在 0.2 版本中提供了 Tensor 数据类型,并基于此原生地提供端到端的 ColBERT 方案。
首先,Tensor 作为一种数据类型,ColBERT 编码输出的多向量,可以直接用一个 Tensor 来存放,因此 Tensor 之间的相似度就可以直接得出 MaxSim 打分。针对 MaxSim 计算,Infinity 给出了 2 种方案, 一种是 binary 量化,它可以让原始 Tensor 的空间只需原始尺寸的 1/32 , 但并不改变 MaxSim 计算的相对排序结果。这种方案紧张用于 Reranker,因为需要根据前一阶段排序的结果取出对应的 Tensor 。 另一种是 Tensor 索引, Infinity 采用 EMVB 技能(参考文献[7])实现了 Tensor Index。EMVB 可以看作是 ColBERT v2 的改进,它紧张通过量化和预过滤技能,并在关键操纵上引入 SIMD 指令来加快实现。Tensor 索引可以用来服务 Retriever 而非 Reranker,因此结合 Infinity 的多路召回能力,用户可以举行如下各种召回选择:例如可以选择直接用 Tensor 提供语义搜刮,从而实现比向量搜刮更高的排序质量,也可以组合 Tensor 和全文搜刮,用来做高质量的 RAG 所必备的 2 路召回,以致可以组合向量搜刮和 Tensor ,前者用来在大规模数据上粗筛,然后用 ColBERT 来快速精排,等等。Infinity 提供了富足强大的能力可以满意对于各种搜刮召回的需求。

  1. res = table_obj.output(['*'])
  2.                .match_tensor('t', [[0.0, -10.0, 0.0, 0.7], [9.2, 45.6, -55.8, 3.5]], 'float', 'maxsim')
  3.                .match_text('title, body', 'hello world', 'topn=10')
  4.                .fusion('weighted_sum', 'weights=0.8, 0.2')
  5.                .to_pl()
复制代码
其次,针对超过 Token 限定的长文本,Infinity 引入了 Tensor Array 类型:

一篇超过 ColBERT 限定的文档,会被切分成多个段落,分别编码天生 Tensor 后,都跟原始文档生存在一行。计算 MaxSim 的时间,查询跟这些段落分别计算,然后取最大值作为整个文档的打分。

从 0.2 release 开始, Infinity 提供了内置的 Tensor 数据类型,并解锁了端到端的 ColBERT 应用,这使得这种以延迟交互模子为代表的排序模子,可以在较大规模数据上直接提供高质量的排序结果,对于提升 RAG 的检索质量具有非常紧张的意义。

有了这么多召回本领,我们需要在真实数据集上举行相应的评测,以验证这些本领的结果。下边是 Infinity 在 MLDR 数据集上举行的评测结果,这也是 MTEB 默认采用的数据集之一。MTEB 是评估 Embedding 模子质量最权势巨子的 Benchmark,目前排行榜上排名前列的模子基本都是基于 Cross Encoder 的编码器。

从图中看到,肴杂 BM25 全文搜刮,可以比单纯向量搜刮有显著的提升。而采用全文搜刮+向量搜刮+稀疏向量,就是 Blended RAG[参考文献3],确实可以比单路搜刮,以及两路肴杂搜刮,有更好的查询质量。在 3 路肴杂搜刮的底子上,进一步添加 ColBERT 做 Reranker,可以有进一步大的提升。同采用外部的 Reranker (例如 MTEB 排名前列的那些编码器)相比,采用 Hybrid search + ColBERT Reranker,它可以在数据库内部完成重排序,有着更高的效率,因此肴杂搜刮可以进一步扩大 Top K 的范围(例如扩大到 Top 1000)之后再重排序,从而既保证最终召回质量还不影响性能,因此是一种性价比很高的高召回肴杂搜刮方案。下图是各种召回方式添加 ColBERT Reranker 之后的提升结果总揽。

需要说明的是,在不同数据集上,雷同的召回本领可能得到不同的返回结果,但有一点是确定的,就是肴杂搜刮的本领越多,返回质量越好。此外,上边的评测并没有涵盖用 Tensor Index 做 Ranker 组合,这是因为在详细实验中,我们发现用 Tensor 做 Reranker的性价比要高许多,这会在我们后边的文章中详细论述。因此推荐的最佳肴杂搜刮方案是 Blended RAG + ColBERT Reranker。

Infinity 0.2 release,不但提供了行业最全的肴杂搜刮能力,还提供最快的肴杂搜刮能力。下文来描述 Infinity 如何做到这一点。
Infinity 是一款在存储引擎和执行引擎层面都精细计划的数据库。 如下是 Infinity 的执行引擎工作流程,可以看到,在完成针对 API 的查询绑定后,接下来执行计划会被编译成一个流水线执行计划。这种机制,常见于一些现代数据仓库,所不同的是,数据仓库的流水线执行,通常服务于并行执行,而 Infinity 的流水线,则同时服务查询的并行和并发执行,需要保证了高并发执行时查询算子的最佳调理策略和 CPU 亲和性,避免了无效上下文切换导致的开销。这种计划,使得查询的端到端开销非常小,完整的查询延迟并不会比运行单独的算法库增加多少。

上图的右边是一个多路召回的查询样例,图中包含 2 个数据 segment 上的向量搜刮执行算子,2 个算子并行执行,以及一个向量搜刮的 Top K 归并算子负责归并来自 2 个 segment 的向量搜刮结果;另有一个全文搜刮算子,两路召回最后是一个 Fusion 融合算子,这些算子在内存中形成一个 DAG 图,由查询执行器负责运行期调理。

存储引擎方面,Infinity 创建了完整的以列存为底子的索引体系,对于多路召回的每一路,都有相对应的索引负责高性能检索,这也使得 Infinity 添加新的类型支持变得非常方便。因此,Infinity 可以看做是一个以列存为底子的全索引数据库,这跟近期 OpenAI 收购的 Rockset 有着相似的特性,而在索引的类型上,Infinity 则提供更加丰富的选择。

下边来看 Infinity 的索引实现。
跟许多向量数据库一样,默认情况下 Infinity 也采用了 HNSW 作为向量索引的实现。但 Infinity 的 HNSW 举行了一系列深入优化,详细来讲,就是对每个需要创建索引的向量举行局部自适应量化——通过对每个向量举行缩放和量化操纵来提升搜刮性能,使得相似性计算速率极快,有用带宽降低,同时减少内存占用,却险些不影响准确性,因此实质上是这一种压缩技能。 


详细的,Infinity 对每个向量采用了两级量化:其中一级量化是针对每个向量和全部向量的均值之间的差值举行量化编码。一级量化紧张在 HNSW 图遍历期间使用,通过将向量压缩到较少的规模,从而有用减少实际消耗的内存带宽,进步搜刮性能。二级量化负责对前述差值后的残差举行量化编码,它紧张用于最后的相似度比对,进步查询精度。局部量化技能因为只针对每个向量举行量化,并不改变任何向量之间的最近邻关系,因此具备随机内存访问模式,以是特别适合基于图索引的相似度搜刮。在 Infinity 中,HNSW 索引只基于一级量化的结果来构建,以是查询性能和内存占用都大大优于传统的 HNSW 索引。除了局部量化技能之外,Infinity 采用大量 SIMD 针对隔断做加快计算,得益于这些计划,Infinity 的向量搜刮性能超出同类许多,下图是 Infinity 和其他向量数据库的 benchmark 对比:

针对全文索引,Infinity 也是采取了全新实现的方案,而没有引入一些流行的全文索引库如 Tantivy,Lucene 等等。这是因为全文索引只是 Infinity 的一个组件,它需要紧密地跟存储引擎和执行引擎高效率协同工作。这体如今几个方面:
除却以上因素,Infinity 是一款专用于 RAG 的数据库,对于 RAG 来说,它需要根据用户的提问搜刮到答案,由于用户的提问可能会比较长,因此在默认情况下,查询的关键词之间不能提供“AND”语义而应提供“OR”语义,否则很容易导致零召回。然而,“OR”语义对性能是极大地损害,因为任何一个关键词掷中的结果都会被打分,并送到最终的结果排序,以是全文索引需要采用动态查询剪枝技能,减少不须要的打分和排序。

例如近十年来学术界最佳的动态查询剪枝方案,是以 WAND,MaxScore 等为代表的系列技能。只管全文搜刮是一个相对成熟的领域,然而在当下,也只有 Lucene,Tantivy 等少数全文索引库具备生产级的算法实现。Infinity 实现了完整的 Block Max WAND 和 Block Max MaxScore 技能,两种查询动态剪枝策略适应的场景略有不同,在默认情况下,Infinity 选择采用 Block Max WAND (参考文献[9])来作为首选剪枝策略。

WAND 是 Weak AND 的缩写,它针对全文搜刮最常见的打分本领 BM25 举行查询时动态剪枝,通过计算每个关键词贡献的上限来估计最终 Top K 结果的上限,并以此为阀值来决定在倒排索引的上如何快速跳过不须要的文档 ID,从而得到提速的结果。每个关键词贡献的上限,根据该关键词的的 IDF(在多少文档中出现) 和最大 TF(在文档中出现的最大词频) 来确定。

上图是 Infinity 和 Elasticsearch 的全文搜刮性能对比,测试方法如下:
可以看到,岂论是长查询,还是短查询, Infinity 相比 Elasticsearch 均具备压倒性优势,而且在测试过程中 Infinity 的内存消耗仅有 Elasticsearch 的 1/2。因此,提供 RAG 所必备的肴杂搜刮能力(全文搜刮 + 向量搜刮),此前用户的唯一选择是 Elasticsearch(包括 Opensearch),而如今不但仅多了 Infinity 这个选项,而且在性能上也远远超过了这些选择。

针对稀疏向量索引,Infinity 采用了跟全文搜刮类似的计划,都采用倒排索引+查询动态剪枝的策略,所不同的是,稀疏向量首先按照区块构造成前向索引,倒排索引只用来存放跟固定区块有关的信息,查询时用来从一个区块跳转到另一个区块,而详细的相似度计算,则通过前向索引来举行。因此,稀疏向量索引并没有包含一个标准的倒排索引,而是基于 Block 的倒排索引跟前向索引的肴杂方案。该详细算法来源于 SIGIR 2024 的 Best Paper Runner Up 论文(参考文献 9)。
下图是 Infinity 跟着名向量数据库 Qdrant 在稀疏向量索引上的性能评测:

由此可见,在稠密向量、稀疏向量、全文搜刮三种召回本领上, Infinity 的性能均到达了极致,再加上强大的多路召回能力,以及各种的 Reranker 尤其是基于张量的 Reranker,可以说 Infinity 不但仅是目前最快的 RAG 专用数据库,也是最强大的 RAG 数据库选择。欢迎关注和 Infinity :https://github.com/infiniflow/infinity


参考文献


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4