Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
e116635
Refactor search post-processing API and default processors
narendatha Mar 9, 2026
855d673
Fix nextest -Dwarnings build and cached delete postprocess bounds
narendatha Mar 9, 2026
ecd81bb
Add determinant-diversity search mode to benchmark pipeline
narendatha Mar 9, 2026
f3d308a
Refactor search API to explicit processors and add search_with
narendatha Mar 9, 2026
4a74343
Add disk determinant-diversity search wiring and benchmark inputs
narendatha Mar 9, 2026
2729ac7
Refactor processor passing by value and remove KnnWith
narendatha Mar 12, 2026
f764aa4
Implement major Search trait refactor and remove Internal<FullPrecision>
narendatha Mar 12, 2026
ab56c93
Relocate determinant_diversity_post_process from diskann to diskann-p…
narendatha Mar 12, 2026
5cad020
Algorithm cleanup: Add determinant-diversity input validation and red…
narendatha Mar 12, 2026
3d79d6d
Benchmark: collapse determinant-diversity helper into knn
narendatha Mar 12, 2026
b8c952e
Rename HasDefaultProcessor to DelegateDefaultPostProcessor
narendatha Mar 12, 2026
b1662c1
Provider refactor: runtime start-point filtering; remove Internal<T>
narendatha Mar 12, 2026
2149388
Fix: Align SearchOutputBuffer bound with trait definition (+?Sized)
narendatha Mar 12, 2026
0540f42
Merge remote-tracking branch 'origin/main' into u/narendatha/post_pro…
narendatha Mar 12, 2026
6a1872d
merge issues fix
narendatha Mar 12, 2026
750d542
fix merge issues, clippy, fmt
narendatha Mar 12, 2026
68e4bfd
Fix cached inplace-delete post-processor wiring
narendatha Mar 12, 2026
48cd833
Revert unrelated quantization changes
Mar 13, 2026
c0f2053
Remove determinant diversity from post-processing refactor
Mar 13, 2026
054398b
Eliminate PostProcess trait — Option A
Mar 13, 2026
bb3d60a
Remove PostProcess impls across providers
Mar 13, 2026
6b8b1f5
Replace manual_async_fn with async fn in SearchPostProcess impls
Mar 13, 2026
5e2db52
Fix unused imports from PostProcess removal
Mar 13, 2026
349d0b6
Remove some more JSONs.
Mar 13, 2026
749d59b
Replace runtime filter_start_points with type-level Pipeline composition
Mar 13, 2026
008c09b
Remove misc files.
Mar 13, 2026
669dec1
Restore knn_search.rs to main's structure
Mar 14, 2026
46f05b3
Almost there.
Mar 14, 2026
6dec4bc
Last cleanups (outside of caching).
Mar 14, 2026
1cc2816
Renames.
Mar 14, 2026
2ad1ed4
Get caching provider working again.
Mar 14, 2026
0ee76b1
Clean up some stragglers.
Mar 14, 2026
5fef991
Unify naming.
Mar 14, 2026
ca84f41
Potential fix for pull request finding
hildebrandmw Mar 14, 2026
0fcfde6
Potential fix for pull request finding
hildebrandmw Mar 14, 2026
7ee952b
Potential fix for pull request finding
hildebrandmw Mar 14, 2026
bc11046
Potential fix for pull request finding
hildebrandmw Mar 14, 2026
4d44eb9
Potential fix for pull request finding
hildebrandmw Mar 14, 2026
cbb2deb
Merge remote-tracking branch 'origin/main' into mhildebr/poster
Mar 17, 2026
1f688bb
Bump version.
Mar 18, 2026
635012d
Reset back to 0.49.1
Mar 18, 2026
3145904
SearchStrategy no longer needs the output "ID" type.
Mar 19, 2026
58579bb
Add determinant-diversity search post-process and benchmark integration
narendatha Mar 23, 2026
329793b
Remove temporary benchmark results artifact
narendatha Mar 23, 2026
595e949
Rename rag terminology to determinant_diversity
narendatha Mar 23, 2026
f4bc307
Merge main into branch and resolve conflicts
narendatha Mar 24, 2026
43ccd91
Generalize benchmark KNN post-processing
narendatha Mar 26, 2026
3ff406d
bug fix in determinant diversity algorithm.
narendatha Mar 26, 2026
55d3a3e
Merge remote-tracking branch 'origin/main' into u/narendatha/determin…
narendatha Mar 26, 2026
75f9aaa
Reduce determinant rerank allocations
narendatha Mar 26, 2026
58e8917
determinant diversity: disk index support and refactoring
narendatha Mar 26, 2026
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
98 changes: 98 additions & 0 deletions diskann-benchmark-core/src/search/graph/knn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,18 @@ where
strategy: Strategy<S>,
}

