Elasticsearch:倒数排序融合 - Reciprocal rank fusion

news2024/12/24 22:17:04

警告:此功能处于技术预览阶段,可能会在未来版本中更改或删除。 Elastic 将尽最大努力修复任何问题,但技术预览中的功能不受官方 GA 功能的支持 SLA 约束。

倒数排序融合(RRF)是一种将具有不同相关性指标的多个结果集组合成单个结果集的方法。 RRF 无需调优,不同的相关性指标也不必相互关联即可获得高质量的结果。该方法的优势在于不利用相关分数,而仅靠排名计算。相关分数存在的问题在于不同模型的分数范围差。

使用 Reciprocal Rank Fusion (RRF) 的简化混合搜索

通常,最好的排名是通过组合多种排名方法来实现的,例如 BM25 和生成密集向量嵌入的 ML 模型。 在实践中,将结果集组合成一个单一的组合相关性排名结果集被证明是非常具有挑战性的。 当然,理论上你可以将每个结果集的分数归一化(因为原始分数在完全不同的范围内),然后进行线性组合,根据每个排名的分数加权和排序最终结果集方法。 只要你提供正确的权重,Elasticsearch 就支持它并且运行良好。 为此,你需要了解环境中每种方法得分的统计分布,并有条不紊地优化权重。 实际上,这超出了绝大多数用户的能力。

另一种方法是 RRF 算法,它提供了出色的排序方法零样本混合,正如学术研究所证明的那样。 如果你不了解不同方法中排名分数的确切分布,这不仅是最好的混合方式,而且客观上也是混合排名方法的好方法 —— 即使你知道如何归一化及分数的分布情况,也很难被击败。 基本概念是结果的组合顺序由每个结果集中每个文档的位置(和存在)定义。 因此可以方便地忽略排名分数。

Elastic 8.8 支持具有多个密集向量查询和在倒排索引上运行的单个查询的 RRF。 在不久的将来,我们希望支持来自 BM25 和 Elastic 的检索模型(两者都是稀疏向量)的混合结果,从而产生同类最佳的零样本集(无域内训练)排名方法。

  • D - 文档集
  • R - 一组排名作为 1..|D| 的排列
  • K - 通常默认设置为 60

RRF 使用以下公式来确定对每个文档进行排名的分数:

score = 0.0
for q in queries:
    if d in result(q):
        score += 1.0 / ( k + rank( result(q), d ) )
return score

# where
# k is a ranking constant
# q is a query in the set of queries
# d is a document in the result set of q
# result(q) is the result set of q
# rank( result(q), d ) is d's rank within the result(q) starting from 1

倒数排序融合 API

你可以将 RRF 用作搜索的一部分,以使用来自:

  • 1 个查询(query)和 1 个或多个 kNN 搜索
  • 2 个或更多 kNN 搜索

rrf 参数是一个可选对象,定义为搜索请求 rank parameter 的一部分。 rrf 对象包含以下参数:

条目描述
rank_constant(可选,整数)此值确定每个查询的单个结果集中的文档对最终排名结果集的影响程度。 较高的值表示排名较低的文档具有更大的影响力。 此值必须大于或等于 1。默认为 60。
window_size(可选,整数)此值确定每个查询的单个结果集的大小。 较高的值将以性能为代价提高结果相关性。 最终排名的结果集被修剪为搜索请求的 <<search-size-param, size>。 window_size 必须大于或等于 size 且大于或等于 1。默认为 100。

使用 RRF 的示例请求:

GET example-index/_search
{
    "query": {
        "term": {
            "text": "shoes"
        }
    },
    "knn": {
        "field": "vector",
        "query_vector": [1.25, 2, 3.5],
        "k": 50,
        "num_candidates": 100
    },
    "rank": {
        "rrf": {
            "window_size": 50,
            "rank_constant": 20
        }
    }
}

在上面的示例中,我们首先执行 kNN 搜索以获取其全球前 50 名的结果。 然后我们执行查询以获取其全球前 50 名的结果。 之后,在一个协调节点上,我们将 knn 搜索结果与查询结果结合起来,根据 RRF 方法对它们进行排序,得到最终的 top 10 结果。

请注意,如果来自 knn 搜索的 k 大于 window_size,则结果将被截断为 window_size。 如果 k 小于 window_size,则结果为 k 大小。

倒数排序融合支持的功能

RRF 确实支持:

  • from
  • aggregations

RRF 目前不支持:

  • scroll
  • point in time
  • sort
  • rescore
  • suggesters
  • highlighting
  • collapse
  • explain
  • profiling

使用不支持的功能作为使用 RRF 的搜索的一部分将导致异常。

倒数排序融合完整示例

我们首先为具有文本字段、向量字段和整数字段的索引创建映射,同时索引多个文档。 对于这个例子,我们将使用一个只有一个维度的向量来使排名更容易解释。

