释放你的元数据:使用 Elasticsearch 的自查询检索器

ops/2025/2/18 20:41:00/

作者:来自 Elastic Josh Asres

了解如何使用 Elasticsearch 的 “self-quering” 检索器来通过结构化过滤器提高语义搜索的相关性。

在人工智能搜索的世界中,在海量的数据集中高效地找到正确的数据至关重要。传统的基于关键词的搜索在处理涉及自然语言的查询时往往会失效,这时就需要语义搜索了。然而,如果你想将语义搜索的功能与过滤日期和数字值等结构化元数据的能力结合起来,那么自查询检索器(self-querying retrievers)就可以发挥作用了。

自查询检索器提供了一种强大的方法来利用元数据进行更精确、更细致的搜索。当与 Elasticsearch 的搜索和索引功能相结合时,自查询变得更加强大,使开发人员能够提高 RAG 应用程序的相关性。这篇博文将探讨自查询检索器的概念,展示它们使用 LangChain 和 Python 与 Elasticsearch 的集成,以及它如何帮助你的搜索变得更加强大!

什么是自查询检索器(self-querying Retrievers)?

自查询检索器是 LangChain 提供的一项功能,它弥合了自然语言查询和结构化元数据过滤之间的差距。他们不再仅仅依靠关键字与文档内容的匹配,而是使用大型语言模型 (LLM) 以及 Elasticsearch 的想量搜索功能来解析用户的自然语言查询并智能地提取相关的元数据过滤器。例如,用户可能会问 “Find science fiction movies released after 2000 with a rating above 8 - 查找 2000 年后上映的评分高于 8 的科幻电影”。传统的搜索引擎如果没有关键词就很难找到隐含的含义,而单独的语义搜索可以理解查询的上下文,但无法应用日期和评级过滤器来获得最佳答案。但是,自查询检索器会分析查询,识别元数据字段(类型、年份、评级),并生成 Elasticsearch 可以理解和有效执行的结构化查询。这可以提供更加直观和用户友好的搜索体验,用户可以用简单的英语表达包含过滤器的复杂搜索条件。

所有这些都通过 LLM 链进行,其中 LLM 解析查询以从自然语言查询中提取过滤器,然后将新的结构化过滤器应用于包含 Elasticsearch 中的嵌入和元数据的文档。

Source: Langchain

实现自查询检索器

将自查询检索器与 Elasticsearch 集成涉及几个关键步骤。在我们的 Python 示例中,我们将使用 LangChain 的 AzureChatOpenAI 和 AzureOpenAIEmbeddings 以及 ElasticsearchStore 来管理它。我们首先引入所有 LangChain 库,设置 LLM 以及用于创建向量的嵌入模型:

from langchain_openai import AzureOpenAIEmbeddings, AzureChatOpenAI
from langchain_elasticsearch import ElasticsearchStore
from langchain.chains.query_constructor.base import AttributeInfo
from langchain.retrievers.self_query.base import SelfQueryRetriever
from langchain.docstore.document import Document
import os
llm = AzureChatOpenAI(azure_endpoint=os.environ["AZURE_ENDPOINT"],deployment_name=os.environ["AZURE_OPENAI_DEPLOYMENT_NAME"],model_name="gpt-4",api_version="2024-02-15-preview"
)embeddings = AzureOpenAIEmbeddings(azure_endpoint=os.environ["AZURE_ENDPOINT"],model="text-embedding-ada-002"
)

在我的示例中,我使用 Azure OpenAI 作为 LLM(gpt-4)以及使用 text-embedding-ada-002 作为嵌入。然而,这应该适用于任何基于云的 LLM 以及像 Llama 3 这样的本地 LLM,甚至适用于我使用 OpenAI 的嵌入模型,因为我们已经在使用 gpt-4。

然后,我们使用元数据定义文档,然后使用已建立的元数据字段将文档索引到 Elasticsearch 中:

