向量数据库实战介绍

本文将介绍三种常用的向量数据库:faiss, Milvus和Qdrant,并给出一个具体的使用例子。
向量数据库(Vector Database)是一种专门用于存储、管理、查询、检索向量的数据库,主要应用于人工智能、机器学习、数据挖掘等领域。
在向量数据库中,数据以向量的形式进行存储和处理,需要将原始的非向量型数据转化为向量表示(比如文本使用Embedding技术获得其表征向量)。
这种数据库能够高效地进行相似性搜索,快速找到最相似的向量,适用于人脸识别、图像搜索、推荐系统等需要相似性匹配的应用。

去年大模型的大火也带动了向量数据库的迅速发展,使得向量数据库成为热门方向之一,成为AI领域不可或缺的一项重要工具。

本文将介绍常见的三种向量数据库,并结合具体的样例文本给出它们在文本相似性搜索方面的应用。这三个向量数据库分别为:

  • faiss
  • Milvus
  • Qdrant

获取文本Embedding向量

我们使用的样例文本来源于百度百科的“中国载人登月工程”词条,将其本文切分为句子,过滤其中的纯数字的句子,保存为dengyue.txt文件。

对于上述文本,使用OpenAI的embedding模型text-embedding-ada-002来获取句子的表征向量(向量维度为1536,L2范数为1,即单位向量),并保存为numpy模块的npz文件,用于离线存储,避免每次使用时都需要加载。
示例的代码如下:

# -*- coding: utf-8 -*-
import os
import re
import json
from typing import List

from dotenv import load_dotenv
import requests
import numpy as np
from sentencex import segment

load_dotenv()


def get_embedding(texts: List[str]):
    url = "https://api.openai.com/v1/embeddings"
    payload = json.dumps({
        "model": "text-embedding-ada-002",
        "input": texts,
        "encoding_format": "float"
    })
    headers = {
        'Content-Type': 'application/json',
        'Authorization': f'Bearer {os.getenv("OPENAI_API_KEY")}'
    }
    response = requests.request("POST", url, headers=headers, data=payload)
    embedding = [_["embedding"] for _ in response.json()['data']]
    response.close()
    return embedding


def read_file():
    with open("dengyue.txt", "r", encoding="utf-8") as f:
        content = [_.strip() for _ in f.readlines() if _.strip()]
    file_sentences = []
    for line in content:
        sents = list(segment(language="zh", text=line))
        for sent in sents:  # filter
            if sent and not re.match(r'\[\d+\]', sent):
                file_sentences.append(sent)
    return file_sentences


if __name__ == '__main__':
    sentences = read_file()
    sentences_embeddings = np.array(get_embedding(sentences))
    np.savez('text_embedding.npz', sentences_embeddings)
    with open('text.json', 'w') as f:
        f.write(json.dumps({i: sentence for i, sentence in enumerate(sentences)}, indent=4, ensure_ascii=False))
    # sentences_embeddings = np.load('text_embedding.npz')
    # print(sentences_embeddings['arr_0'][0].tolist())

运行上述文件,则会得到句子的表征向量文件text_embedding.npz,使用np.load()方法即可加载这些向量。

faiss

faiss全称为Facebook AI Similarity Search,是Facebook开源的一个用于高效相似性搜索和密集向量聚类的库,使用C++编写,提供python接口,对10亿量级的索引可以做到毫秒级检索的性能。它包含的算法可以搜索任意大小的向量集,甚至可能无法容纳在 RAM 中的向量集。它还包含用于评估和参数调整的支持代码。
faiss模块同时支持CPU和GPU.
faiss支持的索引(Index)类型如下图:
在这里插入图片描述
文本相似性搜索:获取与查询文本(query)相似度最接近的k个语料文本:
获取query的表征向量(同一个Embedding模型)
借助faiss查询出与该query向量相似度最接近的k个向量
获取这k个向量对应的文本
示例Python代码如下:

# -*- coding: utf-8 -*-
import json
import numpy as np
from faiss import IndexFlatIP

from get_text_embedding import get_embedding

with open('text.json', 'r') as f:
    sentences = list(json.loads(f.read()).values())

