knowledge-base-design.md 15 KB

知识库子系统设计文档

本文档为「知识库功能」的完整架构与实施指南。所有代码改动以此为准。

一、需求背景与边界

用户原始需求

增加知识库功能,包括文档数据管理结构化数据管理知识图谱管理

  • 文档数据:上传后分类管理 → 直接向量化入库
  • 结构化数据:参考 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 模型默认 chatEmbeddingService 复用 AiModelServiceImpl 的 clientCache 模式构建独立的 EmbeddingModel 缓存。


三、application.yml 新增配置

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.javaKbDocumentRepository.javaKbChunkRepository.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

状态机

PENDINGPARSINGCHUNKINGEMBEDDINGVECTORIZINGREADY 任一步失败 → 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 安全

// 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 默认查询

MATCH (n)-[r]->(m)
RETURN n, r, m
LIMIT 500

后端转换为 cytoscape elements:

{
  nodes: [{ data: { id, label, ...properties } }],
  edges: [{ data: { id, source, target, label, ...properties } }]
}

五、路由 + 菜单

router/index.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/documentsDocumentTextOutline
  • 结构化数据(/kb/datasourcesServerOutline
  • 知识图谱(/kb/graphsGitNetworkOutline

六、外部依赖未就绪时的降级策略 ⚠️ 开发期必须实现

设计原则

  • 应用必须能启动,无论 Milvus/Neo4j 是否在线
  • 代码必须完整,等实例开通后零改动可用
  • UI 必须可见,提交时给出明确错误提示

实现方式

Milvus 降级

@Configuration
@ConditionalOnProperty(name = "app.milvus.enabled", havingValue = "true", matchIfMissing = false)
public class MilvusConfig {
    @Bean
    public VectorStore vectorStore(...) { ... }
}

// VectorStoreServiceImpl 中所有方法都先检查 bean 是否存在
@Override
public List<String> upsert(List<float[]> vectors, List<Map<String,Object>> metadatas) {
    if (!vectorStoreEnabled) {
        throw new ServiceException("Milvus 未启用或未连接,请在 application.yml 配置 app.milvus.enabled=true");
    }
    ...
}

Neo4j 降级

// Neo4jExecutorService 用懒加载 driver,不预连接
// 调用时 try-catch ServiceUnavailable,转换为业务异常

Embedding 降级

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

# 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

# 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 + 用户)