跳到主要内容
版本:v3.0.x

FAISS

FAISS Index 类型是 Milvus 3.0.0 及更高版本提供的专家级透传接口。你可以通过该类型提供 Faiss index-factory string,而无需选择固定的 Milvus Index 类型。

如果你已经有经过测试的 Faiss 方案,并且需要直接控制其组成,请使用 FAISS。对于 Milvus 已提供专用 Index 类型的常用方案,建议优先使用专用类型,因为这类类型具有稳定且有明确文档说明的参数约定。

上游 Faiss 接受的 factory string 并不一定受 Milvus 支持。兼容性取决于向量字段类型、metric、维度、Milvus 镜像中编译的 Faiss 模块,以及生成的 Index 是否支持 Milvus 所需的操作。

Limits

  • FAISS 支持 FLOAT_VECTORBINARY_VECTOR 字段,但不支持 FLOAT16_VECTORBFLOAT16_VECTORINT8_VECTORSPARSE_FLOAT_VECTOR 字段。

  • 通用 FAISS 适配器在 CPU 上运行,并非 Faiss GPU Index 类型。

  • 必须指定构建参数 faiss_index_name。Milvus 会将其值直接传递给 Faiss,而不会将该索引配置转换为 Milvus 的专用 Index 类型。

  • 构建参数和检索参数因 factory 而异。某个 factory 支持的参数可能会被另一个 factory 拒绝。

  • 标量 Filter 要求底层 Faiss Index 支持 ID selector。Milvus 3.0.0 已测试对浮点 factory FlatIVF64,FlatHNSW16,Flat 执行带 Filter 的检索。不要假定所有 factory 都支持 Filter,也不要假定二进制 FAISS Index 支持标量 Filter。

  • 不支持 Search Iterator。

  • 该适配器不支持检索原始向量。

  • Range Search 支持情况取决于 factory。浮点 Flat 已通过发布测试。不要对二进制 FAISS Index 使用 Range Search。

  • factory 可能成功完成构建,但仍会拒绝某些 Milvus 检索操作。例如,独立的 PQ8x4 会拒绝标量 Filter 检索使用的 selector。请单独验证不带 Filter 的使用场景。

  • 在 Milvus 3.0.0 中,Index 重新 Load 后,请验证 COSINE 分数和 Range Search 阈值。Knowhere v3.0.6 在反序列化期间不会恢复 FAISS 适配器的余弦归一化状态。

How it works

FAISS Index 透传工作流

构建 Index 时,Milvus 会将 faiss_index_name、向量字段类型、metric 以及其他构建参数转发给 Knowhere FAISS adapter。对于 FLOAT_VECTOR 字段,adapter 调用 faiss::index_factory();对于 BINARY_VECTOR 字段,则调用 faiss::index_binary_factory()。生成的对象是原生 Faiss Index,由 Milvus 的常规 Index 生命周期管理。

搜索时,adapter 会将提供的 factory 特定参数转换为对应的 Faiss SearchParameters 对象。对于支持的浮点向量 factory,adapter 还会将 Milvus 的 Filter bitset 作为 Faiss selector 传入。selector 支持因 factory 而异,已发布的测试也未证实二进制 FAISS Index 支持标量过滤。因此,在独立 Faiss 中有效的配置方案,可能会拒绝 Milvus 搜索路径所需的操作。

Prerequisites

  • Milvus 3.0.0 或更高版本
  • PyMilvus 3.0.0 或更高版本
  • 熟悉 Faiss index-factory 语法以及所选 factory 的训练要求

有关安装说明,请参阅 安装 PyMilvus

选择 factory string

factory string 使用一系列组件描述 Faiss Index。以下示例已通过 Milvus 3.0.0 发布测试,但并未涵盖所有可用配置。

Factory string字段类型发布测试涵盖的距离度量搜索参数说明
FlatFLOAT_VECTORL2IPCOSINENone精确搜索。
IVF64,FlatFLOAT_VECTORL2IPCOSINEnprobe使用 64 个倒排列表和未压缩向量的 IVF。
HNSW16,FlatFLOAT_VECTORL2IPCOSINEefSearch使用 Flat 向量存储的 HNSW 图。
OPQ16,IVF64,PQ16x4FLOAT_VECTORL2Factory-specific组合使用 OPQ、IVF 和 PQ。请使用你的数据验证训练数据量和召回率。
IVF64,PQ8x4,RFlatFLOAT_VECTORL2nprobek_factor召回 PQ 候选项后,使用 Flat refiner。
PQ8x4FLOAT_VECTORL2None可在发布测试中成功构建。由于该 Index 不接受 selector,使用标量 Filter 的搜索会失败;请单独验证不使用 Filter 的场景。
BFlatBINARY_VECTORHAMMINGNone对二进制向量执行精确搜索。

COSINE 条目表示构建和搜索已通过冒烟测试。对于 Milvus 3.0.0,这些测试无法证明重载 Index 后得分或 Range Search 的正确性。请参阅 限制

构建并检索浮点向量 Index

以下示例创建 3,000 个 128 维向量,为示例中使用的 IVF64,Flat 配置提供充足的训练数据。展开准备步骤,并在构建和检索 Index 前运行其中的代码。

准备浮点向量 Collection
Python
import random

from pymilvus import DataType, MilvusClient

client = MilvusClient(uri="http://localhost:19530")
collection_name = "faiss_float_example"

if client.has_collection(collection_name):
client.drop_collection(collection_name)

rng = random.Random(42)
vectors = [[rng.random() for _ in range(128)] for _ in range(3000)]

