Skip to content

Commit f140b00

Browse files
partychenCopilot
andcommitted
Add normalized cosine PQ integration coverage
Extend the existing SIFT build-and-search tests with normalized cosine cases for both Hybrid and quant-only Product-PQ indexes. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent 6948332 commit f140b00

1 file changed

Lines changed: 32 additions & 9 deletions

File tree

diskann-providers/src/index/diskann_async.rs

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ pub(crate) mod tests {
182182
use diskann_utils::{test_data_root, views::Matrix};
183183
use diskann_vector::{
184184
DistanceFunction, PureDistanceFunction,
185-
distance::{Metric, SquaredL2},
185+
distance::{CosineNormalized, Metric, SquaredL2},
186186
};
187187
use rand::{distr::Distribution, rngs::StdRng, seq::SliceRandom};
188188
use rstest::rstest;
@@ -1378,29 +1378,36 @@ pub(crate) mod tests {
13781378
}
13791379

13801380
const SIFTSMALL: &str = "/sift/siftsmall_learn_256pts.fbin";
1381+
const SIFTSMALL_NORMALIZED: &str = "/sift/siftsmall_learn_256pts_normalized.fbin";
13811382

13821383
#[rstest]
13831384
#[tokio::test]
13841385
async fn test_sift_build_and_search<S>(
13851386
#[values(FullPrecision, Hybrid::new(None))] build_strategy: S,
13861387
#[values(1, 10)] batchsize: usize,
1388+
#[values(
1389+
(Metric::L2, SIFTSMALL),
1390+
(Metric::CosineNormalized, SIFTSMALL_NORMALIZED),
1391+
)]
1392+
metric_and_file: (Metric, &str),
13871393
) where
13881394
S: for<'a> InsertStrategy<'a, TestProvider, &'a [f32]>
13891395
+ MultiInsertStrategy<TestProvider, Matrix<f32>>
13901396
+ Clone,
13911397
{
1398+
let (metric, file) = metric_and_file;
13921399
let ctx = &DefaultContext;
13931400
let parameters = InitParams {
13941401
l_build: 64,
13951402
max_degree: 16,
1396-
metric: Metric::L2,
1403+
metric,
13971404
batchsize: NonZeroUsize::new(batchsize).unwrap(),
13981405
};
13991406

14001407
let (index, data) = init_from_file(
14011408
build_strategy.clone(),
14021409
parameters,
1403-
SIFTSMALL,
1410+
file,
14041411
8,
14051412
StartPointStrategy::RandomSamples {
14061413
nsamples: ONE,
@@ -1433,7 +1440,11 @@ pub(crate) mod tests {
14331440
//
14341441
// Because this dataset is small, we can expect exact equality.
14351442
for (q, query) in data.row_iter().enumerate() {
1436-
let gt = groundtruth(data.as_view(), query, |a, b| SquaredL2::evaluate(a, b));
1443+
let gt = groundtruth(data.as_view(), query, |a, b| match metric {
1444+
Metric::L2 => SquaredL2::evaluate(a, b),
1445+
Metric::CosineNormalized => CosineNormalized::evaluate(a, b),
1446+
_ => unreachable!(),
1447+
});
14371448
{
14381449
let mut result_output_buffer =
14391450
search_output_buffer::IdDistance::new(&mut ids, &mut distances);
@@ -2061,8 +2072,11 @@ pub(crate) mod tests {
20612072
/// PQ only Build & Search ///
20622073
//////////////////////////////
20632074

2075+
#[rstest]
2076+
#[case(Metric::L2, SIFTSMALL)]
2077+
#[case(Metric::CosineNormalized, SIFTSMALL_NORMALIZED)]
20642078
#[tokio::test]
2065-
async fn test_sift_pq_only_build_and_search() {
2079+
async fn test_sift_pq_only_build_and_search(#[case] metric: Metric, #[case] file: &str) {
20662080
let ctx = &DefaultContext;
20672081
let create_fn = |data: Arc<Matrix<f32>>, start_points: &[f32]| {
20682082
let pq_table = train_pq(
@@ -2074,8 +2088,7 @@ pub(crate) mod tests {
20742088
.unwrap();
20752089

20762090
let (config, parameters) =
2077-
simplified_builder(64, 16, Metric::L2, data.ncols(), data.nrows(), no_modify)
2078-
.unwrap();
2091+
simplified_builder(64, 16, metric, data.ncols(), data.nrows(), no_modify).unwrap();
20792092

20802093
let index =
20812094
Arc::new(new_quant_only_index(config, parameters, pq_table, NoDeletes).unwrap());
@@ -2086,7 +2099,7 @@ pub(crate) mod tests {
20862099
index
20872100
};
20882101
let (index, data) =
2089-
init_and_build_index_from_file(SIFTSMALL, create_fn, build_using_single_insert).await;
2102+
init_and_build_index_from_file(file, create_fn, build_using_single_insert).await;
20902103

20912104
let neighbor_accessor = &mut index.provider().neighbors();
20922105
// There should be one more reachable node than points in the dataset to account for
@@ -2131,7 +2144,17 @@ pub(crate) mod tests {
21312144
.await
21322145
.unwrap();
21332146

2134-
assert_top_k_exactly_match(q, &gt, &ids, &distances, top_k);
2147+
if metric == Metric::CosineNormalized {
2148+
let expected: Vec<_> = gt
2149+
.iter()
2150+
.rev()
2151+
.take(top_k)
2152+
.map(|neighbor| *neighbor.id())
2153+
.collect();
2154+
assert_eq!(expected, ids, "failed on query {q}");
2155+
} else {
2156+
assert_top_k_exactly_match(q, &gt, &ids, &distances, top_k);
2157+
}
21352158
}
21362159
}
21372160

0 commit comments

Comments
 (0)