Skip to content
Open
Show file tree
Hide file tree
Changes from 8 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
5 changes: 4 additions & 1 deletion docs/docs/en/src/indexes/pyramid.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ Build-time parameters live under `index_param`.
| `neighbor_sample_rate` | float | — | ODescent neighbor sampling rate. |
| `no_build_levels` | int[] | `[]` | Tree levels that skip graph construction (0-indexed from the root). |
| `use_reorder` | bool | `false` | Keep a high-precision copy for rescoring. |
| `precise_quantization_type` | string | `"fp32"` | Quantizer for reordering. |
| `precise_quantization_type` | string | `"fp32"` | Quantizer for reordering. Use `"rabitq"` with `rabitq_bits_per_dim_precise` to enable RaBitQ x+y split reorder from base storage. |
| `rabitq_bits_per_dim_base` | int | `1` | RaBitQ stored-code bits. In x+y split mode, this is `x`, the filter bits used during graph traversal; allowed range is `[1, 8]`. |
| `rabitq_bits_per_dim_precise` | int | unset | RaBitQ split `y` bits. When set with `base_quantization_type: "rabitq"` and `precise_quantization_type: "rabitq"`, Pyramid uses split storage; `rabitq_bits_per_dim_base` remains `x`, and `x + y <= 8`. |
| `fast_encode_rabitq` | bool | `true` | Use the fast multi-bit RaBitQ encoder for RaBitQ base or precise storage; set to `false` for the exact encoder. |
| `fast_encode_rabitq_rounds` | int | `6` | Fast RaBitQ refinement rounds in `[1, 32]`. |
| `base_io_type` / `precise_io_type` | string | `"block_memory_io"` | Base and reorder storage backends; `uring_io` is available in builds with liburing. |
Expand All @@ -113,6 +115,7 @@ Search-time parameters live under the `pyramid` sub-object:
| `subindex_ef_search` | int | `50` | Candidate list size used when traversing intermediate sub-graphs on the path. |
Comment thread
LightWant marked this conversation as resolved.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[suggestion] rabitq_one_bit_search search parameter is undocumented in the pyramid parameter table

PyramidSearchParameters::FromJson parses pyramid.rabitq_one_bit_search, and the pyramid.h constructor computes default_rabitq_one_bit_search_ to enable one-bit split search by default for split indexes. The rabitq_split.md docs mention this parameter, but the pyramid search parameter tables in both docs/docs/en/src/indexes/pyramid.md and docs/docs/zh/src/indexes/pyramid.md do not list it.

Consider adding a row like:
| rabitq_one_bit_search | bool | auto (true for split indexes) | Force the one-bit lower-bound search path in RaBitQ split mode. |

| `hierarchies` | string[] | `[]` | Select which hierarchy to search. Empty means use the default (unnamed) hierarchy. |
| `hierarchy_op` | string | `"single"` | How to combine results across hierarchies: `single` (search one hierarchy), `union`, or `intersection`. **Note:** `union` and `intersection` are not yet implemented — setting them will cause `KnnSearch`/`RangeSearch` to return an error. |
| `rabitq_error_rate` | float | index default | Positive lower-bound error multiplier for this search. |

```cpp
auto result = index->KnnSearch(
Expand Down
18 changes: 9 additions & 9 deletions docs/docs/en/src/quantization/rabitq.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

`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, an `x+y` split mode stores low-bit base
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.

![RaBitQ: encode each coordinate by its sign relative to a random hyperplane](../figures/quantization/rabitq-hyperplane.svg)

> Implementation: `src/quantization/rabitq_quantization/rabitq_quantizer.cpp`,
> parameter file `rabitq_quantizer_parameter.cpp`.
> For the complete HGraph split layout, lower-bound formula, and IO modes,
> For the complete split layout, lower-bound formula, and IO modes,
> see [RaBitQ x+y Split](rabitq_split.md).

## When to use it
Expand All @@ -32,7 +32,7 @@ as `"pca, rom, rabitq"`.
- `rabitq_bits_per_dim_base = 1`: `ceil(dim / 8)` bytes per vector. With
`dim = 768` that is 96 bytes (vs 3072 for fp32 → 32× smaller).
- `rabitq_bits_per_dim_base = x` plus `rabitq_bits_per_dim_precise = y`
on HGraph: split mode stores roughly `(x + y) * dim / 8` bytes per vector
on HGraph or Pyramid: split mode stores roughly `(x + y) * dim / 8` bytes per vector
for the RaBitQ code bytes. For example, `3+5` is about `dim` bytes per
vector.

