news 2026/8/31 9:42:33

turbovec API参考(上):TurboQuantIndex向量索引完整方法手册

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
turbovec API参考(上):TurboQuantIndex向量索引完整方法手册

turbovec API参考(上):TurboQuantIndex向量索引完整方法手册

【免费下载链接】turbovecA vector index built on TurboQuant, written in Rust with Python bindings项目地址: https://gitcode.com/GitHub_Trending/tu/turbovec

turbovec是一个基于 GoogleTurboQuant算法的向量索引(Vector Index):Rust 内核 + Python 绑定,把高维向量压缩到每维 2–4 bit,1000 万条文档约 31 GB 的 float32 存储可以直接装进 4 GB 内存。它是数据无关(data-oblivious)的量化器——无需训练、无需调参add即可用。本文是 API 参考手册的上篇,完整梳理核心类TurboQuantIndex的每一个方法。

两个索引类:先选对再上手 🎯

turbovec 提供两个索引类,官方完整文档见 docs/api.md:

索引类特点适用场景
TurboQuantIndex位置索引,向量以插入槽位0..n标识只增不删、或接受位置 ID
IdMapIndexTurboQuantIndex之上加一层稳定外部u64ID 映射,remove(id)为 O(1)需要可删除、ID 稳定的生产库(LangChain/LlamaIndex/Haystack 集成内部均使用它)

本篇聚焦TurboQuantIndexIdMapIndex的方法与它高度对称,将在下篇详解。

两类索引的 Rust 实现位于 turbovec/src/lib.rs,Python 绑定位于 turbovec-python/src/lib.rs,Python 端封装与持久化辅助在 turbovec-python/python/turbovec/_persist.py。

构造参数:30秒创建向量索引

from turbovec import TurboQuantIndex idx = TurboQuantIndex(dim=1536, bit_width=4) # 也可省略 dim,首次 add 时自动推断

构造参数一览:

参数取值说明
dim8 的正整数倍,且≤ 16384(MAX_DIM),可选向量维度;省略则为"惰性索引",第一次add时锁定
bit_width{2, 3, 4},默认 4每维压缩位数:2-bit 最省内存,4-bit 精度更高

惰性索引(lazy index)的行为:在首次add之前,idx.dimNonelen(idx)0search()返回空结果;空批次(0 行)的add是 no-op,索引保持惰性。

💡 典型 embedding 模型:OpenAI d=1536 / d=3072、GloVe d=200 都能直接建库。

核心工作流:add 入库、search 检索

import numpy as np idx.add(vectors) # float32 二维数组,形状 (n, dim) scores, indices = idx.search(query, k=10) # 返回内积分数与槽位下标

add(vectors)要点:

  • 输入必须是C 连续的 float32 数组,其他 dtype 会被直接拒绝(而不是静默转换),必要时先np.asarray(x, dtype=np.float32)
  • 出现 NaN / Inf 或|值| ≥ 1e16会抛ValueError,且报错信息精确到第几条向量第几维
  • L2 范数≤ 1e-10的向量没有可表示方向,会以 scale 0 存储,对任何查询得分恒为 0(记录在len(idx)中,但排在所有正常向量之后)

search(queries, k, *, mask=None)要点:

  • 返回(scores, indices),形状均为(nq, effective_k)indicesint64槽位下标
  • 分数是内积,因此与查询向量同向缩放;ID 排序对查询乘以任意正数不变
  • effective_k = min(k, len(idx)):库里向量不足 k 条时返回实际条数,不做 NaN 填充
  • mask:布尔数组(长度len(idx)),只允许mask[i] == True的槽位参与,详见下文"过滤检索"

过滤检索:在 SIMD 内核里直接屏蔽槽位

turbovec 的过滤不是"先搜后扔"(post-filter),而是在内核内直接跳过不允许的向量——总能从允许集合中返回最多 k 条,不会被宽松过滤"掏空"结果:

mask = np.ones(len(idx), dtype=bool) mask[disabled_slots] = False scores, slots = idx.search(query, k=10, mask=mask)

⚠️一个重要陷阱mask引用的是槽位,而任何变更(哪怕len不变)都可能让槽位重排——所以每次变更后必须重建 mask,长度校验救不了你。这一点在 docs/api.md 中有专节说明。

删除与持久化:swap_remove、write、sync 三件套

swap_remove(i):O(1) 位置删除

把最后一个向量换到槽位i并截断一条。它不是移位——不保序,未删除向量的槽位下标可能已指向别的向量。命名对齐 Rust 的Vec::swap_remove,语义可预测。

write(path)/load(path):整文件快照

write以 fsync + 原子重命名产出.tv文件,load读取。write(path, durable=False)可跳过重命名前的 fsync(更快,但断电可能丢文件);Rust 侧对应write_with_durability(path, io::Durability::Fast | Durable)

sync(path):增量保存

sync只写入自上次 sync 以来的变更:追加写入新的 32 行块 + 提交头;删除完全不写数据块,只在提交头里记一条 redo 操作。每次sync返回即持久(sync_all级 fsync),任意字节处崩溃都保留上一次完整提交。load()自动识别快照与增量两种容器格式,且加载后的索引仍绑定原路径,继续增量同步。

