97 lines
3.5 KiB
Java
97 lines
3.5 KiB
Java
package com.superbiz.agent.service;
|
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
import com.superbiz.agent.dto.ComparableRetrievalResult;
|
|
import org.springframework.ai.document.Document;
|
|
import org.springframework.stereotype.Component;
|
|
|
|
import java.util.LinkedHashMap;
|
|
import java.util.Map;
|
|
|
|
@Component
|
|
public class RetrievalResultNormalizer {
|
|
|
|
private final ObjectMapper objectMapper;
|
|
|
|
public RetrievalResultNormalizer(ObjectMapper objectMapper) {
|
|
this.objectMapper = objectMapper;
|
|
}
|
|
|
|
public ComparableRetrievalResult fromCurrent(VectorSearchService.SearchResult result, int rank, int previewLimit) {
|
|
Map<String, String> metadata = parseMetadata(result.getMetadata());
|
|
String source = firstNonBlank(metadata.get("_source"), metadata.get("source"), result.getMetadata(), result.getId());
|
|
return ComparableRetrievalResult.builder()
|
|
.path("current")
|
|
.rank(rank)
|
|
.id(result.getId())
|
|
.source(source)
|
|
.docId(metadata.get("docId"))
|
|
.title(metadata.get("title"))
|
|
.breadcrumb(metadata.get("breadcrumb"))
|
|
.category(metadata.get("category"))
|
|
.contentPreview(truncate(result.getContent(), previewLimit))
|
|
.scoreLabel("l2_distance")
|
|
.scoreValue((double) result.getScore())
|
|
.build();
|
|
}
|
|
|
|
public ComparableRetrievalResult fromSidecar(Document document, int rank, int previewLimit) {
|
|
Map<String, String> metadata = stringifyMetadata(document.getMetadata());
|
|
String source = firstNonBlank(metadata.get("_source"), metadata.get("source"), metadata.get("docId"), document.getId());
|
|
return ComparableRetrievalResult.builder()
|
|
.path("sidecar")
|
|
.rank(rank)
|
|
.id(document.getId())
|
|
.source(source)
|
|
.docId(metadata.get("docId"))
|
|
.title(metadata.get("title"))
|
|
.breadcrumb(metadata.get("breadcrumb"))
|
|
.category(metadata.get("category"))
|
|
.contentPreview(truncate(document.getText(), previewLimit))
|
|
.scoreLabel("similarity")
|
|
.scoreValue(document.getScore())
|
|
.build();
|
|
}
|
|
|
|
private Map<String, String> parseMetadata(String metadata) {
|
|
if (metadata == null || metadata.isBlank()) {
|
|
return Map.of();
|
|
}
|
|
try {
|
|
Map<?, ?> raw = objectMapper.readValue(metadata, Map.class);
|
|
return stringifyMetadata(raw);
|
|
} catch (Exception e) {
|
|
return Map.of();
|
|
}
|
|
}
|
|
|
|
private Map<String, String> stringifyMetadata(Map<?, ?> raw) {
|
|
if (raw == null || raw.isEmpty()) {
|
|
return Map.of();
|
|
}
|
|
Map<String, String> result = new LinkedHashMap<>();
|
|
for (Map.Entry<?, ?> entry : raw.entrySet()) {
|
|
if (entry.getKey() != null && entry.getValue() != null) {
|
|
result.put(String.valueOf(entry.getKey()), String.valueOf(entry.getValue()));
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private String firstNonBlank(String... values) {
|
|
for (String value : values) {
|
|
if (value != null && !value.isBlank()) {
|
|
return value;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private String truncate(String text, int maxLength) {
|
|
if (text == null || text.length() <= maxLength) {
|
|
return text;
|
|
}
|
|
return text.substring(0, maxLength) + "...";
|
|
}
|
|
}
|