Zilliz 11月12日 00:28
理解多向量混合检索,解决复杂搜索难题
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

在电商、医疗、法律等复杂场景下,单一向量检索常因信息维度不足导致召回率偏低。本文深入剖析了多向量混合检索的必要性与实现方式。文章详细介绍了稀疏-稠密向量搜索和多模态向量搜索两大核心类型,并阐述了Milvus/Zilliz Cloud如何在Schema定义、索引构建、全文搜索集成及重排序机制等方面提供技术支持。通过一个产品文本与图像检索的实例,文章手把手演示了如何创建多向量字段的Collection,插入数据,执行混合搜索,并利用RRFRanker等策略对结果进行重排序,最终实现更精准、更贴合用户需求的多维度搜索。

🧰 **多向量混合检索应对复杂搜索需求**:在电商、医疗、法律等领域,用户查询往往包含多重维度信息(如图片+文字描述,或语义+关键词),单一向量检索难以满足要求,导致召回率低。多向量混合检索通过整合文本语义、关键词及跨模态信息,在多个维度上并行检索并进行结果重排序,显著提升了搜索的准确性和贴合度。

💡 **核心类型:稀疏-稠密与多模态向量搜索**:多向量混合检索主要分为两类:稀疏-稠密向量搜索结合了擅长捕捉语义的稠密向量和适合精准关键词匹配的稀疏向量,实现了对整体概念理解和精确术语匹配的平衡;多模态向量搜索则能整合文本、图像、音频等不同形式的信息,提供连贯的跨模态搜索体验。

🛠️ **Milvus/Zilliz Cloud 的关键技术支持**:Milvus/Zilliz Cloud 提供了实现多向量混合检索所需的全方位技术能力,包括灵活定义包含多种数据类型(如稠密向量、稀疏向量)的Collection Schema;支持多样化的索引类型(如AUTOINDEX、SPARSE_INVERTED_INDEX)和度量方式;内置BM25算法简化了稀疏向量的生成;并提供完善的重排序机制(如RRFRanker)来合并和优化搜索结果。

📈 **实战应用:产品文本与图像混合检索**:文章以产品搜索为例,详细演示了如何创建包含文本稠密向量、文本稀疏向量和图像稠密向量字段的Collection。通过为不同向量字段配置合适的索引和度量方式,并结合AnnSearchRequest实例和RRFRanker策略,实现了基于文本语义、关键词匹配和图像内容的混合搜索,最终输出精准度更高的搜索结果。

原创 与你一起学习的 2025-11-11 17:58 上海

一篇文章搞明白两大类型的多向量混合检索

今天是双十一,唠点做电商搜索常踩的坑:复杂描述下的召回率偏低问题。

可能不少人都遇到过这个情况,用户发了张裙子照片,还特意备注 “北方、冬天、妈妈穿”,检索结果却匹配到一条花色、版型相似但明显为夏季穿着的沙滩裙,与需求完全不符。

医疗、法律领域做检索时,也经常出现类似问题:医生搜索 “2 型糖尿病 儿童患者 病例” ,系统却召回一堆 1 型糖尿病的资料,语义相近,但与需求牛头不对马嘴;法律场景更典型,用户明确查询 “XX 场景下的连带责任” 相关法条和案例,系统却返回大量 “XX 场景补充责任” 的文书,虽然就两字之差,实际法律含义却相去甚远。

问题看似各不相同,但本质其实都一样:单靠一种维度的信息(也就是单向量检索),根本应付不了复杂场景的需求:电商搜索需要的是图片 + 文字描述的多模态检索能力;医疗、法律场景则需要把语义理解和关键词精准匹配 结合起来。

要解决这类问题,就需要引入多向量混合检索。其核心在于整合文本语义、关键词及不同模态信息,在多维度上并行检索后对结果进行 rerank,使检索结果更贴合实际需求。