内存序列化与拷贝:to_bytes、from_bytes、pickle

  • idx.to_bytes():返回与write(path)字节完全一致的内存载荷(.tv格式)
  • TurboQuantIndex.from_bytes(data):接受bytes/bytearray,校验规则与load一致,损坏载荷抛ValueError
  • pickle.dumps/copy.copy/copy.deepcopy全部支持,底层都归约为from_bytes(to_bytes()),拷贝与原对象完全独立,可跨越multiprocessing的 spawn 边界

这条路径是缓存与数据库列存储的推荐方式,框架集成库的持久化也构建在它之上。两个小坑值得记住:空索引在布尔上下文中为 falsy(用idx is None判断索引、len(idx)判断内容);索引不允许挂用户属性idx.tag = "x"会抛AttributeError)。

TQ+ 校准:calibrate 与 calibration_state

默认情况下索引是"纯 TurboQuant";调用一次calibrate(sample)后开启TQ+——对每个坐标拟合(shift, scale)校准,平均可提升约 +2.5 个 R@10 召回点,最各向异性的数据上提升近 8.7。要点:

  • 时机:能在校准后再add就尽量先校准;大批量入库后补校准相当于二次量化,会损失几个召回点
  • 样本:随机且有代表性即可,约 1024 行就接近全库拟合效果(2048 行在所有测量语料上达标);排序/聚类前缀会破坏召回
  • 可重调calibrate可随时多次调用,会用存储的码重编码全部存量行,无需原始向量;但被严重偏差校准"剪坏"的数据无法修复,只能从源向量重建
  • idx.calibration_state报告当前状态:"uncalibrated""calibrated"
  • 校准状态可完整往返于write/loadto_bytes/from_bytes、pickle 与拷贝

Rust 侧对应calibrate(&mut self, sample)(2D 批次为calibrate_2d),测试参考 turbovec/tests/tqplus_calibration.rs。

附:prepare 预热与内省属性

  • prepare():可选。提前构建旋转矩阵、Lloyd-Max 质心与 SIMD 分块布局,让第一次search不必支付一次性初始化成本(惰性索引上调用为空操作)
  • 内省:len(idx)(向量数)、idx.dim(已提交维度或None)、idx.bit_widthidx.calibration_state
  • 线程安全:search只读锁,多线程并发搜索互不阻塞;变更走写锁,add/swap_remove期间读者等待

TurboQuantIndex 方法速查表

方法 / 属性说明
TurboQuantIndex(dim=None, bit_width=4)构造;bit_width ∈ {2,3,4}dim可选
add(vectors)批量入库;float32 二维数组(n, dim)
search(queries, k, *, mask=None)返回(scores, indices);支持布尔 mask 过滤
swap_remove(i)O(1) 位置删除,末位向量换入i,返回被移动向量的原位置
prepare()预热缓存,消除首次搜索的一次性开销
calibrate(sample)/calibration_stateTQ+ 校准提交与状态查询
write(path, *, durable=True)/load(path).tv整文件快照读写
sync(path)增量持久化,崩溃安全
to_bytes()/from_bytes(data)内存字节序列化
len(idx)/idx.dim/idx.bit_width内省

📚延伸阅读:完整 API 文档 docs/api.md;Rust 入口与并发约定见 turbovec/src/lib.rs;Python 绑定实现见 turbovec-python/src/lib.rs;召回与速度基准见 benchmarks/results/ 下的 JSON 结果。

下篇预告:IdMapIndex完整方法手册——add_with_idsremove(id)allowlist过滤与.tvim文件格式。

【免费下载链接】turbovecA vector index built on TurboQuant, written in Rust with Python bindings项目地址: https://gitcode.com/GitHub_Trending/tu/turbovec

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/31 9:41:42

算法岗笔试题型全拆解:从KMP到机器学习理论考点梳理

我当年秋招的时候,算法岗的笔试基本就是一场“盲人摸象”——你永远猜不到出题人会从哪个犄角旮旯里扒出一道题来。B站这套2019秋招技术岗(算法)第二套笔试题,我在网上翻到过不少讨论帖,这次结合题目本身和热门考点词&…

作者头像 李华
网站建设 2026/8/31 9:40:39

三极管静态工作点详解:从原理到偏置电阻调试实战

三极管的静态工作点到底是什么,为什么调偏置电阻时波形会变样? 这段时间又看到有人问起三极管静态工作点的问题,问法挺典型的:“老师说要设静态工作点,到底什么是静态工作点?为什么电阻不对波形就削顶&…

作者头像 李华
网站建设 2026/8/31 9:37:32

驾驶人睁闭眼张合嘴检测数据集与YOLO训练实战指南

简介:本资源是面向智能座舱与疲劳驾驶监测领域的YOLO目标检测专用数据集,适用于计算机视觉初学者、车载AI算法工程师及高校相关课题研究者,用于训练和验证驾驶人眼部开闭状态与口腔张合动作的多类别目标检测模型。压缩包共含2000个XML格式标注…

作者头像 李华
网站建设 2026/8/31 9:36:53

Expert Intelligence 读书功能:把书变成可按专家视角追问的AI知识库

Gemini Notebook 的 Expert Intelligence 读书功能,简单说就是把你上传的书籍资料变成可以按专家视角追问的 AI 知识库。以前用 AI 工具读书,最常踩的坑是回答太泛,或者答案和手里这本书对不上。NotebookLM 这类由 Gemini 驱动的在线笔记工具…

作者头像 李华