Milvus(20):基本向量搜索
近似近邻(ANN)搜索是一种基于向量嵌入索引文件的搜索方法,用于高效查找与查询向量最相似的向量子集。与传统的k-NearestNeighbors(kNN)搜索不同,ANN搜索通过预建索引文件快速定位相似向量,减少了计算开销。Milvus系统支持ANN搜索,并提供单向量搜索和批量向量搜索功能,用户可以根据指定的度量类型(如内积、L2距离等)计算相似度并返回前K个结果。
近似近邻(ANN)搜索以记录向量嵌入排序顺序的索引文件为基础,根据接收到的搜索请求中携带的查询向量查找向量嵌入子集,将查询向量与子群中的向量进行比较,并返回最相似的结果。通过 ANN 搜索,Milvus 提供了高效的搜索体验。
1 概述
ANN 和 k-Nearest Neighbors (kNN) 搜索是向量相似性搜索的常用方法。在 kNN 搜索中,必须将向量空间中的所有向量与搜索请求中携带的查询向量进行比较,然后找出最相似的向量,这既耗时又耗费资源。
与 kNN 搜索不同,ANN 搜索算法要求提供一个索引文件,记录向量 Embeddings 的排序顺序。当收到搜索请求时,可以使用索引文件作为参考,快速找到可能包含与查询向量最相似的向量嵌入的子组。然后,你可以使用指定的度量类型来测量查询向量与子组中的向量之间的相似度,根据与查询向量的相似度对组成员进行排序,并找出前 K 个组成员。ANN 搜索依赖于预建索引,搜索吞吐量、内存使用量和搜索正确性可能会因选择的索引类型而不同。您需要在搜索性能和正确性之间取得平衡。为了减少学习曲线,Milvus 提供了AUTOINDEX。通过AUTOINDEX,Milvus 可以在建立索引。
2 单向量搜索
在 ANN 搜索中,单向量搜索指的是只涉及一个查询向量的搜索。根据预建索引和搜索请求中携带的度量类型,Milvus 将找到与查询向量最相似的前 K 个向量。
代码片段假定您已经以快速设置的方式创建了一个 Collections。搜索请求携带单个查询向量,并要求 Milvus 使用内积(IP)计算查询向量与集合中向量的相似度,并返回三个最相似的向量。
from pymilvus import MilvusClient
client = MilvusClient(
uri="http://localhost:19530",
token="root:Milvus"
)
# 单向量搜索
query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]
res = client.search(
collection_name="quick_setup",
anns_field="vector",
data=[query_vector],
limit=3,
search_params={"metric_type": "IP"}
)
for hits in res:
for hit in hits:
print(hit)
# [
# [
# {
# "id": 551,
# "distance": 0.08821295201778412,
# "entity": {}
# },
# {
# "id": 296,
# "distance": 0.0800950899720192,
# "entity": {}
# },
# {
# "id": 43,
# "distance": 0.07794742286205292,
# "entity": {}
# }
# ]
# ]
Milvus 根据搜索结果与查询向量的相似度得分从高到低排列搜索结果。相似度得分也称为与查询向量的距离,其值范围随使用的度量类型而变化。下表列出了适用的度量类型和相应的距离范围。
|
度量类型 |
特征 |
距离范围 |
|---|---|---|
|
|
值越小表示相似度越高。 |
[0, ∞) |
|
|
数值越大,表示相似度越高。 |
[-1, 1] |
|
|
数值越大,表示相似度越高。 |
[-1, 1] |
|
|
值越小,表示相似度越高。 |
[0, 1] |
|
|
值越小,表示相似度越高。 |
[0,dim(向量)] 批量向量搜索 |
3 批量向量搜索
同样,您也可以在一个搜索请求中包含多个查询向量。Milvus 将并行对查询向量进行 ANN 搜索,并返回两组结果。
# 多向量搜索
# 准备查询向量
query_vectors = [
[0.041732933, 0.013779674, -0.027564144, -0.013061441, 0.009748648],
[0.0039737443, 0.003020432, -0.0006188639, 0.03913546, -0.00089768134]
]
# 开始搜索
res = client.search(
collection_name="quick_setup",
data=query_vectors,
limit=3,
)
for hits in res:
print("TopK results:")
for hit in hits:
print(hit)
# Output
#
# [
# [
# {
# "id": 551,
# "distance": 0.08821295201778412,
# "entity": {}
# },
# {
# "id": 296,
# "distance": 0.0800950899720192,
# "entity": {}
# },
# {
# "id": 43,
# "distance": 0.07794742286205292,
# "entity": {}
# }
# ],
# [
# {
# "id": 730,
# "distance": 0.04431751370429993,
# "entity": {}
# },
# {
# "id": 333,
# "distance": 0.04231833666563034,
# "entity": {}
# },
# {
# "id": 232,
# "distance": 0.04221535101532936,
# "entity": {}
# }
# ]
# ]
4 在分区中进行 ANN 搜索
假设您在一个 Collections 中创建了多个分区,您可以将搜索范围缩小到特定数量的分区。在这种情况下,您可以在搜索请求中包含目标分区名称,将搜索范围限制在指定的分区内。减少搜索所涉及的分区数量可以提高搜索性能。下面的代码片段假定在你的 Collections 中有一个名为PartitionA的分区。
# 单向量搜索
query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]
res = client.search(
collection_name="quick_setup",
# highlight-next-line
partition_names=["partitionA"],
data=[query_vector],
limit=3,
)
for hits in res:
print("TopK results:")
for hit in hits:
print(hit)
# [
# [
# {
# "id": 551,
# "distance": 0.08821295201778412,
# "entity": {}
# },
# {
# "id": 296,
# "distance": 0.0800950899720192,
# "entity": {}
# },
# {
# "id": 43,
# "distance": 0.07794742286205292,
# "entity": {}
# }
# ]
# ]
5 使用输出字段
在搜索结果中,Milvus 默认会包含包含 TOP-K 向量嵌入的实体的主字段值和相似度距离/分数。您可以在搜索请求中包含目标字段(包括向量和标量字段)的名称作为输出字段,使搜索结果携带这些实体中其他字段的值。
# 单向量搜索
query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592],
res = client.search(
collection_name="quick_setup",
data=[query_vector],
limit=3, # 要返回的结果数
search_params={"metric_type": "IP"},
# highlight-next-line
output_fields=["color"]
)
print(res)
# [
# [
# {
# "id": 551,
# "distance": 0.08821295201778412,
# "entity": {
# "color": "orange_6781"
# }
# },
# {
# "id": 296,
# "distance": 0.0800950899720192,
# "entity": {
# "color": "red_4794"
# }
# },
# {
# "id": 43,
# "distance": 0.07794742286205292,
# "entity": {
# "color": "grey_8510"
# }
# }
# ]
# ]
6 使用限制和偏移
您可能会注意到,搜索请求中包含的参数limit 决定了搜索结果中包含的实体数量。该参数指定了单次搜索中返回实体的最大数量,通常称为top-K。
如果希望执行分页查询,可以使用循环来发送多个搜索请求,每个查询请求中都包含Limit和Offset参数。具体来说,可以将 "限制 "参数设置为希望包含在当前查询结果中的实体数量,将 "偏移"参数设置为已经返回的实体总数。下表概述了在一次返回 100 个 "实体 "时,如何为分页查询设置 "限制"和"偏移"参数。
|
查询 |
每次查询要返回的实体 |
已返回实体总数 |
|---|---|---|
|
第 1 次查询 |
100 |
0 |
|
第二次查询 |
100 |
100 |
|
第三次查询 |
100 |
200 |
|
第 n 次查询 |
100 |
100 x (n-1) |
请注意,在一次 ANN 搜索中,limit 和offset 的总和应小于 16 384。
# 单向量搜索
query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592],
res = client.search(
collection_name="quick_setup",
data=[query_vector],
limit=3, # 要返回的结果数
search_params={
"metric_type": "IP",
# highlight-next-line
"offset": 10 # 要跳过的记录
}
)
7 增强 ANN 搜索
AUTOINDEX 可大大拉平 ANN 搜索的学习曲线。然而,随着 Top-K 的增加,搜索结果不一定总是正确的。通过缩小搜索范围、提高搜索结果相关性和搜索结果多样化,Milvus 实现了以下搜索增强功能。
- 过滤搜索:您可以在搜索请求中包含过滤条件,这样 Milvus 就会在进行 ANN 搜索前进行元数据过滤,将搜索范围从整个 Collections 缩小到只搜索符合指定过滤条件的实体。
- 范围搜索:您可以将返回实体的距离或得分限制在特定范围内,从而提高搜索结果的相关性。在 Milvus 中,范围搜索包括以与查询向量最相似的嵌入向量为中心画两个同心圆。搜索请求指定了两个圆的半径,Milvus 会返回所有属于外圆但不属于内圆的向量嵌入。
- 分组搜索:如果返回的实体在特定字段中持有相同的值,搜索结果可能无法代表向量空间中所有向量嵌入的分布情况。要使搜索结果多样化,可以考虑使用分组搜索。
- 混合搜索:一个 Collections 最多可以包含四个向量场,以保存使用不同嵌入模型生成的向量嵌入。通过这种方式,可以使用混合搜索对这些向量场的搜索结果进行 Rerankers,从而提高召回率。
- 搜索迭代器:单个 ANN 搜索最多可返回 16,384 个实体。如果需要在单次搜索中返回更多实体,请考虑使用搜索迭代器。
- 全文搜索:全文搜索是一种在文本数据集中检索包含特定术语或短语的文档,然后根据相关性对结果进行排序的功能。该功能克服了语义搜索的局限性(语义搜索可能会忽略精确的术语),确保您获得最准确且与上下文最相关的结果。此外,它还能接受原始文本输入,自动将文本数据转换为稀疏嵌入,无需手动生成向量嵌入,从而简化了向量搜索。
- 关键词匹配:Milvus 的关键词匹配功能可根据特定术语精确检索文档。该功能主要用于满足特定条件的过滤搜索,并可结合标量过滤来完善查询结果,允许在符合标量标准的向量内进行相似性搜索。
- 使用 Partition Key:在元数据过滤中涉及多个标量字段并使用相当复杂的过滤条件可能会影响搜索效率。一旦将一个标量字段设置为分区关键字,并在搜索请求中使用涉及分区关键字的过滤条件,就可以帮助将搜索范围限制在与指定分区关键字值相对应的分区内。
- 使用 mmap
- 聚类压缩
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)