Elasticsearch retrievers 通常与 Elasticsearch 8.16.0 一起正式发布!

news2024/11/16 21:43:41

作者:来自 Elastic Panagiotis Bailis

Elasticsearch 检索器经过了重大改进,现在可供所有人使用。了解其架构和用例。

在这篇博文中,我们将再次深入探讨检索器(retrievers)。我们已经在之前的博文中讨论过它们,从介绍到使用检索器进行语义重新排序。现在,我们很高兴地宣布,检索器已随 Elasticsearch 8.16.0 已正式发布,在这篇博文中,我们将从技术角度介绍如何实现它们,并有机会讨论新推出的功能!

检索器 - retrievers

检索器(retriever)的主要概念与最初版本相同;检索器是一个框架,它提供可以分层堆叠的基本构建块,以构建多阶段复杂检索和排名管道。例如,一个简单的 standard 检索器,它只返回所有文档:

GET retrievers_example/_search
{
    "retriever": {
        "standard": {
            "query": {
                "match_all": {}
            }
        }
    }
}

非常简单,对吧?除了 standard 检索器(本质上只是 standard query 搜索 API 元素的包装器)之外,我们还支持以下类型:

  • knn - 从 kNN(k 最近邻)搜索中返回排名靠前的文档
  • rrf - 根据 RRF(倒数排名融合)排名公式组合来自不同检索器的结果
  • text_similarity_reranker - 使用 rerank 类型推断端点对嵌套检索器的排名靠前结果进行重新排名

还可以在 Elasticsearch 文档中找到更多详细信息以及每个检索器的特定参数。

让我们首先简要介绍一些技术细节,这将有助于我们了解架构、发生了什么变化以及为什么所有这些以前的限制现在都已解除!

技术深入研究

我们想要解决的最重要的(也是要求的)问题之一是能够在任何嵌套级别使用任何检索器。无论这意味着将 2 个或更多 text_similarity_reranker 堆叠在一起,还是将 rrf 检索器与 text_similarity_reranker 一起在另一个 rrf 之上运行,或者你能想到的任何组合和嵌套,我们都希望确保这是可以用检索器表达的东西!

为了解决这个问题,我们对检索器执行计划进行了一些重大更改。到目前为止,检索器是作为 standard 搜索执行流程的一部分进行评估的,其中(在简化的场景中为了说明目的)我们两次接触分片(shard):

  • 一次用于查询分片并从每个分片中带回 from + size 文档,
  • 一次用于获取所有字段数据并执行任何其他操作(例如突出显示/highlighting)以获得真正的顶级 [from, from+size] 结果。

这是一个不错的线性执行流程,(相对)容易遵循,但如果我们想要执行多个查询、对不同的结果集进行操作等,就会引入一些重大限制。为了解决这个问题,我们在查询执行的早期阶段就转向了对检索器管道的所有子检索器进行急切评估。这意味着,如果需要,我们会以递归方式将任何检索器查询重写为更简单的形式,具体形式取决于检索器类型。

  • 对于非复合检索器(non-compound retrievers),我们重写的方式与在 standard 查询中类似,因为它们仍然可以遵循线性执行计划。
  • 对于复合检索器(compound retrievers),即在其他检索器之上操作的检索器,我们将它们展平为单个 rank_window_size 结果集,它本质上是一个 <doc, shard> 元组列表,表示此检索器的排名靠前的文档。

让我们通过以下(相当复杂的)检索器请求来看看它实际上是什么样子:

{
    "retriever": {
        "rrf": {                                                                                    [1]
            "retrievers": [
                {
                    "knn": {                                                                        [2]
                        "field": "emb1",
                        "query_vector_builder": {
                            "text_embedding": {
                                "model_id": "my-text-embedding-model",
                                "model_text": "LLM applications in information retrieval"
                            }
                        }
                    }
                },
                {
                    "standard": {                                                                   [3]
                        "query": {
                            "term": {
                                "topic": "science"
                            }
                        }
                    }
                },
                {
                    "rrf": {                                                                        [4]
                        "retrievers": [
                            {
                                "standard": {                                                       [5]
                                    "query": {
                                        "range": {
                                            "year": {
                                                "gte": 2020
                                            }
                                        }
                                    }
                                }
                            },
                            {
                                "knn": {                                                            [6]
                                    "field": "emb2",
                                    "query_vector_builder": {
                                        "text_embedding": {
                                            "model_id": "my-text-embedding-model",
                                            "model_text": "Vector scale on production systems"
                                        }
                                    }
                                }
                            }
                        ],
                        "rank_window_size": 100,
                        "rank_constant": 10
                    }
                }
            ],
            "rank_window_size": 10,
            "rank_constant": 1
        }
    }
}

上面的 rrf 检索器是一个复合检索器,因为它对其他一些检索器的结果进行操作,因此我们将尝试将其重写为更简单、扁平的 <doc, shard> 元组列表,其中每个元组指定一个文档和它所在的分片。此重写还将强制执行严格的排名,因此当前不支持不同的排序选项。

现在让我们继续识别所有组件并描述如何评估它的过程:

  • [1] 顶级 rrf 检索器;这是所有子检索器的父级,它将最后被重写和评估,因为我们首先需要知道每个子检索器的前 10 个结果(基于 rank_window_size)。
  • [2] 这个 knn 检索器是顶级 rrf 检索器的第一个子级,并使用嵌入服务(my-text-embedding-model)来计算将使用的实际查询向量。这将通过向嵌入服务发出异步请求来计算给定 model_text 的向量,从而将其重写为通常的 knn 查询。
  • [3] standard 检索器,也是顶级 rrf 检索器的子项的一部分,它返回与主题匹配的所有文档:science。
  • [4] 顶级 rrf 检索器的最后一个子项,也是需要展平的 rrf 检索器。
  • [5] [6] 与 [2] 和 [3] 类似,这些检索器是 rrf 检索器的直接子项,我们将为每个检索器获取前 100 个结果(基于 rrf 检索器的 rank_window_size [4]),使用 rrf 公式将它们组合起来,然后重写为真正的前 100 个结果的展平 <doc, shard> 列表。

检索器的更新执行流程现在如下:

  • 我们将从重写所有我们可以重写的叶子开始。这意味着我们将重写 knn 检索器 [2] 和 [6] 来计算查询向量,一旦我们有了它,我们就可以在树中向上移动一层。
  • 在下一个重写步骤中,我们现在准备评估嵌套的 rrf 检索器 [4],我们最终会将其重写为扁平化的 RankDocsQuery 查询(即 <doc, shard> 元组的列表)。
  • 最后,顶级 rrf 检索器 [1] 的所有内部重写步骤都将完成,因此我们应该准备好按照要求合并和排名真正的前 10 个结果。即使是这个顶级 rrf 检索器也会将自身重写为扁平化的 RankDocsQuery,稍后将用于继续执行 standard 线性搜索执行流程。

将以上所有内容可视化,我们有:

查看上面的示例,我们可以看到如何将分层检索器树异步重写为简单的 RankDocsQuery。这种简化为我们带来了良好的(也是我们想要的!)副作用,即最终执行具有明确排名的正常请求,除此之外,我们还可以执行我们选择的任何补充操作。

玩转(golden)检索器!

正如我们上面简要提到的,有了这一重构,我们现在可以支持大量额外的搜索功能!在本节中,我们将介绍一些示例和使用场景,但更多内容也可以在文档中找到。

我们从最受欢迎的功能 —— 组合性开始,也就是说,在检索器树的任何级别都可以使用任意检索器的选项。

组合性 - composabilty

在以下示例中,我们想执行一个语义查询(使用像 ELSER 这样的嵌入服务),然后结合这些结果与 knn 查询,使用 rrf 进行合并。最后,我们希望使用 text_similarity_reranker 检索器进行重新排名。表达上述操作的检索器如下所示:

GET /retrievers_example/_search
{
    "retriever": {
        "text_similarity_retriever": {
            "retriever": {
                "rrf": {
                    "retrievers": [
                        {
                            "standard": {
                                "query": {
                                    "semantic": {
                                        "field": "inference_field",
                                        "query": "Can I use generative AI to identify user intent and improve search relevance?"
                                    }
                                }
                            }
                        },
                        {
                            "knn": {
                                "field": "vector",
                                "query_vector": [
                                    0.23,
                                    0.67,
                                    0.89
                                ],
                                "k": 3,
                                "num_candidates": 5
                            }
                        }
                    ],
                    "rank_window_size": 10,
                    "rank_constant": 1
                }
            },
            "field": "text",
            "inference_text": "LLM applications on production search applications",
            "inference_id": "my-reranker-model",
            "rank_window_size": 10
        }
    },
    "_source": [
        "text",
        "topic"
    ]
}

聚合 - aggregation

回想一下,在我们讨论的重做中,我们将复合检索器重写为 RankDocsQuery(即扁平的显式排名结果列表)。然而,这并不妨碍我们计算聚合,因为我们还会跟踪复合检索器中的源查询。这意味着我们可以回退到下面的嵌套 standard 检索器,以根据两个嵌套检索器结果的并集正确计算 topic 字段的聚合。

GET retrievers_example/_search
{
    "retriever": {
        "rrf": {
            "retrievers": [
                {
                    "standard": {
                        "query": {
                            "range": {
                                "year": {
                                    "gt": 2023
                                }
                            }
                        }
                    }
                },
                {
                    "standard": {
                        "query": {
                            "term": {
                                "topic": "elastic"
                            }
                        }
                    }
                }
            ],
            "rank_window_size": 10,
            "rank_constant": 1
        }
    },
    "_source": [
        "text",
        "topic"
    ],
    "aggs": {
        "topics": {
            "terms": {
                "field": "topic"
            }
        }
    }
}

因此,在上面的例子中,我们将计算 topic 字段的术语聚合,其中年份字段大于 2023,或者文档具有与之关联的主题 elastic。

折叠 - collapsing

除了我们上面讨论的聚合选项之外,我们现在还可以折叠结果,就像我们对 standard 查询请求所做的那样。在下面的示例中,我们计算 rrf 检索器的前 10 个结果,然后将它们折叠在 year 字段下。与 standard 搜索的主要区别在于,这里我们只折叠排名靠前的结果,而不是嵌套检索器中的结果。

GET /retrievers_example/_search
{
    "retriever": {
        "rrf": {
            "retrievers": [
                {
                    "text_similarity_reranker": {
                        "retriever": {
                            "standard": {
                                "query": {
                                    "term": {
                                        "topic": "ai"
                                    }
                                }
                            }
                        },
                        "field": "text",
                        "inference_text": "Can I use generative AI to identify user intent and improve search relevance?",
                        "rank_window_size": 10,
                        "inference_id": "my-reranker-model"
                    }
                },
                {
                    "knn": {
                        "field": "vector",
                        "query_vector":
                        [
                            0.23,
                            0.67,
                            0.89
                        ],
                        "k": 3,
                        "num_candidates": 5
                    }
                }
            ],
            "rank_window_size": 10,
            "rank_constant": 1
        }
    },
    "collapse": {
        "field": "year",
        "inner_hits": {
            "name": "year_results",
            "_source": [
                "text",
                "year"
            ]
        }
    },
    "_source": [
        "text",
        "topic"
    ]
}

分页 - pagination

正如文档中所述,复合检索器也支持分页。与 standard 查询相比,复合检索器有一个显著的区别,与上面的折叠类似,rank_window_size 参数是我们可以执行导航的整个结果集。这意味着,如果 from + size > rank_window_size,那么我们将不会返回任何结果(但我们仍会返回聚合)。

