trait RerankScorer: Send + Sync {
fn prepare(&self, query: &[f32]) -> Self::Prepared;
fn rescore(&self, prepared: &Self::Prepared, doc_id: u64) -> Option<f32>;
}
struct RerankPipeline {
stages: Vec<Box<dyn RerankScorer>>,
factors: Vec<usize>, // top_k * f[0], then top_k * f[1], ...
}
// Each stage narrows the candidate set by factor[i]. Composable per index type.
// Candidate buffer is SoA: (Vec<u64>, Vec<f32>) — not a tuple Vec.
Round-3 perf push sub-issue (tracked under umbrella #536).
[L] Two-stage rerank exists only for HNSW; pipeline is hard-coded
Where:
laurus/src/vector/index/hnsw/searcher.rs:493-522implements Stage-2 inline.laurus/src/vector/index/flat/searcher.rs:31-37andlaurus/src/vector/index/ivf/searcher.rs:121-127returnNotImplementedwhenrerank_factoris set. No sharedReRankScorertrait.Current behavior: Each searcher must reimplement rerank. Flat and IVF can't use the
LRS1 sidecar even though the storage pool exists. 3+ stage chains (PQ → SQ → f32) are
not expressible.
Why it might be a bottleneck / risk: Composable rerank is essential for FastScan-style
3-stage pipelines (PQ initial → SQ verify → f32 final). The current code is locked to a
single int8 → f32 path.
Reference precedent: Qdrant
ReScorertrait pluggable per index; LanceDB IVF_PQreranks against original f32 stored in the rowgroup; FAISS
IndexRefinewraps any baseindex; Lucene 9.10
ScalarQuantizedVectorScorerwithscore()separate fromrescore().Data structure (proposed):
Suggested direction: Generic
RerankScorertrait +RerankPipeline. ImplementPq8Scorer,Pq4FastScanScorer,Sq8Scorer,F32Scorer. HNSW/Flat/IVF emit acandidate set and let the pipeline run.
Risk / scope: Large architectural. Removes duplication, unlocks 3+ stage rerank,
normalises behaviour across index types.
ID:
VS-07— see~/.claude/tasks/laurus/20260523_perf_round3_audit/task_list.mdfor the full Round-3 issue list.Task list
This is now the umbrella for a 3-PR campaign (see the investigation/plan comment, 2026-08-02):
RerankStage/RerankPipelineabstraction, HNSW ported (zero behavior change) — implementation report: refactor(vector/search): RerankStage/RerankPipeline abstraction, port HNSW Stage-2 (#650 PR-1) #931 (comment)NotImplementedgap) — implementation report: feat(vector/search): Stage-2 rerank for Flat/IVF via the shared pipeline (#650 PR-2) #932 (comment)