# create faiss index
faiss_index = IndexFlatIP(1536)
# add vector
sentences_embeddings = np.load("text_embedding.npz")['arr_0']
faiss_index.add(sentences_embeddings)
# vector search
query = "阿波罗登月计划"
query = "神舟五号 杨利伟"
# query = "北京航天城"
query_embedding = get_embedding([query])
distances, doc_indices = faiss_index.search(np.array(query_embedding), 3)
# result
print(f"query: {query}")
print("recall result: ")
for i, sent_index in enumerate(doc_indices.tolist()[0]):
    print(f"rank: {i}, similarity: {distances.tolist()[0][i]}, text: {sentences[sent_index]}")
# reset index
faiss_index.reset()

输入query为阿波罗登月计划,最接近的3个语料文本为:

query: 阿波罗登月计划
recall result: 
rank: 0, similarity: 0.855633020401001, text: 二十世纪六、七十年代,美国人凭借“阿波罗”计划率先登上月球。
rank: 1, similarity: 0.8497034907341003, text: 初步方案是:采用两枚运载火箭分别将月面着陆器和载人飞船送至环月轨道在轨交会对接,航天员从飞船进入月面着陆器。
rank: 2, similarity: 0.8401131629943848, text: 欧阳自远表示,对于载人登月工程国家还没有公布一个明确的时间表,但已经在做积极的论证和准备。

输入query为神舟五号 杨利伟,最接近的3个语料文本为:

query: 神舟五号 杨利伟
recall result: 
rank: 0, similarity: 0.8733900785446167, text: 叶培建表示,中国载人航天计划共有“三步走”,第一步是从“神舟一号”走到“神舟七号”,前4个载人飞船是无人的,“神五”时杨利伟上天,实现中国人第一次进入太空的梦想,虽然比“太空旅行第一人”尤里·阿列克谢耶维奇·加加林晚了几十年,但两个不是一个数量级。
rank: 1, similarity: 0.8618367910385132, text: 加加林只飞了一个小时,是伞降;杨利伟飞了一天,是软着陆,返回舱已达到“容3个人7天往返”标准。
rank: 2, similarity: 0.8449346423149109, text: 加加林落地偏差达400公里;杨利伟落地时,落在中国内蒙古,当时设计“100乘以90公里着陆”都算准确着陆,但最终落地偏差只有10公里,后来“神六”、“神七”落地误差只有1公里,3条飞船实现了第一阶段的全部任务。

输入query为北京航天城,最接近的3个语料文本为:

query: 北京航天城
recall result: 
rank: 0, similarity: 0.8499420881271362, text: 在北京航天城当天举行的“李锦记航天奖学金”颁发仪式上,戚发轫介绍,根据中国的规划,2014年左右在深空探测领域,将把十几吨的航天器送到地球轨道,2020年前将建成自己的空间站。
rank: 1, similarity: 0.8408806920051575, text: 5月29日上午,神舟十六号载人飞行任务新闻发布会在酒泉卫星发射中心举行。
rank: 2, similarity: 0.8388772010803223, text: 戚发轫还介绍,中国将建成全球的自主北斗导航系统,中国的人、车、船、飞机在世界任何地方都可靠自己的卫星来导航定位。

Milvus

Milvus是在2019年创建的,其唯一目标是存储、索引和管理由深度神经网络和其他机器学习(ML)模型生成的大规模嵌入向量。

作为一个专门设计用于处理输入向量查询的数据库,它能够处理万亿级别的向量索引。与现有的关系型数据库主要处理遵循预定义模式的结构化数据不同,Milvus从底层设计用于处理从非结构化数据转换而来的嵌入向量。
在这里插入图片描述
我们使用Docker启动Milvus服务,并进行文本相似性搜索。示例Python代码如下:

# -*- coding: utf-8 -*-
# reference: https://milvus.io/docs
import json
import time
import numpy as np
from pymilvus import MilvusClient, FieldSchema, CollectionSchema, DataType, Collection

from get_text_embedding import get_embedding

with open('text.json', 'r') as f:
    sentences = list(json.loads(f.read()).values())

# add vector
sentences_embeddings = np.load("text_embedding.npz")['arr_0']

