BM42:混合搜索的新基准 - Qdrant

在过去的 40 年里,BM25 一直是搜索引擎的标准。它是一种简单但功能强大的算法,已被许多搜索引擎使用,包括 Google、Bing 和 Yahoo。

虽然看起来向量搜索的出现会削弱其影响力,但效果并不明显。目前最先进的检索方法试图将 BM25 与嵌入结合到混合搜索系统中。

然而,自从引入 RAG 以来,文本检索的使用情况发生了显著变化。BM25 所基于的许多假设不再有效。

例如,传统网络搜索和现代 RAG 系统之间文档和查询的典型长度存在很大差异。

在本文中,我们将回顾 BM25 为何如此受关注,以及为什么其他替代方法难以取代它。最后,我们将讨论 BM42,这是词汇搜索演进的下一步。

为何 BM25 能持续这么长时间?

要了解原因,我们需要分析其组成部分。

著名的BM25公式定义为:
score ⁡ ( D , Q ) = ∑ i = 1 N IDF ⁡ ( q i ) × f ( q i , D ) ⋅ ( k 1 + 1 ) f ( q i , D ) + k 1 ⋅ ( 1 − b + b ⋅ ∣ D ∣ avgdl  ) \operatorname{score}(D, Q)=\sum_{i=1}^N \operatorname{IDF}\left(q_i\right) \times \frac{f\left(q_i, D\right) \cdot\left(k_1+1\right)}{f\left(q_i, D\right)+k_1 \cdot\left(1-b+b \cdot \frac{|D|}{\text { avgdl }}\right)} score(D,Q)=i=1NIDF(qi)×f(qi,D)+k1(1b+b avgdl D)f(qi,D)(k1+1)

让我们简化这一点以便更好地理解。

  • 这score(D,Q)-- 意味着我们计算每对文档的分数并查询。

  • ∑ i = 1 N \sum_{i=1}^N i=1N意味着每个查询中的术语将作为总和的一部分计入最终得分。

  • IDF ⁡ ( q i ) \operatorname{IDF}\left(q_i\right) IDF(qi) 是逆文档频率。术语越罕见,越大,对得分的贡献就越大。简化的公式如下:
    IDF ⁡ ( q i ) = Number of documents  Number of documents with  q i \operatorname{IDF}\left(q_i\right)=\frac{\text { Number of documents }}{\text { Number of documents with } q_i} IDF(qi)= Number of documents with qi Number of documents 

可以说 是IDFBM25 公式中最重要的部分。 IDF选择查询中相对于特定文档集合最重要的术语。 因此直观地,我们可以将 解释为语料库中的术语IDF重要性。

这解释了为什么 BM25 如此擅长处理查询,而密集嵌入认为这些查询超出了域范围。

公式的最后一个部分可以直观地解释为文档中的术语重要性。这可能看起来有点复杂,所以让我们分解一下。
Term importance in document  ( q i ) = f ( q i , D ) ⋅ ( k 1 + 1 ) f ( q i , D ) + k 1 ⋅ ( 1 − b + b ⋅ ∣ D ∣ avgdl  ) \text { Term importance in document }\left(q_i\right)=\frac{f\left(q_i, D\right) \cdot\left(k_1+1\right)}{f\left(q_i, D\right)+k_1 \cdot\left(1-b+b \cdot \frac{|D|}{\text { avgdl }}\right)}  Term importance in document (qi)=f(qi,D)+k1(1b+b avgdl D)f(qi,D)(k1+1)

  • f ( q i , D ) f\left(q_i, D\right) f(qi,D) 是该词的频率在文档中换句话说,该术语的次数出现在文档中。
  • k 1 k1 k1 b 1 b1 b1是 BM25 公式的超参数。在大多数实现中,它们是设置为的常量和这些常数定义了公式中词频和文档长度的相对含义。
  • ∣ D ∣ avgdl  \frac{|D|}{\text { avgdl }}  avgdl D 是文档的相对长度与语料库中的平均文档长度相比。这部分的直觉如下:如果在较小的文档中找到标记,则该标记对该文档而言就更有可能是重要的。