GET /retrievers_example/_search
{
    "retriever": {
        "rrf": {
            "retrievers": [
                  {
                    "standard": {
                        "query": {
                            "term": {
                                "topic": "elastic"
                            }
                        }
                    }
                },
                {
                    "knn": {
                        "field": "vector",
                        "query_vector":
                        [
                            0.23,
                            0.67,
                            0.89
                        ],
                        "k": 3,
                        "num_candidates": 5
                    }
                }
            ],
            "rank_window_size": 10,
            "rank_constant": 1
        }
    },
    "from": 2,
    "size": 2
    "_source": [
        "text",
        "topic"
    ]
}

在上面的例子中,我们将从两个嵌套检索器(standard 和 knn)的组合中计算前 10 个结果(如 rrf 的 rank_window_size 中定义),然后我们将通过查阅 from 和 size 参数来执行分页。因此,在这种情况下,我们将跳过前 2 个结果(from)并选择接下来的 2 个结果(size)。

现在考虑一个不同的场景,在上面的相同查询中,我们将改为使用 from:10 和 size:2。假设 rank_window_size 为 10,并且这些将是我们可以分页的所有结果,在跳过前 10 个结果后请求获取 2 个结果将超出可导航结果集,因此我们将返回空结果。在 rrf 检索器的文档中还可以找到其他示例和更详细的细分。

解释 - explain

我们知道能力越大,责任越大。鉴于我们现在可以任意组合检索器,因此可能很难理解为什么最终会首先返回某个结果,以及如何优化我们的检索策略。出于这个非常具体的原因,我们努力确保检索器请求的解释输出(即通过指定 explain: true)将传达所有子检索器的所有必要信息,以便我们能够正确理解导致结果最终排名的所有因素。以 Collapsing 部分中相当复杂的查询为例,第一个结果的解释如下所示:

{
    "_explanation":{
        "value": 0.8333334,
        "description": "sum of:",
        "details": [
            {
                "value": 0.8333334,
                "description": "rrf score: [0.8333334] computed for initial ranks [2, 1] with rankConstant: [1] as sum of [1 / (rank + rankConstant)] for each query",
                "details": [
                    {
                        "value": 2,
                        "description": "rrf score: [0.33333334], for rank [2] in query at index [0] computed as [1 / (2 + 1)], for matching query with score",
                        "details": [
                            {
                                "value": 0.0011925492,
                                "description": "text_similarity_reranker match using inference endpoint: [my-awesome-rerank-model] on document field: [text] matching on source query ",
                                "details": [
                                    {
                                        "value": 0.3844723,
                                        "description": "weight(topic:ai in 1) [PerFieldSimilarity], result of:",
                                        "details":
                                        [
                                            ...
                                        ]
                                    }
                                ]
                            }
                        ]
                    },
                    {
                        "value": 1,
                        "description": "rrf score: [0.5], for rank [1] in query at index [1] computed as [1 / (1 + 1)], for matching query with score",
                        "details":
                        [
                            {
                                "value": 1,
                                "description": "doc [1] with an original score of [1.0] is at rank [1] from the following source queries.",
                                "details":
                                [
                                    {
                                        "value": 1,
                                        "description": "found vector with calculated similarity: 1.0",
                                        "details":
                                        []
                                    }
                                ]
                            }
                        ]
                    }
                ]
            }
        ]
    }
}

仍然有点冗长,但它传达了有关文档为何位于特定位置的所有必要信息。对于顶级 rrf 检索器,我们指定了 2 个details 信息,每个嵌套检索器一个。第一个是 text_similarity_reranker 检索器,我们可以在其中看到重新排序操作的权重,第二个是 knn 查询,告知我们文档与查询向量的计算相似性。可能需要一点时间才能熟悉,但每个检索器都会确保输出你可能需要评估和优化搜索场景的所有信息!

结论

现在就这些了!我们希望您一直关注我们,并且喜欢这个主题!我们对 retriever 框架的发布以及我们现在可以支持的所有新用例感到非常兴奋!检索器是为了支持从非常简单的搜索到高级 RAG 和混合搜索场景而构建的!如上所述,请关注此空间,更多功能即将推出!