PUT example-index
{
  "mappings": {
    "properties": {
      "text": {
        "type": "text"
      },
      "vector": {
        "type": "dense_vector",
        "dims": 1,
        "index": true,
        "similarity": "l2_norm"
      },
      "integer": {
        "type": "integer"
      }
    }
  }
}

PUT example-index/_doc/1
{
    "text" : "rrf",
    "vector" : [5],
    "integer": 1
}

PUT example-index/_doc/2
{
    "text" : "rrf rrf",
    "vector" : [4],
    "integer": 2
}

PUT example-index/_doc/3
{
    "text" : "rrf rrf rrf",
    "vector" : [3],
    "integer": 1
}

PUT example-index/_doc/4
{
    "text" : "rrf rrf rrf rrf",
    "integer": 2
}

PUT example-index/_doc/5
{
    "vector" : [0],
    "integer": 1
}

POST example-index/_refresh

现在,我们使用带有查询、kNN 搜索和术语聚合的 RRF 执行搜索。

GET example-index/_search
{
  "query": {
    "term": {
      "text": "rrf"
    }
  },
  "knn": {
    "field": "vector",
    "query_vector": [
      3
    ],
    "k": 5,
    "num_candidates": 5
  },
  "rank": {
    "rrf": {
      "window_size": 5,
      "rank_constant": 1
    }
  },
  "size": 3,
  "aggs": {
    "int_count": {
      "terms": {
        "field": "integer"
      }
    }
  }
}

我们收到带有排名 hits 和术语聚合结果的响应。 请注意,_score 为 null,我们改为使用 _rank 来显示排名靠前的文档。

{
  "took": 16,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 5,
      "relation": "eq"
    },
    "max_score": null,
    "hits": [
      {
        "_index": "example-index",
        "_id": "3",
        "_score": null,
        "_rank": 1,
        "_source": {
          "text": "rrf rrf rrf",
          "vector": [
            3
          ],
          "integer": 1
        }
      },
      {
        "_index": "example-index",
        "_id": "2",
        "_score": null,
        "_rank": 2,
        "_source": {
          "text": "rrf rrf",
          "vector": [
            4
          ],
          "integer": 2
        }
      },
      {
        "_index": "example-index",
        "_id": "4",
        "_score": null,
        "_rank": 3,
        "_source": {
          "text": "rrf rrf rrf rrf",
          "integer": 2
        }
      }
    ]
  },
  "aggregations": {
    "int_count": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": 1,
          "doc_count": 3
        },
        {
          "key": 2,
          "doc_count": 2
        }
      ]
    }
  }
}

让我们分解一下这些点击率是如何排名的。 我们首先分别运行查询和 kNN 搜索,以收集它们各自的命中率。

首先,我们查看查询的 hits。

GET example-index/_search?filter_path=**.hits
{
  "query": {
    "term": {
      "text": "rrf"
    }
  }
}

上面的命令显示的结果为:

{
  "hits": {
    "hits": [
      {
        "_index": "example-index",
        "_id": "4",
        "_score": 0.16152832,         [1]
        "_source": {
          "text": "rrf rrf rrf rrf",
          "integer": 2
        }
      },
      {
        "_index": "example-index",
        "_id": "3",
        "_score": 0.15876243,         [2]
        "_source": {
          "text": "rrf rrf rrf",
          "vector": [
            3
          ],
          "integer": 1
        }
      },
      {
        "_index": "example-index",
        "_id": "2",
        "_score": 0.15350538,         [3]
        "_source": {
          "text": "rrf rrf",
          "vector": [
            4
          ],
          "integer": 2
        }
      },
      {
        "_index": "example-index",
        "_id": "1",
        "_score": 0.13963442,         [4]
        "_source": {
          "text": "rrf",
          "vector": [
            5
          ],
          "integer": 1
        }
      }
    ]
  }
}
  • [1]  rank 1, _id 4
  • [2]  rank 2, _id 3
  • [3]  rank 3, _id 2
  • [4]  rank 4, _id 1

请注意,我们的第一个命中没有 vector 字段的值。 现在,我们查看 kNN 搜索的结果。

GET example-index/_search?filter_path=**.hits
{
  "knn": {
    "field": "vector",
    "query_vector": [
      3
    ],
    "k": 5,
    "num_candidates": 5
  }
}

上面搜索的结果为:

