html网站留言板代码,网络营销的基本方式,网站建设服务公司专业服务,高端婚纱摄影网站作者#xff1a;来自 Elastic Panagiotis Bailis Elasticsearch 检索器经过了重大改进#xff0c;现在可供所有人使用。了解其架构和用例。 在这篇博文中#xff0c;我们将再次深入探讨检索器#xff08;retrievers#xff09;。我们已经在之前的博文中讨论过它们#xf…作者来自 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 - 从 kNNk 最近邻搜索中返回排名靠前的文档rrf - 根据 RRF倒数排名融合排名公式组合来自不同检索器的结果text_similarity_reranker - 使用 rerank 类型推断端点对嵌套检索器的排名靠前结果进行重新排名
还可以在 Elasticsearch 文档中找到更多详细信息以及每个检索器的特定参数。
让我们首先简要介绍一些技术细节这将有助于我们了解架构、发生了什么变化以及为什么所有这些以前的限制现在都已解除 技术深入研究
我们想要解决的最重要的也是要求的问题之一是能够在任何嵌套级别使用任何检索器。无论这意味着将 2 个或更多 text_similarity_reranker 堆叠在一起还是将 rrf 检索器与 text_similarity_reranker 一起在另一个 rrf 之上运行或者你能想到的任何组合和嵌套我们都希望确保这是可以用检索器表达的东西
为了解决这个问题我们对检索器执行计划进行了一些重大更改。到目前为止检索器是作为 standard 搜索执行流程的一部分进行评估的其中在简化的场景中为了说明目的我们两次接触分片shard
一次用于查询分片并从每个分片中带回 from size 文档一次用于获取所有字段数据并执行任何其他操作例如突出显示/highlighting以获得真正的顶级 [from, fromsize] 结果。
这是一个不错的线性执行流程相对容易遵循但如果我们想要执行多个查询、对不同的结果集进行操作等就会引入一些重大限制。为了解决这个问题我们在查询执行的早期阶段就转向了对检索器管道的所有子检索器进行急切评估。这意味着如果需要我们会以递归方式将任何检索器查询重写为更简单的形式具体形式取决于检索器类型。
对于非复合检索器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。
现在考虑一个不同的场景在上面的相同查询中我们将改为使用 from10 和 size2。假设 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