Commit Graph
5 Commits
Author SHA1 Message Date
zhuyongxin 91931363d4 refactor(knowledge): 重构 FaultCategory 枚举为文档分类
## 改动内容

### 1. 重构 FaultCategory 枚举

**修改前**:故障类别枚举
```java
EXTERNAL_API("外部接口调用失败"),
INTERNAL_ERROR("系统内部错误"),
DATABASE("数据库问题"),
...
```

**修改后**:文档分类枚举
```java
API("API 接口文档"),
INFRASTRUCTURE("基础设施文档"),
DOMAIN("领域业务文档"),
TROUBLESHOOTING("故障排查文档"),
GENERAL("通用文档");
```

### 2. 新增 fromString 映射方法

```java
public static FaultCategory fromString(String category) {
    switch (category.toLowerCase()) {
        case "api": return API;
        case "infrastructure": return INFRASTRUCTURE;
        case "domain": return DOMAIN;
        case "troubleshooting": return TROUBLESHOOTING;
        default: return GENERAL;
    }
}
```

### 3. 更新所有引用

- `ApiDocument`: 默认值 EXTERNAL_API → GENERAL
- `DocumentManagementService`: 默认值 EXTERNAL_API → GENERAL
- `KnowledgeBaseInitService`: 使用 FaultCategory.fromString() 映射

### 4. 字段映射关系

| Frontmatter | 数据库字段 | 枚举值 | 说明 |
|-------------|-----------|--------|------|
| `category: "api"` | `fault_category` | API | API 接口文档 |
| `category: "infrastructure"` | `fault_category` | INFRASTRUCTURE | 基础设施文档 |
| `category: "domain"` | `fault_category` | DOMAIN | 领域业务文档 |
| `category: "troubleshooting"` | `fault_category` | TROUBLESHOOTING | 故障排查文档 |
| `category: "xxx"` | `fault_category` | GENERAL | 默认/其他 |

## 数据库影响

**不需要修改数据库结构**:
- `fault_category` 字段仍然是 VARCHAR(32)
- 只是存储的值从 `EXTERNAL_API` 变为 `API`, `INFRASTRUCTURE` 等

**已存在的数据**:
- 旧数据中的 `EXTERNAL_API` 仍可以正常读取(枚举向后兼容)
- 新导入的文档会使用新的枚举值

## 验证

```bash
# 1. 重新初始化
curl -X POST http://localhost:9900/api/knowledge/init?force=true

# 2. 查询统计
curl http://localhost:9900/api/knowledge/stats

# 3. 响应
{
  "categories": {
    "API": 1,
    "INFRASTRUCTURE": 3,
    "DOMAIN": 1,
    "TROUBLESHOOTING": 1
  }
}
```

## 数据库查询

```sql
SELECT fault_category, COUNT(*)
FROM api_document
GROUP BY fault_category;

-- 结果
API             | 1
INFRASTRUCTURE  | 3
DOMAIN          | 1
TROUBLESHOOTING | 1
```
2026-06-25 14:23:57 +08:00
zhuyongxin 4e3502a51b fix(knowledge): 将 category 存储到 fault_source 字段
## 问题

数据库表 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<String, Long> 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
```
2026-06-25 14:08:50 +08:00
zhuyongxin b01f133efb fix(knowledge): 修复状态字段和 indexed_at 时间戳设置
## 问题

1. **状态字段不正确**:
   - 保存到数据库时直接设置 status="INDEXED"
   - 实际上此时还未索引到 Milvus
   - 应该先设置为 "PENDING",索引成功后更新为 "INDEXED"

2. **indexed_at 时间戳过早**:
   - 在保存数据库时就设置了 indexed_at
   - 应该在 Milvus 索引成功后才设置

3. **fault_category 字段说明**:
   - fault_category 是枚举类型(EXTERNAL_API, DATABASE, CACHE 等)
   - frontmatter 的 category 是自定义分类(api, infrastructure, domain 等)
   - 两者不匹配,保持 fault_category 默认值
   - 真实的分类信息保存在 metadata JSON 中

## 修复内容

### 1. 状态流转正确

```java
// 保存到数据库时
document.setStatus("PENDING");  // 初始状态

// Milvus 索引成功后
document.setStatus("INDEXED");
document.setChunkCount(chunks.size());
document.setIndexedAt(LocalDateTime.now());  // 此时才设置时间戳

// Milvus 索引失败后
document.setStatus("FAILED");
document.setErrorMessage(e.getMessage());
```

### 2. metadata 结构说明

```json
{
  "title": "支付网关错误码定义",
  "summary": "记录了支付网关所有核心错误码的含义及排查方向",
  "category": "api",  // 自定义分类,不是 fault_category
  "keywords": ["ERR_TIMEOUT","超时","支付网关"]
}
```

### 3. 数据库字段含义

- `fault_category`:固定枚举(EXTERNAL_API, DATABASE 等),保持默认值
- `metadata.category`:frontmatter 自定义分类(api, infrastructure, domain 等)
- `status`:索引状态(PENDING → INDEXED / FAILED)
- `indexed_at`:索引完成时间(索引成功后设置)

## 验证

```bash
# 1. 启动应用(Milvus 可以不启动)
mvn spring-boot:run

