TurboQuant 量化技术原理与 Qdrant 实践指南

0 阅读

为什么 TurboQuant 填补了向量压缩的空白

向量搜索系统需要将大量嵌入向量常驻内存以响应查询。当集合规模扩大,以 float32 存储每个坐标(4 字节)的成本迅速上升。例如,100 万个 1024 维向量占用约 4.1 GB。若能用更少比特表示每个坐标,存储开销可大幅降低。

但压缩会引入误差,可能改变最近邻的排序结果。现有方法各有局限:标量量化(如 SQ8)通常只能做到 4 倍压缩;二值量化虽可达 32 倍压缩,但召回率对嵌入分布敏感;乘积量化(PQ)则需为每个数据集训练专用码本,增加复杂度。

TurboQuant 提供了一种折中方案。它支持 4 位、2 位、1.5 位和 1 位四种模式,无需训练即可使用。TQ4 比 SQ8 节省一半空间,而 TQ1/TQ2 在相同比特预算下通常比二值量化保留更多语义信息。当你发现向量本身成为内存或存储瓶颈时,TurboQuant 值得一试。

TurboQuant 的工作原理

嵌入向量的坐标值往往分布不均——某些维度变化剧烈,另一些则接近常数。直接对原始坐标做低位量化会丢失关键信息。

TurboQuant 的第一步是施加一个随机正交旋转。这个操作混合了所有坐标,但保持向量长度、点积和 L2 距离不变。对于已归一化的向量,旋转后每个坐标的分布趋近于高斯分布(在高维下由 Beta 分布近似)。

接着,每个旋转后的坐标被映射到一个固定码本中最接近的代表值。这个码本基于 Lloyd-Max 算法预先计算,代表值在概率密度高的区域更密集,从而最小化平均重构误差。由于旋转后的分布已知,码本无需针对具体数据集训练。

最终,系统只存储代表值的索引(如 4 位对应 16 个索引),而非原始浮点数。查询时同样先旋转,再与压缩后的索引比较。虽然仍有信息损失,但论文提出的 MSE 变体优化了重构精度,PROD 变体则用额外 1 比特校正内积偏差。

Qdrant 对 TurboQuant 的增强实现

Qdrant 从 1.18 版本起集成 TurboQuant 作为可选量化层。它不仅采用 TurboQuant 的固定码本,还融合了 RaBitQ 论文中的两项改进:

  • 长度重归一化:量化会使向量变短,Qdrant 利用额外存储的原始 L2 范数在打分时恢复长度,使点积和欧氏距离成为有效度量(而不局限于余弦相似度)。
  • 逐坐标校准:调整每个坐标的缩放,使其与固定码本对齐,进一步减少打分误差。

这些校准参数和范数共用 4 字节存储。更重要的是,Qdrant 将码本和查询向量都转为整数,利用 SIMD 指令并行处理坐标块。这使得单次查询能高效比对数百万压缩向量。

值得注意的是,Qdrant 默认保留原始 float32 向量用于重打分(rescoring)。搜索分两阶段:先用压缩向量快速召回候选集,再用原始向量精确重排。大部分召回率损失在此阶段被弥补。

三种量化方案的实测对比

我们在 BEIR 基准的三个数据集上测试:SciFact(科学事实验证)、ArguAna(论点检索)和 NFCorpus(医学信息检索)。所有嵌入均来自 Cohere 的 embed-english-v3.0 模型(1024 维),确保公平比较。

Screenshot 2026-09-07 at 01.45.28

测试配置包括:

  • F32:无压缩基线
  • SQ8:8 位标量量化(4 倍压缩)
  • BQ1/BQ2:1/2 位二值量化
  • TQ1/TQ4:1/4 位 TurboQuant

Screenshot 2026-09-07 at 01.23.51

HNSW 参数统一设为 m=16, ef_construct=128。评估指标采用 Precision@10、Recall@10 和 nDCG@10。

Screenshot 2026-09-06 at 03.15.59

结果表明:

  • TQ4 在 8 倍压缩下,效果接近 SQ8(后者仅 4 倍压缩)
  • TQ1 在 32 倍压缩下,nDCG 普遍优于 BQ1,尤其在 SciFact 上提升显著
  • 二值量化在 ArguAna 表现尚可,但在 NFCorpus 上召回率骤降

Screenshot 2026-09-06 at 23.49.21

Qdrant 官方在更大规模数据(如 arXiv、LAION)上的测试也显示,TurboQuant 在相同存储预算下比二值量化高 10–20 个百分点的召回率。

Screenshot 2026-09-07 at 01.48.00

在 Qdrant 中启用 TurboQuant

连接到 Qdrant Cloud

首先安装客户端并配置环境变量:

pip install "qdrant-client[fastembed]"
import os
from qdrant_client import QdrantClient, models
from fastembed import TextEmbedding

client = QdrantClient(
    url=os.environ["QDRANT_URL"],
    api_key=os.environ["QDRANT_API_KEY"],
)

embedder = TextEmbedding("jinaai/jina-embeddings-v2-base-en")

创建带 TurboQuant 配置的集合

量化策略在集合创建时指定,后续不可更改:

client.create_collection(
    collection_name="catalog",
    vectors_config=models.VectorParams(
        size=768,  # 需匹配嵌入模型维度
        distance=models.Distance.COSINE,
    ),
    quantization_config=models.TurboQuantization(
        turbo=models.TurboQuantQuantizationConfig(
            bits=models.TurboQuantBitSize.BITS4,  # 可选 BITS2/BITS1_5/BITS1
        ),
    ),
)

final

插入文档

写入过程与未量化时完全一致。Qdrant 在索引时自动压缩:

products = [
    "waterproof hiking boots with ankle support",
    "lightweight running shoes for marathon training",
    # ... 其他商品描述
]

vectors = list(embedder.embed(products))

client.upsert(
    collection_name="catalog",
    points=[
        models.PointStruct(
            id=i,
            vector=v.tolist(),
            payload={"text": text}
        )
        for i, (v, text) in enumerate(zip(vectors, products))
    ],
)

带重打分的查询

启用 rescore=True 可触发两阶段搜索。oversampling=2.0 表示先召回 6 个候选(limit×2),再用原始向量重排返回前 3:

query = next(embedder.embed(["shoes for walking long distances outdoors"]))

hits = client.query_points(
    collection_name="catalog",
    query=query.tolist(),
    limit=3,
    search_params=models.SearchParams(
        quantization=models.QuantizationSearchParams(
            rescore=True,
            oversampling=2.0,
        ),
    ),
).points

![Screenshot 2026-09-07 at 12.46.33](https://cdn-uploads.huggingface.co/production/uploads/630f3058236215d0b7078806/87uqUR30-gzkOddD-Yy-l.png)

for hit in hits:
    print(round(hit.score, 4), hit.payload["text"])

输出示例:

0.8215 waterproof hiking boots with ankle support
0.7982 lightweight running shoes for marathon training
0.7641 collapsible trekking poles with cork grips

何时该用 TurboQuant

  • 如果你当前用标量量化且存储压力大,可尝试 TQ4。它在减半存储的同时保持相近效果。
  • 如果你用二值量化,在相同比特数下(如 1 位)测试 TQ1。多数场景下召回率更高,但需实测延迟是否可接受。
  • 当向量占据主要内存/存储成本,且你的嵌入维度较高(≥512)时,TurboQuant 的旋转优势更明显。

不过,如果应用对吞吐量极度敏感,或召回率提升对你业务影响甚微,则维持现有方案可能更稳妥。毕竟,没有免费的压缩——只是 TurboQuant 让代价变得更可控。