跳到主要内容
版本:BYOC 开发指南

Full Text Search

在 Zilliz Cloud 中,Full Text Search 是对基于稠密向量的语义搜索的补充。它能够在大规模文本集合中查找包含特定术语或短语的文本,弥补语义搜索的遗漏,从而提升整体搜索效果。它支持直接插入和使用原始文本数据进行相似性搜索,Milvus 会自动将文本转换为稀疏向量表示。Full Text Search 使用 BM25 算法进行相关性评分,根据查询文本返回最相关的文档,从而提高文本搜索的整体精度。

该功能适用于需要精准术语匹配的相关性搜索场景,如电商中检索产品序列号、客户支持中的工单跟踪,以及法律或医学数据库中的特定术语查找。

📘说明

将 Full Text Search 与基于语义的稠密向量搜索结合使用,可以提升搜索结果的准确性和相关性。更多信息请参考 Hybrid Search

Zilliz Cloud 支持通过代码或通过 Web 控制台开启 Full Text Search 功能。本文着重介绍如何通过代码开启 Full Text Search,如需了解 Web 控制台操作,请参考管理 Collection (控制台)

概述

Full Text Search 简化了基于文本数据的搜索流程,无需您提前将数据转换为向量。其工作流程如下:

  1. 文本输入:直接插入原始文本文档或提供查询文本,无需手动生成向量。

  2. 分词:Milvus 使用分词器(Tokenizer)将输入文本分割成独立的、可搜索的词语。

  3. Function 处理:内置 Function 接收分词结果并将其转换为稀疏向量表示。

  4. Collection 存储:Milvus 将这些稀疏向量存储在 Collection 中,以便高效检索。

  5. BM25 评分:在搜索过程中,Milvus 使用 BM25 算法计算文档得分,并根据查询文本的相关性对匹配结果进行排序。

G4iFwPgJhhEpm5bvReYcmATWnAc

要使用 Full Text Search,主要有以下几个步骤:

  1. 创建 Collection:设置包含必要字段的 Collection,并定义一个将原始文本转换为稀疏向量的 Function。

  2. 插入数据:将原始文本文档导入 Collection。

  3. 执行搜索:使用查询文本搜索 Collection,并获取相关结果。

要启用 Full Text Search,需要创建一个包含特定 Schema 的 Collection。Schema 必须包含以下三个关键字段:

  • 主键字段:用于唯一标识 Collection 中的每个 Entity。

  • VARCHAR 字段:用于存储原始文本文档,并设置 enable_analyzer=True 以使 Milvus 能够对文本进行分词处理。

  • SPARSE_FLOAT_VECTOR 字段:用于存储稀疏向量,Milvus 会自动为 VARCHAR 字段生成这些向量。

定义 Collection Schema

首先,创建 Schema 并添加必要字段:

from pymilvus import MilvusClient, DataType, Function, FunctionType

client = MilvusClient(
uri="YOUR_CLUSTER_ENDPOINT",
token="YOUR_CLUSTER_TOKEN"
)

schema = client.create_schema()

schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True, auto_id=True)
schema.add_field(field_name="text", datatype=DataType.VARCHAR, max_length=1000, enable_analyzer=True)
schema.add_field(field_name="sparse", datatype=DataType.SPARSE_FLOAT_VECTOR)

在此配置中:

  • id:作为主键,并通过 auto_id=True 自动生成。

  • text:用于存储原始文本数据以进行 Full Text Search 操作。数据类型必须为 VARCHAR,因为这是 Zilliz Cloud 的文本存储类型。设置 enable_analyzer=True 以允许 Zilliz Cloud 对文本进行分词。默认情况下,Milvus 使用 default 分词器进行分词。如需配置其他分词器,请参考 Analyzer

  • sparse:向量字段,用于存储 Milvus 为文本数据生成的稀疏向量表示。数据类型必须为 SPARSE_FLOAT_VECTOR

然后,创建一个将文本转换为稀疏向量的 Function,并将其添加到 Schema 中:

bm25_function = Function(
name="text_bm25_emb", # Function name
input_field_names=["text"], # Name of the VARCHAR field containing raw text data
output_field_names=["sparse"], # Name of the SPARSE_FLOAT_VECTOR field reserved to store generated embeddings
function_type=FunctionType.BM25, # Set to `BM25`
)

schema.add_function(bm25_function)

参数

描述

name

Function 的名称。该 Function 将 text 字段中的原始文本转换为可搜索的向量,存储在 sparse 字段中。

input_field_names

需要进行文本到稀疏向量转换的 VARCHAR 字段名称。

output_field_names

用于存储 Milvus 内部自动生成的稀疏向量的字段名称。

function_type

使用的 Function 类型。设置为 FunctionType.BM25

📘说明

对于包含多个需要进行文本到稀疏向量转换的 VARCHAR 字段的 Collection,请为 Schema 添加单独的 Function,并确保每个 Function 具有唯一的名称和 output_field_names 值。

配置索引参数

在定义包含必要字段和内置 Function 的 Schema 后,需要为 Collection 设置向量索引以加速查询。本例中使用 AUTOINDEX 作为 index_type,表示让 Zilliz Cloud 根据数据结构自动选择和配置最适合的索引类型。

index_params = client.prepare_index_params()

index_params.add_index(
field_name="sparse",

index_type="AUTOINDEX",
metric_type="BM25"

)

