02-architecture.md 15 KB

知识库管理系统 - 架构设计

1. 技术栈

技术 版本
后端框架 Spring Boot 3.2.x
ORM MyBatis Plus 3.5.x
数据库 MySQL 8.0+
认证 JWT (jjwt) 0.12.x
抓取 Jsoup 1.17.x
Diff google-diff-match-patch 1.2
HTTP 客户端 Spring RestClient(内置) -
工具库 Hutool / Lombok 最新稳定
前端框架 Vue 3.4.x
构建工具 Vite 5.x
UI 库 Element Plus 最新稳定
状态管理 Pinia 最新稳定
路由 Vue Router 4.x
前端 Diff 展示 diff-match-patch(自渲染)或 vue-diff -

2. 项目目录结构

knowledge-extractor/
├── backend/                                    后端 Spring Boot 工程
│   ├── pom.xml
│   ├── src/main/java/com/knowledge/extractor/
│   │   ├── KnowledgeExtractorApplication.java
│   │   ├── config/
│   │   │   ├── WebMvcConfig.java               (CORS)
│   │   │   ├── SpaController.java              (SPA fallback)
│   │   │   ├── SecurityConfig.java             (JWT 过滤器链)
│   │   │   ├── MybatisPlusConfig.java
│   │   │   └── RestClientConfig.java
│   │   ├── common/
│   │   │   ├── R.java                          (统一返回)
│   │   │   ├── PageResult.java
│   │   │   ├── BizException.java
│   │   │   ├── GlobalExceptionHandler.java
│   │   │   ├── JwtUtil.java
│   │   │   └── AesUtil.java
│   │   ├── module/
│   │   │   ├── auth/                           登录、JWT
│   │   │   │   ├── AuthController.java
│   │   │   │   ├── AuthService.java
│   │   │   │   ├── JwtFilter.java
│   │   │   │   └── entity/SysUser.java
│   │   │   ├── tag/                            标签体系(按 tag-system 技能)
│   │   │   │   ├── TagController.java
│   │   │   │   ├── TagService.java
│   │   │   │   ├── impl/TagServiceImpl.java
│   │   │   │   ├── entity/{TagGroup,Tag,TagAssignment}.java
│   │   │   │   ├── mapper/{TagGroupMapper,TagMapper,TagAssignmentMapper}.java
│   │   │   │   ├── dto/{TagExportDTO,TagImportDTO,TagImportResultDTO}.java
│   │   │   │   └── vo/TagBriefVO.java
│   │   │   ├── article/                        文章录入与抓取
│   │   │   │   ├── ArticleController.java
│   │   │   │   ├── ArticleService.java
│   │   │   │   ├── LinkFetcher.java            (Jsoup + readability)
│   │   │   │   ├── entity/Article.java
│   │   │   │   └── mapper/ArticleMapper.java
│   │   │   ├── llm/                            LLM 配置与客户端
│   │   │   │   ├── LlmConfigController.java
│   │   │   │   ├── LlmConfigService.java
│   │   │   │   ├── OpenAiCompatibleClient.java
│   │   │   │   ├── entity/LlmConfig.java
│   │   │   │   └── mapper/LlmConfigMapper.java
│   │   │   └── knowledge/                      知识聚合 + 版本管理
│   │   │       ├── KnowledgeController.java
│   │   │       ├── KnowledgeService.java
│   │   │       ├── KnowledgeAggregateService.java  (调用 LLM、聚合、diff)
│   │   │       ├── DiffService.java
│   │   │       ├── entity/{Knowledge,KnowledgeVersion}.java
│   │   │       └── mapper/{KnowledgeMapper,KnowledgeVersionMapper}.java
│   │   └── mapper/                             MyBatis mapper xml(如需)
│   └── src/main/resources/
│       ├── application.yml
│       ├── mapper/                             MyBatis xml
│       └── static/                             前端构建产物(vite 直出)
├── frontend/                                   前端 Vue 工程
│   ├── package.json
│   ├── vite.config.js
│   ├── index.html
│   └── src/
│       ├── main.js
│       ├── App.vue
│       ├── router/index.js
│       ├── stores/                             Pinia stores
│       │   ├── auth.js
│       │   ├── tag.js
│       │   └── ...
│       ├── api/                                axios 封装
│       │   ├── request.js
│       │   ├── auth.js
│       │   ├── tag.js
│       │   ├── article.js
│       │   ├── knowledge.js
│       │   └── llm.js
│       ├── layouts/
│       │   └── MainLayout.vue                  (顶部导航 + 侧边栏)
│       ├── components/
│       │   ├── tag/                            (来自 tag-system 技能)
│       │   │   ├── TreeNodeItem.vue
│       │   │   └── TagSelector.vue
│       │   └── knowledge/
│       │       ├── VersionTimeline.vue
│       │       └── DiffViewer.vue
│       └── views/
│           ├── LoginView.vue
│           ├── SetupView.vue                   (首次启动引导)
│           ├── TagsView.vue                    (标签管理)
│           ├── ArticlesView.vue                (文章录入)
│           ├── KnowledgeListView.vue           (知识列表)
│           ├── KnowledgeDetailView.vue         (知识详情 + 时间轴)
│           └── SettingsView.vue                (LLM 配置 + 改密)
├── docs/                                       本设计文档目录
├── run.bat                                     Windows 一键构建脚本
├── run.sh                                      Linux/macOS 一键构建脚本
└── .gitattributes

