Qdrant 1.20 - 全文搜索改进

Qdrant 1.20 - 全文搜索改进

💡 原文英文,约2500词,阅读约需10分钟。
📝

内容提要

Qdrant 1.20 发布,主要更新包括:全文索引支持 BM25 评分,无需生成嵌入向量,统计自动从数据推导;新增代码分词器,按大小写和下划线拆分标识符,提升代码搜索效果;新增逐元素嵌套索引,嵌套过滤速度提升 7 至 38 倍;新增 turbo16 和 turbo8 数据类型,分别以 16 位和 8 位存储向量,turbo16 精度无损且搜索更快,turbo8 召回接近 float16;内存分层扩展至 ID 跟踪器,内联存储不再重复保存向量;集群安全加固,内部 API 默认要求认证,内部端口可绑定私有网络。

🔎

延伸解读

BM25 全文索引:省去嵌入生成,统计自动适配

Qdrant 1.20 允许在全文索引上直接使用 BM25 评分,无需将文本转换为稀疏向量。此前,稀疏 BM25 需要为每个文档和查询执行推理步骤,且平均文档长度需手动维护,数据变化后需重新转换所有文档。新版本从数据中自动推导所有 BM25 统计量,包括平均文档长度,索引后即可搜索。查询时可逐次调整 k 和 b 参数,无需重建索引。已有 payload 文本可无缝迁移,只需创建带评分的全文索引并替换查询方式。

代码分词器:按命名习惯拆分标识符,提升代码搜索召回

默认分词器按空格和标点拆分,会将 getUserName 视为单个 token,导致搜索 user name 或 get_user_name 无法命中。新增的代码分词器会在下划线和大小写变化处拆分标识符,包括缩写,使 getUserName、get_user_name 和 user name 相互匹配。同时保留完整标识符索引,因此 hashmap 仍能命中 HashMap。结合全文索引上的 BM25 评分,代码搜索无需生成嵌入向量即可获得排序结果。

逐元素嵌套索引:过滤无需读取 payload,速度提升 7 至 38 倍

嵌套过滤要求数组中的单个元素同时满足所有条件,例如特定店铺且低于某价格。此前,payload 索引只能缩小候选范围,仍需从磁盘读取每个候选的 payload 逐元素检查,候选多时变慢。1.20 为每种 payload 索引新增 nested 参数,创建逐元素索引,将每个数组元素单独存储。当嵌套过滤的所有条件都使用同一数组上的逐元素索引时,Qdrant 可仅凭索引完成过滤,不读取任何 payload。搜索 API 不变,创建索引后现有过滤自动加速。在 10 万点的基准测试中,即使 payload 全在内存,逐元素索引

turbo16 与 turbo8:更低误差或更高压缩,按需权衡

turbo16 使用与 float16 相同的 16 位,但通过 TurboQuant 旋转将值均匀分布到各坐标,再存储到 16 位整数网格,降低了 float16 在大坐标上的舍入误差。在 13 个数据集上,重建误差比 float16 低 7.5 倍;在 12 个数据集上,精确搜索的 recall@10 与 float32 差距在 0.001 以内,而 float16 在 ada-002 和 CLIP 上降至 0.995。turbo16 的 HNSW 搜索延迟中位数是 float16 的 0.81 倍(x86)和

❓

Q&A

Qdrant 1.20 的全文索引 BM25 评分有什么优势?

Qdrant 1.20 支持直接在全文索引上使用 BM25 评分,无需生成嵌入向量。所有 BM25 统计量(包括平均文档长度)都从数据中自动推导,评分开箱即用。文本一旦索引即可搜索,且 BM25 参数 k 和 b 可在查询时调整,无需重建索引。

如何从稀疏向量 BM25 迁移到全文索引 BM25?

如果文本已存储在 payload 中,无需重新上传数据。创建启用 BM25 评分的全文索引,配置与稀疏 BM25 模型相同的文本处理方式,然后将稀疏向量查询替换为文本查询即可。稀疏向量 BM25 仍然受支持。

代码分词器如何改善代码搜索?

新的代码分词器会按大小写变化和下划线拆分标识符(包括缩写),因此 getUserName、get_user_name 和 user name 可以互相匹配。它还会索引完整标识符,所以 hashmap 仍能搜到 HashMap。结合 BM25 评分,无需生成嵌入向量即可对代码搜索结果排序。

逐元素嵌套索引如何加速嵌套过滤?

逐元素嵌套索引为数组中的每个元素单独建立索引。当嵌套过滤的所有条件都使用同一数组上具有逐元素索引的字段时,Qdrant 可以仅凭索引回答过滤,无需读取 payload。在 10 万点的基准测试中,即使 payload 全在内存,逐元素索引也比常规索引快 7 到 38 倍;若 payload 需从磁盘读取,差距可能更大。

turbo16 和 turbo8 数据类型有什么区别?

turbo16 使用 16 位存储向量,与 float16 相同但误差更低,可将 float32 向量存储减半且无精度损失,搜索速度也比 float16 快(x86 中位延迟为 0.81 倍,ARM 为 0.83 倍)。turbo8 使用 8 位存储,自动量化浮点向量,存储再减半,召回率接近 float16,搜索速度比 float16 快 1.1 到 2.4 倍。

内存分层如何扩展到 ID 跟踪器和内联存储?

ID 跟踪器现在可为每个集合选择内存层级:pinned(默认,保留在 RAM)、cold(磁盘按需读取)或 cached(磁盘但加载到页缓存)。内联存储不再重复保存向量,原始向量仅存于 HNSW 索引文件中,减少磁盘占用,但向量会跟随索引的内存层级,升级前需检查配置。

集群安全加固有哪些具体措施?

内部 gRPC API 默认要求认证:配置 API 密钥后,内部请求必须携带有效密钥,且仅接受读写密钥,拒绝只读密钥和所有 JWT。此外,新增 cluster.p2p.host 设置可将内部端口绑定到私有网络接口,与公共 API 地址分离。

升级到 Qdrant 1.20 需要注意什么?

建议逐版本升级(如 1.18.x→1.19.x→1.20.0)。若设置了 api_key,从 1.19 滚动升级安全;若仅设置 read_only_api_key,节点间将无法通信,需设置 api_key 或 enforce_internal_auth: false。使用内联存储的集合可能需更多 RAM,升级前应设置 hnsw_config.memory 和量化内存层级。

🏷️

标签

➡️

继续阅读