1、快速创建向量数据库Milvus

297 阅读5分钟

1、 失败方法

首先直接用docker创建milvus,每次都失败:

docker run -d --name milvus -p 19530:19530 -p 9091:9091 -v /var/lib/milvus:/var/lib/milvus milvusdb/milvus:latest

2、 windows下成功方法

查看官网在 Docker(Linux)中运行 Milvus | Milvus 文档

从 PowerShell 或 Windows 命令提示符

如果你更熟悉 PowerShell 或 Windows Command Prompt,命令提示符如下。

  1. 在管理员模式下右击并选择以管理员身份运行,打开 Docker Desktop。

  2. 下载安装脚本并将其保存为standalone.bat 。

    C:>Invoke-WebRequest https://raw.githubusercontent.com/milvus-io/milvus/refs/heads/master/scripts/standalone_embed.bat -OutFile standalone.bat
    
  3. 运行下载的脚本,将 Milvus 作为 Docker 容器启动。

    C:>standalone.bat start
    Wait for Milvus starting...
    Start successfully.
    To change the default Milvus configuration, edit user.yaml and restart the service.
    

    运行安装脚本后可用看到Milvus成功

3、客户端选择

我使用attu,大家网上下载

4、代码验证

github下载代码:参考nlp/question_answering目录下的csv文件github.com/yun81911/ex…

以下是我导入数据并进行查询问答查询的代码:

# 从 towhee 库导入 pipe 和 ops 模块,用于构建数据处理管道和操作
from towhee import pipe, ops
# 导入 numpy 库,用于进行数值计算,例如向量的归一化操作
import numpy as np
# 从 towhee.datacollection 模块导入 DataCollection 类,用于数据收集和展示
from towhee.datacollection import DataCollection
# 从 pymilvus 库导入多个模块,用于连接和操作 Milvus 向量数据库
from pymilvus import connections, FieldSchema, CollectionSchema, DataType, Collection, utility

# 连接到本地的 Milvus 服务,指定主机地址和端口
connections.connect(host='127.0.0.1', port='19530')

###################################################################创建集合
# 定义一个函数,用于创建 Milvus 集合
def create_milvus_collection(collection_name, dim):
    """
    创建一个 Milvus 集合,如果集合已存在则先删除
    :param collection_name: 集合的名称
    :param dim: 向量的维度
    :return: 创建好的 Milvus 集合对象
    """
    # 检查指定名称的集合是否已经存在
    if utility.has_collection(collection_name):
        # 如果集合已存在,删除该集合
        utility.drop_collection(collection_name)
    
    # 定义集合的字段
    fields = [
        # 定义一个名为 id 的字段,数据类型为 VARCHAR,用于存储问题的 id
        FieldSchema(name='id', dtype=DataType.VARCHAR, description='问题的 id', max_length=500, is_primary=True, auto_id=False),
        # 定义一个名为 vec 的字段,数据类型为 FLOAT_VECTOR,用于存储问题的向量表示
        FieldSchema(name='vec', dtype=DataType.FLOAT_VECTOR, description='问题的嵌入向量', dim=dim)
    ]
    # 创建集合的模式,指定字段和描述信息
    schema = CollectionSchema(fields=fields, description='问答搜索集合')
    # 根据模式创建集合
    collection = Collection(name=collection_name, schema=schema)
    # 为集合的 vec 字段创建索引
    index_params = {
        # 使用 L2 距离度量
        'metric_type': 'L2',
        # 使用 IVF_FLAT 索引类型
        'index_type': 'IVF_FLAT',
        # 索引参数,nlist 指定分区数量为 2048
        'params': {'nlist': 2048}
    }
    # 在 vec 字段上创建索引
    collection.create_index(field_name='vec', index_params=index_params)
    return collection

# 定义集合的名称
collection_name = 'question_answer_csv'
# 定义向量的维度
dim = 768