{
  "hits": {
    "hits": [
      {
        "_index": "example-index",
        "_id": "3",                      [1]
        "_score": 1,
        "_source": {
          "text": "rrf rrf rrf",
          "vector": [
            3
          ],
          "integer": 1
        }
      },
      {
        "_index": "example-index",
        "_id": "2",                     [2]
        "_score": 0.5,
        "_source": {
          "text": "rrf rrf",
          "vector": [
            4
          ],
          "integer": 2
        }
      },
      {
        "_index": "example-index",
        "_id": "1",                     [3]
        "_score": 0.2,
        "_source": {
          "text": "rrf",
          "vector": [
            5
          ],
          "integer": 1
        }
      },
      {
        "_index": "example-index",
        "_id": "5",                     [4]
        "_score": 0.1,
        "_source": {
          "vector": [
            0
          ],
          "integer": 1
        }
      }
    ]
  }
}
  • [1]  rank 1, _id 3
  • [2]  rank 2, _id 2
  • [3]  rank 3, _id 1
  • [4]  rank 4, _id 5

我们现在可以获取两个单独排名的结果集并将 RRF 公式应用于它们以获得我们的最终排名。

# doc  | query     | knn       | score
_id: 1 = 1.0/(1+4) + 1.0/(1+3) = 0.4500
_id: 2 = 1.0/(1+3) + 1.0/(1+2) = 0.5833
_id: 3 = 1.0/(1+2) + 1.0/(1+1) = 0.8333
_id: 4 = 1.0/(1+1)             = 0.5000
_id: 5 =             1.0/(1+4) = 0.2000

我们根据 RRF 公式对文档进行排名,其中 window_size 为 5,截断 RRF 结果集中底部的 2 个文档,大小为 3。我们以 _id: 3 作为 _rank: 1, _id: 2 作为 _rank: 2, 及 _id: 4 作为 _rank: 3。这个排名符合预期的原始 RRF 搜索的结果集。

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

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

相关文章

蓝牙资讯|Canaly发布2023Q1全球可穿戴腕带设备报告

根据市场调查机构 Canalys 公布的最新报告&#xff0c;2023 年第 1 季度全球可穿戴腕带设备出货量为 4100 万台&#xff0c;同比下降 1%。 其中&#xff0c;本季度全球基础手环市场受到厂商和消费者更关注大屏设备影响&#xff0c;出货量为 750 万台&#xff0c;同比下降 24%…

Vue中如何进行拖拽与排序功能实现

Vue中如何进行拖拽与排序功能实现 在Web应用程序中&#xff0c;拖拽和排序功能是非常常见的。在Vue中&#xff0c;我们可以使用一些组件库来实现这个功能&#xff0c;例如sortablejs和vuedraggable。本文将介绍如何使用vuedraggable组件来实现Vue中的拖拽和排序功能。 什么是v…

Selenium Python教程第7章:Selenium编程其它功能

7. Selenium其它功能 7.1 Action Chains 动作链功能 WebDriver只能模拟针对特定元素的click, send_keys 操作&#xff0c;无法执行鼠标移动、悬浮、按键&#xff0c;选择菜单等操作&#xff0c;需要通过 Action Chains 类来操作 如下面操作&#xff0c;打开主菜单项后&#x…

实战:用dockerfile创建镜像实现springboot项目容器化

文章目录 前言技术积累docker基本操作命令dockerfile简介dockerfile指令说明 实战演示创建dockerfile创建挂载目录构建dockerfile启动容器完成验证 写在最后 前言 docker容器化方案是当下流行的服务部署方式&#xff0c;在软件领域举足轻重。我公司的测试、线上环境都采用dock…

选择最适合你的云服务器:腾讯云、华为云、阿里云对比

云服务器是一种基于云计算技术的服务器&#xff0c;它可以为企业提供高效、灵活、安全的运行环境。目前市场上有很多云服务器的选择&#xff0c;其中腾讯云、华为云和阿里云是最受欢迎的三个品牌&#xff0c;下面我们来看看它们各自的优势。 腾讯云的优势在于其强大的技术支持…

谷粒商城p45-自动装配-stream流-lambda表达式

软件&#xff1a;idea、postman、virtual box 服务&#xff1a;gulimall-product 请求路径&#xff1a;http://localhost:10000/product/category/list/tree 启动&#xff1a;启动idea product模块&#xff0c;启动vm&#xff0c;启动docker mysql controller代码 自动装配C…

LeetCode494. 目标和 0-1背包DP

https://leetcode.cn/problems/target-sum/ 题目描述 给你一个整数数组 nums 和一个整数 target 。 向数组中的每个整数前添加 ‘’ 或 ‘-’ &#xff0c;然后串联起所有整数&#xff0c;可以构造一个 表达式 &#xff1a; 例如&#xff0c;nums [2, 1] &#xff0c;可以在…

网络传输中的那些编码之-UTF8编码漫谈

编码为什么是一个重要的话题&#xff0c;因为我们和计算机交互的主要方式目前还是文字字符。作为一个程序员&#xff0c;相信大部分都都被字符和编码的问题折磨过&#xff0c;从键盘输入文字字符到编辑器 中&#xff0c;编辑器存储字符到硬盘&#xff0c;再到具体一个编程语言如…

