使用 Elasticsearch 进行语义搜索

Elasticsearch 是一款功能强大的开源搜索引擎,可用于全文搜索、分析和数据可视化。传统上,Elasticsearch 以其执行基于关键字/词汇的搜索的能力而闻名,其中文档基于精确或部分关键字匹配进行匹配。然而,Elasticsearch 已经发展到支持语义搜索 —— 一种专注于理解单词和短语背后的含义,而不仅仅是匹配关键字的方法。

Elasticsearch 中的语义搜索可实现更直观和上下文感知的搜索体验,即使查询中没有精确的关键字,也可以找到相关信息。本文将探讨如何在 Elasticsearch 中实现语义搜索、其优势和实际用例。

语义搜索

语义搜索是一种超越传统基于关键字的搜索的技术,它考虑了搜索查询的上下文、意图和含义。与专注于文字匹配的关键字搜索不同,语义搜索了解单词和概念之间的关系,从而实现更准确、更相关的搜索结果。

例如,在基于关键字的搜索中,查询 “laptop battery life” 可能会返回包含这些确切单词的文档。但是,语义搜索可能会返回讨论相关概念的文档,例如 “long-lasting laptops”、“energy-efficient devices”,甚至 “portable computers with extended battery life.”。

Elasticsearch 如何支持语义搜索

Elasticsearch 通过多种技术组合支持语义搜索,包括:

  • 向量表示:使用预训练模型(如 BERT(来自 Transformers 的双向编码器表示))将文本转换为可捕获语义含义的密集向量嵌入。
  • 相似度评分:测量查询向量和文档向量之间的相似度,以根据语义相关性对搜索结果进行排名。
  • 自定义分析器:创建自定义标记器、过滤器和分析器,以增强语义理解的方式预处理文本数据。
  • 与机器学习模型集成:利用与 Elasticsearch 集成的机器学习模型执行实体识别、情感分析等任务

架构 —— 使用 Elasticsearch 进行语义搜索

Elasticsearch 中两个非常重要的概念是文档和索引。

文档

文档是字段及其相关值的集合。每个文档都是一个 JSON 对象,其中包含结构化格式的数据。例如,代表一本书的文档可能包含标题、作者和出版日期等字段。

索引

索引是文档的集合,以高度优化的格式存储,旨在执行高效搜索。索引类似于关系数据库中的表,但它们更灵活,可以存储复杂的数据结构。

要使用 Elasticsearch,你需要将数据组织成文档,然后将所有文档添加到索引中。这使 Elasticsearch 能够根据搜索查询高效地搜索和检索相关文档。

在 Elasticsearch 中实现语义搜索

1. 设置 Elasticsearch

首先,确保你已启动并运行 Elasticsearch。你可以通过启动 Elasticsearch 的 Docker 容器来远程连接到 elasticsearch:

docker run -it \--rm \--name elasticsearch \-p 9200:9200 \-p 9300:9300 \-e "discovery.type=single-node" \-e "xpack.security.enabled=false" \docker.elastic.co/elasticsearch/elasticsearch:8.4.3

2. 数据加载和预处理

在此步骤中,我们将加载 documents.json 文件并对其进行预处理,以使层次结构扁平化,使其适合Elasticsearch。documents.json文件包含课程列表,每个课程都有一个文档列表。我们将提取每个文档并向其中添加一个课程字段,指示它属于哪个课程。

import jsonwith open('documents.json', 'rt') as f_in:docs_raw = json.load(f_in)

Elasticsearch 要求所有内容都处于同一层次结构中,在本例中,我们有两个层次,course 和 documents:

documents = []for course_dict in docs_raw:for doc in course_dict['documents']:doc['course'] = course_dict['course']documents.append(doc)documents[1]
#Output
{'text': 'GitHub - DataTalksClub data-engineering-zoomcamp#prerequisites','section': 'General course-related questions','question': 'Course - What are the prerequisites for this course?','course': 'data-engineering-zoomcamp'}

3. 使用预训练模型创建嵌入