collection_name = "dengyue"
# Connects to a server
client = MilvusClient(uri="http://localhost:19530", db_name="default")
# List all collection names
collections = client.list_collections()
print("exist collections: ", collections)

# create collection if not exists
if collection_name not in collections:
    # Creates a collection
    fields = [
        FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=False),
        FieldSchema(name="text", dtype=DataType.VARCHAR, max_length=1000),
        FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=1536)
    ]
    schema = CollectionSchema(fields, "text search demo")
    index_params = client.prepare_index_params()
    index_params.add_index(
        field_name="embedding",
        index_type="IVF_FLAT",
        metric_type="IP",
        params={"nlist": 128}
    )
    client.create_collection(
        collection_name=collection_name,
        schema=schema,
        index_params=index_params
    )
    time.sleep(3)
    res = client.get_load_state(
        collection_name=collection_name
    )
    print("load state: ", res)

    # Inserts vectors in the collection
    entities = [
        {"id": i + 1,
         "text": sentences[i],
         "embedding": sentences_embeddings[i].tolist()}
        for i in range(len(sentences))
    ]
    client.insert(collection_name=collection_name, data=entities)

# Single vector search
query = "阿波罗登月计划"
# query = "神舟五号 杨利伟"
# query = "北京航天城"
query_embedding = get_embedding([query])
print(query_embedding[0])
res = client.search(
    collection_name=collection_name,
    data=query_embedding,
    limit=3,
    search_params={"metric_type": "IP", "params": {}},
    output_fields=['text']
)

# Convert the output to a formatted JSON string
result = json.dumps(res, indent=4, ensure_ascii=False)
print(result)

其中创建的Milvus collection为dengyue,其schema如下(可视化工具采用Attu):
在这里插入图片描述
运行上述程序,得到的文本相似度搜索结果同上述faiss。

Qdrant

Qdrant是一个用 Rust 编写的开源矢量数据库和矢量相似性搜索引擎,旨在利用先进的高性能矢量相似性搜索技术为下一代人工智能应用赋能。它的主要功能包括多语言支持(可实现各种数据类型的通用性)和适用于各种应用的过滤器。

Qdrant对近似近邻搜索的HNSW算法进行了定制修改,通过保持精确的结果,确保了最先进的搜索能力,从而实现了速度和精确度的双赢。此外,它还支持与向量相关的额外有效载荷,允许根据有效载荷值过滤结果。Qdrant 支持丰富的数据类型和查询条件,包括字符串匹配、数值范围和地理位置,为数据管理提供了多功能性。
Qdrant服务的启动方式如下:

  • 本地模式,不需要服务器(离线db文件或内存)
  • 本地服务器部署
  • Qdrant云

以本地模式(离线db文件)启动Qdrant服务,进行文本相似度搜索。示例Python代码如下:

# -*- coding: utf-8 -*-
import json
import os
import numpy as np
from qdrant_client import QdrantClient
from qdrant_client.http.models import Distance, VectorParams
from qdrant_client.http.models import PointStruct

from get_text_embedding import get_embedding


db_dir = "qdrant_db"
collect_name = "dengyue"
client = QdrantClient(path=db_dir)


if not os.path.exists(f"./{db_dir}/collection/{collect_name}"):
    with open('text.json', 'r') as f:
        sentences = list(json.loads(f.read()).values())
    sentences_embeddings = np.load('text_embedding.npz')
    # create collection
    client.recreate_collection(
        collection_name=collect_name,
        vectors_config=VectorParams(size=1536, distance=Distance.COSINE),
    )
    # insert data into collection
    operation_info = client.upsert(
        collection_name=collect_name,
        wait=True,
        points=[
            PointStruct(
                id=i + 1,
                vector=sentences_embeddings['arr_0'][i].tolist(),
                payload={
                    "text": sentences}) for i,
            sentences in enumerate(sentences)])
    print(operation_info)


# query = "阿波罗登月计划"
# query = "神舟五号 杨利伟"
query = "北京航天城"
query_embedding = get_embedding([query])[0]
# search vector
search_result = client.search(
    collection_name=collect_name,
    query_vector=query_embedding,
    limit=3
)
for search_item in search_result:
    print(search_item)

