Advertisement

《向量数据库指南》——Milvus Cloud以向量为特色的全文检索功能

阅读量:

以向量为特色的全文检索功能

以典型的 RAG 场景为例,尽管语义搜索可以有更好的上下文感知和意图理解,但当用户的问题需要搜索具体的专有名词、序列号,又或者完全匹配一个短语时,具有关键词匹配能力的全文检索往往可以拿到更准确的结果。为了支持社区中对于全文检索的需求,Milvus 在 2.4 版本推出稀疏向量功能的时候,采用了额外的 pymilvus model library 中的 BM25 模块来进行文本稀疏向量的生成。然而这种外挂的实现也带来了只能单机使用,词表等参数无法动态更新以及管理困难等一系列痛点,而 Milvus 2.5 的全文检索将一次性解决这些问题。

Milvus 2.5 通过内置 Sparse-BM25 的方式对全文检索的核心组件进行了原生支持,具体包括:

基于 tantivy 构建的分词器 :我们选择融入 tantivy 蓬勃发展的生态

原始文档的进出能力 :支持直接插入和查询文本数据

BM25 相关性打分: 基于 sparse vector 相似度来实现

首先,值得注意的是分词器的部分,对于有搜索引擎经验的用户来说其重要程度不言而喻,我们选择融入了发展良好的 tantivy 生态,基于 tantivy 构建了我们分词器的基础功能,而未来除了更多分词功能的支持和可观测性的优化之外,我们会探索基于深度学习的 tokenizer 和 stemmer 策略来进一步优化全文检索的表现。以下是在 Milvus 2.5 中使用和配置分词器的示例代码:

复制代码
 # 分词器配置

    
 schema.add_field(
    
     field_name='text', 
    
     datatype=DataType.VARCHAR, 
    
     max_length=65535, 
    
     enable_analyzer=True, # 在该列上开启分词器
    
     analyzer_params={"type": "english"},  # 配置分词器参数,此处选择 english 模版,此外也支持细粒度配置
    
     enable_match=True, # 构建针对 Text_Match 的倒排索引
    
 )
    
  
    
  
    
  
    
    
    
    

其次,在原始文档的处理方面,我们通过全文检索功能打开了这块的能力,用户所需要配置的是预定义在 schema 里,通过 add_function 方法新增一个从原始数据到 sparse vector 的 mapping 步骤,而这之后的增删改查等数据流都可以通过操作原始文档来完成,内部我们将其形象地称之为“Doc in Doc out”。而这只是在 2.5 迈出的第一步,在后续的大版本中,我们将对 dense/sparse embedding 新增 Data in Data out 的全面支持,我们的目标是构建非结构化数据与向量的映射来完成数据进出 Milvus 的能力。

复制代码
 # 在 schema 上定义好原始文本数据与向量的映射关系

    
 bm25_function = Function(
    
     name="text_bm25_emb",
    
     input_field_names=["text"], # 输入的文本字段
    
     output_field_names=["sparse"], # 内部映射的 sparse 向量字段
    
     function_type=FunctionType.BM25, # 处理映射关系的模型
    
 )
    
  
    
 schema.add_function(bm25_function) 
    
 ...
    
 # 支持原始文本进出
    
 MilvusClient.insert('demo', [
    
     {'text': 'Artificial intelligence was founded as an academic discipline in 1956.'},
    
     {'text': 'Alan Turing was the first person to conduct substantial research in AI.'},
    
     {'text': 'Born in Maida Vale, London, Turing was raised in southern England.'},
    
 ])
    
  
    
 MilvusClient.search(
    
     collection_name='demo', 
    
     data=['Who started AI research?'],
    
     anns_field='sparse',
    
     limit=3
    
 )
    
  
    
  
    
  
    
    
    
    

而在 BM25 相关性打分方面,我们采用了独特的 sparse vector 方案来做底层的实现,进而能充分利用 sparse vector 的优势,包括但不限于:

对长上下文 Query 可以构建图索引来加速搜索;

基于量化和 WAND 的 drop_ratio 等技术手段做近似匹配来提升性能;

更重要的是对于 Milvus 本身的产品而言,统一了语义检索和全文检索的表达方式,使用体验以及技术优化。

复制代码
        1. # 创建 sparse 列上的索引

    
        2. index_params.add_index(
    
        3.     field_name="sparse",
    
        4.     index_type="AUTOINDEX",  # 默认 WAND 索引
    
        5.     metric_type="BM25" # 通过 metric_type 配置相关性打分
    
        6. )
    
        7.  
    
        8. # search 时可配置参数来加速搜索
    
        9. search_params = {
    
        10.     'params': {'drop_ratio_search': 0.6}, # WAND 的搜索参数配置可加速搜索
    
        11.     }
    
        12.  
    
        13.  
    
        14.  
    

作为原生的向量数据库,Milvus 引入全文检索功能对基于 dense vector 的搜索能力进行了扩展,方便了用户构建更高质量的 AI 应用。在 Sparse-BM25 方面我们无疑是个探索者,但可以预见的是还有更多的优化手段能在未来尝试,相信这条路上将有更多旖旎风光可以分享给大家。

与全文检索同时推出的还有 Text Match 功能,该功能同样构建在分词的基础之上,通过 enable_match=True
开启。与全文检索不同的是它着重于关键词匹配,省去了文段相关性打分的能力,因此它的使用场景主要在匹配和过滤。需要注意的是 Text Match 中的 Query Text 的处理是分词后 OR 的逻辑,例如在下面的例子中,结果将返回 text 字段上含有 vector 或者 database 的所有文档。

复制代码
        1. filter = "TEXT_MATCH(text, 'vector database')"

    
        2.  
    
        3.  
    
        4.  
    

如果您的场景需要既匹配 vector 又匹配 database,那么您需要写两个单独的 Text Match 并叠加 AND 的方式以达成目的。

复制代码
        1. filter = "TEXT_MATCH(text, 'vector') and TEXT_MATCH(text, 'database')"

    
        2.  
    
        3.  
    
        4.  
    

全部评论 (0)

还没有任何评论哟~