package com.superbiz.agent.controller; import com.superbiz.agent.service.KnowledgeBaseInitService; import lombok.Data; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.Map; /** * 知识库管理控制器 * 提供知识库初始化、查询等接口 */ @RestController @RequestMapping("/api/knowledge") public class KnowledgeBaseController { private static final Logger logger = LoggerFactory.getLogger(KnowledgeBaseController.class); @Autowired private KnowledgeBaseInitService initService; /** * 初始化知识库 * 扫描 knowledge_base 目录下的所有文档,去重后批量导入到数据库和 Milvus * * @param force 是否强制重新导入(跳过去重检查) * @return 初始化结果 */ @PostMapping("/init") public ResponseEntity initKnowledgeBase(@RequestParam(defaultValue = "false") boolean force) { logger.info("收到知识库初始化请求, force={}", force); try { KnowledgeBaseInitService.InitResult result = initService.initializeKnowledgeBase(force); Map response = new HashMap<>(); response.put("success", true); response.put("message", "知识库初始化完成"); response.put("scanned", result.getScanned()); response.put("skipped", result.getSkipped()); response.put("inserted", result.getInserted()); response.put("failed", result.getFailed()); response.put("details", result.getDetails()); logger.info("知识库初始化成功: 扫描={}, 跳过={}, 新增={}, 失败={}", result.getScanned(), result.getSkipped(), result.getInserted(), result.getFailed()); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("知识库初始化失败", e); Map response = new HashMap<>(); response.put("success", false); response.put("message", "初始化失败: " + e.getMessage()); return ResponseEntity.internalServerError().body(response); } } /** * 清空 hybrid collection + MySQL api_document + L0 内存索引, * 再从 knowledge_base 全量重建 dense+BM25 索引。 * *

危险操作:会删除 {@code milvus.collection}(默认 {@code biz})与文档元数据表数据。 * 需要显式 confirm=REBUILD。

*/ @PostMapping("/rebuild-hybrid") public ResponseEntity rebuildHybrid( @RequestParam(defaultValue = "") String confirm) { if (!"REBUILD".equals(confirm)) { Map rejected = new HashMap<>(); rejected.put("success", false); rejected.put("message", "拒绝执行:请传 confirm=REBUILD 以确认清空并重建"); rejected.put("hint", "POST /api/knowledge/rebuild-hybrid?confirm=REBUILD"); return ResponseEntity.badRequest().body(rejected); } logger.warn("收到 hybrid 知识库全量重建请求 confirm={}", confirm); try { KnowledgeBaseInitService.RebuildResult result = initService.rebuildHybridFromKnowledgeBase(); Map response = new HashMap<>(); response.put("success", result.isSuccess()); response.put("message", result.isSuccess() ? "hybrid 知识库重建完成" : "hybrid 知识库重建结束,但存在失败项"); response.put("collection", result.getCollection()); response.put("basePath", result.getBasePath()); response.put("milvus", result.getMilvus()); response.put("mysqlDocumentsBefore", result.getMysqlDocumentsBefore()); response.put("mysqlDocumentsAfterClear", result.getMysqlDocumentsAfterClear()); response.put("mysqlDocumentsAfterInit", result.getMysqlDocumentsAfterInit()); response.put("l0IndexSizeAfterClear", result.getL0IndexSizeAfterClear()); response.put("l0IndexSizeAfterInit", result.getL0IndexSizeAfterInit()); if (result.getInit() != null) { response.put("scanned", result.getInit().getScanned()); response.put("skipped", result.getInit().getSkipped()); response.put("inserted", result.getInit().getInserted()); response.put("failed", result.getInit().getFailed()); response.put("details", result.getInit().getDetails()); } return result.isSuccess() ? ResponseEntity.ok(response) : ResponseEntity.status(500).body(response); } catch (Exception e) { logger.error("hybrid 知识库重建失败", e); Map response = new HashMap<>(); response.put("success", false); response.put("message", "重建失败: " + e.getMessage()); return ResponseEntity.internalServerError().body(response); } } /** * 查询知识库统计信息 * * @return 统计信息 */ @GetMapping("/stats") public ResponseEntity getStats() { try { KnowledgeBaseInitService.Stats stats = initService.getStats(); Map response = new HashMap<>(); response.put("success", true); response.put("totalDocuments", stats.getTotalDocuments()); response.put("totalVectors", stats.getTotalVectors()); response.put("categories", stats.getCategoryCount()); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("查询统计信息失败", e); Map response = new HashMap<>(); response.put("success", false); response.put("message", "查询失败: " + e.getMessage()); return ResponseEntity.internalServerError().body(response); } } }