feat(rag): close eval pipeline with live snapshots

This commit is contained in:
zhuyongxin
2026-07-06 21:39:27 +08:00
parent cf3333d607
commit ed7efc58b7
47 changed files with 2613 additions and 177 deletions
@@ -11,6 +11,7 @@ import lombok.Getter;
import lombok.Setter;
import com.superbiz.agent.constant.MilvusConstants;
import com.superbiz.agent.dto.DocumentChunk;
import com.superbiz.agent.dto.Frontmatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -176,6 +177,10 @@ public class VectorIndexService {
* @throws Exception 索引失败时抛出异常
*/
public void indexDocumentChunks(String docId, List<DocumentChunk> chunks, String category) throws Exception {
indexDocumentChunks(docId, chunks, category, null);
}
public void indexDocumentChunks(String docId, List<DocumentChunk> chunks, String category, Frontmatter frontmatter) throws Exception {
if (chunks == null || chunks.isEmpty()) {
throw new IllegalArgumentException("文档分块列表为空");
}
@@ -194,7 +199,7 @@ public class VectorIndexService {
List<Float> vector = embeddingService.generateEmbedding(buildEmbeddingText(chunk));
// 构建元数据(使用 docId 和 category)
Map<String, Object> metadata = buildDocumentMetadata(docId, chunk, chunks.size(), category);
Map<String, Object> metadata = buildDocumentMetadata(docId, chunk, chunks.size(), category, frontmatter);
// 插入到 Milvus
insertToMilvus(chunk.getContent(), vector, metadata, chunk.getChunkIndex());
@@ -253,30 +258,47 @@ public class VectorIndexService {
/**
* 构建文档元数据(用于上传文档)
*/
private Map<String, Object> buildDocumentMetadata(String docId, DocumentChunk chunk, int totalChunks, String category) {
static Map<String, Object> buildDocumentMetadata(String docId, DocumentChunk chunk, int totalChunks, String category) {
return buildDocumentMetadata(docId, chunk, totalChunks, category, null);
}
static Map<String, Object> buildDocumentMetadata(String docId,
DocumentChunk chunk,
int totalChunks,
String category,
Frontmatter frontmatter) {
Map<String, Object> metadata = new HashMap<>();
// 文档标识
String source = firstNonBlank(frontmatter != null ? frontmatter.getSource() : null, "upload:" + docId);
metadata.put("docId", docId);
metadata.put("_source", "upload:" + docId); // 区分文件索引和上传文档
metadata.put("_source", source); // 区分文件索引和上传文档
metadata.put("source", source);
// 分片信息
metadata.put("chunkIndex", chunk.getChunkIndex());
metadata.put("totalChunks", totalChunks);
// 标题信息
if (chunk.getTitle() != null && !chunk.getTitle().isEmpty()) {
metadata.put("title", chunk.getTitle());
String title = firstNonBlank(chunk.getTitle(), frontmatter != null ? frontmatter.getTitle() : null);
if (title != null) {
metadata.put("title", title);
}
// 面包屑导航(完整标题层级路径)
if (chunk.getBreadcrumb() != null && !chunk.getBreadcrumb().isEmpty()) {
metadata.put("breadcrumb", chunk.getBreadcrumb());
String breadcrumb = firstNonBlank(frontmatter != null ? frontmatter.getBreadcrumb() : null, chunk.getBreadcrumb());
if (breadcrumb != null) {
metadata.put("breadcrumb", breadcrumb);
}
// 文档类别
metadata.put("category", category != null && !category.isBlank() ? category : "upload");
String kbScope = trimToNull(frontmatter != null ? frontmatter.getKbScope() : null);
if (kbScope != null) {
metadata.put("kb_scope", kbScope);
}
return metadata;
}
@@ -304,6 +326,23 @@ public class VectorIndexService {
return value == null ? "" : value.trim();
}
private static String trimToNull(String value) {
if (value == null || value.isBlank()) {
return null;
}
return value.trim();
}
private static String firstNonBlank(String... values) {
for (String value : values) {
String trimmed = trimToNull(value);
if (trimmed != null) {
return trimmed;
}
}
return null;
}
/**
* 删除文件的旧数据(根据 metadata._source)
*/