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
This commit is contained in:
zhuyongxin
2026-06-25 10:49:30 +08:00
parent f002571629
commit dec587959c
5 changed files with 838 additions and 4 deletions
@@ -0,0 +1,94 @@
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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> response = new HashMap<>();
response.put("success", false);
response.put("message", "查询失败: " + e.getMessage());
return ResponseEntity.internalServerError().body(response);
}
}
}