MinHash 函数Compatible with Milvus 3.0.x
MinHash 函数将原始文本转换为二进制向量,这些向量可近似表示文档之间的雅卡德相似度。该函数通过文本分块和多种哈希函数,生成固定长度的签名向量,从而实现快速近似重复检测和大规模文档去重。
作为内置函数,MinHash 在 Milvus 内部运行,无需外部模型推理或预处理。您只需输入原始文本,Milvus 便会自动生成 MinHash 签名向量。
限制
输出字段必须为
BINARY_VECTOR,且其维度需满足dim % 32 == 0,因为每个MinHash签名都是一个32位哈希值。二进制向量字段的
dim必须等于32 * num_hashes。若不匹配,将引发错误。当使用
MINHASH_LSH索引与MinHash函数的输出时,mh_element_bit_width必须设置为32。
MinHash的工作原理
MinHash是一种局部敏感哈希技术,用于估算集合之间的雅卡德相似度。在 Milvus 中,MinHash 函数遵循以下处理流程:您提供原始文本作为输入,Milvus 生成二进制向量作为输出——所有中间步骤均由系统内部处理。
整体工作流由文档摄入和查询处理共用的文本处理管道组成,随后是针对存储和检索阶段的特定操作。
Iaqkbfeh8oqggsx6nsocfosondo
共享文本处理管道
无论是文档摄入还是查询处理,都会将原始文本经过相同的四阶段转换:
文本分析:文本由分析器处理(当
token_level为"word"时),或直接使用(当token_level为"char"时)。词级分词会应用在输入字段上配置的分析器,将文本分割为术语——例如,"milvus is vector db"将变为["milvus", "is", "vector", "db"]。分片:将分词结果拆分为大小为
shingle_size的重叠 n-gram(分片)。例如,在词级使用 3-gram 时,分词结果["information", "retrieval", "is", "a", "field"]将被拆分为类似["information retrieval is", "retrieval is a", "is a field"]的分片。MinHash签名生成:对瓦片集应用多个哈希函数(H1、H2、…、Hn,其中n =
num_hashes)。 对于每个哈希函数,选取所有片段中的最小哈希值。这些最小值的 Collection 构成了 MinHash 签名——一种固定长度的表示形式,近似反映了原始文档的雅卡德相似度。二进制向量编码:每个签名值是一个 32 位哈希值,完整的签名被打包到一个维度为
32 * num_hashes的BINARY_VECTOR中。
文档摄入
在插入过程中,由共享管道生成的二进制向量会被存储在MINHASH_LSH 索引中。该索引维护着一个LSH(局部敏感哈希)表,将相似的签名分组到相同的桶中,从而在查询时能够快速检索候选结果。
查询处理
在搜索过程中,查询文本会经过相同的共享管道以生成二进制向量。该向量用于在MINHASH_LSH 索引中执行LSH查找,从而快速识别出可能相似的候选对。若未启用Jaccard精化,Milvus返回的LSH候选结果不会按估计的Jaccard相似度进行排序。 当启用雅卡德(Jaccard)精化时,Milvus 会利用存储的原始 MinHash 签名,根据估计的雅卡德相似度对候选结果进行排序,并返回前 K 个结果。
由于这两种路径共享相同的转换逻辑,内容高度重叠的两份文档会产生相似的 MinHash 签名。这使得该功能即使在文档的词序、格式或细微措辞存在差异时,也能有效查找近似重复文档。
开始之前
在使用 MinHash 功能之前,请规划您的 Collection Schema,确保包含以下内容:
用于存储原始内容的文本字段
您的Collection必须包含一个
VARCHAR字段来存储原始文本。该字段将作为MinHash函数的输入。文本字段的分析器(当使用词级分词时)
如果 `
token_level` 设置为 `"word"`(默认值),则文本字段必须启用分析器。分析器定义了在分片处理之前如何对文本进行分词。默认情况下,Milvus 使用 `standard` 分析器。若要配置其他分析器,请参阅《根据用例选择合适的分析器》。用于 MinHash 输出的二进制向量字段
您的Collection必须包含一个
BINARY_VECTOR字段,用于存储由MinHash函数生成的二进制向量。该维度的值必须等于32 * num_hashes。
步骤 1:创建包含 MinHash 函数的 Collection
要使用 MinHash 函数,请在创建 Collection 时对其进行定义。该函数将成为 Collection Schema 的部分,并在数据插入和搜索过程中自动应用。
定义Schema字段
您的Collection Schema必须包含至少三个字段:
主字段:用于唯一标识Collection中的每个实体。
文本字段(
VARCHAR):用于存储原始文本文档。请将enable_analyzer=True设置为启用,以便 Milvus 能对文本进行处理以生成 MinHash 签名。默认情况下,Milvus 使用standard分析器进行文本分析。若要配置其他分析器,请参阅《根据用例选择合适的分析器》。二进制向量字段(
BINARY_VECTOR):用于存储由 MinHash 函数自动生成的二进制向量。其维度必须与32 * num_hashes相同。
from pymilvus import MilvusClient, DataType, Function, FunctionType
client = MilvusClient(uri="http://localhost:19530", token="root:Milvus")
schema = client.create_schema()
schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True, auto_id=True)
schema.add_field(field_name="document_content", datatype=DataType.VARCHAR, max_length=9000, enable_analyzer=True)
schema.add_field(field_name="binary_vector", datatype=DataType.BINARY_VECTOR, dim=8192)
// java
// nodejs
// go
# restful
定义 MinHash 函数
MinHash 函数将分析后的文本转换为二进制向量,这些向量可近似表示文档之间的雅卡德相似度。
定义该函数并将其添加到您的Schema中:
minhash_function = Function(
name="minhash_function",
input_field_names=["document_content"], # Name of the VARCHAR field containing raw text
output_field_names=["binary_vector"], # Name of the BINARY_VECTOR field for generated signatures
function_type=FunctionType.MINHASH,
params={
"num_hashes": 256, # Number of hash functions; produces dim = 32 * 256 = 8192
"shingle_size": 3, # N-gram size for shingling
}
)
schema.add_function(minhash_function)
// java
// nodejs
// go
# restful
配置选项
MinHash 函数的 `params ` 字典支持以下参数。所有参数名称均不区分大小写。
参数 |
类型 |
默认值 |
描述 |
|---|---|---|---|
|
int |
源自 |
用于签名生成的哈希函数数量。输出二进制向量的维度等于 |
|
int |
|
用于分段处理的N-gram大小。词级:通常为1-3。字符级:通常为2-6。 |
|
str |
|
要使用的哈希函数。选项:
|
|
str |
|
分词级别。选项:
|
|
int |
|
用于初始化 MinHash 函数的随机种子。 |
配置索引
MinHash 二进制向量的推荐索引类型为MINHASH_LSH ,度量类型为MHJACCARD 。
index_params = client.prepare_index_params()
index_params.add_index(
field_name="binary_vector",
index_type="MINHASH_LSH",
metric_type="MHJACCARD",
params={
"mh_lsh_band": 128,
"mh_element_bit_width": 32,
"with_raw_data": True,
},
)
// java
// nodejs
// go
# restful
如果搜索将使用雅卡德(Jaccard)精化,请将with_raw_data 设置为True 。计算LSH查找返回的候选项的估计雅卡德相似度时,需要原始的MinHash签名。
创建Collection
使用上述定义的Schema和索引参数创建Collection:
client.create_collection(
collection_name="dedup_collection",
schema=schema,
index_params=index_params,
)
// java
// nodejs
// go
# restful
步骤 2:插入文档
设置好 Collection 后,插入文本数据。您只需提供原始文本——MinHash 函数会自动为每份文档生成二进制向量。
client.insert(
"dedup_collection",
[
{"document_content": "information retrieval is a field of study that helps users find relevant information in large datasets"},
{"document_content": "information retrieval is a research field focused on helping users find relevant data in large collections"},
{"document_content": "information retrieval is a field of research helping users search for relevant information in large datasets"},
],
)
// java
// nodejs
// go
# restful
步骤 3:使用 MinHash 进行搜索
插入数据后,通过提供原始文本查询来搜索近似重复的文档。Milvus 会自动将每个查询转换为 MinHash 二进制向量。启用 Jaccard 精炼功能,即可根据估计的 Jaccard 相似度对 LSH 候选结果进行排序。
search_params = {
"metric_type": "MHJACCARD",
"params": {
"mh_search_with_jaccard": True,
"refine_k": 3,
},
}
results = client.search(
collection_name="dedup_collection",
data=["information retrieval is a research field focused on helping users find relevant data in large collections"],
anns_field="binary_vector",
limit=3,
output_fields=["document_content"],
search_params=search_params,
)
for hits in results:
for hit in hits:
print(f"ID: {hit['id']}, Distance: {hit['distance']}")
print(f"Document: {hit['entity']['document_content']}")
// java
// nodejs
// go
# restful
将mh_search_with_jaccard 设置为True 以启用Jaccard精化。refine_k 控制用于精化的候选集容量。Milvus默认使用max(refine_k, limit) 作为容量,但如果LSH查找返回的匹配结果较少,则可能精化较少的候选项。增加refine_k 可以提高结果质量,但会增加计算开销。
下一步
全文搜索:使用 BM25 进行词汇相关性排序,而非近似重复检测。
分析器概述:配置自定义分析器以进行文本分词。
MINHASH_LSH 索引:了解如何调整 LSH 参数以优化召回率和性能。