引言
在当今的数据驱动世界中,非结构化数据如文本、图像、音频和视频等占据了数据总量的绝大部分。传统的关系型数据库对于处理这类复杂且多维的数据并不高效。因此,为了更好地管理和检索这些非结构化数据,向量数据库应运而生。
向量数据库是一种专门设计用于存储和查询高维度向量数据的数据库系统。它通过将原始数据转换为数值向量(即嵌入),然后利用这些向量之间的相似性来实现高效的搜索和分析。这种基于相似性的搜索方法非常适合于需要理解和比较数据语义的应用场景,例如推荐系统、图像搜索、自然语言处理等。向量数据库的重要性在于其能够显著提升对非结构化数据的理解能力,并加速相关应用的开发与部署过程。
Milvus 是一个高性能、高度可扩展的向量数据库,专为处理由深度神经网络和其他机器学习模型生成的大规模嵌入向量而设计。自2019年创建以来,Milvus 已成为众多企业信赖的选择,帮助它们解决在面对海量非结构化数据时遇到的挑战。
安装
安装docker
Milvus的安装是通多docker镜像安装的,所以之前先安装docker:
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
sudo yum remove docker*
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sudo sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.repos.d/docker-ce.repo
yum list docker-ce --showduplicates | sort -r
# 注意docker-ce 和 containerd.io的版本
sudo yum install docker-ce-17.12.1.ce-1.el7.centos containerd.io-_1.2.13-2 docker-buildx-plugin docker-compose-plugin
sudo systemctl start docker
sudo docker run hello-world
安装Milvus
Milvus安装参考官方文档:https://milvus.io/blog/how-to-get-started-with-milvus.md
mkdir milvus_compose
cd milvus_compose
wget https://github.com/milvus-io/milvus/releases/download/v2.2.8/milvus-standalone-docker-compose.yml -O docker-compose.yml
vim /etc/docker/daemon.json
sudo systemctl daemon-reload
sudo systemctl restart docker
docker-compose up -d
# 安装 python接口库
pip install pymilvus
需要注意Milvus和python的对应版本
milvus基本操作
pymilvus 是 Milvus 的官方 Python SDK,用于与 Milvus 向量数据库进行交互。pymilvus 提供了丰富的 API 用于管理集合、索引、插入数据和执行查询等操作。以下是 pymilvus 的一些基本操作介绍,包括连接到 Milvus、创建集合、插入数据、构建索引和执行查询。
安装 pymilvus
首先,你需要安装 pymilvus 库:
pip install pymilvus
连接到 Milvus
使用 connections.connect 方法连接到 Milvus 实例:
from pymilvus import MilvusClient
client = MilvusClient(uri="http://localhost:19530", token="root:Milvus")
创建集合
创建一个新的集合,包括定义集合的名称和字段(例如,向量字段和 id 字段):
if client.has_collection(collection_name="demo_collection"):
client.drop_collection(collection_name="demo_collection")
client.create_collection(collection_name="demo_collection",dimension=768)
向量的维度是 768 维的
文本向量化
from pymilvus import model
import os
# 使用hf的镜像站
os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'
# 使用向量化工具
embedding_fn = model.DefaultEmbeddingFunction()
# tokenizer_config.json: 100%|███████████████████████████████████████████████████| 465/465 [00:00<00:00, 105kB/s]
# config.json: 827B [00:00, 200kB/s]
# spiece.model: 100%|██████████████████████████████████████████████████████████| 760k/760k [00:00<00:00, 794kB/s]
# tokenizer.json: 1.31MB [00:00, 2.11MB/s]
# special_tokens_map.json: 100%|█████████████████████████████████████████████████| 245/245 [00:00<00:00, 106kB/s]
# model.onnx: 100%|█████████████████████████████████████████████████████████| 46.9M/46.9M [00:05<00:00, 8.50MB/s]
docs = [
"我是zhouzhou,我喜欢LLM应用开发",
"未来是人工智能的时代",
"我非常喜欢人工智能相关的工作",
]
vectors = embedding_fn.encode_documents(docs)
print("输出文本的维度Dim:", embedding_fn.dim, vectors[0].shape) # Dim: 768 (768,)
# 输出文本的维度Dim: 768 (768,)
# Each entity has id, vector representation, raw text, and a subject label that we use
# to demo metadata filtering later.
data = [
{
"id": i, "vector": vectors[i], "text": docs[i], "subject": "ai"}
for i in range(len(vectors))
]
print("Data has", len(data), "entities, each with fields: ", data[0].keys())
# Data has 3 entities, each with fields: dict_keys(['id', 'vector', 'text', 'subject'])
print("Vector dim:", len(data[0]["vector"]))
# Vector dim: 768
向量数据写入
res = client.insert(collection_name="demo_collection", data=data)
# res
# {
'insert_count': 3, 'ids': [0, 1, 2], 'cost': 0}
语意搜索
query_vectors = embedding_fn.encode_queries(["zhouzhou喜欢什么?"])
res = client.search(
collection_name="demo_collection", # target collection
data=query_vectors, # query vectors
limit=2, # number of returned entities
output_fields=["text", "subject"], # specifies fields to be returned
)
# res[0]
# [{
'id': 0, 'distance': 0.5694787502288818, 'entity': {
'text': '我是zhouzhou,我喜欢LLM应用开发', 'subject': 'ai'}},
# {
'id': 1, 'distance': 0.3924209773540497, 'entity': {
'text': '未来是人工智能的时代', 'subject': 'ai'}}]
返回的是一个列表,每个元素是一个 json 对象,对于 zhouzhou喜欢什么?, 数据库找到了最相似的文本 我是zhouzhou,我喜欢LLM应用开发
添加主题 subject 过滤进行搜索
docs = [
"zhouzhou是一个ai技术爱好者",
"zhouzhou喜欢人工智能",
"zhouzhou爱吃鱼香肉丝",
]
vectors = embedding_fn.encode_documents(docs)
data = [
{
"id": 3 + i, "vector": vectors[i], "text": docs[i], "subject": "personal"}
for i in range(len(vectors))
]
client.insert(collection_name="demo_collection", data=data)
# This will exclude any text in "history" subject despite close to the query vector.
res = client.search(
collection_name="demo_collection",
data=embedding_fn.encode_queries(["zhouzhou喜欢什么?"]),
filter="subject == 'personal'",
limit=2,
output_fields=["text", "subject"],
)
print(res[0])
# [{
'id': 5, 'distance': 0.8496756553649902, 'entity': {
'text': 'zhouzhou爱吃鱼香肉丝', 'subject': 'personal'}},
# {
'id': 4, 'distance': 0.8496756553649902, 'entity': {
'text': 'zhouzhou喜欢人工智能', 'subject': 'personal'}}]
可以看到只找到了 对应主题下的文档把 filter="subject == 'personal'", 删掉就不限制主题了,可以查询更多的文档
query查询
查找指定 subject 的所有文档
res = client.query(
collection_name="demo_collection",
filter="subject == 'ai'",
output_fields=["text", "subject"],
)
# data: ["{'text': '我是zhouzhou,我喜欢LLM应用开发', 'subject': 'ai', 'id': 0}",
# "{'text': '未来是人工智能的时代', 'subject': 'ai', 'id': 1}",
# "{'text': '我非常喜欢人工智能相关的工作', 'subject': 'ai', 'id': 2}"]
查找指定 id 的所有文档
res = client.query(
collection_name="demo_collection",
ids=[0, 2],
output_fields=["vector", "text", "subject"],
)
删除文档
res = client.delete(collection_name="demo_collection", ids=[0, 2])
# {
'delete_count': 2, 'cost': 0}
res = client.delete(
collection_name="demo_collection",
filter="subject == 'ai'",
)
# {
'delete_count': 1, 'cost': 0}
删除集合
res = client.list_collections()
# ['demo_collection']
client.drop_collection(collection_name="demo_collection")
res = client.list_collections()
# []