要执行语义搜索,我们需要将文档转换为密集向量(嵌入),以捕获文本的语义含义。我们将使用来自 Sentence Transformers 库的预训练模型来生成这些嵌入。然后将这些嵌入编入 Elasticsearch 索引。这些嵌入使我们能够执行语义搜索,其目标是找到与给定查询上下文相似的文本。

文本和问题字段是包含主要信息的实际数据字段,而其他字段(如 section 和 course)则更具分类性,信息量较少,无法创建有意义的嵌入。

  • 安装 sentence_transformers 库。
  • 加载预训练模型并使用它来为我们的文档生成嵌入。
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("all-mpnet-base-v2")#created the dense vector using the pre-trained model
operations = []
for doc in documents:# Transforming the title into an embedding using the modeldoc["text_vector"] = model.encode(doc["text"]).tolist()operations.append(doc)

4. 连接到 Elasticsearch

在此步骤中,我们将建立与 Elasticsearch 实例的连接。确保 Elasticsearch 正在运行。

from elasticsearch import Elasticsearch# Connect to the Elasticsearch instance
es_client = Elasticsearch('http://localhost:9200')
# Check the connection
print(es_client.info())

5. 创建映射和索引

我们将定义映射并在 Elasticsearch 中创建索引,生成的嵌入也将存储在其中。

映射是指定如何在 Elasticsearch 中构建和索引文档及其字段的过程。每个文档由各种字段组成,每个字段都分配有特定的数据类型。

与数据库模式类似,映射概述了文档的结构,详细说明了字段、它们的数据类型(例如字符串、整数或日期)以及如何索引和存储这些字段。

通过定义文档和索引,我们确保索引就像书中的目录一样,有助于高效搜索。

index_settings = {"settings": {"number_of_shards": 1,"number_of_replicas": 0},"mappings": {"properties": {"text": {"type": "text"},"section": {"type": "text"},"question": {"type": "text"},"course": {"type": "keyword"},"text_vector": {"type": "dense_vector", "dims": 768, "index": True, "similarity": "cosine"},}}
}index_name = "course-questions"
# Delete the index if it exists
es_client.indices.delete(index=index_name, ignore_unavailable=True)
# Create the index
es_client.indices.create(index=index_name, body=index_settings)

6. 将文档添加到索引

然后,我们将预处理后的文档及其嵌入添加到 Elasticsearch 索引中。这使得 Elasticsearch 能够有效地存储和管理文档,从而实现快速准确的搜索查询。

for doc in operations:try:es_client.index(index=index_name, document=doc)except Exception as e:print(e)

7. 查询搜索引擎

当用户输入搜索查询时,它会被转换为嵌入并在 Elasticsearch 索引中进行搜索。结果会根据其与查询的相关性进行评分。

search_term = "windows or mac?"
vector_search_term = model.encode(search_term)query = {"field": "text_vector","query_vector": vector_search_term,"k": 5,"num_candidates": 10000, 
}
res = es_client.search(index=index_name, knn=query, source=["text", "section", "question", "course"])
res["hits"]["hits"]

执行关键字搜索和高级搜索(过滤结果)

只要你直接使用用户输入并将该信息传递到你的搜索功能中,这就变成了关键字搜索。

response = es_client.search(index=index_name,query={"bool": {"must": {"multi_match": {"query": "windows or python?", "fields": ["text", "question","course","title"],"type": "best_fields"}},"filter": {"term": {"course": "data-engineering-zoomcamp"}}}}
)

执行语义搜索和高级搜索

为了让 Elasticsearch 执行语义搜索,我们应该传递从最终用户那里收到的信息并将其转换为向量嵌入,并且该向量嵌入是传递到搜索函数中的向量嵌入。

knn_query= {"field": "text_vector","query_vector":vector_search_term,"k": 5,"num_candidates" : 10000
}
response=es_client.search(index=index_name,query={"match": {"course": "data-engineering-zoomcamp"},},knn=knn_query,size=5,explain=True)

以下是主要步骤的简要介绍:

将从最终用户收到的搜索词转换为向量嵌入。

  • 将此向量嵌入传递到高级语义搜索函数中。
  • 将结果限制在特定部分,在本例中为 “General course-related questions”。同样,它可以限制为特定课程,例如 “Data Engineering Zoom Camp.”。基本语义搜索和高级语义搜索之间的一个显着区别在于结果的评分。基本语义搜索分数范围在 0 到 1 之间,其中 0 表示匹配度低,1 表示匹配度高。

使用 Explain 关键字解释分数为了进一步了解分数计算,Elasticsearch 提供了 explain=true 关键字。此工具描述了如何计算分数,提供了有价值的见解。有了这些信息,人们可以开发出更符合特定用户或业务需求的自定义评分函数。

更多阅读,请参阅:Elasticsearch:使用 Open AI 和 Langchain 的 RAG - Retrieval Augmented Generation (二)

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(一)<江科大STM32>——软件环境搭建+新建工程步骤

一、软件环境搭建 (1)安装 Keil5 MDK 文件路径:江科大stm32入门教程资料/Keil5 MDK/MDK524a.EXE,安装即可,路径不能有中文。 (2)安装器件支持包 文件路径:江科大stm32入门教程资料…

【顶刊核心变量】上市公司企业数字创新数据(数字产品、流程、业务模式创新(2001-2023年)

1.资料名称:2023-2001年上市公司企业数字创新数据 2.测算方式:参考《系统工程理论与实践》郑攀攀(2024)老师的做法,本文基于上市公司年报文本, 结合文本分析和机器学习方法, 测度了企业数字创新(DI) . 具体的测度步骤…

在K8s平台部署个人博客

在K8s平台部署个人博客 实验步骤查看wordpress前端的service配置word press 实验步骤 kubectl create secret generic mysql-pass --from-literalpasswordYOUR_PASSWORD把mysql.tar.gz和wordpress.tar.gz上传到K8s工作节点,手动解压即可: 通过网盘分享的…

Qt项目实战:红绿灯小程序

目录 一.初始化对象 二.捕获并处理特定的事件 三.自定义绘制方法 四.绘制外部边框 五.绘制内部边框 六.绘制按钮的背景色 七.绘制覆盖层(高光效果) 八.效果 九.代码 1.h 2.cpp 一.初始化对象 1.设置文本、颜色、边框和背景色等默认值。 2.安…

408——计算机网络(持续更新)

文章目录 一、计算机网络概述1.1 计算机网络的概念1.2 计算机网络体系结构1.3 总结 二、物理层2.1 物理层的基本概念2.2 物理层的基本通信技术2.3 总结 一、计算机网络概述 1.1 计算机网络的概念 计算机网络的定义:将地理位置不同的具有独立功能的计算机通过网络线路…

算法简介:K最近邻算法

KNN 1. 最近邻算法1.1 回归 2. 机器学习OCR创建垃圾邮件过滤器预测股票市场 1. 最近邻算法 KNN(k-nearest neighbours)K最近邻算法:采用此算法进行分类,检索距离该元素最近的几个元素是什么类型,那么该元素即为什么类…

力扣动态规划基础版(矩阵型)

62.不同路径(唯一路径问题) 62. 不同路径https://leetcode.cn/problems/unique-paths/ 方法一:动态规划 找状态转移方程,也就是说它从左上角走到右下角,只能往右或者往下走,那么设置一个位置为&#xff…

adb 常用命令汇总

目录 adb 常用命令 1、显示已连接的设备列表 2、进入设备 3、安装 APK 文件到设备 4、卸载指定包名的应用 5、从设备中复制文件到本地 6、将本地文件复制到设备 7、查看设备日志信息 8、重启设备 9、截取设备屏幕截图 10、屏幕分辨率 11、屏幕密度 12、显示设备的…

基于大语言模型(LLM)自主Agent 智能体综述

近年来,LLM(Large Language Model)取得了显著成功,并显示出了达到人类智能的巨大潜力。基于这种能力,使用LLM作为中央控制器来构建自助Agent,以获得类人决策能力。 Autonomous agents 又被称为智能体、Agent。指能够通过感知周围环境、进行规划以及执行动作来完成既定任务。…

node.js模块化分析

什么是Node.js模块化 Node.js中的模块化‌是指将一个大文件拆分成独立且相互依赖的多个小模块。每个JS文件被视为一个独立的模块,模块之间是互相不可见的。如果一个模块需要使用另一个模块,则需要使用指定的语法来引入该模块,并且只能使用模块…

openstack之guardian介绍与实例创建过程

运行特征 采集模块:扩展Ceilometer,采集存储网、业务网连通性、nova目录是否可读写; 收集模块:将采集到的数据存储到数据库中; 分析模块:根据采集的结果,分析各节点状态,并进行反向检…

C语言 -- qsort的简单使用

qsort函数 一、介绍二、语法格式三、使用函数从小到大从大到小 四、结语 一、介绍 qsort 函数是 C 标准库中的一个通用排序函数&#xff0c;用于对数组进行快速排序。它定义在 <stdlib.h> 头文件中。这个非常灵活&#xff0c;因为它允许用户指定数组的元素类型、数组的大…

unity3d————叉乘的知识点

一、向量叉乘的知识点 定义与公式&#xff1a; 向量叉乘的定义为&#xff1a;对于两个三维向量a和b&#xff0c;它们的叉乘结果是一个向量c&#xff0c;记为cab。叉乘的计算公式为&#xff1a;c(y1z2-y2z1)i(x2z1-x1z2)j(x1y2-x2y1)k&#xff0c;其中a(x1, y1, z1)&#xff0c;…

vue2和vue3在html中引用组件component方式不一样

我的vue版本是&#xff1a;20.17.0 一、在HTML中&#xff0c;引用组件格式区别。 vue2引用组件可以是file.vue格式&#xff0c;需要导入&#xff1a;<script src"https://unpkg.com/http-vue-loader"></script>才可以识别vue格式。 vue3引用组件格式是…

密码学知识点整理一:密码学概论

密码学是什么&#xff1f; 密码学是一门研究编制密码和破译密码的技术科学。 密码学&#xff0c;作为信息安全的核心技术之一&#xff0c;其重要性在于能够为信息传输提供安全保障&#xff0c;确保数据在存储或传输过程中的机密性、完整性与真实性不被破坏。从古至今&#x…

我谈正态分布——正态偏态

目录 pdf和cdf参数 标准正态分布期望和方差分布形态 3 σ 3\sigma 3σ原则 正态和偏态正态偏态瑞利分布偏度 (Skewness)峰度 (Kurtosis) 比较 正态分布的英文是Normal Distribution&#xff0c;normal是“正常”或“标准”的意思&#xff0c;中文翻译是正态&#xff0c;多完美的…

杨传辉:云+AI 时代的一体化数据库|OceanBase发布会实录

在 2024 OceanBase 年度发布会 上&#xff0c; OceanBase CTO 杨传辉进行了主题为《云和 AI 时代的一体化数据库战略思考》的演讲&#xff0c;本文为演讲实录&#xff0c;欢迎阅读。 视频观看可点击&#xff1a;https://www.oceanbase.com/video/9001825 各位 OceanBase 的客…

华为OD机试 - 无重复字符的元素长度乘积的最大值(Python/JS/C/C++ 2024 C卷 100分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

【格式化查看JSON文件】coco的json文件内容都在一行如何按照json格式查看

文章目录 1.使用 Python 中的 json 库2. 使用浏览器3. notepad4. VSCode 如果COCO的JSON文件内容在一行显示&#xff0c;这通常意味着文件被压缩或者是在传输过程中出现了问题。 1.使用 Python 中的 json 库 想更好地查看 COCO 格式的 JSON 标签&#xff0c;可以将其格式化为更…

2025生物发酵展(济南)为生物制造产业注入新活力共谱行业新篇章

2025第十四届国际生物发酵展将于3月3-5日济南盛大举办&#xff01;产业链逐步完整&#xff0c;展会面积再创历史新高&#xff0c;展览面积较上届增涨至60000平方米&#xff0c;专业观众40000&#xff0c;品牌展商800&#xff0c;同期活动会议增加至50场&#xff0c;展会同期将举…