当前位置: 首页 > news >正文

如何使用 Elasticsearch 作为向量数据库

在今天的文章中,我们将很快地通过 Docker 来快速地设置 Elasticsearch 及 Kibana,并设置 Elasticsearch 为向量搜索。

拉取 Docker 镜像

docker pull docker.elastic.co/elasticsearch/elasticsearch:8.12.2
docker pull docker.elastic.co/kibana/kibana:8.12.2

启动 Elasticsearch 及 Kibana 容器

docker network create elasticdocker run -d --name elasticsearch --net elastic -p 9200:9200 -p 9300:9300 -m 1GB -e "discovery.type=single-node" -e "ELASTIC_PASSWORD=password" docker.elastic.co/elasticsearch/elasticsearch:8.12.2docker run -d --name kibana --net elastic -p 5601:5601 docker.elastic.co/kibana/kibana:8.12.2
$ docker run -d --name elasticsearch --net elastic -p 9200:9200 -p 9300:9300 -m 1GB -e "discovery.type=single-node" -e "ELASTIC_PASSWORD=password" docker.elastic.co/elasticsearch/elasticsearch:8.12.2
39dc9085f239edb3c963de4fb122f0ec02f78a6311abd8297cf046c025cd2618
$ docker run -d --name kibana --net elastic -p 5601:5601 docker.elastic.co/kibana/kibana:8.12.2
2766a300b3fd165f793f5f47b55748b2e9d4b016ea78b5c23565442e2c4cdfb5

在上面,我们指定了 elasic 超级用户的密码为 password。这在下面将要使用到。

验证容器是否已启动并正在运行:

$ docker ps
CONTAINER ID   IMAGE                                                  COMMAND                  CREATED              STATUS              PORTS                                            NAMES
2766a300b3fd   docker.elastic.co/kibana/kibana:8.12.2                 "/bin/tini -- /usr/l…"   About a minute ago   Up About a minute   0.0.0.0:5601->5601/tcp                           kibana
39dc9085f239   docker.elastic.co/elasticsearch/elasticsearch:8.12.2   "/bin/tini -- /usr/l…"   3 minutes ago        Up 3 minutes        0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp   elasticsearch

从上面我们可以看到 Elasticsarch 及 Kibana 已经完全运行起来了。我们可以在浏览器中进行验证:

docker exec -it elasticsearch /bin/bash

