一篇文章带你学会向量数据库Milvus(一)

一篇文章带你学会向量数据库Milvus(一)

上一篇文章中 LLM 学习之「向量数据库」 中我们介绍了什么是向量数据库,向量数据库有那些用途,向量数据库与 LLM 的关联以及 RAG 中向量数据库的使用。本篇文章我们重点介绍 Milvus 向量数据库的知识和使用。

Milvus 简介:

向量数据库是一种专用系统,旨在通过向量嵌入和数值表示来管理和检索非结构化数据,这些数据项捕获图像、音频、视频和文本内容等数据项的本质。与使用精确搜索操作处理结构化数据的传统关系数据库不同,向量数据库在使用近似最近邻 (ANN) 算法等技术进行语义相似性搜索方面表现出色。此功能对于开发跨各个领域的应用程序(包括推荐系统、聊天机器人和多媒体内容搜索工具)以及解决 AI 和 ChatGPT 等大型语言模型带来的挑战至关重要,例如理解上下文和细微差别以及 AI 幻觉。

Milvus 这样的向量数据库的出现正在改变行业,它支持对大量非结构化数据进行基于内容的搜索,超越了人工生成标签的限制。使向量数据库与众不同的主要功能包括

  • 可扩展性和可调性,可处理不断增长的数据量
  • 多租户和数据隔离,实现高效的资源使用和隐私保护
  • 适用于各种编程语言的一整套 API
  • 用户友好的界面,简化了与复杂数据的交互。

这些属性确保了矢量数据库能够满足现代应用程序的需求,为探索和利用非结构化数据提供了强大的工具,这是传统数据库无法做到的。

数据库管理

与传统数据库引擎类似,您也可以在 Milvus 中创建数据库,并为某些用户分配权限来管理它们。那么这些用户就有权管理数据库中的集合。一个 Milvus 集群最多支持 64 个数据库。

创建数据库

要创建数据库,您需要首先连接到 Milvus 集群并为其准备一个名称:

ini 复制代码
 from pymilvus import connections, db # type: ignore
 ​
 _HOST = '127.0.0.1'
 _PORT = 19530
 _db_name = "default"
 ​
 _user = "root"
 _passwd = "Milvus"
 ​
 _role_demo = "public"
 _user_demo= "demo"
 _passwd_demo = "demodemo1"
 connections.connect(host=_HOST, port=_PORT, db_name=_db_name, user=_user_demo, password=_passwd_demo)

删除数据库

python 复制代码
 def drop_database(name: str) -> any:
     return db.drop_database(name)
         
 # 创建数据库
 def create_database(name: str) -> any:
     database = db.create_database(name)
     return database
 ​
 # 切换数据库
 def use_database(name: str) -> any:
     return db.using_database(name)
     
 ​
 # 列出数据库
 def list_databases() -> list[str]:
     return db.list_database()

列出数据库

scss 复制代码
 print(list_databases())
 databases = list_databases()
 print(databases)
 ## 删除数据库
 drop_database("demo_v1")
 drop_database("demo_v1")
 ​
 databases = list_databases()
 print(databases)
 ​
 create_database('demo_v1')
 databases = list_databases()
 print(databases)

Milvus 中的 schema, schema 用于定义集合的属性及其中的字段。

Field schema

Field schema 是字段的逻辑定义。我们在定义集合架构和管理集合之前需要定义的第一件事就是定义 Field schema

Milvus 集合中仅支持一个主键字段。

Field schema properties

