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 |
|