docker logs -f kibana
$ docker logs -f kibana
Kibana is currently running with legacy OpenSSL providers enabled! For details and instructions on how to disable see https://www.elastic.co/guide/en/kibana/8.12/production.html#openssl-legacy-provider
{"log.level":"info","@timestamp":"2024-03-22T01:28:37.598Z","log.logger":"elastic-apm-node","ecs.version":"8.10.0","agentVersion":"4.2.0","env":{"pid":7,"proctitle":"/usr/share/kibana/bin/../node/bin/node","os":"linux 6.4.16-linuxkit","arch":"arm64","host":"2766a300b3fd","timezone":"UTC+00","runtime":"Node.js v18.18.2"},"config":{"active":{"source":"start","value":true},"breakdownMetrics":{"source":"start","value":false},"captureBody":{"source":"start","value":"off","commonName":"capture_body"},"captureHeaders":{"source":"start","value":false},"centralConfig":{"source":"start","value":false},"contextPropagationOnly":{"source":"start","value":true},"environment":{"source":"start","value":"production"},"globalLabels":{"source":"start","value":[["git_rev","f5bd489c5ff9c676c4f861c42da6ea99ae350832"]],"sourceValue":{"git_rev":"f5bd489c5ff9c676c4f861c42da6ea99ae350832"}},"logLevel":{"source":"default","value":"info","commonName":"log_level"},"metricsInterval":{"source":"start","value":120,"sourceValue":"120s"},"serverUrl":{"source":"start","value":"https://kibana-cloud-apm.apm.us-east-1.aws.found.io/","commonName":"server_url"},"transactionSampleRate":{"source":"start","value":0.1,"commonName":"transaction_sample_rate"},"captureSpanStackTraces":{"source":"start","sourceValue":false},"secretToken":{"source":"start","value":"[REDACTED]","commonName":"secret_token"},"serviceName":{"source":"start","value":"kibana","commonName":"service_name"},"serviceVersion":{"source":"start","value":"8.12.2","commonName":"service_version"}},"activationMethod":"require","message":"Elastic APM Node.js Agent v4.2.0"}
[2024-03-22T01:28:38.276+00:00][INFO ][root] Kibana is starting
[2024-03-22T01:28:38.320+00:00][INFO ][node] Kibana process configured with roles: [background_tasks, ui]
[2024-03-22T01:28:42.183+00:00][INFO ][plugins-service] Plugin "cloudChat" is disabled.
[2024-03-22T01:28:42.192+00:00][INFO ][plugins-service] Plugin "cloudExperiments" is disabled.
[2024-03-22T01:28:42.193+00:00][INFO ][plugins-service] Plugin "cloudFullStory" is disabled.
[2024-03-22T01:28:42.501+00:00][INFO ][plugins-service] Plugin "profilingDataAccess" is disabled.
[2024-03-22T01:28:42.501+00:00][INFO ][plugins-service] Plugin "profiling" is disabled.
[2024-03-22T01:28:42.587+00:00][INFO ][plugins-service] Plugin "securitySolutionServerless" is disabled.
[2024-03-22T01:28:42.587+00:00][INFO ][plugins-service] Plugin "serverless" is disabled.
[2024-03-22T01:28:42.587+00:00][INFO ][plugins-service] Plugin "serverlessObservability" is disabled.
[2024-03-22T01:28:42.587+00:00][INFO ][plugins-service] Plugin "serverlessSearch" is disabled.
[2024-03-22T01:28:42.929+00:00][INFO ][http.server.Preboot] http server running at http://0.0.0.0:5601
[2024-03-22T01:28:42.996+00:00][INFO ][plugins-system.preboot] Setting up [1] plugins: [interactiveSetup]
[2024-03-22T01:28:43.004+00:00][INFO ][preboot] "interactiveSetup" plugin is holding setup: Validating Elasticsearch connection configuration…
[2024-03-22T01:28:43.019+00:00][INFO ][root] Holding setup until preboot stage is completed.i Kibana has not been configured.Go to http://0.0.0.0:5601/?code=897018 to get started.Your verification code is:  897 018 

我们把上面的 enrollment token 及 verification code 填入下面的方框里:

注意:由于一些原因,在上面显示的地址不是 localhost,而是电脑上的另外一个地址,比如 172.18.0.2:9200。这个并不影响我们的配置。

这样我们就成功地登录了。

创建索引

现在,让我们创建 “movies” 索引。 我们将使用 text-embedding-3-small 模型来生成 title 字段的向量嵌入并将其存储为 title_embedding。 该模型生成长度为 1536 的嵌入。因此我们需要将 title_embedding 字段映射指定为具有 1536 维的密集向量。

PUT /movies
{"mappings": {"properties": {"title": {"type": "text"},"genre": {"type": "keyword"},"release_year": {"type": "integer"},"title_embedding": {"type": "dense_vector","dims": 1536}}}
}

让我们使用 Elasticsearch Python 客户端插入一些文档。

Python 客户端需要 `ssl_assert_fingerprint` 才能连接到 Elasticsearch。 让我们使用以下命令来获取它:

openssl s_client -connect localhost:9200 -servername localhost -showcerts </dev/null 2>/dev/null | openssl x509 -fingerprint -sha256 -noout -in /dev/stdin
$ openssl s_client -connect localhost:9200 -servername localhost -showcerts </dev/null 2>/dev/null | openssl x509 -fingerprint -sha256 -noout -in /dev/stdinsha256 Fingerprint=20:67:39:6C:33:C0:D6:AC:E2:E3:A5:2E:56:6C:57:4F:91:DC:41:4D:99:9B:7F:0F:1C:20:AD:E2:20:FE:1E:1B

写入文档到 Elasticsearch

现在我们可以在电影索引中插入一些文档。

我们现在 terminal 中打入如下的命令:

export OPENAI_API_KEY="YourOpenAiKey"

在上面,请填入自己申请的 OpenAI key。

请按照下面的命令来安装所需要的包:

pip3 install elasticsearch python-dotenv

我们创建如下的 python 应用:

write_index.py

