Milvus搜索机制

目录

一、向量相似度计算规则

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,
    }
相关推荐
TheBestRucy12 天前
从零构建企业级“中文法律智能问答系统”:FastAPI+Milvus+混合检索+真流式RAG实战
fastapi·milvus
Flynn Liang13 天前
内存/Redis/PGVector/Milvus/ES 怎么选?Spring AI VectorStore 抽象与向量库选型对照表
redis·elasticsearch·milvus·rag·springai·pgvector·向量库
kyrie_sakura14 天前
大模型学习19 大模型学习 - LangChain2_Retrieval(RAG-文档处理-向量处理检索-Milvus)
学习·langchain·milvus
Maiko Star14 天前
*【HM-LC】Milvus向量库详解:Collection、索引、混合检索与LangChain实战
langchain·milvus
霸道流氓气质16 天前
AI 图片管理平台:Spring AI 原生多模态、Milvus 向量语义检索与 MinIO 预签名安全管控的 React + 全栈生产级实战
人工智能·spring·milvus
一枕槐安48717 天前
多模态RAG实战:PDF图文混合文档检索问答本地跑通
langchain·pdf·milvus·ai应用开发·多模态rag
ai大模型-探索者21 天前
BGE-M3三种向量在Milvus怎么存(稠密、稀疏、多向量)
milvus·稀疏·多向量·稠密
唠点键盘之外的23 天前
29 切片的权限隔离(实战篇):Milvus + Spring AI,从 0 搭一条带权限过滤的检索链路
人工智能·spring·milvus
ai大模型-探索者23 天前
Milvus向量数据库(介绍与使用)
数据库·milvus