3. 数据库表设计(共 8 张)

3.1 标签体系(tag-system 技能标准)

-- 标签组(分类维度)
CREATE TABLE tag_group (
  id          BIGINT PRIMARY KEY AUTO_INCREMENT,
  name        VARCHAR(100) NOT NULL,
  description VARCHAR(500),
  sort_order  INT DEFAULT 0,
  created_at  DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at  DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  UNIQUE KEY uk_name (name)
);

-- 标签节点(自引用树,每组有一个同名根节点 parent_id=NULL)
CREATE TABLE tag (
  id         BIGINT PRIMARY KEY AUTO_INCREMENT,
  group_id   BIGINT NOT NULL,
  parent_id  BIGINT,
  name       VARCHAR(100) NOT NULL,
  sort_order INT DEFAULT 0,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  KEY idx_group (group_id),
  KEY idx_parent (parent_id)
);

-- 通用打标关联
CREATE TABLE tag_assignment (
  id           BIGINT PRIMARY KEY AUTO_INCREMENT,
  entity_type  VARCHAR(50) NOT NULL,    -- article / knowledge
  entity_id    BIGINT NOT NULL,
  tag_id       BIGINT NOT NULL,
  created_at   DATETIME DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY uk_entity_tag (entity_type, entity_id, tag_id),
  KEY idx_entity (entity_type, entity_id)
);

3.2 系统与配置