那么,多向量混合检索到底是什么,该怎么用?以下是技术解读以及手把手应用实践。

01 

多向量混合检索的两种核心类型

多向量混合检索本质就是整合不同搜索方法或跨模态的embedding信息,主要分为两类:

以下是稀疏 - 稠密向量混合检索的示范:

https://milvus.io/docs/hybrid_search_with_milvus.md

02 

Milvus/Zilliz Cloud 的核心支持能力

要落地多向量混合检索,Milvus 和 Zilliz Cloud 提供了全方位的技术支持:

    灵活的Schema定义:能在Collection Schema中定义多个向量字段,支持整数主键(INT64)、字符串(VARCHAR)、稠密向量(DENSE_VECTOR)、稀疏向量(SPARSE_FLOAT_VECTOR)等多种数据类型,还能开启全文搜索分析器(enable_analyzer)。

    多样化索引与度量:提供自动索引(AUTOINDEX)、稀疏倒排索引(SPARSE_INVERTED_INDEX)等类型,支持内积(IP)、BM25 等度量方式,适配不同类型向量的搜索需求。

    内置全文搜索:集成 BM25 算法,能自动从文本字段生成稀疏向量,不用用户手动计算,简化数据准备流程。

    完善的重排序机制:支持 RRFRanker 等多种策略,支持对多个ANN搜索结果集进行合并与重新排序,高效输出最优结果。

    严谨的搜索流程:明确规定了搜索请求实例创建、集合加载、参数配置等步骤,保障混合搜索的稳定性和准确性。

凭借上述能力,多向量混合检索可以落地到多种实际场景:

03 

示例

下面以 产品文本 + 图像的检索场景为例,详细拆解多向量混合搜索的实现步骤。

这里默认每个产品都有文字描述和图片,能支持三种搜索方式:

接下来,我们会结合产品的文字描述和图片信息,一步步讲清楚怎么把这三种搜索结合起来,实现多模态混合搜索。核心是先学会怎么存储这些多类型的向量数据,再用合适的方法给搜索结果排序。

(1)创建具有多个向量字段的集合

要实现混合搜索,首先得建一个能容纳多种向量的 collection。建这个collection分三步:定义 Collection Schema、配置索引参数和创建 Collection。

这里先重点说第一步 ——定义Collection Schema

因为要支持三种搜索,模板里得有对应不同向量的字段,具体包括这 5 个:

另外,因为我们要用系统自带的 BM25 算法来自动生成文本的稀疏向量,所以在定义这个Schema时,还需要加上 Milvus 的内置函数支持。

    from pymilvus import (

        MilvusClient, DataType, Function, FunctionType

    )

    client = MilvusClient(

        uri="http://localhost:19530",

        token="root:Milvus"

    )

    # Init schema with auto_id disabled

    schema = client.create_schema(auto_id=False)

    # Add fields to schema

    schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True, description="product id")

    schema.add_field(field_name="text", datatype=DataType.VARCHAR, max_length=1000, enable_analyzer=True, description="raw text of product description")

    schema.add_field(field_name="text_dense", datatype=DataType.FLOAT_VECTOR, dim=768, description="text dense embedding")

    schema.add_field(field_name="text_sparse", datatype=DataType.SPARSE_FLOAT_VECTOR, description="text sparse embedding auto-generated by the built-in BM25 function")

    schema.add_field(field_name="image_dense", datatype=DataType.FLOAT_VECTOR, dim=512, description="image dense embedding")

    # Add function to schema

    bm25_function = Function(

        name="text_bm25_emb",

        input_field_names=["text"],

        output_field_names=["text_sparse"],

        function_type=FunctionType.BM25,

    )

    schema.add_function(bm25_function)

    定义好 Collection Schema 后,接下来要给各个向量字段建索引。


    简单说,索引就像给数据建了个快速查找目录,能大幅提升后续搜索的速度和效率。同时,还得明确用什么方法判断两个向量 “像不像”(也就是相似度类型)。

    在这个示例里,三个向量字段的索引配置是这样的:

      # Prepare index parameters

      index_params = client.prepare_index_params()

      # Add indexes

      index_params.add_index(

          field_name="text_dense",

          index_name="text_dense_index",

          index_type="AUTOINDEX",

          metric_type="IP"

      )

      index_params.add_index(

          field_name="text_sparse",

          index_name="text_sparse_index",

          index_type="SPARSE_INVERTED_INDEX",

          metric_type="BM25",

          params={"inverted_index_algo""DAAT_MAXSCORE"}, # or "DAAT_WAND" or "TAAT_NAIVE"

      )

      </include>

      <include target="zilliz">

      index_params.add_index(

          field_name="text_sparse",

          index_name="text_sparse_index",

          index_type="AUTOINDEX",

          metric_type="BM25"

      )

      </include>

      index_params.add_index(

          field_name="image_dense",

          index_name="image_dense_index",

          index_type="AUTOINDEX",

          metric_type="IP"

      )

      定义好 Collection Schema 、创建好向量字段索引之后,第三步就是创建 Collection


      此处,我们创建一个名为demo的 Collection。

        client.create_collection(

            collection_name="my_collection",

            schema=schema,

            index_params=index_params

        )


        (2)插入数据

        接下来,我们要把产品的各种信息按照前面定义的结构,存到名为 my_collection的集合里。这里有个关键点:除了系统能自动生成的内容,其他字段都得按规定格式填,不能出错。

        具体来说,每个产品要填这些信息:id、text、text_dense、image_dense

        另外有两个需要注意的点:

          生成这些稠密向量时,文本和图像可以用同一个模型,也可以用不同的模型。比如这个例子里,text_dense 是 768 维,image_dense 是 512 维,明显是用了不同的模型(比如文本用 BERT,图像用 CLIP)。这就意味着,后面做搜索时,查文本就得用生成 text_dense 的模型来生成查询向量,查图像就得用生成 image_dense 的模型,不然格式对不上,搜不准。

          至于 text_sparse(文本的稀疏向量,用来做关键词匹配的),因为我们用了系统自带的 BM25 算法,它会自动从 text 字段里提取关键词生成稀疏向量,所以不用我们手动填。但如果不想用 BM25,就得自己提前算好稀疏向量。

          import random

          # Generate example vectors

          def generate_dense_vector(dim):

              return [random.random() for _ in range(dim)]

          data=[

              {

                  "id"0,

                  "text""Red cotton t-shirt with round neck",

                  "text_dense": generate_dense_vector(768),

                  "image_dense": generate_dense_vector(512)

              },

              {

                  "id"1,

                  "text""Wireless noise-cancelling over-ear headphones",

                  "text_dense": generate_dense_vector(768),

                  "image_dense": generate_dense_vector(512)

              },

              {

                  "id"2,

                  "text""Stainless steel water bottle, 500ml",

                  "text_dense": generate_dense_vector(768),

                  "image_dense": generate_dense_vector(512)

              }

          ]

          res = client.insert(

              collection_name="my_collection",

              data=data

          )


          (3)执行混合搜索

          步骤 1:创建多个 AnnSearchRequest 实例

          混合搜索的实现,需要在 hybrid_search () 函数中创建多个 AnnSearchRequest 实例 来实现—— 每个实例对应一个向量字段的基础 ANN 搜索请求。因此,执行混合搜索前,必须为每个要用到的向量字段单独创建 AnnSearchRequest。

          此外,还可通过在 AnnSearchRequest 中配置 expr 参数,为混合搜索设置过滤条件(例如限定价格范围、地区等)。需要注意的是:混合搜索中,每个 AnnSearchRequest 仅支持传入一条查询数据。

          为了演示不同向量字段的搜索功能,我们将基于一个示例查询构建三个 AnnSearchRequest,过程中会使用预先计算好的稠密向量。这三个请求分别对应以下向量字段:text_dense用于语义文本搜索、text_sparse用于全文搜索或关键词匹配、image_dense用于多模态文本到图像的搜索。

            from pymilvus import AnnSearchRequest

            query_text = "white headphones, quiet and comfortable"

            query_dense_vector = generate_dense_vector(768)

            query_multimodal_vector = generate_dense_vector(512)

            # text semantic search (dense)

            search_param_1 = {

                "data": [query_dense_vector],

                "anns_field""text_dense",

                "param": {"nprobe": 10},

                "limit": 2

            }

            request_1 = AnnSearchRequest(**search_param_1)

            # full-text search (sparse)

            search_param_2 = {

                "data": [query_text],

                "anns_field""text_sparse",

                "param": {"drop_ratio_search": 0.2},

                "limit": 2

            }

            request_2 = AnnSearchRequest(**search_param_2)

            # text-to-image search (multimodal)

            search_param_3 = {

                "data": [query_multimodal_vector],

                "anns_field""image_dense",

                "param": {"nprobe": 10},

                "limit": 2

            }

            request_3 = AnnSearchRequest(**search_param_3)

            reqs = [request_1, request_2, request_3]


            由于参数 limit 设置为 2,每个 AnnSearchRequest 返回 2 个搜索结果。在这个例子中,创建了 3 个 AnnSearchRequest 实例,总共产生 6 个搜索结果。

            步骤 2:配置重排序策略

            为了合并和重新排序 ANN 搜索结果集,选择合适的重排序策略至关重要。提供多种重排序策略。

            在这个例子中,由于没有特别强调特定的搜索查询,我们将采用 RRFRanker 策略。

              ranker = Function(

                  name="rrf",

                  input_field_names=[], # Must be an empty list

                  function_type=FunctionType.RERANK,

                  params={

                      "reranker""rrf"

                      "k"100  # Optional

                  }

              )

              步骤 3:执行混合搜索


              在启动混合搜索之前,请确保已加载 Collection。如果 Collection 中的任何向量字段缺少索引或未加载到内存中,则在执行混合搜索方法时将发生错误。

                res = client.hybrid_search(

                    collection_name="my_collection",

                    reqs=reqs,

                    ranker=ranker,

                    limit=2

                )

                for hits in res:

                    print("TopK results:")

                    for hit in hits:

                        print(hit)


                (4)以下是输出内容:

                  ["['id: 1, distance: 0.006047376897186041, entity: {}', 'id: 2, distance: 0.006422005593776703, entity: {}']"]


                  在为混合搜索指定了 limit=2 参数的情况下 将对从三次搜索中获得的六个结果进行重新排序。最终,它们将只返回最相似的前两个结果。

                  阅读推荐

                  静态知识库过时了!Agent+Milvus:动态记忆与按需检索实战指南

                  1bit压缩+高召回,RaBitQ如何成为AI infra的embedding 量化最优解

                  多智能体系统中,如何用向量数据库共享上下文?OpenAgents x Milvus

                  Embedding相似度不是万金油,电商、 新闻场景如何按时效性做rerank

                  不再搞Chain 设计的LangChain 1.0,与LangGraph有哪些区别?

                  放弃ES+Mongo,如何用Milvus一套系统搞定千万用户视频检索*关键词

                  阅读原文

                  跳转微信打开

                  Fish AI Reader

                  Fish AI Reader

                  AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

                  FishAI

                  FishAI

                  鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

                  联系邮箱 441953276@qq.com

                  相关标签

                  多向量混合检索 Hybrid Search Milvus Zilliz Cloud 向量数据库 Vector Database 电商搜索 E-commerce Search 稀疏向量 Sparse Vectors 稠密向量 Dense Vectors 多模态检索 Multimodal Search BM25 RRFRanker
                  相关文章