# --- Define Metadata Attributes ---
metadata_field_info = [AttributeInfo(name="year",description="The year the movie was released",type="integer",),AttributeInfo(name="rating",description="The rating of the movie (out of 10)",type="float",),AttributeInfo(name="genre",description="The genre of the movie",type="string",),AttributeInfo(name="director",description="The director of the movie",type="string",),AttributeInfo(name="title",description="The title of the movie",type="string",)
]
docs = [Document(page_content="Following clues to the origin of mankind, a team finds a structure on a distant moon, but they soon realize they are not alone.",metadata={"year": 2012, "rating": 7.7, "genre": "science fiction", "title": "Prometheus"},),
...more documents

接下来将它们添加到 Elasticsearch 索引中,es_store.add_embeddings 函数会将文档添加到你在 ELASTIC_INDEX_NAME 变量中选择的索引中,如果在集群中找不到该索引,则会创建具有该名称的索引。在我的示例中,我使用的是 Elastic Cloud 部署,但这也适用于自管理集群:

es_store = ElasticsearchStore(es_cloud_id=ELASTIC_CLOUD_ID,es_user=ELASTIC_USERNAME,es_password=ELASTIC_PASSWORD,index_name=ELASTIC_INDEX_NAME,embedding=embeddings,
)
es_store.add_embeddings(text_embeddings=list(zip(texts, doc_embeddings)), metadatas=metadatas)

然后创建自查询检索器,接受用户的查询,使用 LLM(我们之前设置的 Azure OpenAI)来解释它,然后构建一个结合语义搜索和元数据过滤器的 Elasticsearch 查询。这一切都由 docs = trieser.invoke(query) 执行:

# --- Create the self-querying Retriever (Using your LLM) ---
retriever = SelfQueryRetriever.from_llm(llm,es_store,"Search for movies",metadata_field_info,verbose=True,
)
while True:# Prompt the user for a queryquery = input("\nEnter your search query (or type 'exit' to quit): ")if query.lower() == 'exit':break# Execute the query and print the resultsprint(f"\nQuery: {query}")docs = retriever.invoke(query)print(f"Found {len(docs)} documents:")for doc in docs:print(doc.page_content)print(doc.metadata)print("-" * 20)

我们做到了!然后根据 Elasticsearch 索引执行查询,返回与内容和元数据标准最匹配的相关文档。此过程使用户能够进行自然语言查询,如下面的示例所示:

Query: What is a highly rated movie from the 1970s?
Found 3 documents:
The aging patriarch of an organized crime dynasty transfers control of his clandestine empire to his reluctant son.
{'year': 1972, 'rating': 9.2, 'genre': 'crime', 'title': 'The Godfather'}
--------------------
Three men walk into the Zone, three men walk out of the Zone
{'year': 1979, 'director': 'Andrei Tarkovsky', 'genre': 'thriller', 'rating': 9.9, 'title': 'Stalker'}
--------------------
Four armed men hijack a New York City subway car and demand a ransom for the passengers
{'year': 1974, 'rating': 7.6, 'director': 'Joseph Sargent', 'genre': 'action', 'title': 'The Taking of Pelham One Two Three'}

结论

虽然自查询检索器提供了一些显著的优势,但必须考虑它们的局限性:

  • 自查询检索器依赖于 LLM 解释用户查询和提取正确的元数据过滤器的准确性。如果查询过于模糊或元数据定义不明确,则检索器可能会产生不正确或不完整的结果。
  • 自查询过程的性能取决于查询的复杂性和数据集的大小。对于极大的数据集或非常复杂的查询,LLM 处理和查询构建可能会带来一些开销。
  • 应该考虑使用 LLM 进行查询解释的成本,尤其是对于高流量应用程序。

尽管存在这些考虑,自查询检索器仍然代表了信息检索的强大增强,尤其是与 Elasticsearch 的可扩展性和强大功能相结合时,为构建搜索 AI 应用程序提供了引人注目的解决方案。

有兴趣自己尝试一下吗?开始免费的云试用并在此处查看示例代码。你对可以在 Elastic Stack 中使用的其他检索器(例如 Reciprocal Rank Fusion)感兴趣吗?请参阅此处的文档以了解更多信息。

Elasticsearch 与行业领先的 Gen AI 工具和提供商进行了原生集成。查看我们的网络研讨会,了解如何超越 RAG 基础知识,或构建可用于生产的应用程序 Elastic Vector Database。

为了为你的用例构建最佳搜索解决方案,请立即开始免费云试用或在您的本地机器上试用 Elastic。

原文:Unleashing your metadata: Self-querying retrievers with Elasticsearch - Elasticsearch Labs


http://www.ppmy.cn/ops/158732.html

相关文章

Git分支管理:从入门到高效协作

引言 在软件开发中,分支管理是团队协作的核心技能。Git作为最流行的版本控制工具,其分支机制以轻量级、高效著称。本文将带你深入掌握Git分支管理的核心技巧,提升团队协作效率。 一、Git分支的本质 分支是什么 Git分支本质上是指向提交对象的…

深度学习框架探秘|PyTorch:AI 开发的灵动画笔

前一篇文章我们学习了深度学习框架——TensorFlow(深度学习框架探秘|TensorFlow:AI 世界的万能钥匙)。在人工智能领域,还有一个深度学习框架——PyTorch,以其独特的魅力吸引着众多开发者和研究者。它就像一…

QT中线程中使用信号和槽传数据

mainwindow.h #ifndef WORKERTHREAD_H #define WORKERTHREAD_H#include <QObject> #include <QThread> #include <QQueue> class WorkerThread : public QThread {Q_OBJECT public:explicit WorkerThread(); private:void run() override; //重新实现run&…

【技术产品】DS三剑客:DeepSeek、DataSophon、DolphineSchduler浅析

引言 在大数据与云原生技术快速发展的时代&#xff0c;开源技术成为推动行业进步的重要力量。本文将深入探讨三个备受瞩目的开源产品组件&#xff1a;DeepSeek、DataSophon 和 DolphinScheduler&#xff0c;分别从产品定义、功能、技术架构、应用场景、优劣势及社区活跃度等方面…

【Elasticsearch】标准化器(Normalizers)

Elasticsearch 的标准化器&#xff08;Normalizers&#xff09;是一种特殊的分析器&#xff0c;用于对keyword类型字段的文本进行统一的格式化处理。与普通分析器不同&#xff0c;标准化器只能产生单个标记&#xff08;token&#xff09;&#xff0c;因此它不包含分词器&#x…

比较循环与迭代器的性能:Rust 零成本抽象的威力

一、引言 在早期的 I/O 项目中&#xff0c;我们通过对 String 切片的索引和 clone 操作来构造配置结构体&#xff0c;这种方法虽然能确保数据所有权的正确传递&#xff0c;但既显得冗长&#xff0c;又引入了不必要的内存分配。随着对 Rust 迭代器特性的深入了解&#xff0c;我…

07:串口通信(二):收发数据包

1、数据包 我们使用上位机个单片机发送数据包时&#xff0c;规定包头和包尾&#xff0c;将我们需要发送的数据放在中间&#xff0c;数据的长度我们也可以自己规定。一般情况下HEX数据包我们使用固定长度数据包。而文本数据包使用是可变长度数据包。 2、HEX数据包 2.1、HEX固定…

Python练习11-20

题目&#xff1a;古典问题&#xff1a;有一对兔子&#xff0c;从出生后第3个月起每个月都生一对兔子&#xff0c;小兔子长到第三个月后每个月又生一对兔子&#xff0c;假如兔子都不死&#xff0c;问每个月的兔子总数为多少&#xff1f; 题目&#xff1a;判断101-200之间有多少…