Expand All @@ -42,9 +42,9 @@ as `"pca, rom, rabitq"`.
| --- | --- | --- | --- |
| `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 `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-only 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 split search; must be finite and positive. It can be overridden per search under the `hgraph` object. |
| `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. |
Expand Down Expand Up @@ -105,8 +105,8 @@ graph-distance evaluation.
```

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 then
automatically selects the split datacell. In the example below, traversal uses
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:

```json
Expand Down Expand Up @@ -139,7 +139,7 @@ also tracks a residual norm so the inner-product estimate is unbiased.
`precise_quantization_type: "fp32"` is the safe default.
- **Rotate first.** For un-normalized data, set `rabitq_use_fht: true` or
use a `tq` chain that includes `rom` / `fht`.
- **Split mode for accuracy.** HGraph `x+y` split keeps an `x`-bit fast path
- **Split mode for accuracy.** HGraph/Pyramid `x+y` split keeps an `x`-bit fast path
for graph traversal and adds `y` supplement bits for re-ranking; expect
significantly higher recall than pure 1-bit when using more total bits.

Expand Down
14 changes: 7 additions & 7 deletions docs/docs/en/src/quantization/rabitq_split.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# RaBitQ x+y Split

RaBitQ x+y split is an HGraph storage and search mode for low-bit base codes.
RaBitQ x+y split is an HGraph and Pyramid storage and search mode for low-bit base codes.
Each vector is divided into two records:

- `x` filter bits are read during graph traversal and lower-bound filtering.
Expand All @@ -13,7 +13,7 @@ memory while the colder supplement record is stored on disk.

## Enable split mode

HGraph selects split mode when both quantization types are `rabitq` and
HGraph and Pyramid select split mode when both quantization types are `rabitq` and
`rabitq_bits_per_dim_precise` is present:

```json
Expand Down Expand Up @@ -55,7 +55,7 @@ The constraints are:
x + y <= 8
```

If `rabitq_bits_per_dim_precise` is omitted, HGraph uses the standard RaBitQ
If `rabitq_bits_per_dim_precise` is omitted, HGraph and Pyramid use the standard RaBitQ
path instead of split storage.

Enable the filter/lower-bound search path with:
Expand Down Expand Up @@ -90,7 +90,7 @@ The split search path has four stages:
4. The final distance combines the filter contribution and supplement
contribution into one `x+y`-bit RaBitQ estimate.

The HGraph heap is therefore not populated with an `x+y` distance for every
The graph-search heap is therefore not populated with an `x+y` distance for every
visited vector. The inexpensive x-bit distance drives traversal; the more
accurate distance is evaluated only during candidate reorder.

Expand Down Expand Up @@ -260,7 +260,7 @@ sum_i q_i * u_i
+ sum_i q_i * s_i
```

For L2 with an x-bit lookup filter, HGraph passes the previously computed
For L2 with an x-bit lookup filter, HGraph and Pyramid pass the previously computed
filter distance to reorder as a hint. `ComputeDistWithSplitCodeAndFilterDist`
recovers the first term from that hint and computes only the second term from
the y supplement planes:
Expand Down Expand Up @@ -356,12 +356,12 @@ search-time `hgraph.rabitq_error_rate` does not.

## Operational notes

