Elasticsearch:无需搜索 “Christmas” 即可找到有关圣诞节的书籍

随着假期的临近,我期待着变得舒适,拿起一本新书,享受轻松的时光。

但是使用搜索栏在线发现图书并不像看起来那么容易......大多数零售搜索引擎仅依赖于关键字搜索,当我们确切地知道我们正在寻找什么书名时,这很好,但当我们确切地知道我们正在寻找什么标题时,它就变得更具挑战性。 我们对主题只有一个模糊的概念。

因此,在这篇简短的文章中,我决定探索如何利用 Elasticsearch 对语义搜索的支持来帮助那些想要查找有关圣诞节的书籍的人......而无需使用 "圣诞节 (Christmas)"一词。

对于我们的示例,我们将使用包含书籍摘要的数据集。 接下来,您需要启动一个 Elasticsearch 集群并运行已下载的 ELSER 模型 2

首先,我们配置一个摄取管道来为每本书概要生成稀疏向量。在本次展示中,我将采用最新的 Elastic Stack 8.11 来进行展示。

安装

安装 Elasticsearch 及 Kibana

如果你还没有安装好自己的 Elasticsearch 及 Kibana,那么请参考一下的文章来进行安装:

在安装的时候,请选择 Elastic Stack 8.x 进行安装。在安装的时候,我们可以看到如下的安装信息:

为了能够上传向量模型,我们必须订阅白金版或试用。

安装 ELSER 模型

如果你还没有安装好 ELSER 模型,请参考文章 "Elasticsearch:部署 ELSER - Elastic Learned Sparse EncoderR" 来进行安装。在这里就不再累述了。请注意安装好的 ELSER 模型的 ID 为 .elser_model_2 而不是之前那篇文章中的 .elser_model_1。

下载数据集

我们在地址 raw.githubusercontent.com/elastic/ela... 下载好数据集并保存于当前的项目目录下。

拷贝 Elasticsearch 证书

我们把 Elasticsearch 的证书拷贝到当前的目录下:

markdown 复制代码
1.  $ pwd
2.  /Users/liuxg/python/elser
3.  $ cp ~/elastic/elasticsearch-8.11.0/config/certs/http_ca.crt .
4.  $ ls
5.  Chatbot with LangChain conversational chain and OpenAI.ipynb
6.  ElasticKnnSearch.ipynb
7.  ElasticVectorSearch.ipynb
8.  ElasticsearchStore.ipynb
9.  Mental Health FAQ.ipynb
10.  Multilingual semantic search.ipynb
11.  NLP text search using hugging face transformer model.ipynb
12.  Question Answering with Langchain and OpenAI.ipynb
13.  RAG-langchain-elasticsearch.ipynb
14.  Semantic search - ELSER.ipynb
15.  Semantic search quick start.ipynb
16.  a.ipynb
17.  book_summaries_1000_chunked.json
18.  books.json
19.  data.json
20.  http_ca.crt
21.  lib
22.  sample_data.json
23.  vector_search_implementation_guide_api.ipynb
24.  workplace-docs.json

如上所示,我们的 Elasticsearch 的证书是 http_ca.crt。我们的数据集是 book_summaries_1000_chunked.json。

创建环境变量

在运行之前,我们必须使用如下的命令来安装相应的 elasticsearch 包:

ini 复制代码
 2.  pip3 install elasticsearch==8.11

在启动 jupyter notebook 之前,我们必须运行如下的命令来创建所需要的环境变量:

ini 复制代码
1.  export ES_USER="elastic"
2.  export ES_PASSWORD="o6G_pvRL=8P*7on+o6XH"
3.  export ES_ENDPOINT="localhost"

我们创建一个新的 find_books_about_christmas_without_searching_for_christmas.ipynb。

运行应用

创建客户端连接

ini 复制代码
1.  elastic_user=os.getenv('ES_USER')
2.  elastic_password=os.getenv('ES_PASSWORD')
3.  elastic_endpoint=os.getenv("ES_ENDPOINT")

