From 4e3502a51bba306f39668007a5cd1cde271fc05f Mon Sep 17 00:00:00 2001 From: zhuyongxin Date: Thu, 25 Jun 2026 14:08:50 +0800 Subject: [PATCH] =?UTF-8?q?fix(knowledge):=20=E5=B0=86=20category=20?= =?UTF-8?q?=E5=AD=98=E5=82=A8=E5=88=B0=20fault=5Fsource=20=E5=AD=97?= =?UTF-8?q?=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 问题 数据库表 api_document 没有独立的 category 字段,导致 frontmatter 的 category 信息无法正确存储。 ### 表结构分析 ```sql CREATE TABLE api_document ( fault_category VARCHAR(32) DEFAULT 'EXTERNAL_API', -- 固定枚举,不合适存储自定义分类 fault_source VARCHAR(128), -- 可以存储自定义分类 ... ) ``` ## 解决方案 使用 `fault_source` 字段存储 frontmatter 的 category: ```java // 保存时 document.setFaultSource(category); // api, infrastructure, domain, troubleshooting // 统计时 Map categoryCount = apiDocumentRepository.findAll().stream() .collect(Collectors.groupingBy( doc -> doc.getFaultSource() != null ? doc.getFaultSource() : "general", Collectors.counting() )); ``` ## 字段映射关系 | Frontmatter | 数据库字段 | 示例值 | |-------------|-----------|--------| | `title` | `api_name` | "支付网关错误码定义" | | `category` | `fault_source` | "api" / "infrastructure" | | `keywords` | `metadata` (JSON) | ["ERR_TIMEOUT","超时"] | | `summary` | `metadata` (JSON) | "记录了..." | ## 优势 1. **充分利用现有字段**:fault_source (VARCHAR 128) 足够存储分类 2. **避免枚举限制**:不受 FaultCategory 枚举约束 3. **查询方便**:直接通过 fault_source 字段查询和统计 4. **向后兼容**:metadata 中仍保留完整的 frontmatter 信息 ## 验证 ```bash # 初始化 curl -X POST http://localhost:9900/api/knowledge/init # 查询统计 curl http://localhost:9900/api/knowledge/stats # 响应 { "categories": { "api": 1, "infrastructure": 3, "domain": 1, "troubleshooting": 1 } } ``` ## 数据库查询 ```sql -- 按分类统计 SELECT fault_source, COUNT(*) FROM api_document GROUP BY fault_source; -- 结果 api | 1 infrastructure | 3 domain | 1 troubleshooting | 1 ``` --- .../service/KnowledgeBaseInitService.java | 48 ++++--------------- 1 file changed, 10 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/superbiz/agent/service/KnowledgeBaseInitService.java b/src/main/java/com/superbiz/agent/service/KnowledgeBaseInitService.java index 7cf64c8..5d57cdf 100644 --- a/src/main/java/com/superbiz/agent/service/KnowledgeBaseInitService.java +++ b/src/main/java/com/superbiz/agent/service/KnowledgeBaseInitService.java @@ -19,6 +19,7 @@ import java.nio.file.attribute.BasicFileAttributes; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Collectors; /** * 知识库初始化服务 @@ -193,12 +194,12 @@ public class KnowledgeBaseInitService { int indexSize = knowledgeIndexService.getIndexSize(); logger.debug("L0 索引大小: {}", indexSize); - // 按分类统计(从 metadata JSON 中提取 category) - Map categoryCount = new HashMap<>(); - apiDocumentRepository.findAll().forEach(doc -> { - String category = extractCategoryFromMetadata(doc.getMetadata()); - categoryCount.merge(category, 1L, Long::sum); - }); + // 按分类统计(从 fault_source 字段读取) + Map categoryCount = apiDocumentRepository.findAll().stream() + .collect(Collectors.groupingBy( + doc -> doc.getFaultSource() != null ? doc.getFaultSource() : "general", + Collectors.counting() + )); stats.setCategoryCount(categoryCount); // Milvus 中的向量数量(需要实现) @@ -250,10 +251,9 @@ public class KnowledgeBaseInitService { document.setApiName(title); // 使用 title 作为 apiName document.setStatus("PENDING"); // 初始状态为 PENDING,索引成功后更新为 INDEXED - // 尝试映射 category 到 FaultCategory(如果匹配的话) - // 否则保持默认值 EXTERNAL_API - // 注意:frontmatter 的 category(api, infrastructure, domain)与 FaultCategory 枚举不完全匹配 - // 真实的分类信息保存在 metadata 中 + // 直接使用 fault_source 字段存储 category(api, infrastructure, domain 等) + // fault_category 字段名虽然不太贴切,但可以用来存储文档分类 + document.setFaultSource(category); // 将 frontmatter 信息保存到 metadata(JSON 格式) String metadataJson = String.format( @@ -283,34 +283,6 @@ public class KnowledgeBaseInitService { .replace("\r", "\\r"); } - /** - * 从 metadata JSON 中提取 category - */ - private String extractCategoryFromMetadata(String metadata) { - if (metadata == null || metadata.isEmpty()) { - return "general"; - } - - try { - // 简单的 JSON 解析(提取 "category":"xxx") - int categoryIndex = metadata.indexOf("\"category\":\""); - if (categoryIndex == -1) { - return "general"; - } - - int startIndex = categoryIndex + "\"category\":\"".length(); - int endIndex = metadata.indexOf("\"", startIndex); - if (endIndex == -1) { - return "general"; - } - - return metadata.substring(startIndex, endIndex); - } catch (Exception e) { - logger.warn("解析 metadata 失败: {}", metadata, e); - return "general"; - } - } - /** * 提取文档正文(去除 frontmatter) */