fix: align vectorstore live retrieval

This commit is contained in:
aruo
2026-07-05 10:53:45 +08:00
parent 5c71f5fc79
commit f2bae0382c
3 changed files with 56 additions and 4 deletions
@@ -106,7 +106,7 @@ public class VectorSearchService {
result.setMetadata(toJson(document.getMetadata()));
result.setRawScore(document.getScore());
result.setScoreLabel("similarity");
result.setScore(toCompatibleL2Distance(document.getScore()));
result.setScore(toCompatibleL2Distance(document));
results.add(result);
}
logger.info("Spring AI VectorStore search complete, candidates={}", results.size());
@@ -166,6 +166,14 @@ public class VectorSearchService {
}
}
private float toCompatibleL2Distance(Document document) {
Double distance = extractDistance(document.getMetadata());
if (distance != null) {
return distance.floatValue();
}
return toCompatibleL2Distance(document.getScore());
}
private float toCompatibleL2Distance(Double similarity) {
if (similarity == null) {
return (float) maxL2Distance;
@@ -174,6 +182,24 @@ public class VectorSearchService {
return (float) ((1.0 - bounded) * maxL2Distance);
}
private Double extractDistance(Map<String, Object> metadata) {
if (metadata == null) {
return null;
}
Object value = metadata.get("distance");
if (value instanceof Number number) {
return number.doubleValue();
}
if (value instanceof String text) {
try {
return Double.parseDouble(text);
} catch (NumberFormatException ignored) {
return null;
}
}
return null;
}
private String toJson(Map<String, Object> metadata) {
if (metadata == null || metadata.isEmpty()) {
return null;
@@ -196,8 +222,8 @@ public class VectorSearchService {
private String content;
/**
* Compatibility score used by existing lookup relevance normalization.
* SDK mode keeps L2 distance; VectorStore mode maps similarity into a
* L2-like distance using retrieval.normalization.max-l2-distance.
* SDK mode keeps L2 distance; VectorStore mode prefers the Milvus
* distance metadata and falls back to similarity mapping.
*/
private float score;
private Double rawScore;
+1 -1
View File
@@ -98,7 +98,7 @@ spring:
milvus:
initialize-schema: false
database-name: ${milvus.database}
collection-name: business_knowledge
collection-name: biz
embedding-dimension: ${milvus.vector-dim}
index-type: IVF_FLAT
metric-type: L2
@@ -67,6 +67,32 @@ class VectorSearchServiceTest {
assertTrue(results.get(0).getMetadata().contains("spring.md"));
}
@Test
void vectorStoreSearchUsesDistanceMetadataAsCompatibleScore() {
VectorStore vectorStore = mock(VectorStore.class);
ObjectProvider<VectorStore> provider = mock(ObjectProvider.class);
when(provider.getIfAvailable()).thenReturn(vectorStore);
when(vectorStore.similaritySearch(any(SearchRequest.class))).thenReturn(List.of(
Document.builder()
.id("spring-doc")
.text("spring content")
.metadata(Map.of("distance", 0.5659486, "category", "api"))
.score(0.4340514)
.build()
));
VectorSearchService service = new VectorSearchService();
setMode(service, "auto");
setVectorStore(service, provider);
List<VectorSearchService.SearchResult> results = service.searchSimilarDocuments("query", 3, null);
assertEquals(1, results.size());
assertEquals("similarity", results.get(0).getScoreLabel());
assertEquals(0.4340514, results.get(0).getRawScore(), 0.0001);
assertEquals(0.5659486f, results.get(0).getScore(), 0.0001);
}
@Test
void autoModeFallsBackToSdkWhenVectorStoreFails() {
VectorStore vectorStore = mock(VectorStore.class);