一架梯子,一头程序猿,仰望星空!
Milvus向量数据库教程 > 内容正文

Python Milvus向量相似搜索


执行矢量相似性搜索

本主题介绍如何使用Milvus搜索实体。

在Milvus中,矢量相似性搜索计算查询矢量与集合中的向量之间的距离(使用指定的相似性度量),并返回最相似的结果。您可以通过指定布尔表达式来执行混合搜索,从而过滤标量字段或主键字段。

以下示例展示了如何在一个包含2000行数据的数据集(其中包括图书ID(主键)、字数(标量字段)和图书简介(矢量字段))上执行矢量相似性搜索,用于模拟根据其向量化介绍搜索特定图书的情况。Milvus将根据您定义的查询矢量和搜索参数返回最相似的结果。

加载集合

所有在Milvus内部的搜索和查询操作都在内存中执行。在执行矢量相似性搜索之前,将集合加载到内存中。

from pymilvus import Collection
collection = Collection("book")      # 获取现有集合。
collection.load()

准备搜索参数

为符合您的搜索场景准备相应的参数。以下示例定义了搜索将使用欧氏距离计算距离,并从由IVF_FLAT索引构建的十个最近聚类中检索向量的参数。

search_params = {
    "metric_type": "L2", 
    "offset": 5, 
    "ignore_growing": False, 
    "params": {"nprobe": 10}
}
参数 描述
metric_type 用于在搜索期间测量向量之间距离的方法。它应与索引构建过程中指定的方法相同。请参见相似性度量以获取更多信息。
offset 在搜索期间要跳过的实体数量。此值与search方法的limit的总和应小于16384。例如,如果您想查询查询矢量的第9和第10个最近邻居,请将limit设置为2,将offset设置为8
ignore_growing 是否在相似性搜索期间忽略增长段。默认值为False,表示搜索包括增长段。
params 特定于指定索引类型的搜索参数。请参见向量索引以获取更多信息。可能的选项如下:- nprobe 表示要搜索的聚类单元数。此参数仅在将index_type设置为IVF_FLATIVF_SQ8IVF_PQ时可用。该值应小于索引构建过程中指定的nlist值。- ef 表示搜索范围。此参数仅在将index_type设置为HNSW时可用。该值应在top_k32768之间。- radius 表示具有最低相似度的向量所在的角度。- range_filter 表示用于过滤与查询向量的相似度落在特定范围的向量字段值的过滤器。

进行向量搜索

使用Milvus进行向量搜索。要在特定分区中搜索,请指定分区名称列表。

Milvus支持为搜索设置一致性级别。本主题中的示例将一致性级别设置为“Strong”。您还可以将一致性级别设置为“Bounded”、“Session”或“Eventually”。有关Milvus中四个一致性级别的更多信息,请参见一致性。

results = collection.search(
    data=[[0.1, 0.2]], 
    anns_field="book_intro", 
    param=search_params,
    limit=10,
    expr=None,
    output_fields=['title'],
    consistency_level="Strong"
)

results[0].ids

results[0].distances

hit = results[0][0]
hit.entity.get('title')
参数 描述
data 搜索使用的向量。
anns_field 要搜索的字段的名称。
param 特定于索引的搜索参数。有关更多信息,请参见Vector Index。
limit 要返回的结果数。此值与param中的offset的和应小于16384。
expr 用于过滤属性的布尔表达式。有关更多信息,请参见布尔表达式规则。
output_fields(可选) 要返回的字段的名称。当前版本不支持向量字段。
consistency_level(可选) 搜索的一致性级别。

检查最相似向量的主键值及其距离。

results[0].ids
results[0].distances

当搜索完成后,在Milvus中释放加载的集合以减少内存消耗。

collection.release()

限制

功能 最大限制
集合名称的长度 255个字符
集合中的分区数 4,096
集合中的字段数 256
集合中的分片数 256
向量的维度 32,768
Top K 16,384
目标输入向量 16,384

进行混合搜索

混合搜索本质上是具有属性过滤的向量搜索。通过指定用于过滤标量字段或主键字段的布尔表达式,可以在特定条件下限制搜索。

以下示例展示了如何在基于常规vector search进行混合搜索的基础上执行混合搜索。假设您想根据向量化的简介搜索某些图书,但您只希望在特定的字数范围内。然后,您可以在搜索参数中指定布尔表达式以过滤word_count字段。Milvus将仅在与表达式匹配的实体中搜索相似向量。