schema = client.create_schema(auto_id=False, enable_dynamic_field=False)
schema.add_field("id", DataType.INT64, is_primary=True)
schema.add_field("category", DataType.VARCHAR, max_length=32)
schema.add_field("vector", DataType.FLOAT_VECTOR, dim=128)

client.create_collection(collection_name=collection_name, schema=schema)

rows = [
{
"id": i,
"category": "reference" if i % 2 == 0 else "query",
"vector": vector,
}
for i, vector in enumerate(vectors)
]

client.insert(collection_name=collection_name, data=rows)
client.flush(collection_name=collection_name)

构建 Index

index_type 设置为 FAISS,并使用 faiss_index_name 选择原生 Faiss factory recipe。

Python
index_params = client.prepare_index_params()
index_params.add_index(
field_name="vector",
index_name="faiss_ivf_flat",
index_type="FAISS",
metric_type="L2",
params={"faiss_index_name": "IVF64,Flat"},
)

client.create_index(collection_name=collection_name, index_params=index_params)
client.load_collection(collection_name=collection_name)

factory 字符串 IVF64,Flat 会创建一个包含 64 个倒排列表的 IVF Index,并在每个列表中存储未压缩的向量。

Search the index

search_params.params 中设置特定于 factory 的搜索参数。对于 IVF factory,nprobe 控制 Faiss 搜索的倒排列表数量。

Python
search_params = {
"params": {"nprobe": 8},
}

results = client.search(
collection_name=collection_name,
data=[vectors[0]],
anns_field="vector",
filter='category == "reference"',
search_params=search_params,
limit=5,
output_fields=["category"],
)

for hits in results:
for hit in hits:
print(hit)

该查询使用 nprobe=8,因此 Faiss 会搜索 64 个倒排列表中的 8 个。Filter 将结果限制为 category 值为 reference 的 Entity。

构建和检索二进制 Index

对于 BINARY_VECTOR 字段,请使用 BFlat 等二进制工厂字符串以及兼容的二进制度量类型。展开以下准备代码块,并在构建和检索 Index 前运行其中的代码。

准备二进制向量 Collection
Python
import random

from pymilvus import DataType, MilvusClient

client = MilvusClient(uri="http://localhost:19530")
collection_name = "faiss_binary_example"

if client.has_collection(collection_name):
client.drop_collection(collection_name)

rng = random.Random(7)
vectors = [bytes(rng.getrandbits(8) for _ in range(16)) for _ in range(300)]

schema = client.create_schema(auto_id=False, enable_dynamic_field=False)
schema.add_field("id", DataType.INT64, is_primary=True)
schema.add_field("binary_vector", DataType.BINARY_VECTOR, dim=128)

client.create_collection(collection_name=collection_name, schema=schema)
client.insert(
collection_name=collection_name,
data=[{"id": i, "binary_vector": vector} for i, vector in enumerate(vectors)],
)
client.flush(collection_name=collection_name)

构建 Index

在此二进制向量示例中,使用 BFlat 作为 factory string,并使用 HAMMING 作为 metric。

Python
index_params = client.prepare_index_params()
index_params.add_index(
field_name="binary_vector",
index_name="faiss_binary_flat",
index_type="FAISS",
metric_type="HAMMING",
params={"faiss_index_name": "BFlat"},
)

client.create_index(collection_name=collection_name, index_params=index_params)
client.load_collection(collection_name=collection_name)

Search the index

BFlat 没有该索引家族特有的搜索参数。构造搜索请求时,请传入空的 params 映射。

Python
search_params = {"params": {}}

results = client.search(
collection_name=collection_name,
data=[vectors[0]],
anns_field="binary_vector",
search_params=search_params,
limit=5,
)

for hits in results:
for hit in hits:
print(hit)

每个 128 维二进制向量使用 16 字节表示。更多信息,请参阅 Binary Vector

配置构建和检索参数

FAISS Index 类型有一个必需的透传构建参数。

参数位置说明
faiss_index_nameadd_index() 中的 paramsFaiss index-factory 字符串,例如 IVF64,Flat

search_params.params 中设置特定于 factory 的检索参数。下表列出了一些常见示例,但并未涵盖所有参数。

参数factory 示例说明
nprobeIVF64,Flat要检索的倒排列表数量。
efSearchHNSW16,FlatHNSW 检索候选列表的大小。
k_factorIVF64,PQ8x4,RFlat相对于所请求 top-K,提供给 refiner 的候选项数量。

Milvus 仅转发 adapter 能够识别的附加参数。未知的构建参数键以及具体 factory 系列不支持的检索参数键将被拒绝。Milvus 不为所有可能的 factory 维护统一的参数 Schema。请查阅所选 factory 的 Faiss 文档,然后针对你计划部署的具体 Milvus 版本和镜像,验证完整的构建和检索流程。

处理错误和不支持的操作

  • 如果 factory 字符串无效,或当前 Milvus 构建版本不支持该字符串,Index 构建将失败。加载 Collection 前,请检查 Index 状态和失败原因。

  • 如果参数类型错误,Search 将失败。例如,nprobe="invalid" 会被拒绝,因为 nprobe 必须是数值。

  • 如果参数不适用于已构建的 factory,适配器会以不支持该参数为由拒绝请求。

  • 如果某个 factory 不支持 Milvus selector,即使同一个 factory 可以在独立运行的 Faiss 中执行 Search,带 Filter 的 Search 仍可能失败。

  • 不要对 FAISS Index 使用 search_iterator()

What's next