From 5175e55ca477790c36e79b30d2260d5850e92775 Mon Sep 17 00:00:00 2001 From: "biao.zhoub" Date: Tue, 18 Aug 2026 11:09:43 +0800 Subject: [PATCH] fix: correct sindi n_candidate error message and doc Signed-off-by: biao.zhoub --- docs/docs/en/src/indexes/sindi.md | 2 +- docs/docs/zh/src/indexes/sindi.md | 2 +- src/algorithm/sindi/sindi.cpp | 2 +- tests/test_sindi.cpp | 25 +++++++++++++++++++++++++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/docs/docs/en/src/indexes/sindi.md b/docs/docs/en/src/indexes/sindi.md index b4f5affdbe..2198f358ba 100644 --- a/docs/docs/en/src/indexes/sindi.md +++ b/docs/docs/en/src/indexes/sindi.md @@ -141,7 +141,7 @@ Search-time parameters live under the `sindi` sub-object: | Parameter | Type | Default | Description | |-----------|------|---------|-------------| -| `n_candidate` | int | `0` | Candidate heap size. When `0`, defaults to `SPARSE_AMPLIFICATION_FACTOR · topk` (500×). If set, must satisfy `1 ≤ n_candidate ≤ SPARSE_AMPLIFICATION_FACTOR · topk`. | +| `n_candidate` | int | `0` | Candidate heap size. The effective candidate effort is `max(n_candidate, topk)`, so the default `0` keeps the heap at `topk` with no candidate amplification. Must satisfy `0 ≤ n_candidate ≤ SPARSE_AMPLIFICATION_FACTOR · topk` (500×). | | `query_prune_ratio` | float | `0.0` | Fraction of lowest-weight query terms skipped (`[0.0, 1.0)`). | | `term_prune_ratio` | float | `0.0` | Fraction of the lowest-value postings skipped from each term list (`[0.0, 1.0)`). | | `term_retain_threshold` | uint64 | `0` | Maximum postings for one term across all windows. A value of `0` disables this limit; positive values allow each non-empty window posting list to scan at most `max(1, floor(threshold / window_count))` postings. | diff --git a/docs/docs/zh/src/indexes/sindi.md b/docs/docs/zh/src/indexes/sindi.md index 075f2be087..6ac186dc37 100644 --- a/docs/docs/zh/src/indexes/sindi.md +++ b/docs/docs/zh/src/indexes/sindi.md @@ -131,7 +131,7 @@ auto result = index->KnnSearch( | 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| -| `n_candidate` | int | `0` | 候选堆大小。为 `0` 时自动取 `SPARSE_AMPLIFICATION_FACTOR · topk`(500 倍);若显式设置,须满足 `1 ≤ n_candidate ≤ SPARSE_AMPLIFICATION_FACTOR · topk` | +| `n_candidate` | int | `0` | 候选堆大小。实际候选规模为 `max(n_candidate, topk)`,缺省 `0` 时候选堆大小等于 `topk`,不做候选放大;须满足 `0 ≤ n_candidate ≤ SPARSE_AMPLIFICATION_FACTOR · topk`(500 倍) | | `query_prune_ratio` | float | `0.0` | 查询时丢弃权重最低查询项的比例,取值范围为 `[0.0, 1.0)` | | `term_prune_ratio` | float | `0.0` | 每条倒排链中按 value 丢弃低权 posting 的比例,取值范围为 `[0.0, 1.0)` | | `term_retain_threshold` | uint64 | `0` | 单个 term 在所有 window 中最多扫描的 posting 总数;`0` 表示关闭此限制,正数使每个 window 的非空 posting list 最多扫描 `max(1, floor(threshold / window_count))` 个 | diff --git a/src/algorithm/sindi/sindi.cpp b/src/algorithm/sindi/sindi.cpp index d449c5ff97..4f78e72605 100644 --- a/src/algorithm/sindi/sindi.cpp +++ b/src/algorithm/sindi/sindi.cpp @@ -641,7 +641,7 @@ SINDI::KnnSearch(const DatasetPtr& query, CHECK_ARGUMENT(search_param.n_candidate <= SPARSE_AMPLIFICATION_FACTOR * k, fmt::format("n_candidate ({}) should be less than {} * k ({})", search_param.n_candidate, - AMPLIFICATION_FACTOR, + SPARSE_AMPLIFICATION_FACTOR, k)); InnerSearchParam inner_param; inner_param.ef = std::max(static_cast(search_param.n_candidate), k); diff --git a/tests/test_sindi.cpp b/tests/test_sindi.cpp index 91e885ffb2..4ce31eaf0b 100644 --- a/tests/test_sindi.cpp +++ b/tests/test_sindi.cpp @@ -200,6 +200,31 @@ TEST_CASE_PERSISTENT_FIXTURE(fixtures::SINDITestIndex, REQUIRE_FALSE(search_result.has_value()); } +TEST_CASE_PERSISTENT_FIXTURE(fixtures::SINDITestIndex, + "n_candidate Limit Matches Error Message", + "[ft][search][sindi]") { + fixtures::SINDIParam param; + auto index = TestFactory("sindi", GenerateBuildParameter(param), true); + auto dataset = pool.GetSparseDatasetAndCreate(base_count, 128, 0.8); + TestBuildIndex(index, dataset, true); + auto query = fixtures::get_one_query(dataset->query_, 0); + + const auto make_param = [](uint32_t n_candidate) { + return fmt::format(R"({{"sindi":{{"n_candidate":{},"query_prune_ratio":0.0,)" + R"("term_prune_ratio":0.0}}}})", + n_candidate); + }; + + constexpr int64_t k = 1; + // the error message must cite the same factor (500) used by the check + auto result = index->KnnSearch(query, k, make_param(500 * k + 1)); + REQUIRE_FALSE(result.has_value()); + REQUIRE(result.error().message.find("should be less than 500 * k") != std::string::npos); + + result = index->KnnSearch(query, k, make_param(500 * k)); + REQUIRE(result.has_value()); +} + TEST_CASE_PERSISTENT_FIXTURE(fixtures::SINDITestIndex, "SINDI Build and Search", "[ft][build][search][sindi]") {