文本字段Compatible with Milvus 3.0.x
在 AI 搜索应用中,向量搜索可帮助您查找语义相似的实体,但应用通常还需要每个匹配结果背后的原始源文本。大型语言模型(LLM)或 Agents 可以利用该文本作为上下文,用于阅读、引用、摘要,或将结果纳入提示词中。
Milvus 提供了TEXT 标量字段类型,用于将长源文本直接与实体关联存储。典型值包括段落、长文档、文章正文、工单和日志。与VARCHAR 不同,后者要求设置固定的max_length ,而TEXT 则无需在 Collection Schema 中设置最大字节长度。
要定义TEXT 字段,请将datatype 设置为DataType.TEXT 。
此功能需要 Storage V3。有关启用说明和兼容性注意事项,请参阅Storage V3。
common.storage.useLoonFFI 默认值为 `false`,这意味着 Storage V3 默认处于禁用状态。在创建包含 `TEXT ` 字段的 Collection 之前,请将此参数设置为 `true`;否则,Milvus 将拒绝该 Collection Schema。
schema.add_field(
field_name="content",
datatype=DataType.TEXT,
)
定义字段后,每个实体都可以在该字段中包含一个字符串值。您可以像处理其他标量字段一样插入TEXT 值,并通过在output_fields 中列出该字段,从查询或搜索结果中返回这些值。
TEXT 字段支持空值。要启用此功能,请将nullable 设置为True 。有关详细信息,请参阅“可为空字段”。
限制
TEXT字段不能作为主字段、Partition Key或聚簇键。TEXT不能用作ARRAY字段的元素类型,包括StructArray中的标量子字段。- 在 Milvus 3.0.0 中,
TEXT字段不支持默认值。 - 在 Milvus 3.0.0 中,外部 Collection 不支持 `
TEXT` 字段。 - 用户无法在
TEXT字段上创建标量索引。当enable_match=True时,Milvus 会构建一个由系统管理的文本索引,用于文本匹配。此内部索引并非用户创建的标量索引。 - 一般的标量过滤操作符无法直接应用于 `
TEXT` 字段。 这些包括比较操作符(如==和!=)、范围操作符(如>、>=、<和<=),以及IN、LIKE、正则表达式操作符(=~和!~)和IS NULL或IS NOT NULL。若要按分析后的术语进行过滤,请使用enable_analyzer=True和enable_match=True定义字段,并使用TEXT_MATCH或TEXT_MATCH_FUZZY。对于按相关性排序的全文检索,请使用 BM25。 - 在 Milvus 3.0.0 中,若要使用以
TEXT字段作为输入的 BM25 或 MinHash 函数,必须在创建 Collection 时进行定义。即使现有 Collection 为空,也无法通过add_function_field或AlterCollectionSchema在后续添加该函数,因为 Milvus 无法根据存储的TEXT值回填该函数的输出结果。 若要将此类函数添加到现有Collection中,请使用VARCHAR输入字段,或在重新创建Collection时将其包含在Schema中。有关添加函数及其生成的向量字段的详细信息,请参阅“修改Collection Schema”。 - 文本嵌入函数也必须在创建 Collection 时定义。Milvus 3.0.0 不支持在运行时添加这些函数。
选择 TEXT 或 VARCHAR
TEXT 和VARCHAR 均用于存储字符串值,但它们支持不同的应用需求。请使用VARCHAR 来存储用于识别、分类或过滤实体的简短、有限元数据。请使用TEXT 来存储较长的源内容,以便为大型语言模型(LLM)或Agents提供足够的上下文,用于阅读、引用、摘要或构建提示词。
| 方面 | VARCHAR | TEXT |
|---|---|---|
| 最适合 | 用于识别、分类或筛选实体的短元数据,例如title 、tag 、category 或external_id 。 | 用于 LLM 或 Agents 工作流的较长源内容,例如content 、passage 、article_body 或log_message 。 |
| 长度设置 | 需要max_length ,该字段定义了该字段可存储的最大字节数。最大值为65,535 字节。如果值可能超过此限制,请使用TEXT 。 | 不要求max_length ,因此Schema无需为文本值设定固定的字节限制。 |
| 存储行为 | 将每个值存储在字段配置的max_length 内。 | 对于较大的文本值,将使用自动存储选择机制。有关详细信息,请参阅《Milvus 如何存储大型 TEXT 值》。 |
| 主字段支持 | 可作为主字段使用。 | 不能用作主字段。 |
| 过滤 | 适用于需要出现在过滤表达式中的短字符串元数据,例如category == "news" 或tag in ["ai", "database"] 。 | 不支持一般的标量过滤操作符。请使用支持匹配的文本操作符进行分析术语过滤,或使用 BM25 进行相关性排序的全文检索。 |
有关VARCHAR 字段的详细信息,请参阅“VarChar 字段”。
Milvus 如何存储大型 TEXT 值
当您插入一个实体时,您为TEXT 字段提供的字符串即为TEXT 值。Milvus 会将该值的大小与dataNode.text.inlineThreshold 进行比较(默认值为65,536 字节),然后选择两种内部存储路径中的一种。
大文本存储
- 内联存储:如果
TEXT值小于dataNode.text.inlineThreshold,Milvus 会将原始文本值直接存储在TEXT字段 data 中。 - LOB 存储:如果 `
TEXT` 的值大于或等于 `dataNode.text.inlineThreshold`,Milvus 会将该值视为大对象,并将原始文本单独存储在对象存储(如 MinIO)中。`TEXT` 字段数据中存储的是指向该单独存储文本的内部引用。当在查询或搜索结果中请求 `TEXT` 字段时,Milvus 会使用该引用检索并返回原始文本。
此存储选择属于内部机制。无论 Milvus 使用何种存储路径,您对TEXT 字段的插入、查询和搜索操作方式均保持一致。若需调整阈值或相关存储、压缩及垃圾回收行为,请参阅与dataNode 相关的配置和 与 dataCoord 相关的配置。
如果您的部署使用对象存储,较大的 `TEXT ` 值可能会以 Milvus 管理的对象形式出现在诸如lobs/... 之类的路径下。这些对象属于实现细节,不应手动移动、复制或删除。 在删除实体、删除分区或压缩数据后,只有当 Milvus 垃圾回收在安全窗口期结束后移除了未被引用的巨型对象数据,对象存储的使用量才会减少。
TEXT 的常见用途是配合 BM25 进行全文搜索。在此模式下,TEXT 字段存储原始源内容,BM25 分析文本并生成稀疏向量,用于对基于关键词的匹配结果进行排序。搜索结果随后可返回匹配的TEXT 值,作为 LLM 或 Agents 工作流的上下文。 以下示例演示了如何将TEXT 字段用作BM25的输入字段。如需了解全文搜索的概念和查询选项,请参阅《全文搜索》。
步骤 1:创建包含 TEXT 字段的 Collection
以下示例创建了一个Collection,其中包含用于源内容的TEXT 字段,以及用于存储BM25生成的稀疏向量向量字段。BM25函数将content 中的分词文本转换为稀疏向量向量,并将其存储在sparse 中。
对于 BM25 全文搜索,输入的TEXT 字段必须设置为enable_analyzer=True 。
from pymilvus import DataType, Function, FunctionType, MilvusClient
client = MilvusClient(uri="http://localhost:19530")
COLLECTION_NAME = "text_bm25_collection"
if client.has_collection(COLLECTION_NAME):
client.drop_collection(COLLECTION_NAME)
schema = client.create_schema(auto_id=False, enable_dynamic_field=False)
schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True)
schema.add_field(
field_name="content",
datatype=DataType.TEXT,
enable_analyzer=True,
)
schema.add_field(field_name="sparse", datatype=DataType.SPARSE_FLOAT_VECTOR)
bm25_function = Function(
name="content_bm25",
input_field_names=["content"],
output_field_names=["sparse"],
function_type=FunctionType.BM25,
)
schema.add_function(bm25_function)
步骤 2:创建稀疏向量索引
在由 BM25 函数生成的稀疏向量字段上创建索引。度量类型必须设置为BM25 。
index_params = client.prepare_index_params()
index_params.add_index(
field_name="sparse",
index_type="SPARSE_INVERTED_INDEX",
metric_type="BM25",
params={
"inverted_index_algo": "DAAT_MAXSCORE",
"bm25_k1": 1.2,
"bm25_b": 0.75,
},
)
client.create_collection(
collection_name=COLLECTION_NAME,
schema=schema,
index_params=index_params,
)
步骤 3:插入 TEXT 数据
将文本直接插入TEXT 字段。请勿为sparse 字段提供值。Milvus会通过将BM25函数应用于content ,在内部生成稀疏向量。
data = [
{
"id": 1,
"content": "Milvus stores vector embeddings and scalar fields in collections. It supports vector search, full text search, and metadata filtering for retrieval applications.",
},
{
"id": 2,
"content": "Long documents are often split into passages before embedding. Store each passage in a TEXT field so search results can return the source text.",
},
{
"id": 3,
"content": "Operational logs and support tickets often contain long natural-language text. TEXT fields can store these values without a fixed max_length setting.",
},
]
client.insert(collection_name=COLLECTION_NAME, data=data)
client.load_collection(collection_name=COLLECTION_NAME)
步骤 4:执行 BM25 全文检索
使用原始查询文本作为搜索数据,并对稀疏向量字段进行搜索。Milvus会将查询文本转换为稀疏向量,使用BM25算法对匹配结果进行排序,并将请求的TEXT 字段结果返回至output_fields 字段中。
results = client.search(
collection_name=COLLECTION_NAME,
data=["how does Milvus store source text for retrieval"],
anns_field="sparse",
limit=2,
output_fields=["content"],
)
步骤 5:读取返回的 TEXT 值
每个搜索命中结果都包含 BM25 得分和原始的TEXT 值。
for hit in results[0]:
print(f"id: {hit['id']}, score: {hit['distance']}")
print(hit["entity"]["content"])
有关 BM25 函数、稀疏向量索引以及全文搜索查询语法的更多信息,请参阅《全文搜索》。