Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

SINDI_V2

SINDI_V2 是 VSAG 的 term-first 稀疏向量索引。它与 SINDI 使用相同的窗口化倒排检索模型和 1 - inner_product 距离定义,但按 term 保存 posting,因此搜索时只需读取查询实际使用的倒排链。

  • 工厂入口:sindi_v2
  • 源码:src/algorithm/sindi_v2/
  • dtype 必须为:sparse
  • metric_type 必须为:ip

存储布局

每个 term payload 只保存非空 window:

non_empty_window_count
ordered {window_id, posting_count}[]
local_doc_ids[]
alignment padding
encoded_values[]

查询时,SINDI_V2 将稀疏 metadata 展开为 window_count + 1 个 window offset, 并通过 reader_io、mmap_io、buffer_io、async_io 或内存后端,只加载 查询保留 term 对应的 posting。

这与 SINDI 的 window-first 序列化不同。两个工厂入口使用不同的持久化格式, 加载索引时不能互换。

快速开始

#include <vsag/vsag.h>

std::string params = R"({
    "dtype": "sparse",
    "metric_type": "ip",
    "dim": 1024,
    "index_param": {
        "term_id_limit": 30000,
        "window_size": 50000,
        "doc_prune_ratio": 0.1,
        "use_quantization": true,
        "use_reorder": true,
        "remap_term_ids": true,
        "term_io": {
            "type": "buffer_io",
            "file_path": "/tmp/sindi_v2.terms"
        },
        "rerank_io": {
            "type": "block_memory_io"
        }
    }
})";
auto index = vsag::Factory::CreateIndex("sindi_v2", params).value();
index->Build(base);

auto result = index->KnnSearch(
    query, 10,
    R"({"sindi_v2": {
        "n_candidate": 100,
        "filter_callback_limit": 10000,
        "query_prune_ratio": 0.1,
        "term_prune_ratio": 0.2,
        "term_retain_threshold": 10000
    }})").value();

构建参数

构建参数放在 index_param 下。

参数类型默认值说明
dimint必填单条稀疏向量允许的最大非零项数量,不是词表大小。
term_id_limitint1000000term ID 上界,最高为 50 000 000。
window_sizeint50000每个 window 的文档数,范围为 10 000 到 60 000。
doc_prune_ratiofloat0.0构建时丢弃最低权重文档 term 的比例,范围为 [0.0, 1.0)。
use_quantizationbool 或 stringfalsefalse 存 FP32,true 存 SQ8,"fp16" 存 FP16。
use_reorderboolfalse保存高精度向量并对粗排候选重排。
rerank_typestring"fp32"重排存储类型:fp32、fp16 或 dmq8。FP16 以半精度保存文档 value,并以 FP32 打分。
dmq_shared_codebook_thresholdint1024低频 term 使用共享 DMQ codebook 的阈值。
remap_term_idsboolfalse压缩稀疏或间隔很大的外部 term ID。
avg_doc_term_lengthint100仅用于内存估算。
immutableboolfalse选择紧凑的只读内存 term DataCell。
term_ioobject{"type": "reader_io"}加载后保存 term-first posting 的后端。
rerank_ioobject{"type": "block_memory_io"}保存重排向量的后端。
rerank_layoutuint320top-terms-signature 布局使用的前导 term 数量;0 表示关闭。

文件型 term_io 支持 mmap_io、buffer_io 和 async_io,并要求设置 file_path。文件型 rerank_io 未设置 file_path 时,VSAG 使用 <term_io.file_path>.rerank。

rerank_type: "fp16" 要求 use_reorder: true,并支持与 fp32 相同的重排 I/O 和布局 选项。rerank_layout > 0 要求 use_reorder: true。rerank_type: "dmq8" 要求 rerank_layout: 0,并使用默认的 block_memory_io 重排后端。

Host 过滤

SINDI_V2 支持与 SINDI 相同的字符串 host 构建数据和 KNN 查询 metadata 约定。mutable 与 immutable 索引均支持该功能。两者共用 host 分组与路由组件,同时 SINDI_V2 保持自己的 term-first posting 存储。host 成员检查统一在 posting-window 检索中执行, 并支持 mutable Add() 产生的多个区间。空字符串缺失 host、持久化内部字典、mutable Add() metadata、streaming 序列化及仅支持 KNN 的规则均与 SINDI 相同。

发布时间过滤

SINDI_V2 同样支持 SINDI 的 Unix 秒输入、UTC 日匹配与闭区间时间范围约定。 两个索引共用一个 metadata 过滤组件,统一处理仅时间、仅 host 以及时间与 host 组合的 KNN 路由; SINDI_V2 仍保留 term-first posting 布局。发布时间过滤支持 mutable、immutable 以及 use_reorder 的任意设置,并由普通与 streaming 序列化共同保存;范围搜索仍不参与过滤。mutable 时间 SINDI_V2 同样是 build-once:只允许通过初次 Build() 或空索引上的第一次 Add() 写入 publish_time_stamp,之后拒绝 Add()。base 时间戳 0 沿用 SINDI 的无时间语义:无时间条件和 仅 host 查询会包含这些文档,时间查询会排除它们。为了执行精确 day 过滤,每个选中 window 都会 关闭 term 级 posting 剪枝,因此时间查询可能比仅 host 查询扫描更多 posting。在启用时间的索引上, 仅 host 查询也遵循 SINDI 所述的边界 window 行为。

检索参数

检索参数放在 {"sindi_v2": {...}} 下。

参数类型默认值说明
n_candidateint0粗排候选数量;0 使用根据 topk 推导的索引默认值。
filter_callback_limituint640单次带过滤检索最多调用用户 Filter::CheckValid 回调的次数;0 表示不限制。达到正数上限时,在正常处理最后一次回调结果后停止候选及后续 window 扫描,并返回此前已经通过过滤的候选,因此结果可能不完整。该限制适用于常规 KNN 和范围检索 API。
query_prune_ratiofloat0.0跳过最低权重查询 term 的比例,范围为 [0.0, 1.0)。
term_prune_ratiofloat0.0每条 term list 中跳过最低存储权重的比例,范围为 [0.0, 1.0)。
term_retain_thresholduint640单个 term 在所有 window 中最多扫描的 posting 总数;0 表示关闭,正数使每个非空 window posting list 最多扫描 max(1, floor(threshold / window_count)) 条。

合并 ratio 与 threshold 限制后,每条非空 term list 至少扫描一个 posting。

SINDI V2 会根据构建阶段的 doc_prune_ratio 与检索阶段的 query_prune_ratio 自动选择堆插入策略。按当前 0.1 阈值,当两个比例都 <= 0.1 时,使用基于距离数组的 入堆路径;只要任一比例大于 0.1,就使用基于 term-list 的入堆路径。

如何选择 SINDI 与 SINDI_V2

完整稀疏索引常驻内存、且 window-first 序列化合适时选择 SINDI。需要按 term 组织持久化 posting,或希望搜索时只从外部存储读取查询 term list 时选择 SINDI_V2。