Milvus中如何实现全文检索(Full Text Seach)?

在前两篇文章中(Milvus python库 pymilvus 常用操作详解之Collection(上)Milvus python库 pymilvus 常用操作详解之Collection(下)),我们了解了Milvus基于dense vector和sparse vector实现的混合向量检索,这篇文章让我们着重了解一下基于sparse vector的检索,即全文检索。

何为全文检索?

以下来自 milvus 官方文档原文:

Full text search is a feature that retrieves documents containing specific terms or phrases in text datasets, then ranking the results based on relevance. This feature overcomes semantic search limitations, which might overlook precise terms, ensuring you receive the most accurate and contextually relevant results. Additionally, it simplifies vector searches by accepting raw text input, automatically converting your text data into sparse embeddings without the need to manually generate vector embeddings.

全文搜索是一种功能,可以在文本数据集中检索包含特定术语或短语的文档,并根据相关性对结果进行排序。该功能克服了语义搜索的限制,语义搜索可能会忽略精确的术语,而全文搜索则确保您获得最准确且在语境上相关的结果。此外,它通过接受原始文本输入来简化向量搜索,自动将您的文本数据转换为稀疏嵌入,而无需手动生成向量嵌入。(ChatGPT-4o翻译)

简而言之,全文检索是一种基于精准关键词匹配的检索方式,相较于基于深度学习生成的向量检索(适合语义匹配检索场景),全文检索在需要基于精确关键词进行匹配的检索场景下表现更佳。当然各取其长将两者结合起来实现混合检索也是非常建议的选择。(感兴趣可以前往 BGE-M3模型结合Milvus向量数据库强强联合实现混合检索

全文检索的流程

Milvus 将实现全文检索一共分为了五个大的流程:

  1. 文本输入:无需人工将原始文本进行向量化处理,我们只需要提供被检索的内容或用户询问文本;
  2. 文本分析;Milvus 使用分析器将输入文本分解成单个的可搜索词条;
  3. 函数处理:内置函数接收已分词的词条,并将其转换为稀疏向量表示;
  4. 集合存储:Milvus 将这些稀疏嵌入存储在一个集合中,以便高效检索;
  5. BM25 评分:在检索时,Milvus 应用 BM25 算法计算查询文本和存储文档的相关性得分,并对匹配结果进行排序。

代码实现

主要分为三个步骤:

  1. 创建集合:设置一个具有必要字段的集合,并定义一个函数将原始文本转换为稀疏向量;

  2. 插入数据:将原始文本文档和生成的稀疏向量表达导入集合;

  3. 执行搜索:使用查询文本搜索集合并得到检索相关结果。

如果希望基于 BM25算法,则参考官方文档代码示例。

一、创建集合

  1. 定义字段模式(分别用于主键、原始文本和稀疏向量的存储):
python 复制代码
text_fields = [
    FieldSchema(name="id", dtype=DataType.INT64,
                is_primary=True, auto_id=True),
    FieldSchema(name="text", dtype=DataType.VARCHAR, max_length=512),
    FieldSchema(name="sparse_vector", dtype=DataType.SPARSE_FLOAT_VECTOR)
]
  1. 定义集合模式并创建集合:
python 复制代码
text_schema = CollectionSchema(text_fields, "")
# Now we can create the new collection with above name and schema.
col = Collection('text_search_demo', 
                 text_schema, 
                 consistency_level="Strong")
  1. 函数准备:

这里使用 bge-m3 模型实现将原始文本转化为稀疏向量的表达。

python 复制代码
from FlagEmbedding import BGEM3FlagModel

model_dir = "bge-m3"
model = BGEM3FlagModel(model_dir) 

def get_docs_embeddings(docs):
    passage_embeddings = model.encode(
    docs, 
    return_dense=False, 
    return_sparse=True, 
    return_colbert_vecs=False)
    docs_embeddings = {}
    docs_embeddings["sparse"] = passage_embeddings["lexical_weights"]
    return docs_embeddings
  1. 将检索文本和被检索的文档内容进行向量化:
python 复制代码
# 文档列表向量化
docs = [
    "提供黄金品种查询服务,支持黄金现货、黄金期货等品种查询;提供黄金价格查询服务,支持查询最新价、开盘价、最高价、最低价等价格信息。",
    "根据股票编号查询股票信息,包括涨跌额、股票名称、开盘价、收盘价、当前价格、最高最低价、竞买价等信息;支持沪深、香港、美国三个市场的股票数据查询,覆盖全球各地的股票信息。",
    "提供最新的新闻头条信息,包括国内、国际、体育、娱乐、科技等各类资讯,让用户获取及时的新闻报道;支持按照不同的新闻分类进行查询,用户可以选择感兴趣的领域,如体育、科技、娱乐等,获取相关的新闻内容。"
]
docs_embeddings = get_docs_embeddings(docs)

# 查询文本向量化
query = "请问股票代码为TSLA的美股今日走势如何?"
query_embeddings = get_query_embeddings(query)

二、插入数据

  1. 将原始文本和稀疏向量插入创建好的集合:
python 复制代码
entities = [docs, docs_embeddings["sparse"]]
col.insert(entities)
  1. 为名为"sparse_vector"的稀疏向量字段创建索引:
python 复制代码
sparse_index = {"index_type": "AUTOINDEX", 
                "metric_type": "BM25"}
col.create_index("sparse_vector", sparse_index)

三、执行检索

类似于混合检索的实现,我们也是调用集合的 hybrid_search() 函数:

  1. 设置top k,使用最大近似近邻检索:
python 复制代码
k = 1 # we want to get the top 1 docs closest to the query
# Prepare the search requests for both vector fields
sparse_search_params = {"metric_type": "IP"}
sparse_req = AnnSearchRequest(query_embeddings["sparse"],
                          "sparse_vector", sparse_search_params, limit=k)
  1. 调用 hybrid_search() 函数,获取rerank即重排序后的检索结果:
python 复制代码
res = col.hybrid_search([sparse_req], rerank=RRFRanker(),
                            limit=k, output_fields=['text'])
  1. 查看检索结果:
python 复制代码
print(res)

data: ['["id: 454487605193942682, distance: 0.016393441706895828, entity: {\'text\': \'根据股票编号查询股票信息,包括涨跌额、股票名称、开盘价、收盘价、当前价格、最高最低价、竞买价等信息;支持沪深、香港、美国三个市场的股票数据查询,覆盖全球各地的股票信息。\'}"]'], cost: 0
相关推荐
幻云20106 小时前
Python深度学习:从筑基到登仙
前端·javascript·vue.js·人工智能·python
仰望星空@脚踏实地6 小时前
本地Python脚本是否存在命令注入风险
python·datakit·命令注入
LOnghas12117 小时前
果园环境中道路与树木结构检测的YOLO11-Faster语义分割方法
python
2501_944526429 小时前
Flutter for OpenHarmony 万能游戏库App实战 - 蜘蛛纸牌游戏实现
android·java·python·flutter·游戏
飞Link9 小时前
【Django】Django的静态文件相关配置与操作
后端·python·django
Ulyanov10 小时前
从桌面到云端:构建Web三维战场指挥系统
开发语言·前端·python·tkinter·pyvista·gui开发
CCPC不拿奖不改名11 小时前
两种完整的 Git 分支协作流程
大数据·人工智能·git·python·elasticsearch·搜索引擎·自然语言处理
a努力。11 小时前
字节Java面试被问:TCP的BBR拥塞控制算法原理
java·开发语言·python·tcp/ip·elasticsearch·面试·职场和发展
费弗里11 小时前
一个小技巧轻松提升Dash应用debug效率
python·dash
小小测试开发11 小时前
Python浮点型常用方法全解析:从基础到实战
python