/// A [`KNN`] variant that uses explicit post-processing during search.
#[derive(Debug)]
pub struct KNNWithPostProcessor<DP, T, S, P>
where
DP: provider::DataProvider,
{
index: Arc<graph::DiskANNIndex<DP>>,
queries: Arc<Matrix<T>>,
strategy: Strategy<S>,
post_processor: Strategy<P>,
}

impl<DP, T, S> KNN<DP, T, S>
where
DP: provider::DataProvider,
Expand Down Expand Up @@ -71,6 +83,39 @@ where
}
}

impl<DP, T, S, P> KNNWithPostProcessor<DP, T, S, P>
where
DP: provider::DataProvider,
{
/// Construct a new [`KNNWithPostProcessor`] searcher.
///
/// If `strategy` or `post_processor` is one of the container variants of [`Strategy`],
/// its length must match the number of rows in `queries`. If this is the case, then the
/// strategies/processors will have a querywise correspondence (see [`search::SearchResults`])
/// with the query matrix.
///
/// # Errors
///
/// Returns an error if the number of elements in `strategy` or `post_processor` is not
/// compatible with the number of rows in `queries`.
pub fn new(
index: Arc<graph::DiskANNIndex<DP>>,
queries: Arc<Matrix<T>>,
strategy: Strategy<S>,
post_processor: Strategy<P>,
) -> anyhow::Result<Arc<Self>> {
strategy.length_compatible(queries.nrows())?;
post_processor.length_compatible(queries.nrows())?;

Ok(Arc::new(Self {
index,
queries,
strategy,
post_processor,
}))
}
}

/// Additional metrics collected during [`KNN`] search.
///
/// # Note
Expand Down Expand Up @@ -132,6 +177,59 @@ where
}
}

impl<DP, T, S, P> Search for KNNWithPostProcessor<DP, T, S, P>
where
DP: provider::DataProvider<Context: Default, ExternalId: search::Id>,
S: glue::DefaultSearchStrategy<DP, [T], DP::ExternalId> + Clone + AsyncFriendly,
T: AsyncFriendly + Clone,
P: for<'a> glue::SearchPostProcess<S::SearchAccessor<'a>, [T], DP::ExternalId>
+ Clone
+ Send
+ Sync
+ AsyncFriendly,
{
type Id = DP::ExternalId;
type Parameters = graph::search::Knn;
type Output = Metrics;

fn num_queries(&self) -> usize {
self.queries.nrows()
}

fn id_count(&self, parameters: &Self::Parameters) -> search::IdCount {
search::IdCount::Fixed(parameters.k_value())
}

async fn search<O>(
&self,
parameters: &Self::Parameters,
buffer: &mut O,
index: usize,
) -> ANNResult<Self::Output>
where
O: graph::SearchOutputBuffer<DP::ExternalId> + Send,
{
let context = DP::Context::default();
let knn_search = *parameters;
let stats = self
.index
.search_with(
knn_search,
self.strategy.get(index)?,
self.post_processor.get(index)?.clone(),
&context,
self.queries.row(index),
buffer,
)
.await?;

Ok(Metrics {
comparisons: stats.cmps,
hops: stats.hops,
})
}
}

