Files
pj0235-eai_agentplatform/docs/04_Backend/BE05_Knowledge_Ingest_Module.md
T
eaiadminandClaude Code 0455f064ac feat: 新增语音转文字(ASR)功能
- 后端:新增 /api/audio/transcribe 接口,调用 Ollama whisper 进行语音识别
- 前端:新增 AudioTranscribePage.vue 页面,支持 MP3/WAV/M4A/OGG/FLAC 等格式
- 注册路由、工具卡片、智能助手欢迎语更新

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-14 00:53:36 +08:00

10 KiB
Raw Blame History

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. 完整目录结构(定稿)

eai_agentplatform_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 表

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 强绑定素材。改造后:

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)

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)

"""知识源摄入脚本:扫描 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. 实现清单(代码侧,已完成)

  • models/knowledge_source.py 新建
  • models/knowledge_chunk.py 来源扩展(media_file_id 可空 + knowledge_source_id)
  • services/knowledge_service.py(md 解析 + 摄入)
  • api/knowledge.py(scan / audit / status)
  • scripts/ingest_knowledge.py
  • scripts/init_db.py 追加 knowledge_source 建表 + knowledge_chunk 字段迁移
  • docs/db_schema.md、docs/api.md 同步更新