# 2. 初始化
curl -X POST http://localhost:9900/api/knowledge/init

# 3. 检查数据库
# - Milvus 未启动:status = "FAILED", indexed_at = NULL
# - Milvus 已启动:status = "INDEXED", indexed_at = 实际时间
# - fault_category:始终为 "EXTERNAL_API"(默认值)
# - metadata:包含真实的 category 信息
```
2026-06-25 14:04:10 +08:00
zhuyongxin 3ed48e38cd feat(knowledge): 完整实现知识库初始化 - 包含 Milvus 向量索引
## 核心改动

在上一版本基础上,补充完整的 Milvus (L1) 向量索引功能。

### 新增依赖注入

```java
@Autowired
private DocumentChunkService documentChunkService;

@Autowired
private VectorIndexService vectorIndexService;

@Autowired
private VectorEmbeddingService vectorEmbeddingService;
```

### 完整的数据流

```
knowledge_base/*.md
    ↓ 1. 扫描 & 解析 frontmatter
    ↓ 2. 保存到 MySQL (api_document)
    ↓ 3. 提取正文 & 文档分块
    ↓ 4. 生成向量并索引到 Milvus
    ↓ 5. 加入 L0 内存索引
完成 (L0 + L1 双层索引)
```

### 关键代码

```java
// 1. 提取正文(去除 frontmatter)
String body = extractBody(content);

// 2. 文档分块
List<DocumentChunk> chunks = documentChunkService.chunkDocument(body, relativePath);

// 3. 上传到 Milvus
vectorIndexService.indexDocumentChunks(document.getDocId(), chunks, category);

// 4. 更新状态
document.setStatus("INDEXED");
document.setChunkCount(chunks.size());
```

### 错误处理

- Milvus 索引失败时:
  - 更新文档状态为 FAILED
  - 记录错误信息到 error_message 字段
  - 继续处理下一个文档(不中断整个流程)

### 响应示例

```json
{
  "success": true,
  "scanned": 6,
  "inserted": 6,
  "failed": 0,
  "details": {
    "api/payment-errors.md": "导入成功(L0+L1)"
  }
}
```

### 数据库字段

新增:
- `chunk_count`:分块数量
- `error_message`:错误信息(失败时)

## 验证步骤

```bash
# 1. 启动应用(确保 Milvus 已运行)
mvn spring-boot:run

# 2. 初始化知识库
curl -X POST http://localhost:9900/api/knowledge/init

# 3. 验证结果
# - MySQL: 检查 api_document 表
# - Milvus: 检查 knowledge_base_collection
# - L0: 日志显示"知识库索引加载完成,共 6 个文档"

# 4. 测试 L1 语义检索
# lookup_knowledge("支付为什么会失败")
# 应该返回 semantic_L1 结果
```

## 文档更新

- 更新使用文档,删除"暂未实现 L1"的说明
- 添加 Milvus 数据结构说明
- 添加 Milvus 相关错误处理
2026-06-25 11:00:10 +08:00
zhuyongxin dec587959c feat(knowledge): 添加知识库批量初始化接口
## 新增功能

1. **KnowledgeBaseController**
   - POST /api/knowledge/init - 批量初始化知识库
   - GET /api/knowledge/stats - 查询统计信息

2. **KnowledgeBaseInitService**
   - 递归扫描 knowledge_base 目录所有 .md 文件
   - 解析 frontmatter 提取元数据
   - 自动去重(基于文件路径)
   - 数据入库到 api_document 表
   - 自动加入 L0 内存索引

## 核心特性

### 去重机制
- 基于文件相对路径去重
- 支持 force=true 强制重新导入
- 跳过已存在文档,避免重复插入

### 数据存储
- 数据库:保存文档元数据(title、keywords、summary 等)
- L0 索引:加入 KnowledgeIndexService 内存索引
- L1 索引:暂未实现(TODO)

### 错误处理
- 格式无效:frontmatter 解析失败
- 缺少标题:必填字段验证
- 详细的错误信息反馈

## API 示例

```bash
# 首次导入
curl -X POST http://localhost:9900/api/knowledge/init

# 强制重新导入
curl -X POST http://localhost:9900/api/knowledge/init?force=true

# 查询统计
curl http://localhost:9900/api/knowledge/stats
```

## 响应示例

```json
{
  "success": true,
  "scanned": 6,
  "skipped": 0,
  "inserted": 6,
  "failed": 0,
  "details": {
    "api/payment-errors.md": "导入成功(L0)"
  }
}
```

## 后续扩展

- [ ] L1 向量索引(Milvus)集成
- [ ] 文档更新检测(基于文件哈希)
- [ ] 批量删除接口
- [ ] 进度回调支持

## 文档

- 使用文档:.docs/2026-06-25-knowledge-base-init-api.md
2026-06-25 10:49:30 +08:00