Elasticsearch 包含新功能,可帮助您为你的用例构建最佳搜索解决方案。立即开始免费云试用或在你的本地机器上试用 Elastic。

原文:Elasticsearch retrievers are generally available with Elasticsearch 8.16.0! - Search Labs

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

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

相关文章

debug笔记:gpustat显示没有进程运行,但是GPU显存被占用

1 问题描述 使用gpustat之后&#xff0c;虽然显示除了gpu5之外别的都没有进程&#xff0c;但是GPU显存却被占用了 2 解决方法 原因是存在僵尸进程&#xff0c;已经运行完&#xff0c;但是内存并没有释放 fuser -v /dev/nvidia* 这个指令查看僵尸进程 然后kill掉即可&#…

【Chapter 3】Machine Learning Classification Case_Prediction of diabetes-XGBoost

文章目录 1、XGBoost Algorithm2、Comparison of algorithm implementation between Python code and Sentosa_DSML community edition(1) Data reading and statistical analysis(2)Data preprocessing(3)Model Training and Evaluation(4)Model visualization 3、summarize 1…

Android OpenGL ES详解——立方体贴图

目录 一、概念 二、如何使用 1、创建立方体贴图 2、生成纹理 3、设置纹理环绕和过滤方式 4、激活和绑定立方体贴图 三、应用举例——天空盒 1、概念 2、加载天空盒 3、显示天空盒 4、优化 四、应用举例——环境映射:反射 五、应用举例——环境映射:折射 六、应用…

聊天服务器(9)一对一聊天功能

目录 一对一聊天离线消息服务器异常处理 一对一聊天 先新添一个消息码 在业务层增加该业务 没有绑定事件处理器的话消息会派发不出去 聊天其实是服务器做一个中转 现在同时登录两个账号 收到了聊天信息 再回复一下 离线消息 声明中提供接口和方法 张三对离线的李…

T6识别好莱坞明星

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 导入基础的包 from tensorflow import keras from tensorflow.keras import layers,models import os, PIL, pathlib import matplotlib.pyplot as pl…

Odoo :一款免费开源的日化行业ERP管理系统

文 / 开源智造Odoo亚太金牌服务 概述 构建以 IPD 体系作为核心的产品创新研发管控体系&#xff0c;增进企业跨部门业务协同的效率&#xff0c;支撑研发管控、智慧供应链、智能制造以及全渠道营销等行业的场景化&#xff0c;构筑行业的研产供销财一体化管理平台。 行业的最新…

48.第二阶段x86游戏实战2-鼠标点击call

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要…

Vue 学习随笔系列十五 -- 数组遍历方法