-- 单用户
CREATE TABLE sys_user (
  id            BIGINT PRIMARY KEY AUTO_INCREMENT,
  username      VARCHAR(50) NOT NULL,
  password_hash VARCHAR(100) NOT NULL,
  salt          VARCHAR(50) NOT NULL,
  created_at    DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- LLM 配置(单行记录,id 固定为 1)
CREATE TABLE llm_config (
  id           BIGINT PRIMARY KEY,
  base_url     VARCHAR(255) NOT NULL,    -- 如 https://api.openai.com/v1
  api_key      VARCHAR(500) NOT NULL,    -- AES 加密后内容
  model        VARCHAR(100) NOT NULL,    -- 如 gpt-4o-mini
  temperature  DECIMAL(3,2) DEFAULT 0.30,
  max_tokens   INT DEFAULT 4000,
  updated_at   DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

3.3 文章

CREATE TABLE article (
  id           BIGINT PRIMARY KEY AUTO_INCREMENT,
  title        VARCHAR(255) NOT NULL,
  source_type  VARCHAR(20) NOT NULL,     -- md / txt / link
  source_url   VARCHAR(500),             -- link 类型记录原 URL
  content      MEDIUMTEXT,               -- 原始正文(用于展示)
  raw_text     MEDIUMTEXT,               -- 抽干后的纯文本(喂给 LLM)
  llm_topic    VARCHAR(100),             -- LLM 归纳的主题名
  status       VARCHAR(20) DEFAULT 'pending',  -- pending/classified/aggregated
  error_msg    VARCHAR(500),             -- LLM 调用失败信息
  created_at   DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at   DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  KEY idx_status (status),
  KEY idx_topic (llm_topic)
);

3.4 知识与版本

-- 聚合知识(每个 LLM 自由生成的主题对应一条记录)
CREATE TABLE knowledge (
  id               BIGINT PRIMARY KEY AUTO_INCREMENT,
  title            VARCHAR(200) NOT NULL,  -- 主题名(如"大模型部署方法")
  current_content  MEDIUMTEXT NOT NULL,    -- 最新版全文(前端展示)
  article_count    INT DEFAULT 0,
  created_at       DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at       DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  KEY idx_title (title)
);

-- 版本快照(每次变更一条)
CREATE TABLE knowledge_version (
  id                BIGINT PRIMARY KEY AUTO_INCREMENT,
  knowledge_id      BIGINT NOT NULL,
  version_no        INT NOT NULL,           -- 第几版(1=初版)
  article_id        BIGINT NOT NULL,        -- 触发本次变更的文章
  change_type       VARCHAR(20) NOT NULL,   -- create / append / revise
  change_desc       VARCHAR(500) NOT NULL,  -- 变更描述(LLM 生成)
  content_snapshot  MEDIUMTEXT NOT NULL,    -- 本版完整 MD 快照
  diff_added        INT DEFAULT 0,          -- 新增行数
  diff_removed      INT DEFAULT 0,          -- 删除行数
  diff_patch        TEXT,                   -- diff-match-patch patch 文本(可选)
  created_at        DATETIME DEFAULT CURRENT_TIMESTAMP,
  KEY idx_knowledge (knowledge_id),
  KEY idx_version (knowledge_id, version_no)
);

4. API 设计

4.1 认证

方法 路径 说明
POST /api/auth/setup 首次启动设置管理员账号
GET /api/auth/setup-status 查询是否已初始化
POST /api/auth/login 登录,返回 JWT
POST /api/auth/change-password 修改密码
GET /api/auth/me 获取当前用户

4.2 标签(按 tag-system 技能规范)

方法 路径 说明
GET /api/tags/groups 列出所有标签组
POST /api/tags/groups 创建标签组
POST /api/tags/groups/{id}/edit 更新
POST /api/tags/groups/{id}/delete 删除
GET /api/tags/groups/{groupId}/tags 获取组内扁平标签列表
POST /api/tags/groups/{groupId}/tags 创建标签节点
POST /api/tags/{id}/edit 重命名
POST /api/tags/{id}/delete 删除(递归)
POST /api/tags/{id}/move 移动(含防循环)
GET /api/tags/export 导出
POST /api/tags/import 导入
POST /api/tags/assignments 设置实体标签(全量替换)
GET /api/tags/assignments?entityType=&entityId= 获取实体标签
GET /api/tags/all-with-tags 全部标签(选择器用)

4.3 文章

方法 路径 说明
GET /api/articles?page=&size=&keyword= 分页列表
GET /api/articles/{id} 文章详情
POST /api/articles 录入文章(md/txt/link)
POST /api/articles/{id}/fetch-link 重新抓取链接
POST /api/articles/{id}/classify 触发 LLM 重新归类
POST /api/articles/{id}/aggregate 触发聚合(手动)
DELETE /api/articles/{id} 删除

4.4 知识

方法 路径 说明
GET /api/knowledge?page=&size=&keyword= 知识列表
GET /api/knowledge/{id} 知识详情(含 current_content)
GET /api/knowledge/{id}/versions 时间轴(版本列表)
GET /api/knowledge/{id}/versions/{versionNo} 单版本详情(含 snapshot + diff)
GET /api/knowledge/{id}/versions/{versionNo}/article 跳转关联原文章
DELETE /api/knowledge/{id} 删除知识(级联删版本)

4.5 LLM 配置

方法 路径 说明
GET /api/llm/config 获取配置(api_key 返回掩码)
POST /api/llm/config 保存配置
POST /api/llm/config/test 测试连通性

5. 业务流程

5.1 文章录入与归类流程

1. 用户提交文章(md/txt/link)
   ├── md/txt:直接保存 content + raw_text
   └── link:Jsoup 抓取 + readability 提取正文;失败提示用户手动贴入

2. 文章入库后状态 = pending
   └── 自动(或用户手动点)触发 classify

3. classify 流程:
   a. 加载所有标签扁平列表(含路径,如"计算机/人工智能/LLM")
   b. 调用 LLM 接口,prompt 让其输出 JSON:
      {
        "candidateTagIds": [12, 34],          // 匹配的已有标签 ID
        "newTags": [                           // 需要新建的标签
          { "parentPath": "计算机/人工智能", "name": "RAG" }
        ],
        "topic": "大模型部署方法"               // 文章主题
      }
   c. 新建缺失标签,写入 tag_assignment
   d. 更新 article.llm_topic = topic, status = classified

4. 自动触发 aggregate(或用户手动)
   a. 查询现有所有 knowledge 列表(仅 id + title)
   b. 调用 LLM,让其判断本文应归入哪个 knowledge(按 topic + 现有标题语义匹配)
   c. 若归入已有:
      - 调用 LLM 生成补充段落 + 变更描述
      - 新建 knowledge_version(type=append, version_no=last+1)
      - 更新 knowledge.current_content
   d. 若不归入任何已有:
      - 调用 LLM 生成初版知识全文
      - 新建 knowledge + knowledge_version(type=create, version_no=1)
   e. 计算 diff(前一版 vs 当前版),存入 diff_added/diff_removed/diff_patch

5.2 知识查看流程

1. 进入知识列表 → 选择一条知识 → 进入详情页
2. 详情页三栏布局:
   ├── 左:版本时间轴(点击节点)
   ├── 中:当前 knowledge.current_content 渲染
   └── 右:选中版本的变更详情面板
       ├── 变更类型徽章(create/append/revise)
       ├── 变更描述
       ├── diff 行数(+x / -y)
       ├── diff 可视化(红绿块)
       └── "查看关联原文章"按钮 → 跳转 /articles/{article_id}
3. 切换时间轴节点 → 右侧面板与中间内容联动:
   - 点击历史版本 → 中间展示该版本 content_snapshot

6. 初始化与引导

首次启动 → 检查 sys_user 表
  ├── 空 → 前端访问任意页面跳转 /setup
  │       → 用户设置 username/password → 同时配置 LLM
  │       → 写入 sys_user + llm_config → 跳转 /login
  └── 非空 → 正常登录流程

7. 安全设计

  • JWT:HS256,密钥从配置读取,过期时间 7 天
  • api_key:AES-128 加密入库,密钥从 application.yml 读取
  • 密码:BCrypt 加盐
  • 所有 /api/** 除 /api/auth/setup、/api/auth/login、/api/auth/setup-status 外需 JWT