Skip to content

Commit db1b88a

Browse files
franklinicclaude
andcommitted
test(rag): update Hybrid/MultiQuery tests for RRF fusion + real query variations
Seven pre-existing HybridRetrieverTests/MultiQueryRetrieverTests asserted the old behavior that the RRF-fusion (#27) and real-query-expansion (#19) changes correctly replaced: exact weighted-sum scores (0.7*d+0.3*s) and the "{query} variation N" placeholder. RRF is rank-based (scores are small, order is what matters) and MultiQuery now emits real reformulations. Reassert the meaningful properties: fused doc presence + ranking, and original-query-first with distinct variations. All 105 pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent fe9cfa7 commit db1b88a

2 files changed

Lines changed: 25 additions & 18 deletions

File tree

tests/AiDotNet.Tests/UnitTests/RetrievalAugmentedGeneration/HybridRetrieverTests.cs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -318,10 +318,10 @@ public async Task Retrieve_OverlappingResults_CombinesScores()
318318

319319
// Assert
320320
Assert.Equal(3, results.Count);
321-
// doc1 should have combined score: 0.9 * 0.7 + 0.8 * 0.3 = 0.63 + 0.24 = 0.87
321+
// doc1 appears in BOTH lists, so RRF fuses its two rank contributions and it ranks first.
322322
var doc1 = results.First(r => r.Id == "doc1");
323323
Assert.True(doc1.HasRelevanceScore);
324-
Assert.True(doc1.RelevanceScore > 0.8); // Combined should be higher than either alone
324+
Assert.Equal("doc1", results[0].Id);
325325
}
326326

327327
[Fact(Timeout = 60000)]
@@ -452,8 +452,9 @@ public async Task Retrieve_EqualWeights_ProducesEqualContribution()
452452

453453
// Assert
454454
Assert.Single(results);
455-
// Score should be 1.0 * 0.5 + 1.0 * 0.5 = 1.0
456-
Assert.Equal(1.0, results[0].RelevanceScore, 3);
455+
// Equal weights → both lists contribute equally to the RRF fusion; the doc is returned.
456+
Assert.Equal("doc1", results[0].Id);
457+
Assert.True(results[0].RelevanceScore > 0);
457458
}
458459

459460
[Fact(Timeout = 60000)]
@@ -497,8 +498,9 @@ public async Task Retrieve_ZeroDenseWeight_OnlyUsesSparseScore()
497498

498499
// Assert
499500
Assert.Single(results);
500-
// Score should be 1.0 * 0.0 + 0.5 * 1.0 = 0.5
501-
Assert.Equal(0.5, results[0].RelevanceScore, 3);
501+
// With zero dense weight only the sparse ranking contributes to RRF; the doc is still returned.
502+
Assert.Equal("doc1", results[0].Id);
503+
Assert.True(results[0].RelevanceScore > 0);
502504
}
503505

504506
[Fact(Timeout = 60000)]
@@ -519,8 +521,10 @@ public async Task Retrieve_ZeroSparseWeight_OnlyUsesDenseScore()
519521

520522
// Assert
521523
Assert.Single(results);
522-
// Score should be 0.8 * 1.0 + 1.0 * 0.0 = 0.8
523-
Assert.Equal(0.8, results[0].RelevanceScore, 3);
524+
// With zero sparse weight the sparse list contributes nothing to the RRF fusion; the doc is
525+
// still returned via the dense ranking with a positive fused score.
526+
Assert.Equal("doc1", results[0].Id);
527+
Assert.True(results[0].RelevanceScore > 0);
524528
}
525529

526530
#endregion
@@ -776,8 +780,10 @@ public async Task Constructor_DefaultWeights_Uses70Dense30Sparse()
776780

777781
// Assert
778782
Assert.Single(results);
779-
// Default weights: 0.7 dense + 0.3 sparse = 1.0 * 0.7 + 1.0 * 0.3 = 1.0
780-
Assert.Equal(1.0, results[0].RelevanceScore, 3);
783+
// Hybrid fusion is now Reciprocal Rank Fusion (rank-based, scale-free) rather than a raw
784+
// weighted sum of scores. A doc ranked #1 in both lists is returned with a positive fused score.
785+
Assert.Equal("doc1", results[0].Id);
786+
Assert.True(results[0].RelevanceScore > 0);
781787
}
782788

783789
[Fact(Timeout = 60000)]

tests/AiDotNet.Tests/UnitTests/RetrievalAugmentedGeneration/MultiQueryRetrieverTests.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -333,9 +333,11 @@ public async Task Retrieve_QueriesContainVariations()
333333
var results = retriever.Retrieve("test").ToList();
334334

335335
// Assert
336-
// Should have variations like "test variation 1", "test variation 2"
337-
Assert.Contains(baseRetriever.QueriesReceived, q => q.Contains("variation 1"));
338-
Assert.Contains(baseRetriever.QueriesReceived, q => q.Contains("variation 2"));
336+
// MultiQuery now produces real query variations (LLM when a generator is supplied, deterministic
337+
// template reformulations otherwise) rather than the old "{query} variation N" placeholder. The
338+
// base retriever should see the original query plus additional distinct variations.
339+
Assert.Contains("test", baseRetriever.QueriesReceived);
340+
Assert.True(baseRetriever.QueriesReceived.Distinct().Count() >= 3);
339341
}
340342

341343
[Fact(Timeout = 60000)]
@@ -698,11 +700,10 @@ public async Task Retrieve_VariationsAppendToOriginal()
698700
var results = retriever.Retrieve("my query").ToList();
699701

700702
// Assert
701-
// Variations should start with original query
702-
foreach (var query in baseRetriever.QueriesReceived.Skip(1))
703-
{
704-
Assert.StartsWith("my query", query);
705-
}
703+
// The original query is retrieved first; the remaining queries are distinct reformulations
704+
// (which embed, but no longer necessarily start with, the original text).
705+
Assert.Equal("my query", baseRetriever.QueriesReceived.First());
706+
Assert.True(baseRetriever.QueriesReceived.Distinct().Count() >= 2);
706707
}
707708

708709
#endregion

0 commit comments

Comments
 (0)