# 知识库子系统设计文档 > 本文档为「知识库功能」的完整架构与实施指南。所有代码改动以此为准。 ## 一、需求背景与边界 ### 用户原始需求 > 增加知识库功能,包括**文档数据管理**、**结构化数据管理**、**知识图谱管理**。 > - 文档数据:上传后分类管理 → 直接向量化入库 > - 结构化数据:参考 beekeeper-studio 的数据源管理(含 SQL Console) > - 知识图谱:图谱数据源管理 + 图谱查看 ### 已锁定的核心架构决策(用户确认) | 子系统 | 选型 | 部署模式 | |--------|------|----------| | 文档向量化 | **Milvus** + Spring AI starter | 外部独立服务(默认 `localhost:19530`) | | 知识图谱 | **Neo4j Community** | 外部独立服务(默认 `bolt://localhost:7687`) | | 结构化数据 | **完整 SQL Console**(Monaco Editor) | JDBC 多驱动 + HikariCP 动态连接池 | | 与工作流集成 | **本期独立**,RAG / 图谱查询节点留待下期 | - | ### 当前实例状态(开发期) - ❌ Milvus 实例未部署 - ❌ Neo4j 实例未部署 - ❌ 智谱 embedding-2 模型未开通 → **降级策略见第六章**。所有外部依赖必须支持「未就绪时优雅降级」,应用能正常启动、UI 可见、提交时给出明确提示。 --- ## 二、技术栈现状 ### 已具备 - Spring Boot 3.3.6 + Java 17 - Spring AI 1.0.0 BOM(OpenAI 兼容,目前用智谱 GLM-5.2 chat) - Spring Data JPA + H2 文件库(`./data/agent-runs`) - JSON 文件存储(`AbstractJsonRepository`) - ChatClient 缓存机制(`AiModelServiceImpl.clientCache`) - 前端:Vue 3 + Vue Flow + naive-ui + monaco-editor ### 待新增依赖 #### `backend/pom.xml` | 依赖 | 版本 | 用途 | |------|------|------| | `org.springframework.ai:spring-ai-starter-vector-store-milvus` | 1.0.0(已有 BOM) | Milvus 集成 + EmbeddingModel 自动配置 | | `org.neo4j.driver:neo4j-java-driver` | 5.27.x | Neo4j Cypher 客户端 | | `org.apache.tika:tika-parsers-standard-package` | 2.9.2 | PDF/Word/Excel/PPT/HTML 解析 | | `org.springframework.boot:spring-boot-starter-jdbc` | 已随 boot | 动态数据源(HikariCP) | | `mysql:mysql-connector-j` | 8.4.x | MySQL 驱动 | | `org.postgresql:postgresql` | 42.7.x | PG 驱动 | | `com.oracle.database.jdbc:ojdbc11` | 23.5.x | Oracle 驱动 | | `com.microsoft.sqlserver:mssql-jdbc` | 12.8.x | SQL Server 驱动 | | `org.xerial:sqlite-jdbc` | 3.46.x | SQLite 驱动 | | `com.github.ulisesbocchio:jasypt-spring-boot-starter` | 3.0.5 | 密码加密(数据源凭据) | #### `frontend/package.json` | 依赖 | 用途 | |------|------| | `cytoscape` | 图谱可视化核心 | | `cytoscape-cose-bilkent` | 自动布局算法 | | `sql-formatter` | SQL 美化(4.x ncompact 版本) | ### AiModel 表扩展 新增 `modelType` 字段(`chat` / `embedding`),现有 chat 模型默认 `chat`。`EmbeddingService` 复用 `AiModelServiceImpl` 的 clientCache 模式构建独立的 `EmbeddingModel` 缓存。 --- ## 三、`application.yml` 新增配置 ```yaml app: kb: enabled: true # 总开关:false 时全部 kb 接口返回 503 upload-dir: ./uploads/kb max-file-size: 52428800 # 50MB chunk-size: 1000 # 字符数 chunk-overlap: 200 allowed-mime-types: - application/pdf - application/vnd.openxmlformats-officedocument.wordprocessingml.document - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet - application/vnd.openxmlformats-officedocument.presentationml.presentation - text/plain - text/markdown - text/html milvus: enabled: true # false 时跳过 bean 创建 host: localhost port: 19530 collection: kb_documents vector-dimension: 1024 # 智谱 embedding-2 输出维度 neo4j: enabled: true # 默认连接(用户也可在 UI 配置多个) default-uri: bolt://localhost:7687 default-user: neo4j default-password: ${NEO4J_PASSWORD:} spring: ai: openai: embedding: options: model: embedding-2 # 智谱 embedding jasypt: encryptor: password: ${JASYPT_KEY:dev-only-key-replace-me-in-prod} ``` --- ## 四、模块清单(共 ~50 个文件) ### Phase 1:文档数据管理(13 个文件) #### 后端 - `model/entity/KbCategory.java` — 树形分类(id, name, parentId, sortOrder) - `model/entity/KbDocument.java` — 文档元数据(id, name, categoryId, sourcePath, fileSize, mimeType, status, chunkCount, vectorCount, errorMessage, createdAt, updatedAt) - `model/entity/KbChunk.java` — 文档分块(id, documentId, chunkIndex, content, vectorId, charCount) - `repository/KbCategoryRepository.java`、`KbDocumentRepository.java`、`KbChunkRepository.java` - `service/KbCategoryService.java` + `impl/KbCategoryServiceImpl.java` — 分类 CRUD - `service/DocumentService.java` + `impl/DocumentServiceImpl.java` — 上传/解析/分块/向量化 - `service/EmbeddingService.java` + `impl/EmbeddingServiceImpl.java` — 调用 embedding-2(懒加载,复用 AiModelServiceImpl 模式) - `service/VectorStoreService.java` + `impl/VectorStoreServiceImpl.java` — Milvus 操作(懒加载 + 降级) - `controller/KbCategoryController.java` — 分类 CRUD - `controller/KbDocumentController.java` — 上传/列表/分类切换/删除/重新向量化 - `config/MilvusConfig.java` — `@ConditionalOnProperty("app.milvus.enabled")` #### 前端 - `views/kb/DocumentManagement.vue` — 主页:左分类树 + 右文档列表 + 状态徽章 - `components/kb/DocumentUploader.vue` — 多文件上传 + 进度 + 分类选择 - `components/kb/CategoryTree.vue`(可复用现有 `components/skill/CategoryTree.vue`,或单独建) - `api/kb.js` — API 客户端 #### 核心流程 ``` 上传文件 → 校验 MIME → 落盘 uploads/kb/ → INSERT KbDocument(status=PENDING) ↓ 异步处理: 1. Tika 解析为纯文本 2. 递归字符分块 (1000 + overlap 200) 3. INSERT KbChunk 批量 4. 批量 embedding (status=EMBEDDING) 5. Milvus upsert (status=VECTORIZING) 6. status=READY / FAILED ``` #### 状态机 `PENDING` → `PARSING` → `CHUNKING` → `EMBEDDING` → `VECTORIZING` → `READY` 任一步失败 → `FAILED`(记录 errorMessage) --- ### Phase 2:结构化数据源管理(18 个文件,工作量最大) #### 后端 - `model/entity/DataSource.java` — id, name, type(MYSQL/PG/ORACLE/SQLSERVER/SQLITE), jdbcUrl, username, passwordEnc, createdAt - `repository/DataSourceRepository.java` - `service/DataSourceService.java` + Impl — CRUD + 测试连接 - `service/DynamicJdbcService.java` — 按 datasourceId 维护 HikariCP 连接池缓存(LRU + 最大 10 池) - `service/SchemaExplorerService.java` + Impl — listSchemas / listTables / describeTable / countRows / pageQuery - `service/SqlGuardService.java` — SQL 白名单校验 - `controller/DataSourceController.java` — CRUD + 测试连接 - `controller/DataSourceQueryController.java` — executeSql / listTables / describeTable / pageQuery #### 前端 - `views/kb/DataSourceManagement.vue` — 主页:左数据源列表 + 右侧 Tab - `components/kb/DataSourceForm.vue` — 新增/编辑表单 + 测试连接 - `components/kb/TableExplorer.vue` — 表/字段树 - `components/kb/SqlConsole.vue` — Monaco 编辑器 + 执行按钮 + 历史记录 - `components/kb/QueryResult.vue` — 虚拟滚动结果表 - `components/kb/QueryHistory.vue` — 查询历史持久化 - `api/datasource.js` #### SQL 安全 ```java // SqlGuardService 白名单 ALLOWED_PREFIXES = ["SELECT", "WITH", "EXPLAIN"] FORBIDDEN_KEYWORDS = ["INSERT", "UPDATE", "DELETE", "DROP", "ALTER", "CREATE", "TRUNCATE", "GRANT", "REVOKE", "MERGE"] // 限制 - 单次查询硬超时 30s - 返回行数硬限 10000 - 禁止系统库(如 information_schema、mysql、sys) ``` --- ### Phase 3:知识图谱管理(11 个文件) #### 后端 - `model/entity/GraphSource.java` — id, name, uri, username, passwordEnc, createdAt - `repository/GraphSourceRepository.java` - `service/GraphSourceService.java` + Impl — CRUD + 测试连接 - `service/Neo4jExecutorService.java` + Impl — 动态 driver 缓存(按 graphId) - `controller/GraphSourceController.java` — CRUD + 图谱数据查询(返回 cytoscape elements 格式) #### 前端 - `views/kb/GraphSourceManagement.vue` — 左图谱列表 + 右图谱可视化 - `components/kb/GraphSourceForm.vue` — 连接配置表单 - `components/kb/GraphViewer.vue` — cytoscape + cose-bilkent 布局 + 节点点击详情 - `components/kb/NodeDetailPanel.vue` — 节点属性展示 - `api/graphsource.js` #### Cypher 默认查询 ```cypher MATCH (n)-[r]->(m) RETURN n, r, m LIMIT 500 ``` 后端转换为 cytoscape elements: ```js { nodes: [{ data: { id, label, ...properties } }], edges: [{ data: { id, source, target, label, ...properties } }] } ``` --- ## 五、路由 + 菜单 ### `router/index.js` ```js { path: '/kb/documents', name: 'KbDocumentManagement', component: () => import('../views/kb/DocumentManagement.vue') }, { path: '/kb/datasources', name: 'KbDataSourceManagement', component: () => import('../views/kb/DataSourceManagement.vue') }, { path: '/kb/graphs', name: 'KbGraphSourceManagement', component: () => import('../views/kb/GraphSourceManagement.vue') }, ``` ### `components/layout/AppSidebar.vue` 新增「知识库」分组,3 个子菜单: - 文档数据(`/kb/documents`,`DocumentTextOutline`) - 结构化数据(`/kb/datasources`,`ServerOutline`) - 知识图谱(`/kb/graphs`,`GitNetworkOutline`) --- ## 六、外部依赖未就绪时的降级策略 ⚠️ 开发期必须实现 ### 设计原则 - **应用必须能启动**,无论 Milvus/Neo4j 是否在线 - **代码必须完整**,等实例开通后零改动可用 - **UI 必须可见**,提交时给出明确错误提示 ### 实现方式 #### Milvus 降级 ```java @Configuration @ConditionalOnProperty(name = "app.milvus.enabled", havingValue = "true", matchIfMissing = false) public class MilvusConfig { @Bean public VectorStore vectorStore(...) { ... } } // VectorStoreServiceImpl 中所有方法都先检查 bean 是否存在 @Override public List upsert(List vectors, List> metadatas) { if (!vectorStoreEnabled) { throw new ServiceException("Milvus 未启用或未连接,请在 application.yml 配置 app.milvus.enabled=true"); } ... } ``` #### Neo4j 降级 ```java // Neo4jExecutorService 用懒加载 driver,不预连接 // 调用时 try-catch ServiceUnavailable,转换为业务异常 ``` #### Embedding 降级 ```java // EmbeddingServiceImpl 调用智谱 embedding-2 失败时 // 1. 不抛出致命错误 // 2. 文档状态置 FAILED + errorMessage="embedding 调用失败:xxx" // 3. 用户在 UI 看到失败状态,可点击"重新向量化"重试 ``` #### 全局开关 `app.kb.enabled=false` 时所有 kb Controller 返回 503,便于运维应急降级。 ### 验证方式 开发期:Milvus/Neo4j/embedding 全部不可用时: - ✅ 应用正常启动 - ✅ 文档可上传、可分类、可查看 - ✅ 文档状态显示"向量化失败:xxx" - ✅ 数据源可保存、可测试连接(JDBC 直连) - ✅ 图谱连接可保存(不预连) - ❌ 向量化、图谱查询、SQL 执行在执行时给出明确提示 --- ## 七、安全设计 ### 密码加密 - DataSource / GraphSource 的 `password` 字段使用 Jasypt 加密入库 - 实体 `@Transient passwordPlain` 仅在内存中临时持有 - Controller 返回时**永远不返回** password 字段 ### SQL 注入防护 1. 强制使用 HikariCP prepared statement 2. SqlGuardService 白名单(仅 SELECT/WITH/EXPLAIN) 3. 单次查询超时 30s、返回行数硬限 10000 4. 禁止系统库访问 ### 文件上传安全 - 白名单 MIME 类型 - 单文件大小限制 50MB - 文件名 sanitize(去除 `../` 等) - 存储目录单独隔离(`uploads/kb/`,不允许外部直接访问) --- ## 八、分阶段实施计划 | Phase | 内容 | 文件数 | 验证条件 | 当前状态 | |-------|------|--------|----------|----------| | **Phase 1** | 基础设施 + 文档数据管理 | 13 | 文档上传 + 分类 + 向量化入库 | ⏳ 进行中 | | **Phase 2** | 结构化数据源管理 | 18 | 5 类 DB 连接 + SQL Console | ⬜ 待启动 | | **Phase 3** | 知识图谱管理 | 11 | Neo4j 连接 + cytoscape 可视化 | ⬜ 待启动 | 每个 Phase 都能独立运行、独立验证。**完成一个 Phase 再启动下一个。** --- ## 九、运维 checklist(实例开通后) ### Milvus ```bash # Docker 快速启动 docker run -d --name milvus-standalone \ -p 19530:19530 -p 9091:9091 \ -v ./milvus/data:/var/lib/milvus \ milvusdb/milvus:latest standalone # 健康检查 curl http://localhost:9091/healthz ``` ### Neo4j ```bash # Docker 快速启动 docker run -d --name neo4j \ -p 7474:7474 -p 7687:7687 \ -e NEO4J_AUTH=neo4j/change-me \ -v ./neo4j/data:/data \ neo4j:5-community # Web UI: http://localhost:7474 ``` ### 智谱 embedding-2 开通 登录智谱开放平台 → 模型广场 → embedding-2 → 申请开通 → API Key 即复用现有 GLM 的 key ### 验证步骤 1. 启动后端,看启动日志无 Milvus/Neo4j 连接失败 2. 上传测试 PDF,等待状态变 READY 3. 创建数据源 → 测试连接 → 表浏览 → SQL 查询 4. 创建图谱源 → 查看图谱 → 点击节点 --- ## 十、后续扩展(下期) ### RAG 节点(接入工作流) - 新增工作流节点类型 `kbRetrieval` - 配置:选择知识库分类 + topK + similarity threshold - 执行:从 Milvus 检索相关 chunks → 拼装上下文 → 喂给下游 LLM ### 图谱查询节点 - 新增工作流节点类型 `graphQuery` - 配置:选择图谱源 + Cypher 模板 - 执行:返回查询结果作为 LLM 上下文 ### 自动知识抽取 - 从已上传文档抽取实体/关系 → 自动入 Neo4j - 从结构化数据源外键关系 → 自动生成图谱 --- ## 十一、风险与权衡 | 风险 | 应对 | |------|------| | Milvus Spring AI starter 版本兼容 | 优先 1.0.0 已有 BOM 锁定版本,开发时验证 | | Oracle/SQL Server 驱动体积大 | 仅按需引入,发布版可裁剪 | | H2 与多数据源共存 | DynamicJdbcService 完全独立,使用单独的 DataSource 实例,不与主 EntityManagerFactory 冲突 | | Tika 依赖膨胀(~30MB) | 文档管理是核心需求,必须接受 | | 智谱 embedding-2 维度 1024 | Milvus collection 初始化时硬编码,后期不可变 | --- **文档版本**:v1.0 **创建日期**:2026-06-15 **最后更新**:2026-06-15 **负责人**:开发协作(Claude + 用户)