启动上述程序,会在本地同级目录下生成qdrant_db/collection/dengyue/storage.sqlite文件,表明该服务使用sqlite作为后端数据库。

运行上述程序,得到的文本相似度搜索结果同上述faiss。

Qdrant还支持本地Docker启动,启动命令为:

docker run -itd -p 6333:6333 -p 6334:6334 -v $(pwd)/qdrant_storage:/qdrant/storage:z qdrant/qdrant

此时,连接Qdrant的Python代码改为:
与此同时,该服务还提供了WebUI,支持在浏览器端进行操作,并提供了RESTful风格的Console界面。
在这里插入图片描述
运行命令GET collections,结果如下:

{
  "result": {
    "collections": [
      {
        "name": "test_collection"
      },
      {
        "name": "dengyue"
      }
    ]
  },
  "status": "ok",
  "time": 0.000011666
}

在这里插入图片描述

总结

本文简单介绍了三种常见的向量数据库:faiss, Milvus, Qdrant,每种向量数据库都有其利弊。同时,结合一个具体的应用案例:文本相似性搜索,来分别展示这三种向量数据库的使用方法。

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

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

相关文章

STM32学习和实践笔记(4): 分析和理解GPIO_InitTypeDef GPIO_InitStructure (b)

继续上篇博文:STM32学习和实践笔记(4): 分析和理解GPIO_InitTypeDef GPIO_InitStructure (a)-CSDN博客 往下写, 为什么:当GPIO_InitStructure.GPIO_PinGPIO_Pin_0 ; 时,其实就是将对应的该引脚的寄存器地…

如何处理Flutter内存泄漏检测和优化

处理Flutter内存泄漏问题是构建高性能、稳定的应用程序的关键部分之一。在本文中,我将详细介绍如何检测和优化Flutter内存泄漏问题,以确保应用程序的良好性能和用户体验。 1. 了解内存泄漏 在深入了解如何处理Flutter内存泄漏之前,首先需要了…

基于Springboot + MySQL + Vue 大学新生宿舍管理系统 (含源码)

目录 📚 前言 📑摘要 📑操作流程 📚 系统架构设计 📚 数据库设计 💬 管理员信息属性 💬 学生信息实体属性 💬 宿舍安排信息实体属性 💬 卫生检查信息实体属性 &…

LeetCode 第391场周赛个人题解

目录 哈沙德数 原题链接 思路分析 AC代码 换水问题 II 原题链接 思路分析 AC代码 交替子数组计数 原题链接 思路分析 AC代码 最小化曼哈顿距离 原题链接 思路分析 AC代码 哈沙德数 原题链接 思路分析 签到题,不说了 AC代码 class Solution:def s…

实时获取 Pacific Time Zone (太平洋时区) 时间

实时获取 Pacific Time Zone [太平洋时区] 时间 1. Google -> Pacific Time2. Pacific Time - exact time nowReferences 1. Google -> Pacific Time 2. Pacific Time - exact time now https://time.is/zh/PT References [1] Yongqiang Cheng, https://yongqiang.blog…

freeRTOS学习

总结 1.总结任务调度算法之间的区别 调度算法:抢占式调度:优先级高的任务可以打断低优先级任务的执行,适用于不同优先级任务的执行。 时间片轮换:分配时间片(1ms),时间片耗尽时,任…

[Python学习篇] Python创建项目

新建项目 打开开发工具 PyCharm 选择 New Project 目录结构如下 运行 hello world 选中项目,右键 New -> Python File 进行创建文件 运行项目

Java中生成一个唯一的文件名的方法

使用java.util.UUID&#xff08;通用唯一识别码&#xff09;的randomUUID()方法&#xff1a; import java.util.UUID;public class Test {public static void main(String[] args) {for (int i 0; i < 100; i) {String fileName UUID.randomUUID().toString();System.out…

设计模式-结构型-享元模式Flyweight

享元模式的特点&#xff1a; 享元模式可以共享相同的对象&#xff0c;避免创建过多的对象实例&#xff0c;从而节省内存资源 使用场景&#xff1a; 常用于需要创建大量相似的对象的情况 享元接口类 public interface Flyweight { void operate(String extrinsicState); } 享…

加域报错:找不到网络路径

