如何使用 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 elastic

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

docker 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/stdin

sha256 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 os

OPENAI_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].embedding
    
    es.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 os

OPENAI_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].embedding

query_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 os

OPENAI_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].embedding

query_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 这个电影。它说明这个大语言模型支持多语言的搜索。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Red Hat Enterprise Linux 9.2

Red Hat Enterprise Linux 9.2的安装 插入安装光盘&#xff0c;从光盘启动&#xff0c;选择 第一个选项&#xff0c;安装Red Hat Enterprise Linux 9.2 9.2支持简体中文 此次安装选择了英文安装&#xff0c;估计在生产环境大多也是选择的英文安装 安装选项此次也是选择的mi…

利用MSF生成php,windows,Linux三类木马

一、什么是msfvenom&#xff1f; msfvenom是msf中的一个独立的负载生成器&#xff0c;它可以利用msf中的payloads和encoders来生成各种格式的木马文件&#xff0c;并在目标机上执行&#xff0c;配合meterpreter在本地监听上线。msfvenom是msfpayload和msfencode的结合体&#x…

保姆级教学 - C语言 之 动态内存管理

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;魔法指针&#xff0c;进阶C&#xff0c;C语言&#xff0c;C语言题集&#xff0c;C语言实现游戏&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持创作博文(平均质量分79.9)&#xff0c;分…

shell常用通配符

目录 介绍 示例 * ? [a,b,...] / [ab...] [^a,b,...] / [^ab...] [x1-x2] {"xxx","xxx","xxx",...} {x1..x2} 介绍 示例 * 匹配0或多个字符 ls的-d选项可以只列出当前目录下的文件,而不会列出他们包含的内容: ? 只匹配任意一个字符 …

MySQL基础(DDL,DML,DQL)

目录 一DDL 1.1数据库操作 1.1.1查询所有数据库&#xff1a; 1.1.2创建数据库 1.1.3 使用数据库 1.1.4 删除数据库 1.2表操作 1.2.1表操作 1.2.1.1创建表 1.2.1.1.1约束 1.2.1.1.2 数据类型 1.2.1.1.2.1 数值类型 1.2.1.1.2.2 字符串类型 1.2.1.1.2.3日期类型 1.…

Linux源码包安装

目录 一、transmission源码包安装 二、 nginx源码包安装 一、transmission源码包安装 1、下载编译环境所需的软件包依赖 2、下载transmision源码包到用户主目录下 https://github.com/transmission/transmission/releases/download/4.0.5/transmission-4.0.5.tar.xz 3、解压…

支持度和置信度

支持度和置信度是数据挖掘和关联规则挖掘领域中常用的两个指标&#xff0c;用于衡量项集之间的关联程度。 支持度&#xff08;Support&#xff09;&#xff1a;支持度是指某个项集在数据集中出现的频率&#xff0c;即该项集在数据集中出现的次数与总事务数之比。支持度用来衡量…

Qt 利用共享内存实现一次只能启动一个程序(单实例运行)

Qt 利用共享内存实现一次只能启动一个程序 文章目录 Qt 利用共享内存实现一次只能启动一个程序摘要利用共享内存实现一次只能启动一个程序示例代码 关键字&#xff1a; Qt、 unique、 单一、 QSharedMemory、 共享内存 摘要 今天接着在公司搞我的屎山代码&#xff0c;按照…

数学建模(层次分析法 python代码 案例)

目录 介绍&#xff1a; 模板&#xff1a; 例题&#xff1a;从景色、花费、饮食&#xff0c;男女比例四个方面去选取目的地 准则重要性矩阵&#xff1a; 每个准则的方案矩阵&#xff1a;​ 一致性检验&#xff1a; 特征值法求权值&#xff1a; 完整代码&#xff1a; 运行结…

基于ssm新生报到系统论文

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对新生报到信息管理混乱&#xff0c;出错率高&#xff0c;信息安全性差…

containerd源代码分析: 整体架构

