目录
一、向量相似度计算规则

metric_type = 向量相似度计算规则,建索引时是什么 metric,检索时就必须保持一致,不能乱改,否则召回结果异常 / 报错Milvus。
L2(欧氏距离)
看的是空间上离得近不近,同时兼顾方向 + 向量长度
- 适合:向量长度本身有业务含义的场景,比如图片特征、一些 CV 特征
- 不适合:文本 Embedding(大部分文本 Embedding
关心语义方向,不关心模长)
COSINE(余弦相似度)
只关心方向(语义夹角),不在乎向量多长,打分区间:-1,1;接近 1 越像
- 适合:RAG、文本向量检索最常用的,因为我们只关心语义是否相近,不关心向量模
IP(内积)
IP = a 和 b 同方向 + 模长越大,分数越高
- 不归一化的时候:IP ≠ 余弦!
- 全部向量归一化(L2 模 = 1)之后:IP = COSINE,排序结果 100% 一致
- 优点:归一化后计算更快(少一次除法),很多大模型向量库(FAISS、Milvus)RAG 场景喜欢用归一化 + IP
根据Milvus集合索引获取metric_type类型
python
def get_metric_type(client: MilvusClient, collection_name: str) -> str:
index_names = client.list_indexes(collection_name, field_name=VECTOR_FIELD)
for index_name in index_names:
index = client.describe_index(collection_name, index_name)
metric_type = index.get("metric_type")
if metric_type is None:
metric_type = (index.get("params") or {}).get("metric_type")
if metric_type:
return str(metric_type).upper()
raise RuntimeError(
"Cannot read metric_type from the vector index. "
"Please create an index for embeddings first."
)
二、三种检索方式
标准 ANN 搜索(TopK 相似度检索) ---------"给我和这个向量最相似的 K 条结果"
======标准 ANN 适合大多数检索场景,比如相似图片推荐、相似文本匹配。只要你的需求是"找一批相似结果",用这种方式最直接。
python
search_params = {
"metric_type": "COSINE",
"params": {"ef": 64},
}
results = collection.search(
data=[query_vector],
anns_field="embedding",
param=search_params,
limit=10,
output_fields=["id", "title"],
)
范围搜索(Range Search):按距离阈值过滤 ---------所有距离小于某个阈值的向量
python
search_params = {
"metric_type": "COSINE", //"距离"越小表示越相似
"params": {
"radius": 0.2, //radius 是"最远能接受多远",所以相似度越高, radius 越小。
"range_filter": 0.0,
}
}
混合检索(Hybrid Search):向量 + 标量联合过滤 ------在向量搜索里同时施加标量过滤表达式,搜索时先用标量条件圈定候选范围,再在这个范围内做 ANN 搜索。
python
results = collection.search(
data=[query_vector],
anns_field="embedding",
param=search_params,
limit=10,
expr="price >= 300 and price <= 500 and stock > 0",
output_fields=["id", "title", "price"],
)
====是增加了expr来进行标量筛选。
三、三种搜索方式的代码示例
3.1、标准 ANN 搜索
python
def standard_ann_search(
client: MilvusClient,
collection_name: str,
query_vector: Sequence[float],
top_k: int,
metric_type: str,
) -> Dict[str, Any]:
"""1. 标准 ANN 搜索:只按向量相似度返回 TopK。"""
search_params = {
"metric_type": metric_type,
"params": {},
}
results = client.search(
collection_name=collection_name,
data=[list(query_vector)],
anns_field=VECTOR_FIELD,
search_params=search_params,
limit=top_k,
output_fields=[DATA_ID_FIELD, TEXT_FIELD],
)
return {
"mode": "standard_ann",
"search_params": search_params,
"filter": None,
"results": results,
}
3.2、范围搜索
python
def range_search(
client: MilvusClient,
collection_name: str,
query_vector: Sequence[float],
top_k: int,
metric_type: str,
radius: float,
range_filter: Optional[float],
) -> Dict[str, Any]:
"""2. Range Search:按距离阈值过滤。"""
params: Dict[str, Any] = {"radius": radius}
if range_filter is not None:
params["range_filter"] = range_filter
search_params = {
"metric_type": metric_type,
"params": params,
}
results = client.search(
collection_name=collection_name,
data=[list(query_vector)],
anns_field=VECTOR_FIELD,
search_params=search_params,
limit=top_k,
output_fields=[DATA_ID_FIELD, TEXT_FIELD],
)
return {
"mode": "range_search",
"search_params": search_params,
"filter": None,
"results": results,
}
3.3、混合检索
python
def hybrid_search(
client: MilvusClient,
collection_name: str,
query_vector: Sequence[float],
top_k: int,
metric_type: str,
data_ids: Sequence[str],
) -> Dict[str, Any]:
"""3. 向量 + 标量联合过滤:data_id in ['...', '...']。"""
# json.dumps 会正确处理引号、逗号和特殊字符,避免手工拼接表达式出错。
chunk_type_value = json.dumps("standard", ensure_ascii=False)
data_id_values = json.dumps(list(data_ids), ensure_ascii=False)
filter_expr = (
f'chunk_type == {chunk_type_value} '
f'and data_id in {data_id_values}'
)
search_params = {
"metric_type": metric_type,
"params": {},
}
results = client.search(
collection_name=collection_name,
data=[list(query_vector)],
anns_field=VECTOR_FIELD,
search_params=search_params,
filter=filter_expr,
limit=top_k,
output_fields=[DATA_ID_FIELD, TEXT_FIELD, DATA_NAME],
)
return {
"mode": "hybrid_vector_scalar",
"search_params": search_params,
"filter": filter_expr,
"results": results,
}