参数

描述

field_name

要索引的向量字段名称。对于 Full Text Search,应设置为存储稀疏向量的字段,在本例中为 sparse

index_type

要创建的索引类型。AUTOINDEX 允许 Milvus 自动优化索引设置。如果需要更多控制,可以选择其他支持的索引类型。有关更多信息,请参考管理 Index

metric_type

设置为 BM25 以启用 Full Text Search 功能。

params

特定于索引的附加参数字典。

params.inverted_index_algo

用于构建和查询索引的算法。有效值:

  • "DAAT_MAXSCORE"(默认):使用最大得分(MaxScore)算法的优化文档逐次处理(DAAT)查询处理。MaxScore 通过跳过可能影响极小的词条和文档,为高 k 值或包含多个词条的查询提供更好的性能。它通过根据词条的最大影响得分将词条划分为关键和非关键组,专注于能够对前 k 个结果有贡献的词条来实现这一点。

  • "DAAT_WAND": 使用WAND算法优化的DAAT查询处理。WAND通过利用最大影响得分跳过非竞争性文档来评估更少的命中文档,但每次命中的开销较高。这使得WAND在k值较小的查询或短查询中更有效,因为在这些情况下跳过操作更可行。

  • "TAAT_NAIVE":基本的逐词(TAAT)查询处理。虽然与 DAAT_MAXSCOREDAAT_WAND 相比速度较慢,但 TAAT_NAIVE 具有独特优势。与 DAAT 算法不同,DAAT 算法使用缓存的最大影响分数,这些分数无论全局集合参数(avgdl)如何变化都保持不变,而 TAAT_NAIVE 会动态适应这些变化。

params.bm25_k1

控制词频饱和度。较高的值会增加词频在文档排名中的重要性。取值范围:[1.2, 2.0]。

params.bm25_b

控制文档长度归一化的程度。通常使用 0 到 1 之间的值,常见的默认值约为0.75。值为 1 表示不进行长度归一化,而值为 0 表示完全归一化。

创建 Collection

使用定义的 Schema 和索引参数创建 Collection:

client.create_collection(
collection_name='my_collection',
schema=schema,
index_params=index_params
)

插入文本数据

在设置好 Collection 和索引后,即可插入文本数据。只需提供原始文本,之前定义的内置 Function 会自动为每条文本生成对应的稀疏向量。

client.insert('my_collection', [
{'text': 'information retrieval is a field of study.'},
{'text': 'information retrieval focuses on finding relevant information in large datasets.'},
{'text': 'data mining and information retrieval overlap in research.'},
])

在向 Collection 插入数据后,可以使用原始查询文本执行 Full Text Search。Milvus 会自动将查询文本转换为稀疏向量,并使用 BM25 算法对匹配的搜索结果进行相关性排序。

search_params = {
'params': {'level': 10},
}

client.search(
collection_name='my_collection',
# highlight-start
data=['whats the focus of information retrieval?'],
anns_field='sparse',
output_fields=['text'], # Fields to return in search results; sparse field cannot be output
# highlight-end
limit=3,
search_params=search_params
)

参数

描述

search_params

包含搜索参数的字典。

搜索时忽略低频词的比例。详细信息请参考稀疏向量

params.level

使用简化的调优手段控制搜索精度。更多详情,可参考召回调优

data

原文查询文本。Zilliz Cloud 使用 BM25 函数自动将查询请求中的文本转换成对应的稀疏向量。因此,请勿提供预算的向量。

anns_field

用于存储 Milvus 内部自动生成的稀疏向量的向量字段名称。

output_fields

搜索结果中要返回的字段名列表。支持除包含 BM25 生成嵌入的稀疏向量字段之外的所有字段。常见的输出字段包括主键字段(例如 id )和原始文本字段(例如 text )。更多信息请参考 FAQ

limit

返回的匹配结果的最大数量。

常见问题

在全文搜索中,我能否输出或访问由 BM25 函数生成的稀疏向量?

不行。BM25 函数生成的稀疏向量在全文搜索中无法直接访问或输出。详情如下:

  • BM25 函数在内部生成稀疏向量,用于排序和检索

  • 这些向量存储在稀疏字段中,但不能包含在输出字段中

  • 你只能输出原始文本字段和元数据(如id、文本)

示例:

# ❌ This throws an error - you cannot output the sparse field
client.search(
collection_name='my_collection',
data=['query text'],
anns_field='sparse',
# highlight-next-line
output_fields=['text', 'sparse'] # 'sparse' causes an error
limit=3,
search_params=search_params
)

# ✅ This works - output text fields only
client.search(
collection_name='my_collection',
data=['query text'],
anns_field='sparse',
# highlight-next-line
output_fields=['text']
limit=3,
search_params=search_params
)

如果无法访问,为何还要定义稀疏向量字段呢?

稀疏向量字段作为内部搜索索引,类似于用户不会直接与之交互的数据库索引。

设计原理:

  • 关注点分离:你处理文本(输入/输出),Milvus处理矢量(内部处理)

  • 性能:预计算的稀疏矢量可在查询期间实现快速的BM25排序

  • 用户体验:将复杂的矢量运算抽象化,隐藏在简单的文本界面之后

如果您需要访问向量:

  • 使用预计算的稀疏向量代替全文搜索

  • 为自定义稀疏向量工作流创建单独的 Collection

详情请参考稀疏向量