5.  url = f"https://{elastic_user}:{elastic_password}@{elastic_endpoint}:9200"
6.  es = Elasticsearch(url, ca_certs = "./http_ca.crt", verify_certs = True)

8.  print(es.info())

如上所示,我们的 Elasticsearch 客户端连接是成功的。

创建 ingest pipeline

ini 复制代码
1.  PIPELINE_ID="vectorize_books_elser"

3.  es.ingest.put_pipeline(id=PIPELINE_ID, processors=[{
4.       "foreach": {
5.           "field": "synopsis_passages",
6.           "processor": {
7.             "inference": {
8.               "field_map": {
9.                 "_ingest._value.text": "text_field"
10.               },
11.               "model_id": ".elser_model_2",
12.               "target_field": "_ingest._value.vector",
13.               "on_failure": [
14.                 {
15.                   "append": {
16.                     "field": "_source._ingest.inference_errors",
17.                     "value": [
18.                       {
19.                         "message": "Processor 'inference' in pipeline 'ml-inference-title-vector' failed with message '{{ _ingest.on_failure_message }}'",
20.                         "pipeline": "ml-inference-title-vector",
21.                         "timestamp": "{{{ _ingest.timestamp }}}"
22.                       }
23.                     ]
24.                   }
25.                 }
26.               ]
27.             }
28.           }
29.         }
30.  }])

如果大家对上面的 processor 的设计不是很清楚的话,可以详细阅读文章 "ELSER 模型 2"。

创建 mappings 及索引

perl 复制代码
1.  mappings = {
2.     "properties": {
3.         "title": {"type": "text"},
4.         "published_date": {"type": "text"},
5.         "synopsis": {"type": "text"},
6.         "synopsis_passages": {
7.           "type": "nested",
8.           "properties": {
9.               "vector": {
10.                 "properties": {
11.                   "is_truncated": {
12.                     "type": "boolean"
13.                   },
14.                   "model_id": {
15.                     "type": "text",
16.                     "fields": {
17.                       "keyword": {
18.                         "type": "keyword",
19.                         "ignore_above": 256
20.                       }
21.                     }
22.                   },
23.                   "predicted_value": {
24.                     "type": "sparse_vector"
25.                   }
26.              }
27.           }
28.       }
29.     }
30.  }
31.  }
32.  # Create the index (deleting any previously existing index)
33.  es.indices.delete(index="books", ignore_unavailable=True)
34.  es.indices.create(index="books", mappings=mappings)

我们可以在 Kibana 中查看到最新的 books 索引:

加载文档到 Elasticsearch

现在我们可以使用 bulk API 来提取我们的文档。 请注意,我们传递了之前创建的管道名称,以使用我们的 ELSER ML 模型来丰富文档。

python 复制代码
1.  import json

3.  with open('book_summaries_1000_chunked.json') as f:
4.     books = json.load(f)

6.  print("length of books: %d" %(len(books)))

8.  from elasticsearch.helpers import streaming_bulk
9.  count = 0
10.  def generate_actions(books):
11.   for book in books:
12.     doc = {}
13.     doc["_index"] = "books"
14.     doc["pipeline"] = "vectorize_books_elser"
15.     doc["_source"] = book
16.     yield doc

19.  for ok, info in streaming_bulk(
20.      client=es, 
21.      index="books", 
22.      actions=generate_actions(books),
23.      max_retries=3, 
24.      request_timeout=60*3, 
25.      chunk_size=10):
26.   if not ok:
27.     print(f"Unable to index {info['index']['_id']}: {info['index']['error']}")

运行完上面的命令后,我们可以在 Kibana 中进行查看:

我们共有 999 个文档。我们可以在 Kibana 中进行查看直到 999 个文档完全被写入:

查询文档

我们现在已经准备好进行有趣的部分:测试一些查询以查看我们得到的结果。 这里的一件很棒的事情是,Elasticsearch 支持使用相同索引的关键字搜索和语义搜索,只要数据已正确索引即可,这里就是这种情况。 我们已将概要索引为文本以及稀疏向量数组。

