elasticsearch 向量初探索

查看 elasticsearch 版本

GET /

我使用的是 7.1.0 已支持向量

起源

最开始探索好奇以图搜图,以文搜图这样的功能是怎样实现?慢慢接触后,其实实现的方式很多种,es 也只是实现向量搜索其中的一种,也有专门的向量的数据库,用来做这件事。当然业务中也有很多使用了ES 所以就想使用ES 来进行实现 向量搜索。

如何实现

大体思路

复制代码
首先梳理下向量搜索:首先拆分为几步:
第一步:理解向量;
第二步:es 与 向量直接的关系 查询的算法;
第三步:如何将数据转化为向量

流程

css 复制代码
第一步:将图片转化为向量存入es: 需要将图片转化为向量:存储到es中;
第二步:将搜索的文本转化为向量,在 ES 库中进行搜索


图片使用:clip-ViT-B-32 模型 
文本使用:sentence-transformers/clip-ViT-B-32-multilingual-v1 模型 
余弦相似度:cosineSimilarity算法进行搜索;
语言:python3

这里我使用的是 python 加载模型:因为 python 对模型支持比较好:

定义 mapping

arduino 复制代码
PUT image-vetor
{
        "mappings": {
            "properties": {
                "entity_name": {
                    "type": "text"
                },
                "entity_name_embedding":{
                  	"type": "dense_vector",
                        "dims": 512
                }
            }
        }
}

dims :需要与你模型生成向量相符

demo 实现

python 复制代码
from sentence_transformers import SentenceTransformer
from PIL import Image
import requests
from elasticsearch import Elasticsearch, helpers

# 使用 CLIP 模型加载和编码图像
img_model = SentenceTransformer('clip-ViT-B-32')


# 加载图像的函数
def load_image(url_or_path):
    if url_or_path.startswith("http://") or url_or_path.startswith("https://"):
        return Image.open(requests.get(url_or_path, stream=True).raw)
    else:
        return Image.open(url_or_path)


# 图像路径
img_paths = [
    "https://unsplash.com/photos/QtxgNsmJQSs/download?ixid=MnwxMjA3fDB8MXxhbGx8fHx8fHx8fHwxNjM1ODQ0MjY3&w=640",
    "https://unsplash.com/photos/9UUoGaaHtNE/download?ixid=MnwxMjA3fDB8MXxzZWFyY2h8Mnx8Y2F0fHwwfHx8fDE2MzU4NDI1ODQ&w=640",
]

images = [load_image(img) for img in img_paths]

# 将图像映射到向量空间
img_embeddings = img_model.encode(images)

# 创建 Elasticsearch 客户端

es = Elasticsearch('name:pwd@xxxx:9200')

# 创建索引和映射
index_name = 'image-vetor'

if not es.indices.exists(index=index_name):
    es.indices.create(index=index_name, body={
        "mappings": {
            "properties": {
                "entity_name_embedding": {
                    "type": "dense_vector",
                    "dims": img_embeddings.shape[1]
                }
            }
        }
    })


# 准备要插入的数据
def generate_docs(embeddings):
    num = 0
    for i, embedding in enumerate(embeddings):
        num = num + 1
        yield {
            "_index": index_name,
            "_id": num,  # 可以使用其他唯一标识符
            "_source": {
                "entity_name": f"image_{i}",
                "entity_name_embedding": embedding.tolist(),  # 将 numpy 数组转换为列表
                "url": img_paths[i]
            }
        }


# 插入数据到 Elasticsearch
helpers.bulk(es, generate_docs(img_embeddings))

print("Data inserted successfully")

text_model = SentenceTransformer('sentence-transformers/clip-ViT-B-32-multilingual-v1')
text_embeddings = text_model.encode("shoes")

queryStr = "dog"
# 执行向量查询
query_body = {
    "query": {
        "script_score": {
            "query": {
                "match_all": {}
            },
            "script": {
                "source": "cosineSimilarity(params.query_vector, 'entity_name_embedding') + 1.0",
                "params": {
                    "query_vector": text_embeddings
                }
            }
        }
    }
}

response = es.search(index=index_name, body=query_body)

# 打印查询结果
for hit in response['hits']['hits']:
    print(hit)

link:

相关推荐
华子w908925859几秒前
基于 SpringBoot+VueJS 的农产品研究报告管理系统设计与实现
vue.js·spring boot·后端
星辰离彬32 分钟前
Java 与 MySQL 性能优化:Java应用中MySQL慢SQL诊断与优化实战
java·后端·sql·mysql·性能优化
GetcharZp2 小时前
彻底告别数据焦虑!这款开源神器 RustDesk,让你自建一个比向日葵、ToDesk 更安全的远程桌面
后端·rust
jack_yin3 小时前
Telegram DeepSeek Bot 管理平台 发布啦!
后端
小码编匠3 小时前
C# 上位机开发怎么学?给自动化工程师的建议
后端·c#·.net
库森学长3 小时前
面试官:发生OOM后,JVM还能运行吗?
jvm·后端·面试
转转技术团队3 小时前
二奢仓店的静默打印代理实现
java·后端
蓝易云3 小时前
CentOS 7上安装X virtual framebuffer (Xvfb) 的步骤以及如何解决无X服务器的问题
前端·后端·centos
秋千码途4 小时前
小架构step系列07:查找日志配置文件
spring boot·后端·架构
蓝倾4 小时前
京东批量获取商品SKU操作指南
前端·后端·api