文档中的 BM25 术语重要性是否适用于 RAG?

我们可以看出,_文档中的术语重要性_很大程度上取决于文档中的统计数据。此外,如果文档足够长,统计数据会很好用。因此,它适合搜索网页、书籍、文章等。

但是,它是否也适用于现代搜索应用程序(例如 RAG)?让我们拭目以待。

RAG 中文档的典型长度比网络搜索的文档长度短得多。事实上,即使我们处理的是网页和文章,我们也更愿意将它们分成块,以便 a) 密集模型可以处理它们,并且 b) 我们可以精确地找到与查询相关的文档的确切部分

因此,RAG 中的文档大小很小且固定。

这实际上使得 BM25 公式的文档部分中的词重要性变得毫无用处。文档中的词频始终为 0 或 1,文档的相对长度始终为 1。

因此,BM25 公式中唯一与 RAG 相关的部分是IDF。让我们看看如何利用它。

为什么 SPLADE 并不总是答案

在讨论我们的新方法之前,让我们先来研究一下 BM25 的当前最先进的替代方案 - SPLADE。

SPLADE 背后的想法很有趣——如果我们让一个智能的、端到端训练的模型为我们生成文本的词袋表示会怎么样?它会将所有权重分配给标记,因此我们无需担心统计数据和超参数。然后,文档将表示为稀疏嵌入,其中每个标记都表示为稀疏向量的一个元素。

而且它在学术基准测试中表现良好。许多论文报告称,SPLADE 在检索质量方面优于 BM25。然而,这种性能是有代价的。

  • 不合适的标记器:要将转换器整合到此任务中,SPLADE 模型需要使用标准转换器标记器。这些标记器不是为检索任务设计的。例如,如果单词不在(相当有限的)词汇表中,它将被拆分为子词或替换为标记[UNK]。这种行为对于语言建模很有效,但对于检索任务却完全是破坏性的。

  • 昂贵的标记扩展:为了补偿标记化问题,SPLADE 使用_标记扩展_技术。这意味着我们为查询中的每个标记生成一组类似的标记。这种方法存在一些问题:

    • 它在计算和内存上都很昂贵。我们需要为文档中的每个标记生成更多值,这会增加存储大小和检索时间。
    • 标记扩展何时停止并不总是很清楚。我们生成的标记越多,我们获得相关标记的可能性就越大。但同时,我们生成的标记越多,我们获得不相关结果的可能性就越大。
    • 标记扩展削弱了搜索的可解释性。我们无法说出文档中使用了哪些标记,哪些标记是由标记扩展生成的。
  • 领域和语言依赖性:SPLADE 模型是在特定语料库上训练的。这意味着它们并不总是可以推广到新的或罕见的领域。由于它们不使用语料库中的任何统计数据,因此它们无法在不进行微调的情况下适应新领域。

  • 推理时间:此外,目前可用的 SPLADE 模型相当大且速度很慢。它们通常需要 GPU 才能在合理的时间内进行推理。

在 Qdrant,我们承认上述问题并正在寻找解决方案。我们的想法是结合两全其美的优势——BM25 的简单性和可解释性以及 transformer 的智能性,同时避免 SPLADE 的缺陷。

这就是我们的想法。

两全其美的

如前所述,IDF是 BM25 公式中最重要的部分。事实上,它非常重要,因此我们决定将其计算构建到 Qdrant 引擎本身中。查看我们最新的发布说明。这种类型的分离允许对稀疏嵌入进行流式更新,同时保持IDF计算最新。

至于公式的第二部分,_文档中的重要性一词_需要重新考虑。

既然我们不能依赖文档内的统计数据,那么我们可以尝试使用文档的语义。而语义正是 Transformer 所擅长的。因此,我们只需要解决两个问题:

  • 如何从变压器中提取重要信息?
  • 如何避免标记化问题?

你只需要关注

Transformer 模型(即使是用于生成嵌入的模型)也会生成大量不同的输出。其中一些输出用于生成嵌入。

