use super::*;
#[test]
fn hand_computed_score_matches_the_maxsim_formula() {
let query = MultiVectorEmbedding::from_rows(2, [vec![1.0, 0.0], vec![0.0, 1.0]]);
let document =
MultiVectorEmbedding::from_rows(2, [vec![1.0, 0.0], vec![0.0, 1.0], vec![1.0, 1.0]]);
assert_eq!(
late_interaction_score(&query, None, &document, None, MaskedRowFill::DtypeMinimum),
2.0
);
}
#[test]
fn swapping_query_and_document_changes_the_score() {
let a = MultiVectorEmbedding::from_rows(2, [vec![1.0, 0.0], vec![0.0, 1.0]]);
let b = MultiVectorEmbedding::from_rows(2, [vec![1.0, 0.0], vec![0.0, 1.0], vec![1.0, 1.0]]);
assert_eq!(
late_interaction_score(&a, None, &b, None, MaskedRowFill::DtypeMinimum),
2.0
);
assert_eq!(
late_interaction_score(&b, None, &a, None, MaskedRowFill::DtypeMinimum),
3.0
);
}
#[test]
fn document_side_padding_never_wins_a_maximum() {
let query = MultiVectorEmbedding::from_rows(2, [vec![1.0, 0.0]]);
let document =
MultiVectorEmbedding::from_rows(2, [vec![0.0, 1.0], vec![0.5, 0.0], vec![100.0, 0.0]]);
let masked = late_interaction_score(
&query,
None,
&document,
Some(&[true, true, false]),
MaskedRowFill::DtypeMinimum,
);
assert_eq!(masked, 0.5);
let unmasked = late_interaction_score(&query, None, &document, None, MaskedRowFill::DtypeMinimum);
assert_eq!(
unmasked, 100.0,
"the padding row would dominate the maximum if it were not excluded"
);
}
#[test]
fn dtype_minimum_and_zero_fill_disagree_when_every_real_row_scores_negative() {
let query = MultiVectorEmbedding::from_rows(2, [vec![1.0, 0.0]]);
let document = MultiVectorEmbedding::from_rows(2, [vec![-1.0, 0.0], vec![10.0, 10.0]]);
let mask = [true, false];
let dtype_min = late_interaction_score(
&query,
None,
&document,
Some(&mask),
MaskedRowFill::DtypeMinimum,
);
let zero = late_interaction_score(&query, None, &document, Some(&mask), MaskedRowFill::Zero);
assert_eq!(
dtype_min, -1.0,
"the real, negative row must still win over a dtype-minimum-filled masked row"
);
assert_eq!(
zero, 0.0,
"the masked row, filled with zero, beats the real negative row"
);
assert_ne!(dtype_min, zero);
}
#[test]
fn query_side_padding_contributes_nothing_to_the_sum() {
let query = MultiVectorEmbedding::from_rows(2, [vec![1.0, 0.0], vec![0.0, 1.0], vec![1.0, 1.0]]);
let document = MultiVectorEmbedding::from_rows(2, [vec![1.0, 0.0], vec![0.0, 1.0]]);
let masked = late_interaction_score(
&query,
Some(&[true, true, false]),
&document,
None,
MaskedRowFill::DtypeMinimum,
);
assert_eq!(masked, 2.0);
let unmasked = late_interaction_score(&query, None, &document, None, MaskedRowFill::DtypeMinimum);
assert_eq!(
unmasked, 3.0,
"the padding row would add its own maximum to the sum if it were not excluded"
);
}
#[test]
fn two_empty_matrices_score_the_empty_document_sentinel_even_with_mismatched_dims() {
let query = MultiVectorEmbedding::from_rows(3, Vec::<Vec<f32>>::new());
let document = MultiVectorEmbedding::from_rows(7, Vec::<Vec<f32>>::new());
assert_eq!(
late_interaction_score(&query, None, &document, None, MaskedRowFill::DtypeMinimum),
-1e9
);
}
#[test]
fn an_empty_query_against_a_real_document_sums_to_zero() {
let query = MultiVectorEmbedding::from_rows(2, Vec::<Vec<f32>>::new());
let document = MultiVectorEmbedding::from_rows(2, [vec![1.0, 1.0]]);
assert_eq!(
late_interaction_score(&query, None, &document, None, MaskedRowFill::DtypeMinimum),
0.0
);
}
#[test]
fn a_real_query_against_an_empty_document_scores_the_empty_document_sentinel() {
let query = MultiVectorEmbedding::from_rows(2, [vec![1.0, 0.0]]);
let document = MultiVectorEmbedding::from_rows(2, Vec::<Vec<f32>>::new());
assert_eq!(
late_interaction_score(&query, None, &document, None, MaskedRowFill::DtypeMinimum),
-1e9
);
}
#[test]
#[should_panic(expected = "query mask length must match its row count")]
fn a_mismatched_query_mask_length_panics() {
let query = MultiVectorEmbedding::from_rows(2, [vec![1.0, 0.0]]);
let document = MultiVectorEmbedding::from_rows(2, [vec![1.0, 0.0]]);
late_interaction_score(
&query,
Some(&[true, true]),
&document,
None,
MaskedRowFill::DtypeMinimum,
);
}
#[test]
#[should_panic(expected = "late interaction compares rows of equal width")]
fn comparing_different_dims_panics_when_there_is_something_real_to_compare() {
let query = MultiVectorEmbedding::from_rows(2, [vec![1.0, 0.0]]);
let document = MultiVectorEmbedding::from_rows(3, [vec![1.0, 0.0, 0.0]]);
late_interaction_score(&query, None, &document, None, MaskedRowFill::DtypeMinimum);
}