- Split storage is currently an HGraph feature and requires fp32 query codes.
- Split storage is currently available on HGraph and Pyramid and requires fp32 query codes. Pyramid enables the one-bit split search path by default for split indexes; pass `rabitq_one_bit_search: false` under `pyramid` to force the standard search path.
- `l2`, `ip`, and `cosine` are supported. The filter-hint reorder shortcut is
currently specialized for L2.
- Keep `use_reorder: true` unless x-bit traversal accuracy alone has been
validated for the dataset.
- Changing x, y, metric, or transform parameters requires rebuilding the
index. A search-time `hgraph.rabitq_error_rate` override does not.
- Use [RaBitQ](rabitq.md) for the general quantizer description and
[HGraph](../indexes/hgraph.md) for the complete index parameter table.
[HGraph](../indexes/hgraph.md) and [Pyramid](../indexes/pyramid.md) for the complete index parameter tables.
5 changes: 4 additions & 1 deletion docs/docs/zh/src/indexes/pyramid.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ auto result = index->KnnSearch(
| `neighbor_sample_rate` | float | — | ODescent 的邻居采样比率 |
| `no_build_levels` | int[] | `[]` | 跳过构图的层级(从根节点开始的 0-based 下标) |
| `use_reorder` | bool | `false` | 是否保留高精度副本用于精排 |
| `precise_quantization_type` | string | `"fp32"` | 精排使用的量化类型 |
| `precise_quantization_type` | string | `"fp32"` | 精排使用的量化类型。与 `rabitq_bits_per_dim_precise` 配合设为 `"rabitq"` 时,可启用从 base storage 重排的 RaBitQ x+y split。 |
| `rabitq_bits_per_dim_base` | int | `1` | RaBitQ 底库存储码的每维位数。在 x+y split 模式下表示 `x`,即图遍历使用的 filter bits;范围为 `[1, 8]`。 |
| `rabitq_bits_per_dim_precise` | int | 未设置 | RaBitQ split 的 `y` bits。和 `base_quantization_type: "rabitq"`、`precise_quantization_type: "rabitq"` 一起设置时,Pyramid 使用 split storage;`rabitq_bits_per_dim_base` 仍表示 `x`,且 `x + y <= 8`。 |
| `fast_encode_rabitq` | bool | `true` | 对 RaBitQ 底层或精排存储使用多 bit 快速编码器;设为 `false` 使用精确编码器 |
| `fast_encode_rabitq_rounds` | int | `6` | RaBitQ 快速编码的微调轮数,范围 `[1, 32]` |
| `base_io_type` / `precise_io_type` | string | `"block_memory_io"` | 底层与精排存储后端;以 liburing 构建时可用 `uring_io` |
Expand All @@ -108,6 +110,7 @@ auto result = index->KnnSearch(
| `subindex_ef_search` | int | `50` | 沿路径向下遍历中间子图时的候选集大小 |
| `hierarchies` | string[] | `[]` | 指定检索哪个层级。空数组表示使用默认(匿名)层级。 |
| `hierarchy_op` | string | `"single"` | 多层级结果合并方式:`single`(检索单个层级)、`union`、`intersection`。**注意:** `union` 和 `intersection` 尚未实现——设置后 `KnnSearch`/`RangeSearch` 会返回错误。 |
| `rabitq_error_rate` | float | 索引默认值 | 本次搜索使用的正数 lower-bound 误差倍率。 |

```cpp
auto result = index->KnnSearch(
Expand Down
18 changes: 9 additions & 9 deletions docs/docs/zh/src/quantization/rabitq.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# RaBitQ

`rabitq` 是 VSAG 的二值 / 低比特量化器。默认模式下每个坐标用 **1 比特**
编码,给出所有内建量化器中最高的压缩率。在 HGraph 上,`x+y` split 模式把
编码,给出所有内建量化器中最高的压缩率。在 HGraph 和 Pyramid 上,`x+y` split 模式把
底库码拆成 `x` 个过滤 bit 和 `y` 个 supplement bit:图遍历只使用 filter code,
重排 / full-distance 阶段只额外读取 supplement bits。

![RaBitQ:按坐标相对随机超平面的符号进行编码](../figures/quantization/rabitq-hyperplane.svg)

> 实现:`src/quantization/rabitq_quantization/rabitq_quantizer.cpp`,
> 参数文件 `rabitq_quantizer_parameter.cpp`。
> HGraph split 的完整存储布局、lower bound 公式和 IO 模式见
> split 的完整存储布局、lower bound 公式和 IO 模式见
> [RaBitQ x+y Split](rabitq_split.md)。

## 何时使用
Expand All @@ -27,7 +27,7 @@

- `rabitq_bits_per_dim_base = 1`:每向量 `ceil(dim / 8)` 字节。`dim = 768`
时为 96 字节(对比 fp32 的 3072 → 小 32×)。
- HGraph 上 `rabitq_bits_per_dim_base = x` 且
- HGraph 或 Pyramid 上 `rabitq_bits_per_dim_base = x` 且
`rabitq_bits_per_dim_precise = y`:split 模式约存储
`(x + y) * dim / 8` 字节的 RaBitQ code。例如 `3+5` 约为每向量 `dim`
字节。
Expand All @@ -38,9 +38,9 @@
| --- | --- | --- | --- |
| `pca_dim` | int | `0`(= 输入维度) | RaBitQ 内部可选的 PCA 预处理维度。`0` 表示不做 PCA 降维(`rabitq_quantizer_parameter.cpp:30-32`)。 |
| `rabitq_bits_per_dim_query` | int | `32` | 搜索时**查询**的每维位数。允许值:`4` 或 `32`(`rabitq_quantizer_parameter.cpp:38-43`)。 |
| `rabitq_bits_per_dim_base` | int | `1` | standard RaBitQ 下表示底库码每维位数;HGraph `x+y` split 下,这个外部 key 表示 `x`,即图遍历过滤阶段使用的 filter bits。范围 `[1, 8]`。 |
| `rabitq_bits_per_dim_precise` | int | 未设置 | HGraph-only split 模式 key。和 `base_quantization_type: "rabitq"`、`precise_quantization_type: "rabitq"` 一起出现时表示 `y`,即重排 / full-distance 阶段读取的 supplement bits。要求 `x + y <= 8`。 |
| `rabitq_error_rate` | float | `1.9` | HGraph split 搜索的默认 lower-bound 误差倍率;必须为有限正数,也可以在 `hgraph` 搜索参数中按次覆盖。 |
| `rabitq_bits_per_dim_base` | int | `1` | standard RaBitQ 下表示底库码每维位数;HGraph/Pyramid `x+y` split 下,这个外部 key 表示 `x`,即图遍历过滤阶段使用的 filter bits。范围 `[1, 8]`。 |
| `rabitq_bits_per_dim_precise` | int | 未设置 | HGraph/Pyramid split 模式 key。和 `base_quantization_type: "rabitq"`、`precise_quantization_type: "rabitq"` 一起出现时表示 `y`,即重排 / full-distance 阶段读取的 supplement bits。要求 `x + y <= 8`。 |
| `rabitq_error_rate` | float | `1.9` | HGraph/Pyramid split 搜索的默认 lower-bound 误差倍率;必须为有限正数,也可以在 `hgraph` 或 `pyramid` 搜索参数中按次覆盖。 |
| `use_fht` | bool | `false` | `true` 时在二值化前应用快速 Hadamard 变换旋转。以 O(dim log dim) 的廉价代价提升各向异性数据上的精度(`rabitq_quantizer_parameter.cpp:76-78`)。 |
| `fast_encode_rabitq` | bool | `true` | 对大于 1 bit 的底库码启用基于 CAQ 的快速编码;设为 `false` 时使用原有精确编码。1 bit 编码会忽略此参数。 |
| `fast_encode_rabitq_rounds` | int | `6` | CAQ 坐标微调轮数,范围 `[1, 32]`;每个坐标在每轮最多移动一级。 |
Expand All @@ -59,7 +59,7 @@
`rabitq_bits_per_dim_precise`、`rabitq_error_rate`、`rabitq_use_fht`;IVF
暴露 `rabitq_pca_dim`、`rabitq_bits_per_dim_query`、
`rabitq_bits_per_dim_base`、`rabitq_version`、`rabitq_error_rate`、
`rabitq_use_fht`;Pyramid 为底层量化器暴露 PCA、底库/查询位数和 FHT
`rabitq_use_fht`;Pyramid 为底层量化器暴露 PCA、底库/查询位数、split precise 位数、误差倍率和 FHT
相关 key。其中 `rabitq_use_fht` 是索引层对量化器内部 `use_fht` key
的别名,会由索引层重写。

Expand Down Expand Up @@ -97,7 +97,7 @@ PCA、ROM/FHT 或 RaBitQ 量化。scalar record 与 code-sum 数组都会在
```

切换到高精度的 `x+y` split 模式:把 base 和 precise 量化都设置为 RaBitQ,
并提供 `rabitq_bits_per_dim_precise`。HGraph 会自动选择 split datacell。
并提供 `rabitq_bits_per_dim_precise`。HGraph 和 Pyramid 会自动选择 split datacell。
下面例子中,图遍历使用 `x = 3` 个 filter bits,重排只读取 `y = 5` 个
supplement bits:

Expand Down Expand Up @@ -128,7 +128,7 @@ FHT 旋转是固定的(无需学习),因此不增加训练代价;PCA 预
`use_reorder: true` + `precise_quantization_type: "fp32"` 是稳妥默认。
- **先旋转。** 对未归一化数据,设 `rabitq_use_fht: true`,或在 `tq` 链路
中包含 `rom` / `fht`。
- **精度优先时用 split 模式。** HGraph `x+y` split 保留 `x` bit 快速
- **精度优先时用 split 模式。** HGraph/Pyramid `x+y` split 保留 `x` bit 快速
过滤路径,再添加 `y` 个 supplement bits 用于重排;相对纯 1 比特,使用
更多总 bit 时召回明显更高。

Expand Down
Loading
Loading