- Merge vector+graph into single wiki source before RRF with web - Wiki pages no longer get 2x advantage from dual retrieval - Add vector similarity threshold (0.7 default) - Skip synonyms in graph search to reduce noise - Fix duplicate entity links bug in graph search 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
+38
-37
@@ -219,53 +219,54 @@ async def test_vector_data(vector_service, test_wiki_page):
|
||||
# ============================================================================
|
||||
|
||||
class TestRRFFusion:
|
||||
"""Test Reciprocal Rank Fusion algorithm."""
|
||||
"""Test two-stage Reciprocal Rank Fusion algorithm."""
|
||||
|
||||
def test_rrf_single_source(self, hybrid_rag_service):
|
||||
"""Test RRF with single source."""
|
||||
results_by_source = {
|
||||
"vector": [
|
||||
{"page_id": 1, "title": "Doc 1", "content": "test"},
|
||||
{"page_id": 2, "title": "Doc 2", "content": "test"}
|
||||
]
|
||||
}
|
||||
def test_wiki_merge_single_source(self, hybrid_rag_service):
|
||||
"""Test wiki merge with single source (vector only)."""
|
||||
vector_results = [
|
||||
{"page_id": 1, "title": "Doc 1", "content": "test"},
|
||||
{"page_id": 2, "title": "Doc 2", "content": "test"}
|
||||
]
|
||||
|
||||
fused = hybrid_rag_service._reciprocal_rank_fusion(results_by_source, k=60)
|
||||
merged = hybrid_rag_service._merge_wiki_sources(vector_results, [], k=60)
|
||||
|
||||
assert len(fused) == 2
|
||||
assert fused[0]["rrf_score"] > fused[1]["rrf_score"] # Rank 1 > Rank 2
|
||||
assert fused[0]["sources"] == ["vector"]
|
||||
assert len(merged) == 2
|
||||
assert merged[0]["wiki_rrf_score"] > merged[1]["wiki_rrf_score"] # Rank 1 > Rank 2
|
||||
assert merged[0]["found_by"] == ["vector"]
|
||||
|
||||
def test_rrf_multiple_sources_same_doc(self, hybrid_rag_service):
|
||||
"""Test RRF with same document from multiple sources."""
|
||||
results_by_source = {
|
||||
"vector": [{"page_id": 1, "title": "Doc 1", "content": "test"}],
|
||||
"graph": [{"page_id": 1, "title": "Doc 1", "content": ""}],
|
||||
}
|
||||
def test_wiki_merge_multiple_sources_same_doc(self, hybrid_rag_service):
|
||||
"""Test wiki merge with same document from vector and graph."""
|
||||
vector_results = [{"page_id": 1, "title": "Doc 1", "content": "test"}]
|
||||
graph_results = [{"page_id": 1, "title": "Doc 1", "content": ""}]
|
||||
|
||||
fused = hybrid_rag_service._reciprocal_rank_fusion(results_by_source, k=60)
|
||||
merged = hybrid_rag_service._merge_wiki_sources(vector_results, graph_results, k=60)
|
||||
|
||||
assert len(fused) == 1 # Deduplicated
|
||||
assert len(fused[0]["sources"]) == 2 # Both sources
|
||||
assert "vector" in fused[0]["sources"]
|
||||
assert "graph" in fused[0]["sources"]
|
||||
# RRF score should be sum: 1/(60+1) + 1/(60+1)
|
||||
assert len(merged) == 1 # Deduplicated
|
||||
assert len(merged[0]["found_by"]) == 2 # Both sources
|
||||
assert "vector" in merged[0]["found_by"]
|
||||
assert "graph" in merged[0]["found_by"]
|
||||
# Wiki RRF score should be sum: 1/(60+1) + 1/(60+1)
|
||||
expected_score = 1/61 + 1/61
|
||||
assert abs(fused[0]["rrf_score"] - expected_score) < 0.001
|
||||
assert abs(merged[0]["wiki_rrf_score"] - expected_score) < 0.001
|
||||
|
||||
def test_rrf_web_results(self, hybrid_rag_service):
|
||||
"""Test RRF with web results (URL-based)."""
|
||||
results_by_source = {
|
||||
"web": [
|
||||
{"url": "https://example.com/1", "title": "Web 1", "content": "test"},
|
||||
{"url": "https://example.com/2", "title": "Web 2", "content": "test"}
|
||||
]
|
||||
}
|
||||
def test_final_rrf_wiki_and_web(self, hybrid_rag_service):
|
||||
"""Test final RRF between wiki and web results."""
|
||||
# Pre-merged wiki results
|
||||
wiki_results = [
|
||||
{"page_id": 1, "title": "Wiki 1", "content": "test", "found_by": ["vector"]}
|
||||
]
|
||||
web_results = [
|
||||
{"url": "https://example.com/1", "title": "Web 1", "content": "test"},
|
||||
{"url": "https://example.com/2", "title": "Web 2", "content": "test"}
|
||||
]
|
||||
|
||||
fused = hybrid_rag_service._reciprocal_rank_fusion(results_by_source, k=60)
|
||||
fused = hybrid_rag_service._reciprocal_rank_fusion(wiki_results, web_results, k=60)
|
||||
|
||||
assert len(fused) == 2
|
||||
assert fused[0]["result"]["url"] == "https://example.com/1"
|
||||
assert len(fused) == 3
|
||||
# Wiki rank 1 and web rank 1 should have same RRF score
|
||||
wiki_score = next(r["rrf_score"] for r in fused if r["source_type"] == "wiki")
|
||||
web_score = next(r["rrf_score"] for r in fused if r["source_type"] == "web")
|
||||
assert abs(wiki_score - web_score) < 0.001 # Equal footing
|
||||
|
||||
|
||||
class TestContextFormatting:
|
||||
|
||||
Reference in New Issue
Block a user