/// An [`search::Aggregate`]d summary of multiple [`KNN`] search runs
/// returned by the provided [`Aggregator`].
///
Expand Down
2 changes: 1 addition & 1 deletion diskann-benchmark-runner/src/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ mod tests {
let _: Type<f32> = value.convert::<DataType, _>().unwrap();

// An invalid match should return an error.
let value = Any::new(0usize, "random-rag");
let value = Any::new(0usize, "random-determinant-diversity");
let err = value.convert::<DataType, Type<f32>>().unwrap_err();
let msg = err.to_string();
assert!(msg.contains("invalid dispatch"), "{}", msg);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"search_directories": [
"C:/data/openai"
],
"jobs": [
{
"type": "disk-index",
"content": {
"source": {
"disk-index-source": "Load",
"data_type": "float32",
"load_path": "C:/data/openai/openai_index_normal"
},
"search_phase": {
"queries": "openai_query.bin",
"groundtruth": "openai_gt_50.bin",
"search_list": [100, 200, 400],
"beam_width": 4,
"recall_at": 10,
"num_threads": 8,
"is_flat_search": false,
"distance": "squared_l2",
"vector_filters_file": null
}
}
},
{
"type": "disk-index",
"content": {
"source": {
"disk-index-source": "Load",
"data_type": "float32",
"load_path": "C:/data/openai/openai_index_normal"
},
"search_phase": {
"queries": "openai_query.bin",
"groundtruth": "openai_gt_50.bin",
"search_list": [100, 200, 400],
"beam_width": 4,
"recall_at": 10,
"num_threads": 8,
"is_flat_search": false,
"distance": "squared_l2",
"vector_filters_file": null,
"is_determinant_diversity_search": true,
"determinant_diversity_eta": 0.01,
"determinant_diversity_power": 2.0
}
}
}
]
}
25 changes: 25 additions & 0 deletions diskann-benchmark/src/backend/disk_index/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ pub(super) struct DiskSearchStats {
pub(super) beam_width: usize,
pub(super) recall_at: u32,
pub(crate) is_flat_search: bool,
pub(crate) is_determinant_diversity_search: bool,
pub(crate) determinant_diversity_eta: Option<f64>,
pub(crate) determinant_diversity_power: Option<f64>,
pub(crate) distance: SimilarityMeasure,
pub(crate) uses_vector_filters: bool,
pub(super) num_nodes_to_cache: Option<usize>,
Expand Down Expand Up @@ -276,6 +279,9 @@ where
Some(search_params.beam_width),
vector_filter,
search_params.is_flat_search,
search_params.is_determinant_diversity_search,
search_params.determinant_diversity_eta,
search_params.determinant_diversity_power,
) {
Ok(search_result) => {
*stats = search_result.stats.query_statistics;
Expand Down Expand Up @@ -341,6 +347,9 @@ where
beam_width: search_params.beam_width,
recall_at: search_params.recall_at,
is_flat_search: search_params.is_flat_search,
is_determinant_diversity_search: search_params.is_determinant_diversity_search,
determinant_diversity_eta: search_params.determinant_diversity_eta,
determinant_diversity_power: search_params.determinant_diversity_power,
distance: search_params.distance,
uses_vector_filters: search_params.vector_filters_file.is_some(),
num_nodes_to_cache: search_params.num_nodes_to_cache,
Expand Down Expand Up @@ -425,6 +434,22 @@ impl fmt::Display for DiskSearchStats {
writeln!(f, "Beam width, : {}", self.beam_width)?;
writeln!(f, "Recall at, : {}", self.recall_at)?;
writeln!(f, "Flat search, : {}", self.is_flat_search)?;
writeln!(
f,
"Det-div search, : {}",
self.is_determinant_diversity_search
)?;
writeln!(
f,
"Det-div params, : {}",
match (
self.determinant_diversity_eta,
self.determinant_diversity_power,
) {
(Some(eta), Some(power)) => format!("eta={eta}, power={power}"),
_ => "None".to_string(),
}
)?;
writeln!(f, "Distance, : {}", self.distance)?;
writeln!(f, "Vector filters, : {}", self.uses_vector_filters)?;
writeln!(
Expand Down
53 changes: 45 additions & 8 deletions diskann-benchmark/src/backend/index/benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ use diskann_benchmark_runner::{
};
use diskann_providers::{
index::diskann_async,
model::{configuration::IndexConfiguration, graph::provider::async_::common},
model::{
configuration::IndexConfiguration,
graph::provider::async_::{common, DeterminantDiversitySearchParams},
},
};
use diskann_utils::{
future::AsyncFriendly,
Expand Down Expand Up @@ -350,6 +353,8 @@ where
+ provider::SetElement<[T]>,
T: SampleableForStart + std::fmt::Debug + Copy + AsyncFriendly + bytemuck::Pod,
S: glue::DefaultSearchStrategy<DP, [T]> + Clone + AsyncFriendly,
DeterminantDiversitySearchParams:
for<'a> glue::SearchPostProcess<S::SearchAccessor<'a>, [T], DP::ExternalId> + Send + Sync,
{
match &input {
SearchPhase::Topk(search_phase) => {
Expand All @@ -366,19 +371,51 @@ where
let groundtruth =
datafiles::load_groundtruth(datafiles::BinFile(&search_phase.groundtruth))?;

let knn = benchmark_core::search::graph::KNN::new(
index,
queries,
benchmark_core::search::graph::Strategy::broadcast(search_strategy),
)?;

let steps = search::knn::SearchSteps::new(
search_phase.reps,
&search_phase.num_threads,
&search_phase.runs,
);

let search_results = search::knn::run(&knn, &groundtruth, steps)?;
let search_results = if let (Some(eta), Some(power)) = (
search_phase.determinant_diversity_eta,
search_phase.determinant_diversity_power,
) {
let processor = DeterminantDiversitySearchParams::new(
search_phase
.determinant_diversity_results_k
.unwrap_or_else(|| {
search_phase
.runs
.iter()
.map(|run| run.search_n)
.max()
.unwrap_or(1)
}),
eta,
power,
)
.map_err(|err| {
anyhow::anyhow!("Invalid determinant-diversity parameters: {err}")
})?;

let knn = benchmark_core::search::graph::knn::KNNWithPostProcessor::new(
index,
queries,
benchmark_core::search::graph::Strategy::broadcast(search_strategy),
benchmark_core::search::graph::Strategy::broadcast(processor),
)?;

search::knn::run(&knn, &groundtruth, steps)?
} else {
let knn = benchmark_core::search::graph::KNN::new(
index,
queries,
benchmark_core::search::graph::Strategy::broadcast(search_strategy),
)?;

search::knn::run(&knn, &groundtruth, steps)?
};
result.append(AggregatedSearchResults::Topk(search_results));
Ok(result)
}
Expand Down
Loading
Loading