本文从代码的大的整体组织上来熟悉containerd项目 containerd项目总的说是一个cs模式的原生控制台程序组。containerd作为服务端来接收处理client的各种请求&#xff0c;如常用的拉取推送镜像&#xff0c;创建查询停止容器&#xff0c;生成快照&#xff0c;发送消息等。client/…

About Online Taxis

About Online Taxis 关于网络预约出租汽车&#xff08;网约车&#xff09; 1&#xff09;网络预约出租汽车 驾驶员证&#xff08;人证&#xff09; 2&#xff09;网络预约出租汽车 运输证&#xff08;车证&#xff09; 民之苦已久......

【PHP】通过PHP安装数据库并使数据初始化

一、前言 有些CMS在部署的时候不用使用数据库工具&#xff0c;而是通过数据库安装页面就能完成数据库创建和数据填充&#xff0c;所以自己就想动手做一个这样的功能&#xff0c;这样在给别人安装系统的时候就不用再那么麻烦了&#xff0c;直接一键安装解决了。 二、效果图 输…

jupyter notebook使用教程

首先是打开jupyter notebook 下载安装好之后&#xff0c;直接在命令行中输入‘jupyter notebook’即可跳转到对应页面 还可以进入想要打开的文件夹&#xff0c;然后再文件夹中打开中断&#xff0c;执行‘jupyter notebook’命令&#xff0c;就能够打开对应文件界面的jupyter …

iOS模拟器 Unable to boot the Simulator —— Ficow笔记

本文首发于 Ficow Shen’s Blog&#xff0c;原文地址&#xff1a; iOS模拟器 Unable to boot the Simulator —— Ficow笔记。 内容概览 前言终结模拟器进程命令行改权限清除模拟器缓存总结 前言 iOS模拟器和Xcode一样不靠谱&#xff0c;问题也不少。&#x1f602; 那就有病治…

时序预测 | Matlab基于BiTCN-LSTM双向时间卷积长短期记忆神经网络时间序列预测

时序预测 | Matlab基于BiTCN-LSTM双向时间卷积长短期记忆神经网络时间序列预测 目录 时序预测 | Matlab基于BiTCN-LSTM双向时间卷积长短期记忆神经网络时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab基于BiTCN-LSTM双向时间卷积长短期记忆神经网络时…

PSO-CNN-SVM,基于PSO粒子群优化算法优化卷积神经网络CNN结合支持向量机SVM数据分类(多特征输入多分类)-附代码

PSO-CNN-SVM&#xff0c;基于PSO粒子群优化算法优化卷积神经网络CNN结合支持向量机SVM数据分类 下面是一个大致的步骤&#xff1a; 数据准备&#xff1a; 准备训练集和测试集数据。对数据进行预处理&#xff0c;包括归一化、标准化等。 设计CNN模型&#xff1a; 设计合适的CNN…

vue.config.js配置项

vue.config.js配置项 vue-cli3 脚手架搭建完成后&#xff0c;项目目录中没有 vue.config.js 文件&#xff0c;需要手动创建 创建vue.config.js vue.config.js(相当于之前的webpack.config.js) 是一个可选的配置文件&#xff0c;如果项目的 (和 package.json 同级的) 根目录中存…

基于OrangePi Zero2的智能家居项目(准备阶段)

一、需求及项目准备&#xff08;前期准备&#xff09; 1、各类的需求 以及复习巩固的东西 2、系统框架图 3、硬连接线 3.1硬件准备 USB充电头&#xff08;当前实测可用&#xff1a;5V/2.5A)x1、USB转TYPE-Cx1、SU-03Tx1、烟雾报警模块x1、4路继 电器x1、 OLEDx1、 电磁锁x1&a…

【C语言】多文件编程以及static关键字

1、多文件编程 把函数声明放在头文件xxx.h中&#xff0c;在主函数中包含相应头文件在头文件对应的xxx.c中实现xxx.h声明的函数 a、主文件 #include<stdio.h> #include "MyMain.h"//需要包含头文件&#xff0c;头文件包含我们自定义的函数int main(){int num…