在这里,我们将尝试使用以下查询来查找有关圣诞节的书籍:

markdown 复制代码
1.  "Story with Santa Claus"
2.  "Xmas stories"
3.  "Gift receiving and festive season"

使用关键字搜索(BM25)进行搜索的查询如下:

bash 复制代码
1.  POST books/_search
2.  {
3.    "_source": ["title"], 
4.    "query": {
5.      "match": {
6.        "synopsis": "Xmas stories"
7.      }
8.    }
9.  }

使用语义搜索进行搜索的查询是这样的:

bash 复制代码
1.  POST books/_search
2.  {
3.    "_source": [
4.      "title"
5.    ],
6.    "query": {
7.      "nested": {
8.        "path": "synopsis_passages",
9.        "query": {
10.          "text_expansion": {
11.            "synopsis_passages.vector.predicted_value": {
12.              "model_id": ".elser_model_2",
13.              "model_text": "Xmas stories"
14.            }
15.          }
16.        }
17.      }
18.    }
19.  }

我不是英文的专家,也不是圣诞节书的爱好者。但是在搜索的有些词里,我们还是可以看到和圣诞或者 christian 有关的文字:

因为我们没有使用关键字 Christmas,所以在这种情况下语义搜索优于词汇搜索。

查看第一个查询的结果:"Story with Santa Claus"。 语义搜索看起来更相关。

我们可以做如下 keyword 查询:

我们做语义搜索:

对于其他两个测试查询,我们得到以下结果:

  • "Xmas stories"

    • Lexical search:

      1. Naked Lunch
      2. Lost Girls
      3. Gilgamesh the King
    • Semantic search:

      1. A Visit from St. Nicholas
      2. Light in August
      3. A Christmas Carol
  • "Gift receiving and festive season"

    • Lexical search:

      1. Smith of Wootton Major
      2. A Canticle for Leibowitz
      3. A Gift Upon the Shore
    • Semantic search:

      1. Smith of Wootton Major
      2. A Visit from St. Nicholas

我让你看看哪些书与圣诞节庆祝活动最相关。

最后我们完整的代码在地址:github.com/liu-xiao-gu...

相关推荐
Elasticsearch13 小时前
在 ES|QL 中的混合搜索和多阶段检索
elasticsearch
AC赳赳老秦15 小时前
量化交易脚本开发:DeepSeek生成技术指标计算与信号触发代码
数据库·elasticsearch·信息可视化·流程图·数据库架构·memcached·deepseek
Elastic 中国社区官方博客15 小时前
使用 Elastic Agent Builder 和 MCP 实现 Agentic 参考架构
大数据·人工智能·elasticsearch·搜索引擎·ai·架构·全文检索
予枫的编程笔记16 小时前
Elasticsearch深度搜索与查询DSL实战:精准定位数据的核心技法
java·大数据·人工智能·elasticsearch·搜索引擎·全文检索
予枫的编程笔记17 小时前
Elasticsearch聚合分析与大规模数据处理:解锁超越搜索的进阶能力
java·大数据·人工智能·分布式·后端·elasticsearch·全文检索
我是海飞17 小时前
Git 本地仓库推送到远程空仓库指南
大数据·git·elasticsearch
better_liang17 小时前
每日Java面试场景题知识点之-ELK技术栈实战应用
java·elk·elasticsearch·kibana·logstash·日志分析·企业级应用
予枫的编程笔记17 小时前
Elasticsearch核心架构与基础原理:解密其极速性能的底层逻辑
java·大数据·人工智能·elasticsearch·搜索引擎·架构·全文检索
长路 ㅤ   1 天前
ES索引切分方案4:索引+别名 应用层自己维护:时间序列索引
elasticsearch·索引模板·时间序列索引·别名系统·大数据优化
小龙1 天前
【Git 报错解决】本地分支与远程分支名称/提交历史不匹配
大数据·git·elasticsearch·github