属性 描述 备注
name 要创建的集合中的字段名称 String,必填
dtype 字段的数据类型 必填
description 字段描述 String,选填
is_primary 是否设置该字段为主键字段 Boolean (true or false) 主键字段必填
auto_id(主键字段必填) 切换以启用或禁用自动 ID(主键)分配 TrueFalse
max_length(VARCHAR 字段必需) 允许插入的字符串的最大长度。 [1, 65,535]
dim 向量的维数 ∈[1, 32768]
is_partition_key 该字段是否是分区键字段 布尔值(truefalse

创建 field schema

Milvus 允许我们在创建字段 schema 时为每个标量字段指定默认值,从而减低插入数据的复杂性,但不包括主键字段。如果在插入数据时将字段留空,则将应用为此字段指定的默认值。

创建常规字段 schema:

ini 复制代码
 from pymilvus import FieldSchema, DataType
 ​
 # 创建一个名为id 的 primary id
 id_field = FieldSchema(name='id', dtype=DataType.INT64, is_primary=True, description='primary key')
 age_field = FieldSchema(name='age', dtype=DataType.INT64, description='age')
 embedding_field = FieldSchema(name='embedding',dtype=DataType.FLOAT_VECTOR, dim=128, description='vector')
 # 使用 position 作为分区键
 position_field = FieldSchema(name='position', dtype=DataType.VARCHAR, max_length=256,is_partition_key=True)

创建具有默认字段值的 schema

ini 复制代码
 from pymilvus import FieldSchema, DataType
 ​
 fields = [
     FieldSchema(name='id', dtype=DataType.INT64, is_primary=True),
     FieldSchema(name='age', dtype=DataType.INT64, default_value=25,description='age'),
     FieldSchema(name='embedding', dtype=DataType.FLOAT_VECTOR, dim=128, description='vector')
 ];

collection schema

collection schemacollection 的逻辑定义。我们需要在定义 collection schema 之前定义 field schema

Collection schema 属性

属性 描述 备注
field 集合中要创建的字段 必填
description 集合描述 String,选填
partition_key_field 设计用作分区键的字段的名称。 String, 选填
enable_dynamic_field 是否启用动态模式 Boolean (true or false)
ini 复制代码
 from pymilvus import FieldSchema, CollectionSchema
 ​
 id_field = FieldSchema(name='id', dtype=DataType.INT64, is_primary=True, description='primary id')
 age_field = FieldSchema(name='age', dtype=DataType.INT64, description='age'),
 embedding_field = FieldSchema(name='embedding', dtype=DataType.FLOAT_VECTOR, dim=128,description='vector')
 ​
 # 启用分区字段
 position_field = FieldSchema(name='position', dtype=DataType.VARCHAR, max_length=256, is_partition=True)
 # 如果需要使用动态字段,请将 enable_dynamic_field 设置为 True。
 schema = CollectionSchema(fields=[id_field, age_field, embedding_field],
                           auto_id=False, enable_dynamic_field=True, description='desc of a collection')
 ​
ini 复制代码
 from pymilvus import Collection
 collection_name1 = 'demo_v2'
 collection1 = Collection(name=collection_name1, schema=schema, using='default', shards_num=2)

参数解析:

  • 我们使用 shard_num 自定义分片编号

  • 我们通过参数 using 来指定别名定义要在其上创建集合的 Milvus 服务器。

  • 如果我们需要实现基于分区上面的多租户,可以通过在字段上面将 is_partition_key设置为True来启用该字段的分区键功能。

  • 如果需要启用动态字段,可以通过在集合架构中将 enable_dynamic_field 设置为True 来启用动态架构。

Milvus 集合管理

本教程之前你需要先安装 Milvus 服务。你可以安装单机版或者集群版。详细教程可以参考 Milvus 官方文档。

在 Milvus 中,我们将向量嵌入存储在集合中。集合中的所有向量嵌入共享相同的维度和距离度量来测量相似性。

Milvus 集合支持动态字段(即 schema 中未预定义的字段)和主键自动递增。

为了适应不同的人的习惯,Milvus 提供了两种创建集合的方法。一种提供快速设置,另一种则允许对集合架构和索引参数进行详细定制。

创建 collection

我们可以通过下面的两种方式创建 collection

  • 通过官方包 MilvusClient 创建。
  • 定制设置,也就是上面文档的部分。

下面我们使用第一种方式创建 collection

在人工智能行业大跃进的背景下,大多数开发者只需要一个简单而动态的集合来开始。 Milvus 允许仅使用三个参数快速设置这样的集合:

  • 要创建的集合的名称
  • 要插入的向量嵌入的维度
  • 用于测量向量嵌入之间相似性的度量类型

示例代码:

ini 复制代码
 # 导入相关的 python 包
 from pymilvus import MilvusClient, DataType
 ​
 # 连接服务,初始化 MilvusClient
 client = MilvusClient(
     uri="http://localhost:19530"
 )
 ​
 # 创建一个 collection 
 client.create_collection(
     collection_name="demo_v2",
     dimension=5
 )
 ​
 # 获取 collection 的状态
 res = client.get_load_state(
     collection_name="demo_v2"
 )
 ​
 print(res)

使用上面的代码设置的 collection 只包括两个字段. id 作为主键, vector 作为向量字段,以及自动设置 auto_idenable_dynamic_fieldTrue

  • auto_id 启用此设置可确保主键自动递增。在数据插入期间无需手动提供主键。
  • enable_dynamic_field 启用后,要插入的数据中除 idvector 之外的所有字段都将被视为动态字段。这些附加字段作为键值对保存在名为 $meta 的特殊字段中。此功能允许在数据插入期间包含额外的字段。

自定义设置

我们可以自行确定集合的架构和索引参数,而不是让 Milvus 决定您集合的几乎所有内容。而且如果我们系统中重度使用了 Milvus 的情况下,建议使用定制设置.

设置 schema

schema 中,我们可以选择启用或者禁用 enable_dynamic_field,添加预定一字段以及为每个字段设置属性。

ini 复制代码
 schema = MilvusClient.create_schema(
     auto_id=False,
     enable_dynamic_field=True,
 )
 ​
 schema.add_field(field_name="my_id", datatype=DataType.INT64, is_primary=True)
 schema.add_field(field_name="my_vector", datatype=DataType.FLOAT_VECTOR, dim=5)

代码片段中,enable_dynamic_field 设置为 True,并为主键启用 auto_id。此外,还引入了一个vector字段,其维度配置为5,并包含四个标量字段,每个标量字段都有其各自的属性。

设置索引参数

索引参数决定 Milvus 如何组织集合中的数据。我们可以通过调整特定字段的 metric_typeindex_type 来设置特定字段的索引过程。对于矢量,可以灵活选择COSINEL2IP作为metric_type

ini 复制代码
 # 创建索引字段
 index_params = client.prepare_index_params()
 ​
 index_params.add_index(
     field_name="my_id",
     index_type="STL_SORT"
 )
 ​
 index_params.add_index(
     field_name="my_vector", 
     index_type="IVF_FLAT",
     metric_type="IP",
     params={ "nlist": 128 }
 )

上面的代码中演示了如何分别为向量和标量设置索引参数。对于向量字段同时设置度量类型和索引类型。对于标量字段,仅设置索引类型。建议为向量字段和任何经常使用用于过滤器的标量字段创建索引。

创建 collection

我们可以选择分别创建集合和索引文件,或者创建集合并在创建时同时加载索引。

看个例子:

ini 复制代码
 # 创建集合
 client.create_collection(
     collection_name="demo_v3",
     schema=schema,
     index_params=index_params
 )
 # 因为上面的代码是异步操作,所以这里 sleep 一下。
 time.sleep(5)
 # 获取集合的状态
 res = client.get_load_state(
     collection_name="customized_setup_1"
 )
 ​

查看集合

创建完集合后我们可以去检索集合,看下面的示例:

ini 复制代码
 # 查询集合详情
 res = client.describe_collection(
     collection_name="demo_v3"
 )
 ​
 print(res)

如果要查看现有有哪些集合可以使用下面的代码查看:

ini 复制代码
 # 列出所有集合名称
 res = client.list_collections()
 ​
 print(res)

加载和释放集合

在集合加载过程中,Milvus 会将集合的索引文件加载到内存中,当释放集合时,Milvus 会从内存中卸载索引文件。在集合进行搜索之前,我们需要确保集合已加载。

加载集合

ini 复制代码
 # 加载集合代码
 client.load_collection(
     collection_name="demo_v3"
 )
 ​
 res = client.get_load_state(
     collection_name="demo_v3"
 )
 ​

发布集合

ini 复制代码
 # 发布一个集合
 client.release_collection(
     collection_name="demo_v3"
 )
 ​
 res = client.get_load_state(
     collection_name="demo_v3"
 )

设置集合别名

我们可以为集合分配别名,以使它们在特定上下文中更有意义。可以为一个集合指定多个别名,但多个集合不能共享一个别名

创建别名

ini 复制代码
 # 创建别名
 client.create_alias(
     collection_name="demo_v3",
     alias="dv3"
 )
 ​
 client.create_alias(
     collection_name="demo_v2",
     alias="dv2"
 )

列出别名

shell 复制代码
 res = client.list_aliases(
     collection_name="demo_v2"
 )
 # Output
 #
 # {
 #     "aliases": [
 #         "dv3",
 #         "alice"
 #     ],
 #     "collection_name": "demo_v3",
 #     "db_name": "default"
 # }

我们还可以为别名设置描述, 重新分配别名,删除别名。

删除集合

如果我们不再需要某个集合,可以删除该集合。

ini 复制代码
 client.drop_collection(
     collection_name="demo_v3"
 )
 ​
 client.drop_collection(
     collection_name="demo_v2"
 )

总结

本文主要是介绍了目前很火的向量数据库 Milvus 的相关知识,包括:

  • Milvus 是什么,能做什么。

  • Milvus 数据库管理(添加,删除,查询列表, 字段)

  • Milvus 集合管理

    • 创建集合包括两种方式(默认方式和自定义的方式)
    • 查看集合
    • 集合加载和释放

相关文章

相关推荐
陈哥聊测试11 小时前
软件格局在变,谁能扛起国产替代的大旗?
安全·程序员·产品
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭1 天前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
bastgia1 天前
Tokenformer: 下一代Transformer架构
人工智能·机器学习·llm
少年姜太公1 天前
从零开始详解js中的this(下)
前端·javascript·程序员
凌虚1 天前
Kubernetes APF(API 优先级和公平调度)简介
后端·程序员·kubernetes
新智元1 天前
李飞飞谢赛宁:多模态 LLM「空间大脑」觉醒,惊现世界模型雏形!
人工智能·llm
小华同学ai1 天前
ShowDoc:Star12.3k,福利项目,个人小团队的在线文档“简单、易用、轻量化”还专门针对API文档、技术文档做了优化
前端·程序员·github
RWKV元始智能1 天前
RWKV-7:极先进的大模型架构,长文本能力极强
人工智能·llm
zaim12 天前
计算机的错误计算(一百八十七)
人工智能·ai·大模型·llm·错误·正弦/sin·误差/error
张拭心2 天前
Google 提供的 Android 端上大模型组件:MediaPipe LLM 介绍
android·人工智能·llm