from elasticsearch import Elasticsearch
from openai import OpenAI
import osOPENAI_API_KEY= os.getenv("OPENAI_API_KEY")es = Elasticsearch("https://localhost:9200",ssl_assert_fingerprint='20:67:39:6C:33:C0:D6:AC:E2:E3:A5:2E:56:6C:57:4F:91:DC:41:4D:99:9B:7F:0F:1C:20:AD:E2:20:FE:1E:1B',basic_auth=("elastic", "password")
)openai = OpenAI(api_key=OPENAI_API_KEY)movies = [{"title": "Inception", "genre": "Sci-Fi", "release_year": 2010},{"title": "The Shawshank Redemption", "genre": "Drama", "release_year": 1994},{"title": "The Godfather", "genre": "Crime", "release_year": 1972},{"title": "Pulp Fiction", "genre": "Crime", "release_year": 1994},{"title": "Forrest Gump", "genre": "Drama", "release_year": 1994}
]# Indexing movies
for movie in movies:movie['title_embedding'] = openai.embeddings.create(input=[movie['title']], model='text-embedding-3-small').data[0].embeddinges.index(index="movies", document=movie)

我们使用如下的命令来运行脚本:

python3 write_index.py

我们可以在 Kibana 中进行查看:

GET movies/_search

搜索索引

比方说,我们想要搜索与片名《godfather》紧密匹配的电影。 我们可以使用K最近邻(KNN)算法来搜索相关文档。 我们会将搜索限制为仅显示 1 个最接近的匹配结果。

首先我们需要获得单词 Godfather 的向量表示:

vector_value = openai_client.embeddings.create(input=["Godfather"], model='text-embedding-3-small').data[0].embedding

现在我们可以搜索电影索引来获取与片名《Godfather》紧密匹配的电影。 在我们的例子中,它应该与标题为《Godfather》的电影文档匹配。

query_string = {"field": "title_embedding","query_vector": vector_value,"k": 1,"num_candidates": 100
}results = es_client.search(index="movies", knn=query_string, source_includes=["title", "genre", "release_year"])print(results['hits']['hits'])

完整的 Python 应用如下:

search_index.py

from elasticsearch import Elasticsearch
from openai import OpenAI
import osOPENAI_API_KEY= os.getenv("OPENAI_API_KEY")es = Elasticsearch("https://localhost:9200",ssl_assert_fingerprint='20:67:39:6C:33:C0:D6:AC:E2:E3:A5:2E:56:6C:57:4F:91:DC:41:4D:99:9B:7F:0F:1C:20:AD:E2:20:FE:1E:1B',basic_auth=("elastic", "password")
)openai = OpenAI(api_key=OPENAI_API_KEY)vector_value = openai.embeddings.create(input=["Godfather"], model='text-embedding-3-small').data[0].embeddingquery_string = {"field": "title_embedding","query_vector": vector_value,"k": 1,"num_candidates": 100
}results = es.search(index="movies", knn=query_string, source_includes=["title", "genre", "release_year"])print(results['hits']['hits'])

运行上面的代码:

$ python3 search_index.py 
[{'_index': 'movies', '_id': 'koeTZI4BvK48CYytTCuI', '_score': 0.8956262, '_source': {'title': 'The Godfather', 'genre': 'Crime', 'release_year': 1972}}]

很显然,它找到了 Godfather 这个文档。

很多开发者可能想问,我们是不是也可以使用中文来进行搜索呢?

我们尝试如下的代码:

search_index.py

from elasticsearch import Elasticsearch
from openai import OpenAI
import osOPENAI_API_KEY= os.getenv("OPENAI_API_KEY")es = Elasticsearch("https://localhost:9200",ssl_assert_fingerprint='20:67:39:6C:33:C0:D6:AC:E2:E3:A5:2E:56:6C:57:4F:91:DC:41:4D:99:9B:7F:0F:1C:20:AD:E2:20:FE:1E:1B',basic_auth=("elastic", "password")
)openai = OpenAI(api_key=OPENAI_API_KEY)vector_value = openai.embeddings.create(input=["教父"], model='text-embedding-3-small').data[0].embeddingquery_string = {"field": "title_embedding","query_vector": vector_value,"k": 1,"num_candidates": 100
}results = es.search(index="movies", knn=query_string, source_includes=["title", "genre", "release_year"])print(results['hits']['hits'])

在上面的代码中,我们使用 “教父” 而不是 Godfather。运行上面的代码,它显示:

$ python3 search_index.py
[{'_index': 'movies', '_id': 'koeTZI4BvK48CYytTCuI', '_score': 0.6547822, '_source': {'title': 'The Godfather', 'genre': 'Crime', 'release_year': 1972}}]