其他用于解决其他类型的任务,例如分类、文本生成等。

对我们来说,一个特别有趣的输出是注意力矩阵。

注意力矩阵

注意力矩阵

注意力矩阵是一个方阵,每行每列对应输入序列中的token,表示输入序列中每个token对彼此的重要性。

经典的 Transformer 模型经过训练可以预测上下文中的掩码标记,因此注意力权重定义了哪些上下文标记对掩码标记的影响最大。

除了常规的文本 token,Transformer 模型还有一个名为 的特殊 token [CLS]。这个 token 代表了分类任务中的整个序列,这正是我们所需要的。

通过查看[CLS]token 的注意力行,我们可以得到文档中每个 token 对整个文档的重要性。

sentences = "Hello, World - is the starting point in most programming languages"features = transformer.tokenize(sentences)# ...attentions = transformer.auto_model(**features, output_attentions=True).attentionsweights = torch.mean(attentions[-1][0,:,0], axis=0)                       
#                ▲               ▲  ▲   ▲                                 
#                │               │  │   └─── [CLS] token is the first one
#                │               │  └─────── First item of the batch         
#                │               └────────── Last transformer layer       
#                └────────────────────────── Averate all 6 attention headsfor weight, token in zip(weights, tokens):print(f"{token}: {weight}")# [CLS]       : 0.434 // Filter out the [CLS] token
# hello       : 0.039
# ,           : 0.039
# world       : 0.107 // <-- The most important token
# -           : 0.033
# is          : 0.024
# the         : 0.031
# starting    : 0.054
# point       : 0.028
# in          : 0.018
# most        : 0.016
# programming : 0.060 // <-- The third most important token
# languages   : 0.062 // <-- The second most important token
# [SEP]       : 0.047 // Filter out the [SEP] token

BM42 分数的最终公式如下:
score ⁡ ( D , Q ) = ∑ i = 1 N IDF ⁡ ( q i ) × Attention ⁡ ( C L S , q i ) \operatorname{score}(D, Q)=\sum_{i=1}^N \operatorname{IDF}\left(q_i\right) \times \operatorname{Attention}\left(\mathrm{CLS}, q_i\right) score(D,Q)=i=1NIDF(qi)×Attention(CLS,qi)
请注意,经典的 Transformer 有多个注意力头,因此我们可以为同一篇文档获得多个重要性向量。将它们组合起来的最简单方法就是简单地对它们取平均值。

这些平均注意力向量构成了我们正在寻找的重要性信息。最好的部分是,人们可以从任何 Transformer 模型中获取它们,而无需任何额外的训练。因此,只要有 Transformer 模型,BM42 就可以支持任何自然语言。

在我们的实现中,我们使用了该sentence-transformers/all-MiniLM-L6-v2模型,与 SPLADE 模型相比,该模型大大提高了推理速度。实际上,可以使用任何 Transformer 模型。它不需要任何额外的训练,并且可以轻松适应用作 BM42 后端。

WordPiece 重新标记

我们需要解决的最后一块拼图是标记化问题。为了获得注意力向量,我们需要使用原生的 Transformer 标记化。但这种标记化不适合检索任务。我们能做些什么呢?

其实我们想出的解决方案很简单,得到注意力向量后,再逆向进行 token 化的过程。

Transformers 使用WordPiece标记化。如果它看到不在词汇表中的单词,它会将其拆分为子词。

看起来是这样的:

"unbelievable" -> ["un", "##believ", "##able"]

什么可以将子词重新合并到单词中。幸运的是,子词标有前缀##,因此我们可以轻松检测到它们。由于注意力权重已归一化,我们可以简单地将子词的注意力权重相加,以获得单词的注意力权重。

之后,我们可以应用相同的传统 NLP 技术,例如

  • 删除停用词
  • 删除标点符号
  • 词形还原

通过这种方式,我们可以显著减少 token 的数量,从而最大限度地减少稀疏嵌入的内存占用。我们不会同时损害匹配(几乎)精确 token 的能力。

实例