# 调用函数创建 Milvus 集合
collection = create_milvus_collection(collection_name, dim)
#########################################################################################################插入数据到数据库
# 定义一个名为 insert_pipe 的数据处理管道
insert_pipe = (
    # 定义管道的输入参数,分别为 'id'、'question' 和 'answer'
    pipe.input('id', 'question', 'answer')
    # 对输入的 'question' 进行映射处理,使用 DPR 模型(facebook/dpr-ctx_encoder-single-nq-base)将问题转换为向量
    .map('question', 'vec', ops.text_embedding.dpr(model_name='facebook/dpr-ctx_encoder-single-nq-base'))
    # 对生成的向量 'vec' 进行归一化处理,使用 numpy 的 linalg.norm 函数计算向量的范数
    .map('vec', 'vec', lambda x: x / np.linalg.norm(x, axis=0))
    # 将 'id' 和归一化后的向量 'vec' 作为输入,插入到 Milvus 向量数据库中
    # 连接到本地的 Milvus 服务,端口为 19530,使用的集合名为 'question_answer_csv'
    .map(('id', 'vec'), 'insert_status', ops.ann_insert.milvus_client(host='127.0.0.1', port='19530', collection_name='question_answer_csv'))
    # 定义管道的输出,这里未指定具体输出内容,默认输出处理后的结果
    .output()
)

# 导入 csv 模块,用于处理 CSV 文件
import csv
# 打开 'question_answer.csv' 文件,使用 UTF-8 编码
with open('question_answer.csv', encoding='utf-8') as f:
    # 创建一个 CSV 读取器对象
    reader = csv.reader(f)
    # 跳过 CSV 文件的第一行(通常为表头)
    next(reader)
    # 遍历 CSV 文件中的每一行数据
    for row in reader:
        # 将每一行数据传入 insert_pipe 管道进行处理
        insert_pipe(*row)

# 加载 Milvus 集合的数据到内存,以便后续的搜索操作
collection.load()
#########################################################################################################查询问题
# 定义一个名为 ans_pipe 的数据处理管道,用于查询问题的答案
ans_pipe = (
    # 定义管道的输入参数,为 'question'
    pipe.input('question')
    # 对输入的 'question' 进行映射处理,使用 DPR 模型(facebook/dpr-ctx_encoder-single-nq-base)将问题转换为向量
    .map('question', 'vec', ops.text_embedding.dpr(model_name="facebook/dpr-ctx_encoder-single-nq-base"))
    # 对生成的向量 'vec' 进行归一化处理,使用 numpy 的 linalg.norm 函数计算向量的范数
    .map('vec', 'vec', lambda x: x / np.linalg.norm(x, axis=0))
    # 将归一化后的向量 'vec' 作为输入,在 Milvus 向量数据库中进行搜索
    # 连接到本地的 Milvus 服务,端口为 19530,使用的集合名为 'question_answer_csv',返回最相似的 1 个结果
    .map('vec', 'res', ops.ann_search.milvus_client(host='127.0.0.1', port='19530', collection_name='question_answer_csv', limit=1))
    # 对搜索结果 'res' 进行映射处理,根据结果中的 id 从 id_answer 字典中获取对应的答案
    .map('res', 'answer', lambda x: [id_answer[int(i[0])] for i in x])
    # 定义管道的输出,包括输入的问题和对应的答案
    .output('question', 'answer')
)

# 提示信息:id_answer 变量在代码中未定义,需要正确定义
# 例如:
# 导入 pandas 库,用于处理 CSV 文件
import pandas as pd
# 读取 'question_answer.csv' 文件到 DataFrame
df = pd.read_csv('question_answer.csv')
# 查看 DataFrame 的前几行
df.head()
# 将 DataFrame 的 id 列设为索引,并将 answer 列转换为字典
id_answer = df.set_index('id')['answer'].to_dict()

# 定义一个查询问题
# ans = ans_pipe('Is  Disability  Insurance  Required  By  Law?')
ans = ans_pipe('How to purchase disability insurance?')

# 将查询结果封装为 DataCollection 对象
ans = DataCollection(ans)
# 展示查询结果
ans.show()