在Milvus中使用DataType.BINARY_VECTOR执行汉明距离搜索的问题及data参数设置咨询
在Milvus中使用DataType.BINARY_VECTOR执行汉明距离搜索的问题及data参数设置咨询
看起来你在Milvus里用二进制向量做汉明距离搜索时,卡在了data参数的格式上,我来帮你分析并解决这个问题:
问题根源
Milvus的DataType.BINARY_VECTOR类型不直接支持np.bool_格式的布尔数组——它要求向量数据以字节流(bytes)或者uint8类型的numpy数组传入。这是因为二进制向量在Milvus底层是按字节打包存储的,每个字节对应8个二进制维度位,而你当前直接传入的布尔数组(每个元素占1位逻辑空间,但实际存储是按字节对齐的)不符合Milvus的存储/检索要求,这就是搜索失败的核心原因。
解决方案:统一向量格式为字节流
你需要把布尔数组转换成Milvus认可的二进制向量格式,这里推荐用numpy的packbits工具把布尔数组打包成字节流,具体操作如下:
1. 新增格式转换函数
先写一个工具函数,把布尔数组打包成符合要求的字节流:
def bool_array_to_binary_vector(bool_arr): # 确保输入是布尔类型的numpy数组 assert bool_arr.dtype == np.bool_ # 按8位一组打包成uint8数组,再转成字节流 return np.packbits(bool_arr).tobytes()
2. 修改插入数据的向量格式
插入数据时,用上面的函数处理vector字段:
# 修改后的插入数据代码 data = [ {'id': i, 'vector': bool_array_to_binary_vector(np.array([1] * DIM, dtype=DTYPE)), 'text': f'doc {i}'} for i in range(100) ] client.insert(collection_name=COLLECTION_NAME, data=data)
3. 修改搜索的查询向量格式
搜索时的查询向量也需要用同样的方式转换:
# 修改后的搜索代码 query_bool_vec = np.array([1] * DIM, dtype=DTYPE) query_vector = bool_array_to_binary_vector(query_bool_vec) search_params = { 'metric_type': METRIC_TYPE, 'params': {}, } result = client.search( collection_name=COLLECTION_NAME, data=[query_vector], # 传入打包后的字节流 limit=2, search_params=search_params, ) print(result)
额外注意点
- 你的维度
DIM=4096刚好是8的整数倍(4096/8=512字节),用packbits打包后不会有补位问题;如果维度不是8的整数倍,packbits会自动在末尾补0,Milvus会正确识别实际的维度数(你在schema里设置的dim=DIM),不会影响汉明距离的计算。 - 也可以直接用
np.uint8类型的数组作为向量(比如np.ones(512, dtype=np.uint8)对应4096位全1的向量),效果和字节流是一样的。
修改后的完整代码
把上面的修改整合到你的原代码中,完整可运行版本如下:
from pymilvus import MilvusClient, DataType from pathlib import Path import numpy as np DB_FILE = 'demo.db' DIM = 4096 COLLECTION_NAME = 'dim_reduction' METRIC_TYPE = 'HAMMING' INDEX_TYPE = 'BIN_FLAT' DATATYPE = DataType.BINARY_VECTOR DTYPE = np.bool_ # Remove DB_FILE if exists db_path = Path(DB_FILE) if db_path.exists(): db_path.unlink() # Build client client = MilvusClient(DB_FILE) # Create schema schema = MilvusClient.create_schema() schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True) schema.add_field(field_name='text', datatype=DataType.VARCHAR, max_length=1024) schema.add_field(field_name='vector', datatype=DATATYPE, dim=DIM) # Create collection client.create_collection( collection_name=COLLECTION_NAME, schema=schema, ) # 新增格式转换函数 def bool_array_to_binary_vector(bool_arr): assert bool_arr.dtype == np.bool_ return np.packbits(bool_arr).tobytes() # Insert data data = [ {'id': i, 'vector': bool_array_to_binary_vector(np.array([1] * DIM, dtype=DTYPE)), 'text': f'doc {i}'} for i in range(100) ] client.insert(collection_name=COLLECTION_NAME, data=data) # Create index index_params = MilvusClient.prepare_index_params() index_params.add_index( field_name='vector', metric_type=METRIC_TYPE, index_type=INDEX_TYPE, ) client.create_index( collection_name=COLLECTION_NAME, index_params=index_params, ) # Search query_bool_vec = np.array([1] * DIM, dtype=DTYPE) query_vector = bool_array_to_binary_vector(query_bool_vec) search_params = { 'metric_type': METRIC_TYPE, 'params': {}, } result = client.search( collection_name=COLLECTION_NAME, data=[query_vector], limit=2, search_params=search_params, ) print(result)
这样修改后,你的插入和搜索操作就能正常执行了,汉明距离的计算也会按预期工作。
备注:内容来源于stack exchange,提问作者tmandyai
相关产品推荐
相关产品推荐