通过指定布尔表达式,您可以在向量搜索期间过滤实体的标量字段。以下示例将搜索范围限制为指定的word_count值范围内的向量。

您还可以在过滤表达式中使用动态字段,并在搜索请求中使用输出字段。例如,请参见动态模式。

search_param = {
  "data": [[0.1, 0.2]],
  "anns_field": "book_intro",
  "param": {"metric_type": "L2", "params": {"nprobe": 10}, "offset": 0},
  "limit": 10,
  "expr": "word_count <= 11000",
}
res = collection.search(**search_param)

检查返回的结果。

assert len(res) == 1
hits = res[0]
assert len(hits) == 2
print(f"- Total hits: {len(hits)}, hits ids: {hits.ids} ")
print(f"- Top1 hit id: {hits[0].id}, distance: {hits[0].distance}, score: {hits[0].score} ")

进行范围搜索

范围搜索是一种根据查询向量与向量字段值之间的距离对搜索结果进行过滤的方法。可以使用不同的度量类型来测量距离。

在执行范围搜索时,Milvus首先进行向量相似性搜索。然后根据指定的距离条件执行向量过滤,最后返回距离在特定范围内的向量结果。

以下示例展示了如何在基于常规向量搜索的基础上进行范围搜索。

加载集合

Milvus中的所有搜索和查询操作都是在内存中执行的。在进行向量相似性搜索之前,将集合加载到内存中。

from pymilvus import Collection
collection = Collection("book")      # 获取现有集合
collection.load()

配置向量过滤范围

与普通的向量搜索相比,Milvus中的范围搜索通过传入两个新参数radiusrange_filter来控制搜索范围并获取所需的搜索结果。

radius指定向量具有最低相似度的角度。可选的range_filter可以结合使用,用于过滤与查询向量的相似度落入特定范围的向量字段值。参数radiusrange_filter的数据类型都是FLOAT。通过设置这两个参数,可以有效地平衡搜索的准确性和效率。

通常,相似度是通过向量字段值与查询向量之间的距离来测量的。选择不同的距离度量类型会对radiusrange_filter的配置产生重要影响。

例如,在L2距离的情况下,搜索结果必须根据距离小于radius的向量字段值进行过滤。这是因为在L2距离中,距离越小,向量越相似。基于这个知识,如果你想要过滤掉部分最相似的向量不返回,可以指定一个有效的range_filter值,该值小于radius

search_params = {
    "metric_type": "L2",
    "params": {
        "radius": 10.0,
        "range_filter" : 5.0
    }
}

在IP距离的情况下,情况有所不同。根据IP距离,较大的距离表示更大的相似度。因此,与L2距离相比,IP距离中的radiusrange_filter的值是相反的。也就是说,根据IP距离,如果使用range_filter来过滤掉部分最相似的向量,则有效的range_filter值必须大于radius,并且结果向量的距离应该大于radius但小于等于range_filter

search_params = {
    "metric_type": "IP",
    "params": {
        "radius": 0.8,
        "range_filter" : 1.0
    }
}

进行范围搜索

通过根据距离度量类型指定radiusrange_filter,您可以定义要返回的结果向量的范围。

根据L2距离,在范围为5.010.0之间的相似度进行范围搜索:

search_param = {
  "data": [[0.1, 0.2]], # 查询向量
  "anns_field": "book_intro", # 要搜索的字段名称
  "param": { "metric_type": "L2", "params": { "nprobe": 10, "radius": 10.0, "range_filter" : 5.0 }, "offset": 0 },
  "limit": 2,
  "output_fields": ["int64", "float"]  # 要返回的字段
}

res = collection.search(**search_param)

根据IP距离,在范围为1.00.8之间的相似度进行范围搜索:

search_param = {
  "data": [[0.1, 0.2]], # 查询向量
  "anns_field": "book_intro", # 要搜索的字段名称
  "param": {"metric_type": "IP", "params": { "nprobe": 10, "radius": 0.8, "range_filter" : 1.0 }, "offset": 0 },
  "limit": 2,
  "output_fields": ["int64", "float"] # 要返回的字段
}

res = collection.search(**search_param)

总结

在Milvus中,范围搜索可以返回与指定范围内的距离相似的向量结果。通过在搜索参数中指定radiusrange_filter来启用这个功能。下表总结了距离度量类型对这两个参数的配置方式。

距离度量类型 配置方式
L2和其他距离 range_filter <= 距离 < radius
IP和余弦距离 radius < 距离 <= range_filter


关联主题