在尝试将计算机加入Windows域时&#xff0c;如果收到“找不到网络路径”的错误提示&#xff0c;可能的原因及解决方法如下&#xff1a; 网络连接问题&#xff1a;确保计算机与域控制器之间的物理网络连接是正常的&#xff0c;可以通过ping命令测试与域控制器的连通性。例如&…

LCD1602显示屏

LCD1602显示 概述 LCD1602&#xff08;Liquid Crystal Display&#xff09;是一种工业字符型液晶&#xff0c;能够同时显示 1602 即 32 字符(16列两行) 引脚说明 //电源 VSS -- GND VDD -- 5V //对比度 VO -- GND //控制线 RS -- P1.0 RW -- P1.1 E -- P1.4 //背光灯 A -- 5…

大数据学习第十一天(复习linux指令3)

1、su和exit su命令就是用于账户切换的系统命令 基本语法&#xff1a;su[-] [用户名] 1&#xff09;-表示是否在切换用户后加载变量&#xff0c;建议带上 2&#xff09;参数&#xff1a;用户名&#xff0c;表示切换用户 3&#xff09;切换用户后&#xff0c;可以通过exit命令退…

欧拉路径欧拉回路

欧拉回路&#xff0c;指遍历图时通过图中每条边且仅通过一次&#xff0c;最终回到起点的一条闭合回路&#xff0c;适用于有向图与无向图&#xff0c;如果不强制要求回到起点&#xff0c;则被称为欧拉路径。 欧拉图&#xff1a;具备欧拉回路的图 无向图&#xff1a;图的所有顶…

Java解析实体类的属性和属性注释

前言 获取某个类的属性&#xff08;字段&#xff09;是我们经常都会碰到的&#xff0c;通常我们是通过反射来获取的。 但是有些特殊情况下&#xff0c;我们不仅要获取类的属性&#xff0c;还需要获取属性注释。这种情况下&#xff0c;我们只能通过注解去获取注释。可以自己定…

LC 111.二叉树的最小深度

111. 二叉树的最小深度 给定一个二叉树&#xff0c;找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 说明&#xff1a; 叶子节点是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a; root [3,9,20,null,null,15,7] 输出&#xff1a;…

python读取excel,转换成json格式,for国际化前端菜单

# -*- coding: utf-8 -*-import pandas as pd import json# 读取Excel文件中的数据 excel_file rD:\解析excel\zy.xlsx df pd.read_excel(excel_file)# 生成中文JSON和英文JSON cn_data {} en_data {} pu_data {} special_data_cn {} special_data_en {} special_data_p…

肿瘤免疫反应瀑布图(源于The Miller Lab)

目录 数据格式 绘图 ①根据剂量 ②根据type ③根据治疗响应度 添加水平线 数据格式 肿瘤免疫响应数据 rm(list ls()) library(tidyverse) library(dplyr) library(knitr)#模拟数据 # We will randomly assign the two doses, 80 mg or 150 mg, to the 56 subjects Me…

使用 Docker 部署 Puter 云桌面系统

1&#xff09;Puter 介绍 :::info GitHub&#xff1a;https://github.com/HeyPuter/puter ::: Puter 是一个先进的开源桌面环境&#xff0c;运行在浏览器中&#xff0c;旨在具备丰富的功能、异常快速和高度可扩展性。它可以用于构建远程桌面环境&#xff0c;也可以作为云存储服…

【EI会议征稿】2024年智能计算、信号处理与计算机科学国际会议(ICSPCS 2024)

2024 International Conference on Intelligent Computing, Signal Processing and Computer Science (ICSPCS 2024) ●会议简介 2024年智能计算、信号处理与计算机科学国际会议&#xff08;ICSPCS 2024&#xff09;即将在青岛隆重开幕。本次会议将汇聚全球智能计算、信号处理…

【动态】江西省小型水库安全监测能力提升试点项目通过验收

近日&#xff0c;由北京国信华源科技有限公司和长江勘测规划设计研究有限责任公司联合承建的江西省小型水库安全监测能力提升试点项目圆满通过验收。 在项目业主单位的组织下&#xff0c;省项目部、特邀专家、县水利局二级项目部以及项目设计、监理、承建等单位的代表组成验收工…