很显然,它也同样找到 Godfather 这个电影。它说明这个大语言模型支持多语言的搜索。

相关文章:

如何使用 Elasticsearch 作为向量数据库

在今天的文章中&#xff0c;我们将很快地通过 Docker 来快速地设置 Elasticsearch 及 Kibana&#xff0c;并设置 Elasticsearch 为向量搜索。 拉取 Docker 镜像 docker pull docker.elastic.co/elasticsearch/elasticsearch:8.12.2 docker pull docker.elastic.co/kibana/kiba…...

高精度AI火灾烟雾检测算法,助力打造更加安全的楼宇环境

一、方案背景 近日&#xff0c;南京居民楼火灾事故导致15人死亡的新闻闹得沸沸扬扬&#xff0c;这一事件又激起了大家对楼宇火灾隐患的进一步担忧。事后我们除了思考政府、消防及物业部门应对此事的解决办法&#xff0c;我们还应该思考如何利用现有的技术帮助人们减少此类事情的…...

node和npm yarn包管理工具

node和包管理工具 今日目标&#xff1a; 1.dos常用指令 2.node的模块化 3.npm包管理工具 4.yarn的常用指令 5.node的内置模块 00-回顾 # Promose:作用&#xff1a;解决ajax请求响应顺序不可控的问题特性&#xff1a;1. Promise是一个构造函数&#xff0c;需要通过new关…...

鸿蒙Harmony应用开发—ArkTS(@Link装饰器:父子双向同步)

子组件中被Link装饰的变量与其父组件中对应的数据源建立双向数据绑定。 说明&#xff1a; 从API version 9开始&#xff0c;该装饰器支持在ArkTS卡片中使用。 概述 Link装饰的变量与其父组件中的数据源共享相同的值。 限制条件 Link装饰器不能在Entry装饰的自定义组件中使用…...

【数据结构】猛猛干7道链表OJ