中国电子学会2023年05月份青少年软件编程Scratch图形化等级考试试卷二级真题(含答案)

2023-05 Scratch二级真题 题数&#xff1a;37 分数&#xff1a;100 测试时长&#xff1a;60min 一、单选题(共25题&#xff0c;共50分) 1.运行下列哪段程序&#xff0c;可以让狗狗走到木屋门口&#xff1f;&#xff08;C&#xff09;(2分) A. B. C. D. 答案解析&a…

我用AI提高我的代码质量,周边同事对我的代码赞不绝口,速来围观

文章目录 前言功能演示1.使用Stream API来简化集合操作2.使用switch语句来替代多个if-else语句3.使用try-with-resources语句来自动关闭资源4. Lambda 表达式来简化代码,并提高代码的可读性和可维护性5.查找代码中的bug并优化6.python 使用sort方法来对列表进行排序7.javaScrpi…

一文看懂MySQL是什么

你可以前往我的博客查看更多关于云服务器和数据库以及域名注册、建站等相关文章。 MySQL是一种开源关系型数据库管理系统&#xff0c;它是最受欢迎的数据库之一。MySQL是由瑞典公司MySQL AB创建的&#xff0c;后来被Sun Microsystems收购&#xff0c;现在是Oracle Corporation…

Flink 系列二 Flink 状态化流处理概述

本篇作为Flink系列的第二篇&#xff0c;第一篇是环境准备&#xff0c;需要的同学可以看&#xff1a;https://blog.csdn.net/lly576403061/article/details/130358449?spm1001.2014.3001.5501。希望可以通过系统的学习巩固该方面的知识&#xff0c;丰富自己的技能树。废话不多说…

解决 org.eclipse.jface.text.Document class file version 61.0 报错

问题描述 运行好好的项目&#xff0c;没有做任何改动&#xff0c;最近在编译时报以下错误 java.lang.UnsupportedClassVersionError: org/eclipse/jface/text/Document has been compiled by a more recent version of the Java Runtime (class file version 61.0), this vers…

解决Python使用pip安装库文件出现“ERROR: Cannot unpack file…”

解决问题 1 ERROR: Could not find a version that satisfies the requirement robotframework (from versions: none) ERROR: No matching distribution found for robotframework 在dos命令输入 pip install robotframework 在线安装robotframework 如下报错&#xff1a; …

在紧急情况下,120可以定位我们的位置吗

随着科技的快速发展&#xff0c;越来越多的人们开始意识到科技对于生活的重要性。在现代社会中&#xff0c;GPS定位系统已经成为了一个不可或缺的工具&#xff0c;并且被广泛应用于各个领域&#xff0c;包括医疗救援行业。 120急救车和120急救指挥调度系统都采用了GPS定位技术…

SpringCloud Eureka注册中心高可用集群配置(八)

当注册中心扛不住高并发的时候&#xff0c;这时候 要用集群来扛&#xff1b; 我们再新建两个module microservice-eureka-server-2002 microservice-eureka-server-2003 第一步&#xff1a; pom.xml 把依赖加下&#xff1a; <dependencies> <dependency…

失败的统一错误处理

1.拦截器 在调用接口的时候,客户端会向服务器发送请求,请求之前有请求拦截器&#xff0c;返回数据之前有响应拦截器。 2:示例 根据自己的状态码来进行判断的一般2字开头代表成功&#xff0c;这个状态码是由后端来进行控制的。 成年的代码处理: if (res.data.success) {// 成功…

都是被逼的... ,LM算法的具体实现python和C++代码

L-M方法全称Levenberg-Marquardt方法&#xff0c;是一种非线性最小二乘优化算法&#xff0c;它通过同时利用高斯牛顿方法和梯度下降方法来解决非线性最小二乘问题。其核心思想是在每次迭代中&#xff0c;根据当前参数估计计算目标函数的梯度和海森矩阵&#xff0c;并使用这些信…

华为OD机试之最大N个数与最小N个数的和

最大N个数与最小N个数的和 题目描述 给定一个数组&#xff0c;编写一个函数来计算它的最大N个数与最小N个数的和。你需要对数组进行去重。 说明&#xff1a; 数组中数字范围[0, 1000]最大N个数与最小N个数不能有重叠&#xff0c;如有重叠&#xff0c;输入非法返回-1输入非法返…

Python之pyecharts的常见用法3-极坐标图-漏斗图

Pyecharts是一个基于Echarts的Python可视化库&#xff0c;可以用Python语言轻松地生成各种交互式图表和地图。它支持多种图表类型&#xff0c;包括折线图、柱状图、散点图、饼图、地图等&#xff0c;并且可以通过简单的API调用实现数据可视化。 Pyecharts的优点包括&#xff1a…