feat(phase1): 支持上传时指定文档类别
功能增强: - DocumentController 新增 category 参数 POST /api/documents/upload?category=api - DocumentUploadRequest 新增 category 字段 - 支持用户指定:api、domain、troubleshoot 等 - 默认值:upload(未指定时) - VectorIndexService.indexDocumentChunks 接收 category - 将用户指定的类别存入 Milvus metadata - metadata.category = 用户指定值 或 "upload" 使用示例: ```bash # 上传 API 文档 curl -X POST /api/documents/upload \ -F "file=@redis-api.md" \ -F "category=api" # 上传领域知识文档 curl -X POST /api/documents/upload \ -F "file=@cache-theory.md" \ -F "category=domain" # 检索时按类别过滤 searchSimilarDocuments("Redis接口", 5, "api") ``` 完整流程: 1. 文件索引:自动从路径提取(aiops-docs/api/ → "api") 2. 用户上传:从接口参数获取(category=api) 3. 检索时:可按类别过滤(category 参数) 编译验证:BUILD SUCCESS
This commit is contained in:
@@ -28,6 +28,7 @@ public class DocumentController {
|
|||||||
@PostMapping("/upload")
|
@PostMapping("/upload")
|
||||||
public Result<String> uploadDocument(
|
public Result<String> uploadDocument(
|
||||||
@RequestParam("file") MultipartFile file,
|
@RequestParam("file") MultipartFile file,
|
||||||
|
@RequestParam(value = "category", required = false) String category,
|
||||||
@RequestParam(value = "faultCategory", required = false) String faultCategory,
|
@RequestParam(value = "faultCategory", required = false) String faultCategory,
|
||||||
@RequestParam(value = "faultSource", required = false) String faultSource,
|
@RequestParam(value = "faultSource", required = false) String faultSource,
|
||||||
@RequestParam(value = "apiName", required = false) String apiName,
|
@RequestParam(value = "apiName", required = false) String apiName,
|
||||||
@@ -38,6 +39,7 @@ public class DocumentController {
|
|||||||
try {
|
try {
|
||||||
DocumentUploadRequest request = DocumentUploadRequest.builder()
|
DocumentUploadRequest request = DocumentUploadRequest.builder()
|
||||||
.file(file)
|
.file(file)
|
||||||
|
.category(category)
|
||||||
.faultCategory(faultCategory)
|
.faultCategory(faultCategory)
|
||||||
.faultSource(faultSource)
|
.faultSource(faultSource)
|
||||||
.apiName(apiName)
|
.apiName(apiName)
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ public class DocumentUploadRequest {
|
|||||||
*/
|
*/
|
||||||
private MultipartFile file;
|
private MultipartFile file;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文档类别(api、domain、troubleshoot 等,默认 upload)
|
||||||
|
*/
|
||||||
|
private String category;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 故障类别(默认 EXTERNAL_API)
|
* 故障类别(默认 EXTERNAL_API)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -110,11 +110,15 @@ public class DocumentManagementService {
|
|||||||
|
|
||||||
// 6. 向量化并索引
|
// 6. 向量化并索引
|
||||||
try {
|
try {
|
||||||
vectorIndexService.indexDocumentChunks(docId, chunks);
|
String category = request.getCategory();
|
||||||
|
if (category == null || category.isBlank()) {
|
||||||
|
category = "upload"; // 默认类别
|
||||||
|
}
|
||||||
|
vectorIndexService.indexDocumentChunks(docId, chunks, category);
|
||||||
document.setStatus("INDEXED");
|
document.setStatus("INDEXED");
|
||||||
document.setIndexedAt(LocalDateTime.now());
|
document.setIndexedAt(LocalDateTime.now());
|
||||||
apiDocumentRepository.save(document);
|
apiDocumentRepository.save(document);
|
||||||
log.info("文档索引完成,docId: {}", docId);
|
log.info("文档索引完成,docId: {}, 类别: {}", docId, category);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("文档索引失败,docId: {}", docId, e);
|
log.error("文档索引失败,docId: {}", docId, e);
|
||||||
|
|||||||
@@ -172,14 +172,15 @@ public class VectorIndexService {
|
|||||||
*
|
*
|
||||||
* @param docId 文档ID
|
* @param docId 文档ID
|
||||||
* @param chunks 文档分块列表
|
* @param chunks 文档分块列表
|
||||||
|
* @param category 文档类别(api、domain、troubleshoot 等)
|
||||||
* @throws Exception 索引失败时抛出异常
|
* @throws Exception 索引失败时抛出异常
|
||||||
*/
|
*/
|
||||||
public void indexDocumentChunks(String docId, List<DocumentChunk> chunks) throws Exception {
|
public void indexDocumentChunks(String docId, List<DocumentChunk> chunks, String category) throws Exception {
|
||||||
if (chunks == null || chunks.isEmpty()) {
|
if (chunks == null || chunks.isEmpty()) {
|
||||||
throw new IllegalArgumentException("文档分块列表为空");
|
throw new IllegalArgumentException("文档分块列表为空");
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info("开始索引文档分块,docId: {}, 分块数: {}", docId, chunks.size());
|
logger.info("开始索引文档分块,docId: {}, 分块数: {}, 类别: {}", docId, chunks.size(), category);
|
||||||
|
|
||||||
// 1. 删除该文档的旧数据(如果存在)
|
// 1. 删除该文档的旧数据(如果存在)
|
||||||
deleteDocumentChunks(docId);
|
deleteDocumentChunks(docId);
|
||||||
@@ -192,8 +193,8 @@ public class VectorIndexService {
|
|||||||
// 生成向量
|
// 生成向量
|
||||||
List<Float> vector = embeddingService.generateEmbedding(chunk.getContent());
|
List<Float> vector = embeddingService.generateEmbedding(chunk.getContent());
|
||||||
|
|
||||||
// 构建元数据(使用 docId 作为来源标识)
|
// 构建元数据(使用 docId 和 category)
|
||||||
Map<String, Object> metadata = buildDocumentMetadata(docId, chunk, chunks.size());
|
Map<String, Object> metadata = buildDocumentMetadata(docId, chunk, chunks.size(), category);
|
||||||
|
|
||||||
// 插入到 Milvus
|
// 插入到 Milvus
|
||||||
insertToMilvus(chunk.getContent(), vector, metadata, chunk.getChunkIndex());
|
insertToMilvus(chunk.getContent(), vector, metadata, chunk.getChunkIndex());
|
||||||
@@ -206,7 +207,7 @@ public class VectorIndexService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info("文档索引完成,docId: {}, 共 {} 个分块", docId, chunks.size());
|
logger.info("文档索引完成,docId: {}, 共 {} 个分块,类别: {}", docId, chunks.size(), category);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -252,7 +253,7 @@ public class VectorIndexService {
|
|||||||
/**
|
/**
|
||||||
* 构建文档元数据(用于上传文档)
|
* 构建文档元数据(用于上传文档)
|
||||||
*/
|
*/
|
||||||
private Map<String, Object> buildDocumentMetadata(String docId, DocumentChunk chunk, int totalChunks) {
|
private Map<String, Object> buildDocumentMetadata(String docId, DocumentChunk chunk, int totalChunks, String category) {
|
||||||
Map<String, Object> metadata = new HashMap<>();
|
Map<String, Object> metadata = new HashMap<>();
|
||||||
|
|
||||||
// 文档标识
|
// 文档标识
|
||||||
@@ -268,8 +269,8 @@ public class VectorIndexService {
|
|||||||
metadata.put("title", chunk.getTitle());
|
metadata.put("title", chunk.getTitle());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 默认类别:上传文档
|
// 文档类别
|
||||||
metadata.put("category", "upload");
|
metadata.put("category", category != null && !category.isBlank() ? category : "upload");
|
||||||
|
|
||||||
return metadata;
|
return metadata;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user