## 新增功能 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
8.7 KiB
8.7 KiB
知识库初始化 API 使用文档
概述
提供了知识库批量初始化接口,用于将 knowledge_base 目录下的所有 Markdown 文档导入到数据库和向量索引(L0)。
功能特点:
- ✅ 批量扫描:递归扫描 knowledge_base 目录下所有 .md 文件
- ✅ 自动去重:基于文件路径检查,避免重复导入
- ✅ 数据入库:保存文档元数据到 MySQL
- ✅ L0 索引:自动加入内存精确匹配索引
- ⏳ L1 索引:暂未实现,需要后续通过独立索引任务完成
API 接口
1. 初始化知识库
端点:
POST /api/knowledge/init?force=false
参数:
force(可选):是否强制重新导入,跳过去重检查false(默认):跳过已存在的文档true:强制重新导入所有文档
请求示例:
# 首次导入(去重模式)
curl -X POST http://localhost:9900/api/knowledge/init
# 强制重新导入
curl -X POST http://localhost:9900/api/knowledge/init?force=true
响应示例:
{
"success": true,
"message": "知识库初始化完成",
"scanned": 6,
"skipped": 0,
"inserted": 6,
"failed": 0,
"details": {
"api/payment-errors.md": "导入成功(L0)",
"domain/spring-ai-tool-best-practices.md": "导入成功(L0)",
"infrastructure/flyway-best-practices.md": "导入成功(L0)",
"infrastructure/mysql-connection-pool.md": "导入成功(L0)",
"infrastructure/redis-config.md": "导入成功(L0)",
"troubleshooting/fault-diagnosis-process.md": "导入成功(L0)"
}
}
字段说明:
scanned:扫描到的文件总数skipped:跳过的文件数量(已存在)inserted:成功导入的文件数量failed:失败的文件数量details:每个文件的处理结果详情
2. 查询知识库统计
端点:
GET /api/knowledge/stats
请求示例:
curl http://localhost:9900/api/knowledge/stats
响应示例:
{
"success": true,
"totalDocuments": 6,
"totalVectors": 0,
"categories": {
"api": 1,
"domain": 1,
"infrastructure": 3,
"troubleshooting": 1
}
}
字段说明:
totalDocuments:数据库中的文档总数totalVectors:Milvus 中的向量总数(当前为 0,未实现)categories:按分类统计的文档数量
使用场景
场景 1:项目启动时初始化
# 1. 启动应用
mvn spring-boot:run
# 2. 等待应用启动完成(约 10 秒)
# 3. 调用初始化接口
curl -X POST http://localhost:9900/api/knowledge/init
# 4. 查看结果
# 日志输出:知识库初始化完成: 扫描=6, 跳过=0, 新增=6, 失败=0
场景 2:添加新文档后重新初始化
# 1. 添加新文档到 knowledge_base 目录
echo "---
title: 新文档
keywords: [测试, test]
summary: 这是一个测试文档
category: test
---
# 新文档内容
" > knowledge_base/test/new-doc.md
# 2. 调用初始化接口(去重模式)
curl -X POST http://localhost:9900/api/knowledge/init
# 3. 查看结果
# 只会导入新文档,跳过已存在的 6 个文档
# 响应: scanned=7, skipped=6, inserted=1, failed=0
场景 3:强制重新导入所有文档
# 适用场景:
# - 数据库被清空,需要重新导入
# - 文档内容有更新,需要刷新
# - 索引损坏,需要重建
curl -X POST http://localhost:9900/api/knowledge/init?force=true
# 响应: scanned=6, skipped=0, inserted=6, failed=0
去重机制
去重依据
- 文件路径:相对于
knowledge_base目录的相对路径 - 示例:
api/payment-errors.md
去重逻辑
if (!force && existingFilePaths.contains(relativePath)) {
跳过该文档
} else {
导入该文档
}
注意事项
-
文件移动会被视为新文档:
# 移动前:api/payment-errors.md # 移动后:errors/payment-errors.md # 结果:会被当作两个不同的文档 -
文件重命名会被视为新文档:
# 重命名前:payment-errors.md # 重命名后:payment-error-codes.md # 结果:会被当作两个不同的文档 -
内容更新不触发重新导入(非 force 模式):
# 修改文件内容后调用 init(非 force) # 结果:跳过该文档,数据库中仍是旧内容 # 解决:使用 force=true 强制重新导入
数据存储
数据库表结构(api_document)
| 字段 | 类型 | 说明 | 示例 |
|---|---|---|---|
id |
BIGINT | 主键 | 1 |
doc_id |
VARCHAR(64) | 文档唯一标识 | uuid |
file_name |
VARCHAR(256) | 文件名 | payment-errors.md |
file_path |
VARCHAR(512) | 相对路径 | api/payment-errors.md |
api_name |
VARCHAR(128) | 文档标题 | 支付网关错误码定义 |
status |
VARCHAR(16) | 状态 | INDEXED |
metadata |
TEXT | Frontmatter JSON | {"title":"...","keywords":[...]} |
file_size |
BIGINT | 文件大小(字节) | 2048 |
indexed_at |
DATETIME | 索引时间 | 2026-06-25 10:00:00 |
metadata JSON 结构
{
"title": "支付网关错误码定义",
"summary": "记录了支付网关所有核心错误码的含义及排查方向",
"category": "api",
"keywords": ["ERR_TIMEOUT","超时","支付网关"]
}
L0 内存索引
导入过程会自动将文档加入 KnowledgeIndexService 的内存索引:
KnowledgeEntry entry = KnowledgeEntry.builder()
.filePath(relativePath)
.title(title)
.keywords(keywords)
.summary(summary)
.category(category)
.build();
knowledgeIndexService.addToIndex(entry);
验证 L0 索引:
# 应用启动后查看日志
grep "知识库索引加载完成" logs/application.log
# 输出示例:
# [INFO] 知识库索引加载完成,共 6 个文档
错误处理
常见错误
1. 目录不存在
{
"success": false,
"message": "初始化失败: 知识库目录不存在: knowledge_base"
}
解决:
mkdir -p knowledge_base/api
mkdir -p knowledge_base/infrastructure
mkdir -p knowledge_base/domain
mkdir -p knowledge_base/troubleshooting
2. 文档格式无效
{
"success": true,
"scanned": 6,
"inserted": 5,
"failed": 1,
"details": {
"test/invalid.md": "格式无效: frontmatter 解析失败"
}
}
原因:
- 缺少 frontmatter
- YAML 格式错误
- 缺少必填字段(title, keywords, summary)
解决:
---
title: 文档标题
keywords: [关键词1, 关键词2]
summary: 文档摘要
category: api
---
# 正文内容
3. 文档缺少标题
{
"details": {
"test/no-title.md": "缺少标题"
}
}
解决:在 frontmatter 中添加 title 字段。
后续扩展(L1 向量索引)
当前版本暂未实现 L1 向量索引(Milvus),计划后续扩展:
扩展方案
-
独立索引任务:
POST /api/knowledge/build-vectors- 读取数据库中所有文档
- 调用
DocumentManagementService处理分块 - 上传到 Milvus
-
或者修改当前接口:
- 在
initializeKnowledgeBase中调用文档分块和向量索引 - 需要处理大文件的分块逻辑
- 在
验证 L1 的方法(未来)
# 1. 调用 L1 索引构建
curl -X POST http://localhost:9900/api/knowledge/build-vectors
# 2. 查询统计信息
curl http://localhost:9900/api/knowledge/stats
# 3. 确认 totalVectors > 0
最佳实践
✅ 推荐做法
-
首次启动后立即初始化:
mvn spring-boot:run sleep 15 # 等待启动完成 curl -X POST http://localhost:9900/api/knowledge/init -
新增文档后增量导入:
# 不使用 force,只导入新文档 curl -X POST http://localhost:9900/api/knowledge/init -
定期检查统计信息:
curl http://localhost:9900/api/knowledge/stats -
更新文档内容后强制刷新:
curl -X POST http://localhost:9900/api/knowledge/init?force=true
❌ 避免做法
-
不检查响应就认为成功:
- 始终检查
failed字段 - 查看
details了解具体失败原因
- 始终检查
-
频繁使用 force=true:
- 会重复插入数据(违反唯一约束)
- 建议先清理数据库,再使用 force
-
不检查文档格式就导入:
- 先手动验证 frontmatter 格式
- 确保必填字段完整
相关文档
- 知识库使用指南:
mvp/architecture/knowledge-retrieval-usage.md - 知识库架构:
mvp/architecture/knowledge-retrieval-architecture.md - Executor Prompt:
src/main/resources/prompts/executor-prompt.md