fix: align vectorstore live retrieval
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user