一篇文章带你学会向量数据库Milvus
一篇文章带你学会向量数据库Milvus索引管理
Milvus 提供多种索引类型来对字段值举行排序,以实现高效的相似性搜刮。它还提供三种度量类型:余弦相似度 (COSINE)、欧几里得间隔 (L2) 和内积 (IP)来测量向量嵌入之间的间隔。
建议对常常利用的向量字段和标量字段创建索引
如果集合创建哀求中指定了以下任一条件,Milvus 在创建集合时会自动生成索引并将其加载到内存中:
[*]向量的维度和类型
[*]schema 和索引参数
下面的代码片断重新调整了现有代码的用途,以建立与 Milvus 实例的毗连并创建一个集合,而无需指定其索引参数。在这种情况下,集合缺少索引而且保持卸载状态。
from pymilvus import MilvusClient, DataType
# 实例化客户端,连接 Milvus 服务
client = MilvusClient(
uri="http://localhost:19530"
)
# 创建 schema
schema = MilvusClient.create_schema(
auto_id=False,
enable_dynamic_field=True,
)
# schema 添加字段 id、vector
schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True)
schema.add_field(field_name="vector", datatype=DataType.FLOAT_VECTOR, dim=5)
# 创建集合
client.create_collection(
collection_name="demo_v4",
schema=schema,
)
集合索引
要为集合创建索引或为集合建立索引,我们需要设置索引参数并调用create_index()。
# 设置索引的参数
index_params = MilvusClient.prepare_index_params()
# 在向量字段 vector 上面添加一个索引
index_params.add_index(
field_name="vector",
metric_type="COSINE",
index_type=,
index_name="vector_index"
)
# 在集合demo_v4创建索引文件
client.create_index(
collection_name="demo_v4",
index_params=index_params
)
Milvus 现在只支持为集合的每个字段创建一个索引文件
检察索引详细信息
创建索引后我们可以检索索引的详细信息:
res = client.list_indexes(
collection_name="demo_v4"
)
# Output
#
# [
# "vector_index",
# ]
res = client.describe_index(
collection_name="demo_v4",
index_name="vector_index"
)
# Output
#
# {
# "index_type": ,
# "metric_type": "COSINE",
# "field_name": "vector",
# "index_name": "vector_index"
# }
我们可以检察针对特定字段创建的索引文件,并统计利用该索引简历的索引行数。类比 关系性数据库的索引。
删除索引
如果不在需要索引,我们可以删除相关的索引
client.drop_index(
collection_name="demo_v4",
index_name="vector_index"
)
检索标量字段
什么是标量字段?变量字段就是除 vector 字段,id 字段之外的字段。在 Milvus 中,标量索引用于加速特定非向量字段值的元过滤,类似于传统的数据库索引。
变量索引类型
[*]auto-index Milvus 根据标量字段的数据类型自动决定索引类型。这实用于不需要控制详细索引类型的情况。
[*]custom-index 可以指定明确的索引类型,好比倒排索引。这就提供了对索引的类型的更多选择。
Auto index 自动索引
要利用自动索引,请省略 index_type 参数,以便 Milvus 可以根据标量字段类型推断索引类型。
例子:
# Auto indexing
client = MilvusClient(
uri="http://localhost:19530"
)
#准备一个空的IndexParams对象,无需指定任何索引参数。
index_params = client.create_index_params()
index_params.add_index(
field_name="scalar_1", # 要索引的标量字段的名称
index_type="", # 要创建的索引类型。对于自动索引,请将其留空或省略此参数。
index_name="default_index" # 要创建的指数名称
)
# 在集合中添加索引
client.create_index(
collection_name="demo_v4", # 指定集合名称
index_params=index_params
)
自界说索引
如果我们要利用自界说索引,请在 index_type 参数中指定特定索引类型。
看下面的例子:
index_params = client.create_index_params() #准备一个 IndexParams 对象
index_params.add_index(
field_name="scalar_2", # 标量字段名称
index_type="INVERTED", # 明确索引类型
index_name="inverted_index" # 索引的名称
)
client.create_index(
collection_name="demo_v4", # 将索引添加到集合中
index_params=index_params
)
对于自界说索引,有效值为:
[*]INVERTED:(推荐)倒排索引由术语词典组成,此中包罗按字母顺序排序的全部标记化单词。有关详细信息,请参阅标量索引。
[*]STL_SORT:利用标准模板库排序算法对标量字段举行排序。支持布尔和数字字段(比方 INT8、INT16、INT32、INT64、FLOAT、DOUBLE)。
[*]Trie:用于快速前缀搜刮和检索的树形数据布局。支持 VARCHAR 字段。
索引检索
利用 list_indexes() 方法验证标量索引的创建:
client.list_indexes(
collection_name="demo_v4"# 指定集合名称
)
# Output:
# ['default_index','inverted_index']
索引限定
现在,标量索引支持 INT8、INT16、INT32、INT64、FLOAT、DOUBLE、BOOL 和 VARCHAR 数据类型,但不支持 JSON 和 ARRAY 类型。
数据 CRUD
在 Milvus 集合的上下文中,实体是集合中单个、可识别的实例。它代表特定种别的独特成员,无论是图书馆中的一本书、基因组中的基因还是任何其他可识别的实体。
集合中的实体共享一组通用的属性,称为schema,概述了每个实体必须遵守的布局,包括字段名称、数据类型和任何其他束缚。
将实体成功插入集合中要求提供的数据应包罗目标集合的全部架构界说字段。别的,仅当您启用了动态字段时,您还可以包罗非架构界说的字段。
准备工作
from pymilvus import MilvusClient
# Milvus 连接数据库
client = MilvusClient(
uri="http://localhost:19530"
)
# 创建 collection
client.create_collection(
collection_name="demo_v5",
dimension=5,
metric_type="IP"
)
插入实体
要插入实体,您需要将数据组织到字典列表中,此中每个字典代表一个实体。每个字典都包罗与目标集合中的预界说字段和动态字段对应的键。
# 3. Insert some data
data=[
{"id": 0, "vector": , "color": "pink_8682"},
{"id": 1, "vector": , "color": "red_7025"},
{"id": 2, "vector": , "color": "orange_6781"},
{"id": 3, "vector": , "color": "pink_9298"},
{"id": 4, "vector": , "color": "red_4794"},
{"id": 5, "vector": , "color": "yellow_4222"},
{"id": 6, "vector": , "color": "red_9392"},
{"id": 7, "vector": [-0.33445148015177995, -0.2567135004164067, 0.8987539745369246, 0.9402995886420709, 0.5378064918413052], "color": "grey_8510"},
{"id": 8, "vector": , "color": "white_9381"},
{"id": 9, "vector": , "color": "purple_4976"}
]
res = client.insert(
collection_name="demo_v5",
data=data
)
插入分区
要将数据插入到特定分区,可以在插入哀求中指定分区名称,如下所示:
data=[
{"id": 10, "vector": [-0.5570353903748935, -0.8997887893201304, -0.7123782431855732, -0.6298990746450119, 0.6699215060604258], "color": "red_1202"},
{"id": 11, "vector": , "color": "blue_4150"},
{"id": 12, "vector": , "color": "orange_4590"},
{"id": 13, "vector": [-0.5449109892498731, 0.043511240563786524, -0.25105249484790804, -0.012030655265886425, -0.0010987671273892108], "color": "pink_9619"},
{"id": 14, "vector": , "color": "orange_4863"},
{"id": 15, "vector": [-0.8825129181091456, -0.9204557711667729, -0.935350065513425, 0.5484069690287079, 0.24448151140671204], "color": "orange_7984"},
{"id": 16, "vector": , "color": "blue_9010"},
{"id": 17, "vector": [-0.20151825016059233, -0.905239387635804, 0.6749305353372479, -0.7324272081377843, -0.33007998971889263], "color": "blue_4521"},
{"id": 18, "vector": , "color": "orange_2529"},
{"id": 19, "vector": , "color": "red_9437"}
]
# 创建分区
client.create_partition(
collection_name="demo_v4",
partition_name="partitionA"
)
# 分区中插入数据
res = client.insert(
collection_name="demo_v4",
data=data,
partition_name="partitionA"
)
更新插入数据
更新插入数据是更新和插入操作的组合。在 Milvus 中,upsert 操作实行数据级操作,根据集合中是否已存在主键来插入或更新实体。详细来说:
[*]如果集合中已存在该实体的主键,则现有实体将被覆盖。
[*]如果集合中不存在主键,则将插入一个新实体。
data=[
{"id": 0, "vector": [-0.619954382375778, 0.4479436794798608, -0.17493894838751745, -0.4248030059917294, -0.8648452746018911], "color": "black_9898"},
{"id": 1, "vector": , "color": "red_7319"},
{"id": 2, "vector": [-0.8864122635045097, 0.9260170474445351, 0.801326976181461, 0.6383943392381306, 0.7563037341572827], "color": "white_6465"},
{"id": 3, "vector": , "color": "orange_7580"},
{"id": 4, "vector": , "color": "red_3314"},
{"id": 5, "vector": , "color": "black_9955"},
{"id": 6, "vector": , "color": "yellow_2461"},
{"id": 7, "vector": , "color": "white_5015"},
{"id": 8, "vector": [-0.3038434006935904, 0.1279149203380523, 0.503958664270957, -0.2622661156746988, 0.7407627307791929], "color": "purple_6414"},
{"id": 9, "vector": [-0.7125086947677588, -0.8050968321012257, -0.32608864121785786, 0.3255654958645424, 0.26227968923834233], "color": "brown_7231"}
]
# 插入与更新
res = client.upsert(
collection_name='demo_v4',
data=data
)
分区更新也是同样的操作:
res = client.upsert(
collection_name="demo_v4",
data=data,
partition_name="partitionA" # 指定分区名称
)
删除实体
如果不再需要某个实体,您可以将其从集合中删除。 Milvus 提供两种方式供您识别要删除的实体。
[*]通过过滤器删除实体。
[*]按 ID 删除实体。
# 按过滤器删除
res = client.delete(
collection_name="quick_setup",
filter="id in "
)
# 按 id 删除
res = client.delete(
collection_name="quick_setup",
ids=,
partition_name="partitionA"
)
向量查询
插入数据后,下一步是在 Milvus 中检索集合实行相似性搜刮。
Milvus 允许您举行两种类型的搜刮,详细取决于集合中向量字段的数量:
[*]单向量搜刮:如果您的集合只有一个向量字段,请利用search()方法查找最相似的实体。此方法将您的查询向量与集合中的现有向量举行比较,并返回最接近匹配的 ID 以及它们之间的间隔。或者,它还可以返回效果的向量值和元数据。
[*]多向量搜刮:对于具有两个或多个向量场的集合,请利用hybrid_search()方法。此方法实行多个近似近来邻 (ANN) 搜刮哀求,并组合效果以在重新排名后返回最相关的匹配项。
多种搜刮类型可以满足不同的搜刮需求:
[*]基本搜刮:包括单向量搜刮、批量向量搜刮、分区搜刮和指定输出字段搜刮。
[*]过滤搜刮: 应用基于标量字段的过滤条件来细化搜刮效果。
[*]范围搜刮: 查找距查询向量特定间隔范围内的向量。
[*]分组搜刮: 根据特定字段对搜刮效果举行分组,以确保效果的多样性。
基本搜刮:
发送 search 哀求时,我们可以提供一个或多个表示查询嵌入的向量值以及指示要返回的效果数的 limit 值。根据数据和查询向量,我们获得的效果可能会少于 limit 个。当 limit 大于查询可能匹配向量的数量时,就会发生这种情况。
单向量搜刮
单向量搜刮是 Milvus 中search操作的最简朴形式,旨在查找与给定查询向量最相似的向量。
要实行单向量搜刮,请指定目标集合名称、查询向量和所需的效果数量 (limit)。此操作返回一个效果集,此中包罗最相似的向量、它们的 ID 以及与查询向量的间隔。
批量向量搜刮
批量向量搜刮通过允许在单个哀求中搜刮多个查询向量来扩展单向量搜刮概念。这种类型的搜刮非常适合需要为一组查询向量查找相似向量的场景,从而显着减少所需的时间和计算资源。
在批量向量搜刮中,您可以在 data 字段中包罗多个查询向量。系统并行处理这些向量,为每个查询向量返回一个单独的效果集,每个效果集包罗在集合中找到的最接近的匹配项。
下面是从两个查询向量中搜刮两个不同的最相似实体集的示例:
# 批量向量搜索
res = client.search(
collection_name="demo_v4",
data=[
,
],
limit=2,
search_params={"metric_type": "IP", "params": {}}
)
result = json.dumps(res, indent=4)
分区搜刮
分区搜刮将搜刮范围缩小到集合的特定子集或分区。这对于有组织的数据集特殊有效,此中数据被分段为逻辑或分类部分,从而通过减少要扫描的数据量来实现更快的搜刮操作。
要举行分区搜刮,只需在搜刮哀求的 partition_names 中包罗目标分区的名称即可。这指定search操作仅考虑指定分区内的向量。
res = client.search(
collection_name="test_collection",
data=[],
limit=5,
search_params={"metric_type": "IP", "params": {}},
partition_names=["partition_1"] # 这里指定搜索的分区
)
利用输出字段举行搜刮
利用输出字段举行搜刮允许您指定搜刮效果中应包罗匹配向量的哪些属性或字段。
您可以在哀求中指定output_fields以返回包罗特定字段的效果。
# 输出字段搜索
res = client.search(
collection_name="test_collection",
data=[],
limit=5,
search_params={"metric_type": "IP", "params": {}},
output_fields=["color"] # 返回定义的字段
)
过滤搜刮
筛选搜刮将标量筛选器应用于矢量搜刮,允许我们根据特定条件优化搜刮效果。
比方,要根据字符串模式优化搜刮效果,可以利用 like 运算符。此运算符通过考虑前缀、中缀和后缀来启用字符串匹配:
[*]若要匹配以特定前缀开头的值,请利用语法. 如: ‘like “prefix%”’ 。
[*]若要匹配字符串中任意位置包罗特定字符序列的值,请利用语法 ‘like “%infix%”’
[*]若要匹配以特定后缀结尾的值,请利用语法: ‘like “%suffix”’ .
[*]like 运算符还可以通过利用下划线 (_) 表示任何单个字符来用于单字符匹配。 ‘like “y_llow”’ .
筛选颜色以绿色为前缀的效果:
# 过滤器搜索
res = client.search(
collection_name="test_collection",
data=[],
limit=5,
search_params={"metric_type": "IP", "params": {}},
output_fields=["color"],
filter='color like "gree%"'
)
范围搜刮
范围搜刮允许查找距查询向量指定间隔范围内的向量。
通过设置 radius 和可选的 range_filter,可以调整搜刮的广度以包罗与查询向量有些相似的向量,从而提供潜在匹配的更全面的视图。
[*]radius:界说搜刮空间的外界限。只有距查询向量在此间隔内的向量才被视为潜在匹配。
[*]range_filter:固然radius设置搜刮的外部限定,但可以选择利用range_filter来界说内部界限,创建一个间隔范围,在该范围内向量必须落下才被视为匹配。
# 范围搜索
search_params = {
"metric_type": "IP",
"params": {
"radius": 0.8, # 搜索圆的半径
"range_filter": 1.0 # 范围过滤器,用于过滤出不在搜索圆内的向量。
}
}
res = client.search(
collection_name="test_collection",
data=[],
limit=3, # 返回的搜索结果最大数量
search_params=search_params,
output_fields=["color"],
)
更多搜刮方式可以参考 Milvus 官网。
多向量搜刮
在 Milvus2.4 版本开始,引入了多想两支持和混合搜刮功能。这就意味着用户可以将多个向量字段引入到单个集合中。不同的向量长可以表示不同的方面,不同的 embedding Model 以致表征同一实体的不同数据模态。这同时意味着扩展了信息的丰富性。有了这个功能我们可以在综合场景利用,好比:根据图片、语言、指纹等各种属性来识别向量中最相似的人。
多向量搜刮支持在各种字段上实行搜刮哀求,并利用重新排名策略的组合效果。
示例:
from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType
import random
# 连接 Milvus
connections.connect(
host="127.0.0.1", # 可以替换为自己的服务地址
port="19530"
)
# 创建 schema
fields = [
FieldSchema(name="film_id", dtype=DataType.INT64, is_primary=True),
FieldSchema(name="filmVector", dtype=DataType.FLOAT_VECTOR, dim=5), # 向量字段
FieldSchema(name="posterVector", dtype=DataType.FLOAT_VECTOR, dim=5)] # 向量字段
schema = CollectionSchema(fields=fields,enable_dynamic_field=False)
# 创建 collection
collection = Collection(name="test_collection", schema=schema)
# 添加索引
index_params = {
"metric_type": "L2",
"index_type": "IVF_FLAT",
"params": {"nlist": 128},
}
# 字段 filmVector 创建索引
collection.create_index("filmVector", index_params)
# 字段 posterVector 创建索引
collection.create_index("posterVector", index_params)
# 向量数据库中插入的实体
entities = []
for _ in range(1000):
# 构造实体
film_id = random.randint(1, 1000)
film_vector = [ random.random() for _ in range(5) ]
poster_vector = [ random.random() for _ in range(5) ]
entity = {
"film_id": film_id,
"filmVector": film_vector,
"posterVector": poster_vector
}
entities.append(entity)
# 集合中插入实体
collection.insert(entities)
创建 AnnSearchRequest 实例
多向量搜刮利用 hybrid_search() API 在一次调用中实行多个 ANN 搜刮哀求。每个 AnnSearchRequest 代表特定矢量场上的单个搜刮哀求。
示例创建两个 AnnSearchRequest 实例以对两个向量字段实行单独的相似性搜刮。
from pymilvus import AnnSearchRequest
# 创建多搜索请求 filmVector
query_filmVector = []
search_param_1 = {
"data": query_filmVector, # 请求查询的向量数据
"anns_field": "filmVector", # 搜索的向量字段 filmVector
"param": {
"metric_type": "L2", # 该参数值必须与集合模式中使用的值相同。
"params": {"nprobe": 10}
},
"limit": 2 # 限定 AnnSearchRequest 搜索中返回的结束数量
}
request_1 = AnnSearchRequest(**search_param_1)
# 创建多搜索请求 posterVector
query_posterVector = []
search_param_2 = {
"data": query_posterVector, #请求查询的向量数据
"anns_field": "posterVector", # 搜索的向量字段 posterVector
"param": {
"metric_type": "L2", # 该参数值必须与集合模式中使用的值相同。
"params": {"nprobe": 10}
},
"limit": 2 # 限定 AnnSearchRequest 搜索中返回的结束数量
}
request_2 = AnnSearchRequest(**search_param_2)
reqs =
设置排名策略
创建 AnnSearchRequest 实例后,设置重新排名策略以组合效果并重新排名。现在有两个选项:WeightedRanker 和 RRFRanker。
[*]利用加权评分:WeightedRanker 用于为每个具有指定权重的向量场搜刮效果分配重要性。如果将某些向量字段的优先级置于其他向量字段之上,WeightedRanker(value1, value2, ..., valueN) 可以在组合搜刮效果中提现出来。
from pymilvus import WeightedRanker
# 使用 WeightedRanker 来结合具有指定权重的结果
# 将文本搜索赋予权重 0.8,将图像搜索赋予权重 0.2。
rerank = WeightedRanker(0.8, 0.2)
利用WeightedRanker时,请注意:
每个权重值的范围从 0(最不重要)到 1(最重要),影响终极的总分。
WeightedRanker 中提供的权重值总数应便是您创建的 AnnSearchRequest 实例的数量。
实行混合搜刮
设置 AnnSearchRequest 实例和重新排名策略后,利用 hybrid_search() 方法实行多向量搜刮。
# 在进行多向量搜索之前,将集合加载到内存中。
collection.load()
res = collection.hybrid_search(
reqs, # 第1步创建的AnnSearchRequests列表
rerank, # 在第2步指定的重新排序策略
limit=2 # 限定最终返回数据量
)
参数说明:
[*]reqs: 搜刮哀求列表,此中每个哀求都是一个 ANNSearchRequest 对象。每个哀求可以对应于不同的矢量场和不同的搜刮参数集。
[*]rerank(对象):用于混合搜刮的重新排名策略。可能的值:WeightedRanker(value1, value2, ..., valueN) 和 RRFRanker()。
[*]limit (int):混合搜刮中返回的终极效果的最大数量。
limits 限定
[*]通常,每个集合默认允许最多 4 个向量字段。但是,您可以选择调整 proxy.maxVectorFieldNum 设置以扩展集合中矢量字段的最大数量,每个集合的最大限定为 10 个矢量字段
[*]集合中部分索引或加载的向量字段将导致错误。
[*]现在,混合搜刮中的每个 AnnSearchRequest 只能携带一个查询向量。
怎样学习AI大模型?
我在一线互联网企业工作十余年里,指导过不少同行子弟。资助很多人得到了学习和成长。
自己也整理很多AI大模型资料:AI大模型入门学习头脑导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。
https://img-blog.csdnimg.cn/direct/1f716c327caf4b2596f981e8b7aaedf7.png
第一阶段: 从大模型系统设计入手,讲解大模型的主要方法;
第二阶段: 在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;
第三阶段: 大模型平台应用开发借助阿里云PAI平台构建电商领域假造试衣系统;
第四阶段: 大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;
第五阶段: 大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;
第六阶段: 以SD多模态大模型为主,搭建了文生图小步调案例;
第七阶段: 以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。
https://img-blog.csdnimg.cn/direct/65fa158ead174be98faffe3be3aeccf6.jpeg#pic_center
页:
[1]