混合搜索
自 Milvus 2.4 版起,我们引入了多向量支持和混合搜索框架,这意味着用户可以在一个 Collections 中引入多个向量场(最多 10 个)。不同列中的这些向量代表数据的不同方面,源自不同的 Embeddings 模型或经过不同的处理方法。混合搜索的结果使用 Rerankers 策略进行整合,如互易等级融合(RRF)和加权评分。要了解有关 Rerankers 策略的更多信息,请参阅Reranking。
这一功能在综合搜索场景中特别有用,例如根据图片、声音、指纹等各种属性识别向量库中最相似的人。
在本教程中,您将学习如何
创建多个
AnnSearchRequest
实例,用于不同向量场的相似性搜索;配置重排策略,对来自多个
AnnSearchRequest
实例的搜索结果进行组合和重排;使用
hybrid_search()
方法执行混合搜索。
本页的代码片段使用PyMilvus ORM 模块与 Milvus 进行交互。使用新的MilvusClient SDK的代码片段即将发布。
准备工作
在开始混合搜索之前,请确保您有一个包含多个向量字段的 Collections。目前,Milvus 引入的每个 Collection 默认有四个向量字段,通过修改proxy.maxVectorFieldNum配置,最多可扩展到十个。
下面是一个示例,说明如何创建一个名为test_collection
的集合,其中包含两个向量字段filmVector
和posterVector
,并在其中插入随机实体。
from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType
import random
# Connect to Milvus
connections.connect(
host="127.0.0.1", # Replace with your Milvus server IP
port="19530"
)
# Create schema
fields = [
FieldSchema(name="film_id", dtype=DataType.INT64, is_primary=True),
FieldSchema(name="filmVector", dtype=DataType.FLOAT_VECTOR, dim=5), # Vector field for film vectors
FieldSchema(name="posterVector", dtype=DataType.FLOAT_VECTOR, dim=5)] # Vector field for poster vectors
schema = CollectionSchema(fields=fields,enable_dynamic_field=False)
# Create collection
collection = Collection(name="test_collection", schema=schema)
# Create index for each vector field
index_params = {
"metric_type": "L2",
"index_type": "IVF_FLAT",
"params": {"nlist": 128},
}
collection.create_index("filmVector", index_params)
collection.create_index("posterVector", index_params)
# Generate random entities to insert
entities = []
for _ in range(1000):
# generate random values for each field in the schema
film_id = random.randint(1, 1000)
film_vector = [ random.random() for _ in range(5) ]
poster_vector = [ random.random() for _ in range(5) ]
# create a dictionary for each entity
entity = {
"film_id": film_id,
"filmVector": film_vector,
"posterVector": poster_vector
}
# add the entity to the list
entities.append(entity)
collection.insert(entities)
步骤 1:创建多个 AnnSearchRequest 实例
混合搜索使用hybrid_search()
API 在一次调用中执行多个 ANN 搜索请求。每个AnnSearchRequest
代表对特定向量场的单个搜索请求。
下面的示例创建了两个AnnSearchRequest
实例,用于对两个向量场执行单独的相似性搜索。
from pymilvus import AnnSearchRequest
# Create ANN search request 1 for filmVector
query_filmVector = [[0.8896863042430693, 0.370613100114602, 0.23779315077113428, 0.38227915951132996, 0.5997064603128835]]
search_param_1 = {
"data": query_filmVector, # Query vector
"anns_field": "filmVector", # Vector field name
"param": {
"metric_type": "L2", # This parameter value must be identical to the one used in the collection schema
"params": {"nprobe": 10}
},
"limit": 2 # Number of search results to return in this AnnSearchRequest
}
request_1 = AnnSearchRequest(**search_param_1)
# Create ANN search request 2 for posterVector
query_posterVector = [[0.02550758562349764, 0.006085637357292062, 0.5325251250159071, 0.7676432650114147, 0.5521074424751443]]
search_param_2 = {
"data": query_posterVector, # Query vector
"anns_field": "posterVector", # Vector field name
"param": {
"metric_type": "L2", # This parameter value must be identical to the one used in the collection schema
"params": {"nprobe": 10}
},
"limit": 2 # Number of search results to return in this AnnSearchRequest
}
request_2 = AnnSearchRequest(**search_param_2)
# Store these two requests as a list in `reqs`
reqs = [request_1, request_2]
参数:
AnnSearchRequest
对象代表 ANN 搜索请求的类。每次混合搜索可包含 1 到 1,024 个
ANNSearchRequest
对象。data
列表要在单个
AnnSearchRequest
中搜索的查询向量。目前,该参数只接受包含单个查询向量的列表,例如[[0.5791814851218929, 0.5792985702614121, 0.8480776460143558, 0.16098005945243, 0.2842979317256803]]
。今后,该参数将扩展为接受多个查询向量。anns_field
(字符串)要在单个
AnnSearchRequest
中使用的向量字段名称。param
(dict)单个
AnnSearchRequest
的搜索参数字典。这些搜索参数与单向量搜索参数相同。更多信息,请参阅搜索参数。limit
(int)要包含在单个
ANNSearchRequest
中的搜索结果的最大数量。该参数只影响单个
ANNSearchRequest
中返回的搜索结果数,并不决定hybrid_search
调用的最终返回结果。在混合搜索中,最终结果是通过对多个ANNSearchRequest
实例的结果进行组合和 Rerankers 来决定的。
步骤 2:配置 Rerankers 策略
创建AnnSearchRequest
实例后,配置 Rerankers 策略,对结果进行组合和重排。目前有两个选项:WeightedRanker
和RRFRanker
。有关重排策略的更多信息,请参阅Rerankers。
使用加权评分
WeightedRanker
用于以指定权重为每个向量场搜索结果分配重要性。如果您将某些向量场的优先级高于其他向量场,WeightedRanker(value1, value2, ..., valueN)
可以在合并搜索结果中反映出来。from pymilvus import WeightedRanker # Use WeightedRanker to combine results with specified weights # Assign weights of 0.8 to text search and 0.2 to image search rerank = WeightedRanker(0.8, 0.2)
使用
WeightedRanker
时,请注意- 每个权重值的范围从 0(最不重要)到 1(最重要),影响最终的综合得分。
WeightedRanker
中提供的权重值总数应等于您创建的AnnSearchRequest
实例数。
使用互惠排名融合(RFF)
# Alternatively, use RRFRanker for reciprocal rank fusion reranking from pymilvus import RRFRanker rerank = RRFRanker()
步骤 3:执行混合搜索
设置好AnnSearchRequest
实例和 Rerankers 策略后,使用hybrid_search()
方法执行混合搜索。
# Before conducting hybrid search, load the collection into memory.
collection.load()
res = collection.hybrid_search(
reqs, # List of AnnSearchRequests created in step 1
rerank, # Reranking strategy specified in step 2
limit=2 # Number of final search results to return
)
print(res)
参数:
reqs
列表搜索请求列表,其中每个请求都是一个
ANNSearchRequest
对象。每个请求可以对应不同的向量场和不同的搜索参数集。rerank
对象用于混合搜索的 Rerankers 排序策略。可能的值:
WeightedRanker(value1, value2, ..., valueN)
和RRFRanker()
。有关重排策略的更多信息,请参阅Rerankers。
limit
(int)在混合搜索中返回的最终结果的最大数量。
输出类似于下图:
["['id: 844, distance: 0.006047376897186041, entity: {}', 'id: 876, distance: 0.006422005593776703, entity: {}']"]
限制
通常情况下,每个 Collections 默认最多允许 4 个向量字段。不过,您可以选择调整
proxy.maxVectorFieldNum
配置,以扩展集合中向量字段的最大数量,每个集合的最大限制为 10 个向量字段。有关更多信息,请参阅 "代理相关配置"。集合中部分索引或加载的向量字段将导致错误。
目前,混合搜索中的每个
AnnSearchRequest
只能携带一个查询向量。
常见问题
在哪些情况下推荐使用混合搜索?
混合搜索非常适合需要高精确度的复杂情况,尤其是当一个实体可以由多个不同向量表示时。这适用于同一数据(如一个句子)通过不同的 Embeddings 模型进行处理的情况,或多模态信息(如个人的图像、指纹和声纹)转换为不同向量格式的情况。通过给这些向量分配权重,它们的综合影响可以极大地丰富召回率,提高搜索结果的有效性。
加权排序器如何对不同向量场之间的距离进行归一化处理?
加权排序器使用为每个向量场分配的权重对向量场之间的距离进行归一化处理。它根据权重计算每个向量场的重要性,优先考虑权重较高的向量场。建议在 ANN 搜索请求中使用相同的度量类型,以确保一致性。这种方法可以确保被认为更重要的向量对整体排名有更大的影响。
是否可以使用 Cohere Ranker 或 BGE Ranker 等其他排名器?
目前只支持所提供的排名器。正在计划在未来的更新中加入其他排名器。
是否可以同时进行多个混合搜索操作?
可以,支持同时执行多个混合搜索操作符。
能否在多个 AnnSearchRequest 对象中使用相同的向量字段来执行混合搜索?
从技术上讲,可以在多个 AnnSearchRequest 对象中使用相同的向量字段进行混合搜索。混合搜索并不需要多个向量字段。