特征BM25斯普拉德BM42
可解释性高✅好的🆗高✅
文档推理速度非常高✅慢🐌高✅
查询推理速度非常高✅慢🐌非常高✅
内存占用低✅高 ❌低✅
域内准确度好的🆗高✅高✅
域外准确度好的🆗低❌好的🆗
小文件准确度低❌高✅高✅
大型文件准确度高✅低❌好的🆗
未知令牌处理是的✅糟糕❌是的✅
多语言支持是的✅没有❌是的✅
最佳匹配是的✅没有❌是的✅

从 Qdrant v1.10.0 开始,BM42 可以通过 FastEmbed 推理在 Qdrant 中使用。

让我们看看如何使用 BM42 和jina.ai密集嵌入设置混合搜索集合。

PUT collections/my-hybrid-collection
{"vectors": {"jina": {"size": 768,"distance": "Cosine"}},"sparse_vectors": {"bm42": {"modifier": "idf" // <--- This parameter enables the IDF calculation}}
}

搜索查询将检索具有密集和稀疏嵌入的文档,并使用倒数秩融合 (RRF) 算法合并分数。

from fastembed import SparseTextEmbedding, TextEmbeddingquery_text = "best programming language for beginners?"model_bm42 = SparseTextEmbedding(model_name="Qdrant/bm42-all-minilm-l6-v2-attentions")
model_jina = TextEmbedding(model_name="jinaai/jina-embeddings-v2-base-en")sparse_embedding = list(embedding_model.query_embed(query_text))[0]
dense_embedding = list(model_jina.query_embed(query_text))[0]client.query_points(collection_name="my-hybrid-collection",prefetch=[models.Prefetch(query=sparse_embedding.as_object(), using="bm42", limit=10),models.Prefetch(query=dense_embedding.tolist(),  using="jina", limit=10),],query=models.FusionQuery(fusion=models.Fusion.RRF), # <--- Combine the scoreslimit=10
)

基准

为了进一步证明这一点,我们进行了一些基准测试,以突出 BM42 优于 BM25 的情况。请注意,我们无意进行详尽的评估,因为我们介绍的是一种新方法,而不是一种新模型。

对于我们的实验,我们选择了quora数据集,它代表了一个问题去重任务问答任务

该数据集的典型示例如下:

{"_id": "109", "text": "How GST affects the CAs and tax officers?"}
{"_id": "110", "text": "Why can't I do my homework?"}
{"_id": "111", "text": "How difficult is it get into RSI?"}

正如您所见,它的文本很短,没有太多可依赖的统计数据。

使用 BM42 编码后,每个文档的平均向量大小仅为5.6 个元素。

在 Qdrant 中,对于约 530k 个文档,datatype: uint8稀疏向量索引的总大小约为13Mb 。

BM25(坦蒂维)BM42
~精度为 10~*0.450.49
召回率@100.710.85

* - 由于评估脚本中的错误,发布后对值进行了更正。

为了使我们的基准透明,我们发布了用于评估的脚本:请参阅github repo。

请注意,BM25 和 BM42 在生产环境中单独使用效果都不是很好。最佳效果是通过混合方法结合稀疏和密集嵌入来实现的。在这种情况下,这两个模型是互补的。稀疏模型负责精确的标记匹配,而密集模型负责语义匹配。

一些更高级的模型可能会比sentence-transformers/all-MiniLM-L6-v2我们使用的默认模型表现更好。我们鼓励参与训练嵌入模型的开发人员加入一种提取注意力权重的方法,并为 BM42 后端做出贡献。

培养好奇心和实验精神

尽管 BM42 具有诸多优点,但它并非万能药。对于没有块的大型文档,BM25 可能仍然是更好的选择。

可能有更智能的方法从 transformer 中提取重要性信息。可能有更好的方法来权衡 IDF 与注意力得分。

Qdrant 并不专注于模型训练。我们的核心项目是搜索引擎本身。但是,我们明白,我们并不是在真空中运作。通过引入 BM42,我们正在加紧为我们的社区提供新颖的实验工具。

我们确实相信稀疏向量方法处于精确的抽象层次,能够产生强大而灵活的结果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/45434.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python库(11):Box库简化字典和对象之间的转换

1Box库简介 Box是一个Python库&#xff0c;它提供了一种将数据封装在字典和列表中的方式&#xff0c;同时提供了一些额外的功能&#xff0c;比如数据验证、默认值设置等。这使得Box库非常适合用于配置管理、数据传输对象&#xff08;DTO&#xff09;的创建&#xff0c;以及任何…

sqlmap使用之-post注入、head注入(ua、cookie、referer)

1、post注入 1.1、方法一&#xff0c;通过保存数据包文件进行注入 bp抓包获取post数据 将数据保存到post.txt文件 加上-r指定数据文件 1.2、方法二、通过URL注入 D:\Python3.8.6\SQLmap>python sqlmap.py -u "http://localhost/login.php" --data "userna…

替换:show-overflow-tooltip=“true“ ,使用插槽tooltip,达到内容可复制

原生的show-overflow-tooltip“true” 不能满足条件&#xff0c;使用插槽自定义编辑&#xff1b; 旧code <el-table-column prop"reason" label"原因" align"center" :show-overflow-tooltip"true" /> <el-table-column pro…

压缩文件的解析方式

Java中我们用ZipInputStream和ZipOutputStream来完成对zip文件和rar文件的读写 I /O流&#xff1a; Input:输入&#xff0c;通过“输入流”进行文件的读取操作 output:输出&#xff0c;通过“输出流”进行文件的写入操作 一、将压缩包解压缩 1.解压缩.zip格式文件&#xf…

微信小程序毕业设计-汽车维修项目管理系统项目开发实战(附源码+论文)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;微信小程序毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计…

NoSQL 之Redis集群模式

一&#xff1a;Redis集群方式 Redis有三种模式&#xff1a;分别是主从复制、哨兵模式、Cluster 1&#xff1a;主从模式: 主从复制是高可用Redis的基础&#xff0c;哨兵和群集都是在主从复制基础上实现高可用的。主从复制主要实现了数据的多机备份&#xff0c;以及对于读操作的…

netscaler LDAP+RADIUS传统的双因素认证方式(之一)

如果使用传统的双因素认证方式&#xff0c;可以通过在Citrix ADC (NetScaler) 13.1上配置Gateway Virtual Server来实现LDAP和RADIUS的双因素认证。当前配置方式&#xff0c;采用Cateway vServer两个Basic Authtication Policy方式实现&#xff0c;以下是详细步骤&#xff1a; …

【码题集】习题

目录 史莱姆融合 松鼠接松果 新月轩就餐 史莱姆融合 根据题意就是一道集合合并的题&#xff0c;所以要用并查集&#xff0c;不过最后我们要输出整个序列&#xff0c;所以要在合并的时候维护一个链表&#xff0c;以便最终合并成一个大集合的时候&#xff0c;输出整个链表就是…

Kotlin Misk Web框架

Kotlin Misk Web框架 1 添加依赖1.1 build.gradle.kts1.2 settings.gradle.kts1.3 gradle.properties 2 请求接口3 程序模块4 主服务类5 测试结果 Misk 是由 Square 公司开发的一个开源的多语言服务器框架&#xff0c;主要用于构建微服务。它主要使用 Kotlin 语言&#xff0c;但…

UGC与AI引领的下一个10年,丝芭传媒已经准备好

丝芭传媒最近传来的消息&#xff0c;都跟技术相关。 基于自研AI大模型“Paro&#xff08;心乐舞河&#xff09;”的AIGPT及AIGC生成工具APP“鹦鹉人”开启用户内测。2023年3月技术测试的图形化智能社交基座“美踏元宇宙”&#xff0c;也将开放首轮用户内测。 此外&#xff0c…

Studying-代码随想录训练营day31| 56.合并区间、738.单调递增的数字、968.监控二叉树、贪心算法总结

第31天&#xff0c;贪心最后一节(ง •_•)ง&#x1f4aa;&#xff0c;编程语言&#xff1a;C 目录 56.合并区间 738.单调递增的数字 968.监控二叉树 贪心算法总结 56.合并区间 文档讲解&#xff1a;代码随想录合并区间 视频讲解&#xff1a;手撕合并区间 题目&#xf…

高效图纸管理:彩虹图纸管理软件助您一臂之力

高效图纸管理&#xff1a;彩虹图纸管理软件助您一臂之力 在制造业的激烈竞争中&#xff0c;高效图纸管理是企业提升竞争力和降低成本的关键。然而&#xff0c;传统的图纸管理方式往往存在效率低下、信息混乱等问题。此时&#xff0c;彩虹图纸管理软件凭借其卓越的性能和丰富的功…

一个vue页面复用方案

前言 问大家一个问题&#xff0c;曾经的你是否也遇到过&#xff0c;一个项目中有好几个页面长得基本相同&#xff0c;但又差那么一点&#xff0c;想用 vue extends 继承它又不能按需继承html模板部分&#xff0c;恰好 B 页面需要用的 A 页面 80% 的模板&#xff0c;剩下的 20%…

【验收支撑】软件系统验收计划书(直接套用原件doc)

编写软件验收计划是软件开发过程中的一个关键步骤&#xff0c;其重要性体现在以下几个方面&#xff1a; 明确验收标准&#xff1a;软件验收计划详细列出了验收的标准、测试方法、测试环境等&#xff0c;确保所有相关人员对验收的期望和要求有清晰的认识。这有助于避免在验收阶段…

triton需要cuda11.8版本--so 安装个11.8的cuda

1.安装一个11.8的cuda 查看ubunto版本 lsb_release -a查看cpu架构 uname -m到官网得到相应的命令&#xff1a;CUDA Toolkit Archive | NVIDIA Developer 依次输入两条命令。如果没有没有sudo权限就将cuda安装路径修改在自己目录下&#xff1a; sh cuda_11.8.0_520.61.05_li…

论文AIGC率超标?一键降重快速搞定

如何有效降低AIGC论文的重复率&#xff0c;也就是我们说的aigc如何降重&#xff1f;AIGC疑似度过高确实是个比较愁人的问题。如果你用AI帮忙写了论文&#xff0c;就一定要在交稿之前做一下AIGC降重的检查。一般来说&#xff0c;如果论文的AIGC超过30%&#xff0c;很可能会被判定…

【EI征稿】第四届机器人、自动化与智能控制国际会议

【快速通道】 参会方式&#xff1a;担任会议committee成员、组建workshop 、参会报告、参会交流、审稿专家、投稿参会。 会议地点&#xff1a; 湖南 长沙 会议时间&#xff1a;12月6日-9日 会议检索&#xff1a;EI检索 会议官网&#xff1a;https://www.icraic.org/ 投稿链接&a…

华为910b推理Qwen1.5-72b

前情提要&#xff1a;华为910b部署训练推理大模型&#xff0c;本人之前并没有接触过&#xff0c;所以&#xff0c;写此文档进行记录。 &#xff08;注意&#xff1a;版本适配很重要&#xff01;&#xff01;不然就像我一样走了好多坑~~~&#xff09; 首先&#xff0c;看一张图…

大鲸鱼—docker 基本概念及安装使用

目录 一、docker前言 1.什么是Docker&#xff1f; 2.Docker的宗旨 3.容器的优点 4.Docker与虚拟机的区别 5.Docker核心概念 镜像 容器 仓库 6.为什么要用容器 7.容器越来越受欢迎的原因 8.容器在内核中支持2种重要技术 二、Docker安装 三、Docker 镜像操作 1.搜…

旷视AI开源新突破:上传照片即可生成表情包视频!

日前&#xff0c;旷视科技发布了一项新的开源AI人像视频生成框架——MegActor。该框架让用户只需输入一张静态肖像图片和一段视频&#xff08;如演讲、表情包、rap&#xff09;&#xff0c;便可生成一段表情丰富、动作一致的AI人像视频。生成的视频长度取决于输入的视频长度。与…