前言知识点 链表的调试技巧 int main() {struct ListNode* n1(struct ListNode*)malloc(sizeof(struct ListNode));assert(n1);struct ListNode* n2(struct ListNode*)malloc(sizeof(struct ListNode));assert(n2);struct ListNode* n3(struct ListNode*)malloc(sizeof(struc…...

记录C++中,子类同名属性并不能完全覆盖父类属性的问题

问题代码&#xff1a; 首先看一段代码&#xff1a;很简单&#xff0c;就是BBB继承自AAA&#xff0c;然后BBB重写定义了同名属性&#xff0c;然后调用父类AAA的打印函数&#xff1a; #include <iostream> using namespace std;class AAA { public:AAA() {}~AAA() {}void …...

使用 ONLYOFFICE API 构建 Java 转换器,在 Word 和 PDF 之间进行转换

文章作者&#xff1a;ajun 随着文档处理需求的增加&#xff0c;格式转换成为了一个重要的需求点。由于PDF格式具有跨平台、不易被篡改的特性&#xff0c;将Word格式(.docx)转换为PDF格式(.pdf)的需求尤为强烈。ONLYOFFICE作为一个强大的办公套件&#xff0c;提供了这样的转换功…...

SpringCloudAlibaba Nacos配置及应用

Nacos搭建及配置 nacos本机服务搭建 windows上搭建单机nacos&#xff1a; Releases alibaba/nacos GitHub 下载安装包 下载本地&#xff0c;解压&#xff0c;直接运行&#xff08;保证安装包的绝度路径只有英文字符&#xff0c;有中文会导致运行失败&#xff09;&#xff…...

#Linux(权限管理)

&#xff08;一&#xff09;发行版&#xff1a;Ubuntu16.04.7 &#xff08;二&#xff09;记录&#xff1a; &#xff08;1&#xff09; &#xff08;2&#xff09;-开头代表普通文件 划分为三组&#xff1a; rw- rw- r-- rw-: 文件拥有…...

easyExcel复杂表头导出

代码 import com.alibaba.excel.EasyExcel; import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy; import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;import java.util.ArrayList; import java.util.Arrays; imp…...

【大数据】五、yarn基础

Yarn Yarn 是用来做分布式系统中的资源协调技术 MapReduce 1.x 对于 MapReduce 1.x 的版本上&#xff1a; 由 Client 发起计算请求&#xff0c;Job Tracker 接收请求之后分发给各个TaskTrack进行执行 在这个阶段&#xff0c;资源的管理与请求的计算是集成在 mapreduce 上的…...

语义分割实战项目(从原理到代码环境配置)

语义分割&#xff08;Semantic Segmentation&#xff09; 先看结果&#xff1a; 是计算机视觉和深度学习领域的一项核心任务&#xff0c;它主要致力于对图像中的每一个像素进行分类&#xff0c;赋予每个像素一个类别标签&#xff0c;以达到理解图像内容的目的。换句话说&#…...

基于python+vue 的一加剧场管理系统的设计与实现flask-django-nodejs-php

二十一世纪我们的社会进入了信息时代&#xff0c;信息管理系统的建立&#xff0c;大大提高了人们信息化水平。传统的管理方式对时间、地点的限制太多&#xff0c;而在线管理系统刚好能满足这些需求&#xff0c;在线管理系统突破了传统管理方式的局限性。于是本文针对这一需求设…...

【Entity Framework】 EF中DbContext类详解

【Entity Framework】 EF中DbContext类详解 一、概述 DbContext类是实体框架的重要组成部分。它是应用域或实例类与数据库交互的桥梁。 从上图可以看出DbContext是负责与数据交互作为对象的主要类。DbContext负责以下活动&#xff1a; EntitySet&#xff1a;DbContext包含…...

智能风扇的新篇章:唯创知音WTK6900G语音识别芯片引领行业革新

随着科技浪潮的推进&#xff0c;智能化技术逐渐渗透到生活的每一个角落&#xff0c;家电领域尤为明显。风扇&#xff0c;这一夏日清凉神器&#xff0c;也通过智能化改造&#xff0c;焕发出前所未有的光彩。其中&#xff0c;智能语音控制功能的加入&#xff0c;为风扇的使用带来…...

[json.exception.type_error.316] invalid UTF-8 byte报错

[json.exception.type_error.316] invalid UTF-8 byte at index 1: 解决方法重新编译程序即可。...

深度强化学习(九)(改进策略梯度)

深度强化学习&#xff08;九&#xff09;&#xff08;改进策略梯度&#xff09; 一.带基线的策略梯度方法 Theorem: 设 b b b 是任意的函数, b b b与 A A A无关。把 b b b 作为动作价值函数 Q π ( S , A ) Q_\pi(S, A) Qπ​(S,A) 的基线, 对策略梯度没有影响: ∇ θ J …...

Oracle修改Number类型精度报错:ORA-01440

修改Number类型的字段的精度SQL ALTER TABLE XXXX MODIFY RATE NUMBER(30,6); 如果表已经存在数据&#xff0c;报错信息如下&#xff1a; ORA-01440: column to be modified must be empty to decrease precision or scale 废话不多说&#xff0c;解决方案如下&#xff1a;…...

美团到店-后端开发一面

1. 介绍一下spring的两大核心思想 2. 介绍一下java的代理&#xff0c;以及动态代理和静态代理的区别 3. spring动态代理是如何生成的&#xff0c;jdk动态代理和cglib的区别 4. 介绍一下synchronized关键字、以及synchronized锁和lock的区别 5. 讲一下java中synchronized的锁升级…...

面试算法-77-括号生成

题目 数字 n 代表生成括号的对数&#xff0c;请你设计一个函数&#xff0c;用于能够生成所有可能的并且 有效的 括号组合。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;[“((()))”,“(()())”,“(())()”,“()(())”,“()()()”] 解 class Solution {publ…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)

船舶制造装配管理现状&#xff1a;装配工作依赖人工经验&#xff0c;装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书&#xff0c;但在实际执行中&#xff0c;工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人&#xff0c;点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置&#xff0c;详见说明文档 成功后&#xff0c;记录Webhook 2 API文档说明 点击设置说明 查看自…...

JS手写代码篇----使用Promise封装AJAX请求

15、使用Promise封装AJAX请求 promise就有reject和resolve了&#xff0c;就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】&#xff0c;注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录&#xff08;即exe所在文件夹&#xff09;加入系统变量…...

【UE5 C++】通过文件对话框获取选择文件的路径

目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 &#xff0c;这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器&#xff0c;右键点击 .uproject 文件&#xff0c;选择 "Generate Visual Studio project files"&#xff0c;重…...