RaBitQ
rabitq is VSAG’s binary / low-bit quantizer. In its default mode each
coordinate is encoded with 1 bit, giving the highest compression ratio
of any built-in quantizer. On HGraph and Pyramid, an x+y split mode stores low-bit base
codes as x filter bits plus y supplement bits, so graph traversal can use
only the filter code and re-ranking can fetch only the supplement bits it needs.
Implementation:
src/quantization/rabitq_quantization/rabitq_quantizer.cpp, parameter filerabitq_quantizer_parameter.cpp. For the complete split layout, lower-bound formula, and IO modes, see RaBitQ x+y Split.
When to use it
- Maximum compression. 1-bit codes are the smallest possible storage for dense vectors.
- High-dim embeddings where rotation + binarization preserves enough geometry for nearest-neighbor search.
- Combined with a precise reorder store (
fp16/fp32) — the standard recipe is “RaBitQ + reorder”, because the binary distance is noisy on its own.
For best accuracy, also enable rabitq_use_fht: true or wrap with a
Transform Quantizer chain such
as "pca, rom, rabitq".
Memory cost (codes only)
rabitq_bits_per_dim_base = 1:ceil(dim / 8)bytes per vector. Withdim = 768that is 96 bytes (vs 3072 for fp32 → 32× smaller).rabitq_bits_per_dim_base = xplusrabitq_bits_per_dim_precise = yon HGraph or Pyramid: split mode stores roughly(x + y) * dim / 8bytes per vector for the RaBitQ code bytes. For example,3+5is aboutdimbytes per vector.
Parameters
| Key | Type | Default | Meaning |
|---|---|---|---|
pca_dim | int | 0 (= input dim) | Optional PCA preprocessing dimension applied inside RaBitQ. 0 means no PCA reduction (rabitq_quantizer_parameter.cpp:30-32). |
rabitq_bits_per_dim_query | int | 32 | Bits per dimension used to encode the query during search. Allowed values: 4 or 32 (rabitq_quantizer_parameter.cpp:38-43). |
rabitq_bits_per_dim_base | int | 1 | In standard RaBitQ, bits per dimension for the stored base code. In HGraph/Pyramid x+y split mode, this external key means x, the filter bits used during graph traversal. Allowed range [1, 8]. |
rabitq_bits_per_dim_precise | int | unset | HGraph/Pyramid split-mode key. When present with base_quantization_type: "rabitq" and precise_quantization_type: "rabitq", this means y, the supplement bits used for reorder/full-distance refinement. The sum x + y must be <= 8. |
rabitq_error_rate | float | 1.9 | Default lower-bound error multiplier for HGraph/Pyramid split search; must be finite and positive. It can be overridden per search under the hgraph or pyramid object. |
use_fht | bool | false | If true, applies a Fast Hadamard Transform rotation before binarization. Improves accuracy on anisotropic data with cheap O(dim log dim) cost (rabitq_quantizer_parameter.cpp:76-78). |
fast_encode_rabitq | bool | true | For stored codes wider than one bit, use CAQ-based fast encoding. Set to false to retain the exact RaBitQ encoder. The setting is ignored for one-bit codes. |
fast_encode_rabitq_rounds | int | 6 | Number of CAQ coordinate-adjustment rounds. Allowed range: [1, 32]. Each coordinate moves by at most one level per round. |
Multi-bit RaBitQ uses an LVQ initialization followed by fixed-round coordinate
adjustment when fast_encode_rabitq is enabled. This reduces code selection
from approximately O(2^B * dim * log(dim)) to O(rounds * dim) while keeping
the existing code layout and query estimator. The implementation follows the
CAQ component of SAQ; use the exact fallback
when measuring the quality/speed trade-off on a new dataset. These build-only
settings do not affect index loading compatibility. VSAG uses a clean-room
implementation and does not depend on the Apache-2.0 licensed
SAQ reference repository.
Index pages expose RaBitQ settings as top-level index_param keys:
HGraph exposes rabitq_pca_dim, rabitq_bits_per_dim_query,
rabitq_bits_per_dim_base, rabitq_bits_per_dim_precise,
rabitq_error_rate, and rabitq_use_fht; IVF exposes
rabitq_pca_dim, rabitq_bits_per_dim_query, rabitq_bits_per_dim_base,
rabitq_version, rabitq_error_rate, and rabitq_use_fht; Pyramid exposes
the PCA, base/query bit, and FHT keys for its base quantizer. The
rabitq_use_fht key is an index-level alias for the quantizer’s internal
use_fht key and is rewritten by the index layer.
fast_encode_rabitq and fast_encode_rabitq_rounds are available on HGraph,
IVF, and Pyramid and are propagated to both base and precise RaBitQ quantizers.
For a normal first HGraph build with split RaBitQ and fast_encode_rabitq=true,
HGraph first encodes all vectors into one unsigned-byte scalar code per dimension, together
with the standard RaBitQ metadata and a separate 8-byte code sum per vector. It waits for
that parallel encoding phase before starting graph tasks. Those tasks use scalar SIMD kernels
for code-code distances; the raw inner-product kernels are independent of the configured
x+y bit count, while the quantizer still applies the matching quantization range and
center. After construction, the scalar codes are packed
once into bit planes and written to the persistent filter and supplement stores without
rerunning PCA, ROM/FHT, or RaBitQ quantization. The temporary scalar records and code sums
are released before Build returns. For an 8-bit total code the scalar and packed
payloads have the same size; lower total bit counts trade extra build memory for faster
graph-distance evaluation.
{
"dtype": "float32",
"metric_type": "l2",
"dim": 768,
"index_param": {
"base_quantization_type": "rabitq",
"rabitq_use_fht": true,
"rabitq_pca_dim": 0,
"rabitq_bits_per_dim_base": 1,
"rabitq_bits_per_dim_query": 32,
"max_degree": 32,
"ef_construction": 300,
"use_reorder": true,
"precise_quantization_type": "fp32"
}
}
Swap to the higher-accuracy x+y split mode by setting both base and precise
quantization to RaBitQ and providing rabitq_bits_per_dim_precise. HGraph and Pyramid then
automatically select the split datacell. In the example below, traversal uses
x = 3 filter bits and reorder reads only y = 5 supplement bits:
{
"base_quantization_type": "rabitq",
"precise_quantization_type": "rabitq",
"rabitq_bits_per_dim_base": 3,
"rabitq_bits_per_dim_precise": 5,
"rabitq_use_fht": true
}
Training
NEED_TRAIN is set. Training learns the rotation and per-dimension
statistics that make the 1-bit encoding well-balanced. The optional FHT
rotation is fixed (not learned), so it adds no extra training cost; PCA
preprocessing (when pca_dim > 0) trains a projection matrix.
Metric compatibility
l2, ip, cosine — all supported. The binary distance kernel is a
popcount over XORed code words; for ip / cosine the implementation
also tracks a residual norm so the inner-product estimate is unbiased.
Tips
- Always enable reorder unless you have validated that 1-bit recall
is acceptable on your data.
use_reorder: true+precise_quantization_type: "fp32"is the safe default. - Rotate first. For un-normalized data, set
rabitq_use_fht: trueor use atqchain that includesrom/fht. - Split mode for accuracy. HGraph/Pyramid
x+ysplit keeps anx-bit fast path for graph traversal and addsysupplement bits for re-ranking; expect significantly higher recall than pure 1-bit when using more total bits.