数组遍历方法 文章目录 数组遍历方法1. for 循环2. forEach (不会修改数组本身)3. map (不修改数组本身)4. some(不修改数组本身&#xff09;5. every(不修改数组本身&#xff09;6. filter(不修改数组本身)7. find(不修改数组本身)8. findIndex拓展 9. reduce(累加)拓展 1. fo…

FreeRTOS的列表与列表项

目录 1.为什么要学列表&#xff1f; 2.什么是列表和列表项&#xff1f; 2.1 列表 2.2列表项 2.3&#xff0c;迷你列表项 3.列表与列表项的初始化 3.1 列表初始化 3.2列表项初始化 4.列表项的“增删查”&#xff08;插入、删除、遍历&#xff09; 4.1列表项的插入 4.1.1…

数字IC后端教程之Innovus hold violation几大典型问题

今天小编给大家分享下数字IC后端实现Physical Implementation过程中经常遇到的几个hold violation问题。每个问题都是小编自己在公司实际项目中遇到的。 数字后端实现静态时序分析STA Timing Signoff之min period violation Q1: 在Innouvs postCTS时序优化的log中我们经常会看…

VS2022编译32位OpenCV

使用环境 Visual Studio 2022 OpenCV: 4.7.0 cmake: 3.30.2一、使用CMake工具生成vs2022的openCV工程解决方案 打开cmake&#xff0c;选择opencv的源代码目录&#xff0c;创建一个文件夹&#xff0c;作为VS工程文件的生成目录 点击configure构建项目&#xff0c;弹出构建设置…

企业生产环境-麒麟V10(ARM架构)操作系统部署Zookeeper单节点集群版

前言&#xff1a;ZooKeeper是一个分布式协调服务&#xff0c;它为分布式应用提供一致性服务&#xff0c;是Apache Hadoop的子项目。它被设计为易于编程&#xff0c;同时具有高性能和高可靠性。ZooKeeper提供了一个简单的接口和一些基本的文件系统操作&#xff0c;使得开发者能够…

vue3 中直接使用 JSX ( lang=“tsx“ 的用法)

1. 安装依赖 npm i vitejs/plugin-vue-jsx2. 添加配置 vite.config.ts 中 import vueJsx from vitejs/plugin-vue-jsxplugins 中添加 vueJsx()3. 页面使用 <!-- 注意 lang 的值为 tsx --> <script setup lang"tsx"> const isDark ref(false)// 此处…

深度学习服务器租赁AutoDL

1. 根据需要选择租用的显卡 算力市场 1.1 显卡选择 1.2 环境配置 2. 服务器使用 2.1 上传文件 2.2 调试环境 2.3 跑代码 python train.py && /usr/bin/shutdown # && /usr/bin/shutdown表示代码成功运行结束后&#xff0c;自动关机3. 省钱绝招 省钱绝招 …

IDEA部署AI代写插件

前言 Hello大家好&#xff0c;当下是AI盛行的时代&#xff0c;好多好多东西在AI大模型的趋势下都变得非常的简单。 比如之前想画一幅风景画得先去采风&#xff0c;然后写实什么的&#xff0c;现在你只需描述出你想要的效果AI就能够根据你的描述在几分钟之内画出一幅你想要的风景…

【大数据技术基础 | 实验十】Hive实验:部署Hive

文章目录 一、实验目的二、实验要求三、实验原理四、实验环境五、实验内容和步骤&#xff08;一&#xff09;安装部署&#xff08;二&#xff09;配置HDFS&#xff08;三&#xff09;启动Hive 六、实验结果&#xff08;一&#xff09;启动结果&#xff08;二&#xff09;Hive基…

Flume1.9.0自定义Sink组件将数据发送至Mysql

需求 1、将Flume采集到的日志数据也同步保存到MySQL中一份&#xff0c;但是Flume目前不支持直接向MySQL中写数据&#xff0c;所以需要用到自定义Sink&#xff0c;自定义一个MysqlSink。 2、日志数据默认在Linux本地的/data/log/user.log日志文件中&#xff0c;使用Flume采集到…

Onlyoffice配置一 JWT認證

案例 使用官網給c# MVC的例子&#xff0c;主要在版本7.2之後&#xff0c;默認加入JWT認證&#xff0c;docker版本尚且可以在创建的时候使用默认的指令避开&#xff0c;但是在exe版本&#xff0c;即使配置为false&#xff0c;重启之后也会默认开启。 简单说一下如何配置 配置J…

ZeroSSL HTTPS SSL证书ACMESSL申请3个月证书

目录 一、引言 二、准备工作 三、申请 SSL 证书 四、证书选型 五、ssl重要性 一、引言 目前免费 Lets Encrypt、ZeroSSL、BuyPass、Google Public CA SSL 证书&#xff0c;一般免费3-6个月。从申请难易程度分析&#xff0c;zerossl申请相对快速和简单&#xff0c;亲测速度非…

MySql 日期周处理方式

MySql 日期周处理方式 最近在做数仓相关工作&#xff0c;最近遇到 几个问题&#xff0c; 1、计算指定日期是一年中的第几周&#xff0c;周一为周的第一天 2、计算周的开始时间&#xff0c;结束时间 3、计算周对应的年 比如 2023-01-01 WEEKOFYEAR(2023-01-01) 是2022年的52周&…