init: 数字员工平台初始代码
包含前端(Vue3 + VueFlow 画布)、后端(Go)、文档体系。 - 工作台画布:节点拖放、连线模式、右键菜单、AI 助手 - 后端:连接器 API、专员种子数据 - 导航:左侧导航、工坊、市场、控制台
This commit is contained in:
@@ -0,0 +1,226 @@
|
||||
# BE05 — 知识入库体系总设计(Knowledge Ingest)
|
||||
|
||||
> **版本:V1.1 | 定稿**
|
||||
> **定位**:把「素材入库」与「结构化知识入库」统一为一套可复用的知识入库体系,覆盖上传 → 生成 → 审批 → 入库全链路。
|
||||
> **配套**:BE03(素材转换管线)、BE04(AI 检索)、`docs/knowledge_source/README.md`(知识源格式契约)。
|
||||
|
||||
---
|
||||
|
||||
## 1. 模块职责
|
||||
|
||||
知识入库体系负责把两类知识源,统一经过「审批前置」流入三张消费表,最终支撑「可浏览 / 可考试 / 可 AI 检索」。
|
||||
|
||||
| 知识源类型 | 载体 | 审批单元 | 流入表 |
|
||||
|-----------|------|---------|--------|
|
||||
| **非结构化素材** | PPT/PDF/Word/视频/图片 | 逐文件 | knowledge_chunk(+ 预览) |
|
||||
| **结构化知识** | 知识源 md(docs/knowledge_source/) | 逐文档 | product / question / knowledge_chunk |
|
||||
|
||||
**核心原则(与 P02/P04 对齐)**:所有知识只有 `approved` 才生效;`pending` / `rejected` 一律不解析、不进库、前台不可见。
|
||||
|
||||
---
|
||||
|
||||
## 2. 完整目录结构(定稿)
|
||||
|
||||
```
|
||||
eaisalestrain_app/
|
||||
├── docs/
|
||||
│ └── knowledge_source/ # 知识源文档(权威源,纳入 git 版本管理)
|
||||
│ ├── README.md # 格式契约 + 答案契约 + 审批状态机
|
||||
│ ├── 01_通用规则.md
|
||||
│ ├── 02_资本咨询类.md
|
||||
│ ├── 03_资质认定辅导类.md
|
||||
│ ├── 04_AI咨询与实施类.md
|
||||
│ └── 05_企业级AI工具与平台.md
|
||||
│
|
||||
├── backend/
|
||||
│ ├── app/
|
||||
│ │ ├── api/
|
||||
│ │ │ ├── media.py # 【已有】素材上传/审批/预览
|
||||
│ │ │ └── knowledge.py # 【新增】知识源扫描/审批/摄入
|
||||
│ │ ├── models/
|
||||
│ │ │ ├── media_file.py # 【已有】素材表
|
||||
│ │ │ ├── knowledge_chunk.py # 【改造】来源扩展(见 §4)
|
||||
│ │ │ └── knowledge_source.py # 【新增】知识源文档表
|
||||
│ │ ├── services/
|
||||
│ │ │ ├── media_service.py # 【已有】LibreOffice/PyMuPDF 转换管线
|
||||
│ │ │ └── knowledge_service.py # 【新增】md 解析 + 摄入
|
||||
│ │ └── scripts/
|
||||
│ │ ├── init_db.py # 【已有】建表 + 种子
|
||||
│ │ └── ingest_knowledge.py # 【新增】知识源扫描/摄入脚本
|
||||
│ └── data/
|
||||
│ ├── media/ # 【已有】素材物理文件(git 忽略)
|
||||
│ │ ├── upload/
|
||||
│ │ └── _preview_cache/
|
||||
│ └── logs/ # 【已有】special_trace 按天日志
|
||||
│
|
||||
└── docker-compose.yml # 【待创建】
|
||||
```
|
||||
|
||||
**约定**:
|
||||
- `docs/knowledge_source/` 是知识源 md 的唯一入库口(权威源,git 管理,可 diff 可回滚)。
|
||||
- 运行时摄入**直接读取**该目录,不复制到 backend/data(单一事实源,避免双份漂移)。
|
||||
- 素材物理文件仍在 `backend/data/media/`(git 忽略)。
|
||||
|
||||
---
|
||||
|
||||
## 3. 两条流程的状态机(定稿)
|
||||
|
||||
### 流程 A:非结构化素材(BE03 已实现)
|
||||
|
||||
```
|
||||
员工上传 ──▶ media_file(pending) ──审批──▶ approved ──▶ 异步转换
|
||||
管理员上传 ──▶ media_file(approved) ──▶ 立即异步转换 │
|
||||
▼
|
||||
┌──────────────────────────┐
|
||||
│ 文档: LibreOffice→PDF→ │
|
||||
│ PyMuPDF 提取→切片 │
|
||||
│ 视频/图片: 仅预览 │
|
||||
└──────────┬───────────────┘
|
||||
▼
|
||||
knowledge_chunk
|
||||
```
|
||||
|
||||
### 流程 B:结构化知识源(本次新增)
|
||||
|
||||
```
|
||||
知识源 md(docs/knowledge_source/)
|
||||
│
|
||||
▼
|
||||
【扫描】ingest_knowledge.py / POST /api/knowledge/scan
|
||||
│ 解析 front-matter → 为每个 md 建 knowledge_source 记录
|
||||
▼
|
||||
knowledge_source(pending) ──审批──▶ approved ──▶ 解析摄入
|
||||
│ │
|
||||
│ ├─→ product(status=active)
|
||||
│ ├─→ question(status=active)
|
||||
│ └─→ knowledge_chunk(source=knowledge_source)
|
||||
│
|
||||
└─驳回──▶ rejected(理由必填,不生效)
|
||||
```
|
||||
|
||||
**对称性**:素材「审批通过→转换提取」,知识源「审批通过→解析摄入」。两条通道最终都汇入 `knowledge_chunk` 供 AI 检索。
|
||||
|
||||
---
|
||||
|
||||
## 4. 数据模型变更
|
||||
|
||||
### 4.1 新增 `knowledge_source` 表
|
||||
|
||||
```sql
|
||||
CREATE TABLE knowledge_source (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
title VARCHAR(256) NOT NULL COMMENT '文档标题',
|
||||
file_path VARCHAR(512) NOT NULL UNIQUE COMMENT 'md 相对路径(docs/knowledge_source/ 下)',
|
||||
category VARCHAR(64) NOT NULL COMMENT '分类:general/capital_consulting/qualification_counseling/ai_consulting/ai_tools_platform',
|
||||
domain ENUM('company','product','sales') NOT NULL DEFAULT 'product',
|
||||
source_version VARCHAR(32) NOT NULL COMMENT '源版本,如 V1.0',
|
||||
audit_status ENUM('pending','approved','rejected') NOT NULL DEFAULT 'pending',
|
||||
audit_by BIGINT UNSIGNED DEFAULT NULL COMMENT '审批人ID',
|
||||
audit_at DATETIME(6) DEFAULT NULL COMMENT '审批时间',
|
||||
reject_reason VARCHAR(512) DEFAULT NULL COMMENT '驳回理由',
|
||||
ingested TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否已摄入',
|
||||
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
||||
|
||||
INDEX idx_ks_status (audit_status),
|
||||
INDEX idx_ks_category (category),
|
||||
CONSTRAINT fk_ks_auditor FOREIGN KEY (audit_by) REFERENCES user(id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
```
|
||||
|
||||
### 4.2 改造 `knowledge_chunk` 表(来源扩展)
|
||||
|
||||
现状 `media_file_id BIGINT UNSIGNED NOT NULL` 强绑定素材。改造后:
|
||||
|
||||
```sql
|
||||
media_file_id BIGINT UNSIGNED DEFAULT NULL, -- 由 NOT NULL 改为可空
|
||||
knowledge_source_id BIGINT UNSIGNED DEFAULT NULL, -- 新增
|
||||
-- 约束:media_file_id 与 knowledge_source_id 二者必居其一(应用层校验,Fail Fast)
|
||||
```
|
||||
|
||||
对应 ORM `models/knowledge_chunk.py`:`media_file_id` 改为可空,新增 `knowledge_source_id` 外键与 relationship。
|
||||
|
||||
---
|
||||
|
||||
## 5. 模块清单(8 模块)
|
||||
|
||||
| # | 模块 | 状态 | 职责 | 落点 |
|
||||
|---|------|------|------|------|
|
||||
| 1 | 上传模块 | ✅ 已有 | 直传 + 分片(>100MB) | `api/media.py` |
|
||||
| 2 | 转换模块 | ✅ 已有 | LibreOffice → PDF | `services/media_service.py` |
|
||||
| 3 | 提取切片模块 | ✅ 已有 | PyMuPDF 提取 + 段落切片 | `services/media_service.py` |
|
||||
| 4 | **摄入模块** | 🆕 新增 | 解析知识源 md → product/question/chunk | `services/knowledge_service.py` |
|
||||
| 5 | 审批模块 | 🔧 扩展 | 素材审批(已有)+ 知识源审批(新增) | `api/media.py` + `api/knowledge.py` |
|
||||
| 6 | 入库模块 | 🔧 扩展 | 写 product/question/knowledge_chunk | `services/knowledge_service.py` |
|
||||
| 7 | 预览模块 | ✅ 已有 | approved 素材预览 | `api/media.py` |
|
||||
| 8 | 检索模块 | ✅ 已有 | MySQL FULLTEXT 召回 | `services/ai_service.py` |
|
||||
|
||||
---
|
||||
|
||||
## 6. 新增 API(knowledge.py)
|
||||
|
||||
```python
|
||||
router = APIRouter(prefix="/api/knowledge", tags=["knowledge"])
|
||||
|
||||
# ── 扫描(管理员)──
|
||||
POST /api/knowledge/scan
|
||||
# 扫描 docs/knowledge_source/*.md
|
||||
# 为新增/变更的 md 建 knowledge_source 记录(status=pending)
|
||||
# 已存在且未摄入的记录跳过;返回扫描结果列表
|
||||
|
||||
# ── 审批(管理员)──
|
||||
GET /api/knowledge/audit-list?status=pending
|
||||
POST /api/knowledge/audit/{source_id}
|
||||
# { "action": "approve" | "reject", "reject_reason": "..." }
|
||||
# approve → 触发摄入(同步解析写入 product/question/chunk,标记 ingested=1)
|
||||
# reject → 必填 reject_reason,不摄入
|
||||
|
||||
# ── 状态查询 ──
|
||||
GET /api/knowledge/status/{source_id}
|
||||
# { "audit_status", "ingested", "reject_reason" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 摄入脚本(ingest_knowledge.py)
|
||||
|
||||
```python
|
||||
"""知识源摄入脚本:扫描 md → 建记录 → (审批通过后)解析入库
|
||||
|
||||
用法:
|
||||
cd backend && source venv/bin/activate
|
||||
python -m app.scripts.ingest_knowledge --scan # 仅扫描建 pending 记录
|
||||
python -m app.scripts.ingest_knowledge --ingest <source_id> # 摄入单个已审批源
|
||||
"""
|
||||
|
||||
# 解析规则(严格对齐 knowledge_source/README.md 格式契约):
|
||||
# 1. 读 YAML front-matter:category / domain / source_version
|
||||
# 2. 按 "## " 二级标题切块:
|
||||
# ## 结构化产品数据 → 解析 "### code name" + "key: value" 列表 → product
|
||||
# ## AI 检索知识 → 每个 "### 标题" 段落 → knowledge_chunk
|
||||
# ## 考试题目 → 每个 "### Qn" 的字段列表 → question
|
||||
# 3. 摄入后 product/question 置 status=active
|
||||
# 4. knowledge_chunk 写入 knowledge_source_id,media_file_id 留空
|
||||
```
|
||||
|
||||
**Fail Fast 约束(G02)**:解析失败(front-matter 缺失、section 缺块、字段缺失)立即抛错并中断该源摄入,不静默跳过、不写半截数据。
|
||||
|
||||
---
|
||||
|
||||
## 8. 格式契约(已定,见 knowledge_source/README.md)
|
||||
|
||||
- 每个 md:YAML front-matter(`category` / `domain` / `source_version`)+ 三个固定 `## ` section。
|
||||
- 题目答案契约:`judge=[bool]`、`single=[索引]`、`multiple=[索引列表]`。
|
||||
- 已生成 5 个知识源:`01_通用规则` + `02/03/04/05` 四大分类,共 28 产品 + 20 题。
|
||||
|
||||
---
|
||||
|
||||
## 9. 实现清单(代码侧,已完成)
|
||||
|
||||
- [x] `models/knowledge_source.py` 新建
|
||||
- [x] `models/knowledge_chunk.py` 来源扩展(media_file_id 可空 + knowledge_source_id)
|
||||
- [x] `services/knowledge_service.py`(md 解析 + 摄入)
|
||||
- [x] `api/knowledge.py`(scan / audit / status)
|
||||
- [x] `scripts/ingest_knowledge.py`
|
||||
- [x] `scripts/init_db.py` 追加 knowledge_source 建表 + knowledge_chunk 字段迁移
|
||||
- [x] `docs/db_schema.md`、`docs/api.md` 同步更新
|
||||
Reference in New Issue
Block a user