Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
name: Release wheels

on:
push:
tags:
- "v*"
workflow_dispatch:

permissions:
contents: read

jobs:
linux-wheels:
name: Linux x86-64 wheels
runs-on: ubuntu-latest
timeout-minutes: 90

steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.14"

- name: Check tag matches package version
if: github.event_name == 'push'
env:
RELEASE_TAG: ${{ github.ref_name }}
run: |
python - <<'PY'
import os
import tomllib

with open("pyproject.toml", "rb") as file:
version = tomllib.load(file)["project"]["version"]

expected_tag = f"v{version}"
if os.environ["RELEASE_TAG"] != expected_tag:
raise SystemExit(
f"release tag {os.environ['RELEASE_TAG']!r} does not match "
f"package version {version!r}; expected {expected_tag!r}"
)
PY

- name: Build and test wheels
uses: pypa/cibuildwheel@v4.2.0
with:
output-dir: wheelhouse

- name: Store wheel artifacts
uses: actions/upload-artifact@v4
with:
name: linux-x86_64-wheels
path: wheelhouse/*.whl
if-no-files-found: error

pypi-publish:
name: Publish wheels to PyPI
if: github.event_name == 'push'
needs: linux-wheels
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/project/rabitqlib/
permissions:
id-token: write

steps:
- name: Download wheel artifacts
uses: actions/download-artifact@v4
with:
name: linux-x86_64-wheels
path: wheelhouse

- name: Publish wheels
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: wheelhouse

github-release:
name: Create GitHub release
if: github.event_name == 'push'
needs: [linux-wheels, pypi-publish]
runs-on: ubuntu-latest
permissions:
contents: write

steps:
- name: Download wheel artifacts
uses: actions/download-artifact@v4
with:
name: linux-x86_64-wheels
path: wheelhouse

- name: Create GitHub release
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ github.ref_name }}
run: gh release create "$RELEASE_TAG" wheelhouse/*.whl --generate-notes --verify-tag
184 changes: 107 additions & 77 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,55 +1,81 @@
# RaBitQ Library
<div align="center">

[![C++ tests](https://github.com/VectorDB-NTU/RaBitQ-Library/actions/workflows/test.yaml/badge.svg)](https://github.com/VectorDB-NTU/RaBitQ-Library/actions/workflows/test.yaml)
[![Python tests](https://github.com/VectorDB-NTU/RaBitQ-Library/actions/workflows/python.yml/badge.svg)](https://github.com/VectorDB-NTU/RaBitQ-Library/actions/workflows/python.yml)
[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
<h1>RaBitQ Library</h1>

RaBitQ Library is a C++17 library with Python bindings for compact, accurate
vector quantization and approximate nearest-neighbor search. It provides:
<h3>Compact vectors. Accurate distances. Fast ANN search.</h3>

- the [1-bit](https://arxiv.org/abs/2405.12497) and
[multi-bit](https://arxiv.org/abs/2409.09913) RaBitQ quantizers;
- IVF, HNSW, and [SymphonyQG](https://dl.acm.org/doi/abs/10.1145/3709730)
indexes powered by RaBitQ;
- Euclidean distance and inner-product search (cosine search is
available by normalizing vectors before using inner product); and
- optimized AVX2 and AVX-512 kernels with runtime CPU dispatch.
<p>
A research-backed C++17 library with Python bindings for 1-bit and multi-bit<br>
vector quantization, IVF, HNSW, and SymphonyQG.
</p>

RaBitQ is developed by the
[VectorDB group](https://vectordb-ntu.github.io/) at Nanyang Technological
University, Singapore. A GPU implementation is also available in
[cuvs_rabitq](https://github.com/Stardust-SJF/cuvs_rabitq/tree/cuvs_ivf_rabitq).
<p>
<a href="https://pypi.org/project/rabitqlib/"><img alt="PyPI" src="https://img.shields.io/pypi/v/rabitqlib.svg"></a>
<a href="https://pypi.org/project/rabitqlib/"><img alt="Python versions" src="https://img.shields.io/pypi/pyversions/rabitqlib.svg"></a>
<a href="https://github.com/VectorDB-NTU/RaBitQ-Library/actions/workflows/test.yaml"><img alt="C++ tests" src="https://github.com/VectorDB-NTU/RaBitQ-Library/actions/workflows/test.yaml/badge.svg"></a>
<a href="https://github.com/VectorDB-NTU/RaBitQ-Library/actions/workflows/python.yml"><img alt="Python tests" src="https://github.com/VectorDB-NTU/RaBitQ-Library/actions/workflows/python.yml/badge.svg"></a>
<a href="https://vectordb-ntu.github.io/RaBitQ-Library/"><img alt="Documentation" src="https://github.com/VectorDB-NTU/RaBitQ-Library/actions/workflows/docs.yml/badge.svg"></a>
<a href="https://doi.org/10.1145/3725413"><img alt="Paper DOI" src="https://img.shields.io/badge/DOI-10.1145%2F3725413-blue"></a>
<a href="LICENSE"><img alt="License" src="https://img.shields.io/badge/license-Apache--2.0-blue.svg"></a>
</p>

## Quick start
<p>
<a href="https://vectordb-ntu.github.io/RaBitQ-Library/">Documentation</a> ·
<a href="https://pypi.org/project/rabitqlib/">Python package</a> ·
<a href="https://doi.org/10.1145/3725413">Paper</a> ·
<a href="https://github.com/VectorDB-NTU/RaBitQ-Library/releases">Releases</a>
</p>

### Python
</div>

#### Requirements
## Install

- Python 3.9 or newer
- a C++17 compiler
- CMake 3.15 or newer
- OpenMP
- an x86-64 CPU supported by the selected kernels: most paths accept either
AVX2 with FMA or AVX-512F/BW/DQ with FMA
```bash
pip install rabitqlib
```

Most SIMD entry points select AVX-512 kernels when AVX-512F, AVX-512BW, and
AVX-512DQ are detected; otherwise they use AVX2 when AVX2 and FMA are
available. AVX-512 VPOPCNTDQ enables additional popcount kernels. The HNSW
AVX-512 core path also checks for AVX2 and FMA, and otherwise uses its AVX2
path when available. AVX-512 translation units are compiled with FMA enabled.
Prebuilt wheels support Linux x86-64 and CPython 3.9–3.14. AVX2 + FMA is the
portable CPU baseline; supported AVX-512 kernels are selected at runtime.

On Ubuntu or Debian, install the system build tools and then install RaBitQ
from the repository:
## Adopted across the vector-search ecosystem

```bash
sudo apt-get update
sudo apt-get install -y build-essential cmake libomp-dev
[Milvus](https://github.com/milvus-io/milvus) ·
[Faiss](https://github.com/facebookresearch/faiss) ·
[VSAG](https://github.com/antgroup/vsag) ·
[VectorChord](https://github.com/tensorchord/VectorChord) ·
[Volcengine OpenSearch](https://www.volcengine.com/docs/6465/1553583) ·
[CockroachDB](https://github.com/cockroachdb/cockroach) ·
[Elasticsearch](https://github.com/elastic/elasticsearch) ·
[Lucene](https://github.com/apache/lucene) ·
[turbopuffer](https://turbopuffer.com/blog/ann-v3#:~:text=ANN%20v3%20employs%20the%20RaBitQ) ·
[Zvec](https://github.com/alibaba/zvec)

git clone https://github.com/VectorDB-NTU/RaBitQ-Library.git
cd RaBitQ-Library
python -m pip install .
```
## Accuracy at a glance

![RaBitQ estimation error benchmark across MSong, YouTube, OpenAI embeddings, Word2Vec, and GIST](docs/docs/assets/img/acc_bench.png)

*Average and maximum relative estimation error across six datasets; lower is
better. Results from the
[SIGMOD camera-ready paper](https://doi.org/10.1145/3725413).*

## Why RaBitQ?

| | |
| --- | --- |
| **Compact by design** | Choose [1-bit](https://arxiv.org/abs/2405.12497) or [multi-bit](https://doi.org/10.1145/3725413) codes to match your memory and accuracy target. |
| **Accurate estimates** | An asymptotically optimal theoretical error bound supports reliable ordering and reranking. |
| **Fast on x86-64** | Dedicated AVX2 and AVX-512 kernels are selected through runtime CPU dispatch. |
| **Ready for ANN search** | Use the quantizer directly or build complete IVF, HNSW, and [SymphonyQG](https://dl.acm.org/doi/abs/10.1145/3709730) indexes. |

The library supports Euclidean distance and inner product. Cosine search is
available by normalizing vectors before using inner product.

RaBitQ is developed by the
[VectorDB group](https://vectordb-ntu.github.io/) at Nanyang Technological
University, Singapore. A GPU implementation is also available in
[cuvs_rabitq](https://github.com/Stardust-SJF/cuvs_rabitq/tree/cuvs_ivf_rabitq).

## Python quick start

The following complete example builds a small IVF index and searches it. It
uses deterministic synthetic data, so no dataset download is required.
Expand Down Expand Up @@ -86,20 +112,41 @@ Python bindings are also available for `HnswIndex` and `SymqgIndex`. See the
[Python examples](sample/python/) for index construction, querying, and index
persistence.

### C++
<details>
<summary>Build the Python bindings from source</summary>

Source builds require a C++17 compiler, CMake 3.15 or newer, and OpenMP. On
Ubuntu or Debian:

```bash
sudo apt-get update
sudo apt-get install -y build-essential cmake libomp-dev
git clone https://github.com/VectorDB-NTU/RaBitQ-Library.git
cd RaBitQ-Library
python -m pip install .
```

</details>

## C++ quick start

#### Requirements
### Requirements

- CMake 3.15 or newer
- a C++17 compiler with OpenMP support
- an x86-64 CPU supported by the selected kernels: most paths accept either
AVX2 with FMA or AVX-512F/BW/DQ with FMA

<details>
<summary>CPU dispatch details</summary>

Most SIMD entry points select AVX-512 kernels when AVX-512F, AVX-512BW, and
AVX-512DQ are detected; otherwise they use AVX2 when AVX2 and FMA are
available. AVX-512 VPOPCNTDQ enables additional popcount kernels. The HNSW
AVX-512 core path also checks for AVX2 and FMA, and otherwise uses its AVX2
path when available. AVX-512 translation units are compiled with FMA enabled.
AVX-512 core path also checks for AVX2 and FMA. AVX-512 translation units are
compiled with FMA enabled.

</details>

Clone and build the library and example programs:

Expand Down Expand Up @@ -139,53 +186,36 @@ GoogleTest is downloaded during test configuration. For a full benchmark on
the GIST dataset, see [`example.sh`](example.sh). More detailed API and
algorithm guidance is available in the [documentation](docs/docs/index.md).

## Contributing
## Choose the right building block

Contributions are welcome. See the [contributing guide](CONTRIBUTING.md) for
the build, formatting, pre-commit, and static-analysis workflows.
| Component | Best fit | Storage and search profile |
| --- | --- | --- |
| **Quantizer** | Integrating RaBitQ into an existing system | Low-level 1-bit or multi-bit encoding and distance estimation. |
| **IVF** | Memory-efficient partitioned search | Stores quantized codes without retaining the raw dataset. |
| **HNSW** | Graph search with compact vectors | Adds graph links and searches directly from quantized codes. |
| **SymphonyQG** | Query speed when more memory is available | Retains raw vectors and stores per-neighborhood quantization data. |

## Why RaBitQ?

- **High accuracy with tiny codes.** RaBitQ provides state-of-the-art similarity
estimation across different bit widths and remains effective with a
one-bit code per padded dimension plus per-vector factors.
- **Fast distance estimation.** IVF and SymphonyQG use
[FastScan](https://arxiv.org/abs/1704.07355) for batched estimates, while
HNSW uses single-code AVX2 or AVX-512 kernels.
- **Theoretical error bounds.** RaBitQ provides an asymptotically optimal error
bound that can support reliable ordering and reranking.
- **Multiple index trade-offs.** IVF stores quantized codes without the raw
dataset. HNSW adds graph links but also searches from quantized codes.
SymphonyQG retains raw vectors and stores per-neighborhood quantization data
to improve its access pattern.
IVF and SymphonyQG use [FastScan](https://arxiv.org/abs/1704.07355) for batched
estimates, while HNSW uses single-code AVX2 or AVX-512 kernels.

In typical workloads, 4-bit, 5-bit, and 7-bit quantization can achieve roughly
90%, 95%, and 99% recall, respectively, without reranking. Actual results
depend on the dataset, index configuration, and search parameters.

## RaBitQ in industry

RaBitQ has been adopted by vector databases, search engines, and libraries:

- [Milvus](https://github.com/milvus-io/milvus) — IVF + RaBitQ (C++)
- [Faiss](https://github.com/facebookresearch/faiss) — IVF + RaBitQ (C++)
- [VSAG](https://github.com/antgroup/vsag) — HGraph + RaBitQ (C++)
- [VectorChord](https://github.com/tensorchord/VectorChord) — IVF + RaBitQ (Rust)
- [Volcengine OpenSearch](https://www.volcengine.com/docs/6465/1553583) — DiskANN + RaBitQ
- [CockroachDB](https://github.com/cockroachdb/cockroach) — CSPANN + RaBitQ (Go)
- [Elasticsearch](https://github.com/elastic/elasticsearch) — HNSW + BBQ, a modified RaBitQ implementation (Java)
- [Lucene](https://github.com/apache/lucene) — HNSW + BBQ, a modified RaBitQ implementation (Java)
- [turbopuffer](https://turbopuffer.com/blog/ann-v3#:~:text=ANN%20v3%20employs%20the%20RaBitQ) — SPFresh + RaBitQ
- [Zvec](https://github.com/alibaba/zvec) — HNSW/IVF + RaBitQ (C++)

## Citation

If RaBitQ helps your research or system, please cite:

> Jianyang Gao, Yutong Gou, Yuexuan Xu, Yongyi Yang, Cheng Long, and Raymond
> Chi-Wing Wong. “Practical and Asymptotically Optimal Quantization of
> High-Dimensional Vectors in Euclidean Space for Approximate Nearest Neighbor
> Search.” SIGMOD 2025. [arXiv:2409.09913](https://arxiv.org/abs/2409.09913).
> Search.” *Proceedings of the ACM on Management of Data* 3, 3, Article 202
> (June 2025), 26 pages. [https://doi.org/10.1145/3725413](https://doi.org/10.1145/3725413).

## Contributing

Contributions are welcome. See the [contributing guide](CONTRIBUTING.md) for
the build, formatting, pre-commit, and static-analysis workflows.

## Acknowledgements

Expand Down
Binary file added docs/docs/assets/img/acc_bench.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 12 additions & 2 deletions docs/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ indexes backed by optimized AVX2 and AVX-512 kernels.
</div>
</div>

## Accuracy at a glance

![RaBitQ estimation error benchmark across MSong, YouTube, OpenAI embeddings, Word2Vec, and GIST](assets/img/acc_bench.png)

*Average and maximum relative estimation error across six datasets; lower is
better. Results from the
[SIGMOD camera-ready paper](https://doi.org/10.1145/3725413).*

## Start with Python

Install the latest release from PyPI:
Expand Down Expand Up @@ -103,7 +111,7 @@ degree, and search parameters.
The library supports Euclidean distance and inner product. Cosine similarity
can be implemented by normalizing vectors and using inner product.
It implements the [1-bit RaBitQ](https://arxiv.org/abs/2405.12497) and
[multi-bit RaBitQ](https://arxiv.org/abs/2409.09913) research from the
[multi-bit RaBitQ](https://doi.org/10.1145/3725413) research from the
[VectorDB Group](https://vectordb-ntu.github.io/) at Nanyang Technological
University.

Expand All @@ -114,6 +122,7 @@ RaBitQ has been adopted by projects including
[Faiss](https://github.com/facebookresearch/faiss),
[VSAG](https://github.com/antgroup/vsag),
[VectorChord](https://github.com/tensorchord/VectorChord),
[Volcengine OpenSearch](https://www.volcengine.com/docs/6465/1553583),
[CockroachDB](https://github.com/cockroachdb/cockroach),
[Elasticsearch](https://github.com/elastic/elasticsearch),
[Lucene](https://github.com/apache/lucene),
Expand All @@ -127,4 +136,5 @@ If RaBitQ helps your research or system, please cite:
> Jianyang Gao, Yutong Gou, Yuexuan Xu, Yongyi Yang, Cheng Long, and Raymond
> Chi-Wing Wong. “Practical and Asymptotically Optimal Quantization of
> High-Dimensional Vectors in Euclidean Space for Approximate Nearest Neighbor
> Search.” SIGMOD 2025. [arXiv:2409.09913](https://arxiv.org/abs/2409.09913).
> Search.” *Proceedings of the ACM on Management of Data* 3, 3, Article 202
> (June 2025), 26 pages. [https://doi.org/10.1145/3725413](https://doi.org/10.1145/3725413).
2 changes: 1 addition & 1 deletion docs/docs/rabitq/quantizer.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ The binary code is easily computed by the function `one_bit_code` in `rabitq_imp

The computation of ex-codes includes two versions of implementation.

In the first implementation, we compute the ex-codes of RaBitQ based on the algorithm described in the RaBitQ [paper](https://arxiv.org/abs/2409.09913) (Section 3.2.2). For a vector, to minimize the quantization error, the algorithm tries many different rescaling factors. For each rescaling factor, it rescales the vector and performs rounding (i.e., scalar quantization) to generate a quantization code. Then it finds out the factor and codes which minimizes the quantization error. Note that in the library, the range of enumeration is approriately shrinked, which brings better efficiency without affecting the accuracy.
In the first implementation, we compute the ex-codes of RaBitQ based on the algorithm described in the RaBitQ [SIGMOD paper](https://doi.org/10.1145/3725413) (Section 3.2.2). For a vector, to minimize the quantization error, the algorithm tries many different rescaling factors. For each rescaling factor, it rescales the vector and performs rounding (i.e., scalar quantization) to generate a quantization code. Then it finds out the factor and codes which minimizes the quantization error. Note that in the library, the range of enumeration is approriately shrinked, which brings better efficiency without affecting the accuracy.

In the second implementation, instead of enumerating different rescaling factors, it directly rounds every vector based on the **expected optimal factor**. Specifically, recall that all data vectors are randomly rotated before quantization. The expected optimal factor is computed as follows. We sample several random vectors which follow uniform distribution on the unit sphere and use the first implementation to quantize them. We record the optimal factor for each and take the average of the optimal factors as the expected optimal factor. This implementation introduces some accuracy decrease while significantly speeds up the quantization.

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/rabitq/rabitq.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# RaBitQ

The RaBitQ algorithm is a drop-in replacement of binary quantization and (uniform) scalar quantization, with its [1-bit version](https://arxiv.org/abs/2405.12497) (released in May 2024) and [multi-bit version](https://arxiv.org/abs/2409.09913) (released in Sep 2024), respectively.
The RaBitQ algorithm is a drop-in replacement of binary quantization and (uniform) scalar quantization, with its [1-bit version](https://arxiv.org/abs/2405.12497) (released in May 2024) and [multi-bit version](https://doi.org/10.1145/3725413) (published at SIGMOD 2025), respectively.

<!-- It provides significantly better accuracy under the same space budget and is theoretically proven to be asymptotically optimal. -->

Expand Down
Loading
Loading