Milvus学习整理
[1. 概述总结](#1. 概述总结)
[1. 概述](#1. 概述)
[2. 使用全文搜索步骤](#2. 使用全文搜索步骤)
一、度量类型(metric_type)
相似度量用于衡量向量之间的相似性。选择合适的距离度量有助于显著提高分类和聚类性能。
目前,Milvus 支持这些类型的相似性度量:欧氏距离 (L2
)、内积 (IP
)、余弦相似度 (COSINE
)、JACCARD
,HAMMING
和BM25
(专门为稀疏向量的全文检索而设计)。
下表总结了所有支持的度量类型的相似性距离值特征及其取值范围。
度量类型 | 相似性距离值的特征 | 相似性距离值范围 |
---|---|---|
L2 |
值越小表示相似度越高。 | [0, ∞) |
IP |
数值越大,表示相似度越高。 | [-1, 1] |
COSINE |
数值越大,表示相似度越高。 | [-1, 1] |
JACCARD |
数值越小,表示相似度越高。 | [0, 1] |
HAMMING |
值越小,表示相似度越高。 | 0,dim(向量)] [0, dim(vector) |
BM25 |
根据词频、反转文档频率和文档规范化对相关性进行评分。 | [0, ∞) |
二、向量字段和适用场景介绍
|--------------------------------------------------|-------------|------------------------------------|----------------------------------------------------|
| 数据类型 | 维度范围 | 支持的度量(metric_type) | 适用场景 |
| FLOAT_VECTOR 存储 32 位浮点数 | 2-32,768 | COSINE
,L2
,IP
(默认:CONSINE)
| 非常适合需要高精度的场景,例如区分相似向量 |
| FLOAT16_VECTOR 存储 16 位半精度浮点数 | 2-32,768 | COSINE
,L2
,IP
(默认:CONSINE)
| 在精度要求不高的情况下,如推荐系统的低精度召回阶段,它可以节省存储空间。 |
| BFLOAT16_VECTOR 存储精度降低但指数范围与 Float32 相同的 16 位浮点数 | 2-32,768 | COSINE
,L2
,IP
(默认:CONSINE)
| 可在不明显影响精度的情况下降低内存和计算要求。 可用于需要快速处理大量向量的场景,如大规模图像检索。 |
| SPARSE_FLOAT_VECTOR 存储非零元素及其相应索引的列表 | 无需指定 | IP
,BM25
(仅用于全文检索) (默认:IP)
| 涉及需要精确匹配关键词或短语的应用 |
| BINARY_VECTOR 二进制向量 | 8-32,768*8 | HAMMING
,JACCARD
(默认:HAMMING)
| 用于图像处理或紧凑特征表示 移动设备和嵌入式系统等资源受限的环境中 |
三、索引字段介绍
(一)、概述总结
- 创建索引(Flat除外)时:都需要需要指定一些创建参数,如nlist
- 搜索数据时:可以指定一些索引的搜索参数来提高搜索精度,每种索引都有指定的搜索参数(即如果搜索数据时传入了这种索引不支持的参数,则不会起作用)
(二)、详细说明
下面表格说明了每一种索引的优缺点、构建索引需要指定参数、搜索数据可设置参数以及适用场景
类型 | 描述(概述、优缺点) | 索引构建参数 params | 搜索参数 | 场景 |
---|---|---|---|---|
FLAT | 不压缩向量是唯一能保证精确搜索结果的索引 采用的是穷举搜索方法,这意味着每次查询都要将目标输入与数据集中的每一组向量进行比较 优点:搜索精度高 缺点:海量数据搜索慢 | 不需要 | search_params中可指定metric_type 如: python search_params = { "metric_type":"L2" } |
数据集相对较小(百万级别) 需要 100% 的召回率 |
IVF_FLAT | 将向量数据划分为nlist(群组单位数) 个聚类单元,然后比较目标输入向量与每个聚类中心之间的距离。根据系统设置查询的簇数 (nprobe ),相似性搜索结果仅根据目标输入与最相似簇中向量的比较结果返回--大大缩短了查询时间 优点:搜索效率高,支持近似搜索 缺点:搜索精度依赖搜索参数调整 |
nlist(群组单位数): 默认:128,范围:[1, 65536] | search_params.params中可指定 A:nprobe(要查询的单位数) 默认:8, 范围:[1,nlist] B:max_empty_result_buckets 未返回任何搜索结果的桶的最大数量。 这是一个范围搜索参数,当连续空桶的数量达到指定值时,将终止搜索过程。 增加该值可以提高召回率,但代价是增加搜索时间。 如 python search_params = { "params":{ "nprobe":8 } } |
高速查询 要求尽可能高的召回率 |
IVF_SQ8 | 不进行任何压缩,因此它生成的索引文件大小与原始的非索引向量数据大致相同 优点:存储需求低 缺点:搜索精度低 | nlist(群组单位数): 默认:128 ,范围:[1, 65536] | A:nprobe(要查询的单位数) 默认:8, 范围:[1,nlist] B:max_empty_result_buckets 未返回任何搜索结果的桶的最大数量。 这是一个范围搜索参数,当连续空桶的数量达到指定值时,将终止搜索过程。 增加该值可以提高召回率,但代价是增加搜索时间 如 python search_params = { "params": { "nprobe": 10, } } |
极高速查询 内存资源有限 可接受召回率略有下降 |
IVF_PQ | 将原始高维向量空间均匀分解为 低维向量空间的笛卡尔乘积,然后对分解后的低维向量空间进行量化,大大降低了算法的时间复杂度和空间复杂度 | A. nlist(群组单位数): 默认:128 ,范围:[1, 65536] B. m(乘积量化因子数): 范围:dim mod m == 0 C. nbits(每个低维向量的存储位数) [1,64] (默认为 8) | A:nprobe(要查询的单位数) 默认:8, 范围:[1,nlist] 如 python search_params = { "params": { "nprobe": 10, } } |
* 高速查询 * 内存资源有限 * 可略微降低召回率 |
HNSW | 是一种基于图的索引算法。它根据一定的规则为图像建立多层导航结构 优点:高性能,高维数据效果良好 缺点: | A. M(定义图形中传出连接的最大数量) 在固定 ef/efConstruction 条件下,M 越大,精度/运行时间越长,范围[2, 2048] B. ef_construction控制索引搜索速度/构建速度的权衡。增加 efConstruction 参数可能会提高索引质量,但也会延长索引编制时间。 范围:[1,int_max] | ef:控制查询时间/准确性权衡的参数。ef 越高,搜索越准确,但速度越慢 范围:[top_k , int_max] 如: python search_params = { "params": { "ef": 10 } } |
* 极高速查询 * 要求尽可能高的召回率 * 内存资源大 |
四、简单代码示例
(一)、建立集合和索引示例
python
client = MilvusClient(uri="http://127.0.0.1:19530",db_name="test_embedding")
schema = client.create_schema(
auto_id=False,
enable_dynamic_field=False,
)
schema.add_field(field_name="id",datatype=DataType.INT64,is_primary=True,auto_id=True)
schema.add_field(field_name="embedding_content",datatype=DataType.FLOAT_VECTOR,dim=1024)
schema.add_field(field_name="content",datatype=DataType.VARCHAR,max_length=65535)
index_params = client.prepare_index_params()
index_params.add_index(
field_name="id",
index_type="STL_SORT"
)
index_params.add_index(
field_name="embedding_content",
index_type="FLAT",
metric_type="IP",
params={ "nlist": 1024 }
)
if "embedding_collection" not in client.list_collections():
print("create collection")
client.create_collection(collection_name="embedding_collection", schema=schema,index_params=index_params)
(二)、搜索示例
python
# 这里的搜索参数,需要根据创建的向量索引字段的类型,再结合上面表格对应的搜索参数进行设置
search_params = {
"metric_type":"IP",
"params":{
#召回率设置
"nprobe":128,
#保留相似度大于radius的
"radius":0.6
}
}
search_res = client.search(
collection_name="embedding_collection",
data=[query_embedding],
search_params=search_params,
output_fields=["id", "content"]
)
(三)、参考文档
五、数据搜索
(一)、基础搜索参数说明
python
query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]
client.search(
collection_name="my_collection",
anns_field="vector",
data=[query_vector],
limit=3,
output_fields=["color"],
search_params={
"metric_type": "IP",
"offset": 10
}
)
-
collection_name:集合名称
-
anns_field:向量字段名称
-
data:查询向量,可以是多个查询向量,如
pythonquery_vectors = [ [0.041732933, 0.013779674, -0.027564144, -0.013061441, 0.009748648], [0.0039737443, 0.003020432, -0.0006188639, 0.03913546, -0.00089768134] ]
当是多个查询向量时,返回的也是多维数组,如
python[ [ { "id": 551, "distance": 0.08821295201778412, "entity": {} }, { "id": 552, "distance": 0.08821295201778412, "entity": {} } ], [ { "id": 56, "distance": 0.08821295201778412, "entity": {} }, { "id": 52, "distance": 0.08821295201778412, "entity": {} } ] ]
-
limit:单次搜索中返回实体的最大数量,通常称为top-K
-
offset:跳过的数量,设置为已经返回的实体总数
-
output_fields:输出的字段名称集
-
metric_type:使用那种度量类型来计算查询向量与 Collections 中向量的相似度
(二)、范围搜索
1. 概述总结
- 范围搜索可将返回实体的距离或得分限制在特定范围内,从而提高搜索结果的相关性。
- 需要再search_params.params中指定radius和rang_filter的值,如
python
search_params={
# highlight-start
"params": {
"radius": 0.4,
"range_filter": 0.6
}
# highlight-end
}
- 如果正确设置值:
IP和CONSINE:距离越大越相似,所以如果要返回相似度高且在某个范围之间的则需要保证 radius < range_filter
L2及其他:距离越小越相似,所以如果要返回相似度高且在某个范围之间的则需要保证 radius > range_filter
2.详细说明
执行范围搜索请求时, 搜索结果中与查询向量最相似的向量为圆心
以搜索请求中指定的半径radius 为外圈半径,以range_filter为内圈半径 ,画出两个同心圆**。**
所有相似度得分在这两个同心圆形成的环形区域内的向量都将被返回。

上图显示,范围搜索请求包含两个参数:radius 和range_filter。收到范围搜索请求后,Milvus 会执行以下操作。
-
使用指定的度量类型**(** metric_type:consine)查找与查询向量最相似的所有向量嵌入。
-
过滤与查询向量的距离 或得分 在radius 和range_filter参数指定范围内的向量嵌入。
-
从筛选出的实体中返回前 limit个实体。
设置 radius 和range_filter 的方法因搜索的度量类型metric_type而异。下表列出了在不同度量类型下设置这两个参数的要求。
度量类型 | 名称 |
---|---|
L2 |
L2 距离越小,表示相似度越高。 |
IP |
IP 距离越大,表示相似度越高。 |
COSINE |
COSINE 距离越大,表示相似度越高。 |
JACCARD |
Jaccard 距离越小,表示相似度越高。 |
HAMMING |
汉明距离越小,表示相似度越高。 |
python
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="my_collection",
data=[query_vector],
limit=3,
search_params={
# highlight-start
"params": {
"radius": 0.4,
"range_filter": 0.6
}
# highlight-end
}
)
for hits in res:
print("TopK results:")
for hit in hits:
print(hit)
(三)、全文搜索 (BM25)
1. 概述
全文搜索是一种在文本数据集中检索包含特定术语或短语的文档,然后根据相关性对结果进行排序的功能。该功能克服了语义搜索可能会忽略精确术语的局限性,确保您获得最准确且与上下文最相关的结果。此外,它还通过接受原始文本输入来简化向量搜索,自动将您的文本数据转换为稀疏嵌入,而无需手动生成向量嵌入。
该功能使用 BM25 算法进行相关性评分,在检索增强生成 (RAG) 场景中尤为重要,它能优先处理与特定搜索词密切匹配的文档。
通过将全文检索与基于语义的密集向量搜索相结合,可以提高搜索结果的准确性和相关性。

2. 使用全文搜索步骤
要使用全文搜索,请遵循以下主要步骤。
-
创建 Collections:设置一个带有必要字段的 Collections,并定义一个将原始文本转换为稀疏嵌入的函数。
-
插入数据:将原始文本文档插入 Collections。
-
执行搜索:使用查询文本搜索你的 Collections 并检索相关结果。
python
from pymilvus import MilvusClient, DataType, Function, FunctionType
client = MilvusClient(uri="http://localhost:19530")
# 第一步 创建 Schema 并添加必要的字段。
schema = client.create_schema()
schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True, auto_id=True)
#存储原始文本数据,用于全文搜索操作,设置enable_analyzer=True 以允许 Milvus 对文本进行标记化
schema.add_field(field_name="text", datatype=DataType.VARCHAR, max_length=1000, enable_analyzer=True)
#矢量字段,用于存储内部生成的稀疏嵌入,以进行全文搜索操作
schema.add_field(field_name="sparse", datatype=DataType.SPARSE_FLOAT_VECTOR)
# 第二步 定义一个将文本转换为稀疏向量表示的函数,然后将其添加到 Schema 中
bm25_function = Function(
name="text_bm25_emb", # 函数名称
input_field_names=["text"], # 需要将文本转换为稀疏向量的VARCHAR 字段的名称a
output_field_names=["sparse"], # 存储内部生成的稀疏向量的字段名称
function_type=FunctionType.BM25, # 要使用的函数类型。将值设为FunctionType.BM25
)
schema.add_function(bm25_function)
# 第三步 配置索引
index_params = client.prepare_index_params()
index_params.add_index(
field_name="sparse",
index_name="sparse_inverted_index",
index_type="SPARSE_INVERTED_INDEX", # 要创建的索引类型。SPARSE_INVERTED_INDEX 是稀疏向量的推荐索引类型
metric_type="BM25",#该参数的值必须设置为BM25 ,以专门用于全文搜索功能。
params={"inverted_index_algo": "DAAT_MAXSCORE"}, # 索引构建和查询所使用的算法。有效值:DAAT_MAXSCORE、DAAT_WAND、TAAT_NAIVE
)
# 第四步 创建 Collections,插入数据
client.create_collection(
collection_name='demo',
schema=schema,
index_params=index_params
)
client.insert('demo', [
{'text': 'information retrieval is a field of study.'},
{'text': 'information retrieval focuses on finding relevant information in large datasets.'},
{'text': 'data mining and information retrieval overlap in research.'},
])
# 第五步 执行全文搜索
search_params = {
'params': {'drop_ratio_search': 0.2}, # 搜索时要忽略的低重要性词语的比例
}
client.search(
collection_name='demo',
data=['whats the focus of information retrieval?'], # 原始查询文本。
anns_field='sparse', # 存储内部生成的稀疏嵌入的字段名称
limit=3,
search_params=search_params
)