note/app_prd/知识增强服务KES.md

8.1 KiB
Raw Blame History

产品需求文档:知识增强服务 (KES)

Knowledge Enrichment Service - Backend

文档版本 V1.0
依赖模块 UDC-M (模块一), QPES (模块二)
最后更新 2025-12-09
状态 待开发
涉及端 后端 API, 异步 Worker, 外部 API 交互

1. 项目背景与目标

1.1 背景

模块二QPES已经完成了“文档 -> 题目”的物理拆解,数据库中已经有了干净的题干、答案和图片。 但此时的题目是“孤立”的,无法支持“查找所有关于‘勾股定理’的题”或“生成一份‘三角函数’的试卷”等业务场景。我们需要为题目注入元数据Metadata

1.2 目标

构建一个异步的知识增强与人工审核服务

  • 自动打标:监控未处理的题目,调用外部 summary_api 自动提取知识点和方法。
  • 人工介入 (HITL):提供接口,允许教研人员对 AI 提取的标签进行审核、修改和确认。
  • 数据回填:将处理结果结构化地更新回主数据库。

2. 系统架构设计

系统设计为 “生产者-消费者” 模式,以解耦数据库读取与外部 API 调用(防止外部 API 阻塞系统)。

2.1 核心组件

  1. Enrichment Scheduler (调度器):
    • 定时任务 (Celery Beat) 或 事件触发。
    • 扫描 questions 表中 enrich_status = 'pending' 的记录。
    • 将任务推送到 Redis 队列。
  2. API Client Worker (执行器):
    • 消费队列。
    • 调用外部 summary_api
    • 关键特性: 实现流控 (Rate Limiting)、重试 (Retry) 和熔断机制。
  3. Review API (审核接口):
    • 提供给前端/教研后台,用于人工修改知识点。

2.2 外部接口定义 (Mock Summary API)

假设外部接口契约如下(开发时需对接真实接口):

  • Input: {"question_text": "...", "answer": "..."}
  • Output:
    {
      "summary": "一道关于利用勾股定理求解直角三角形斜边的应用题",
      "knowledges": ["勾股定理", "直角三角形性质"],
      "methods": ["数形结合", "方程思想"]
    }
    

3. 功能需求详细说明

3.1 自动打标流程

  1. 任务获取: 查询 questions 表,条件:enrich_status='pending'
  2. Write-Protect (写保护)。IF question.is_reviewed == True: UPDATE ONLY raw_fields; ELSE: UPDATE raw_fields AND updated_fields;
  3. 构建 Payload: 拼接 ocr_text (含公式/图片链接) 和 answer_md
  4. 调用 API: 发送 HTTP POST 请求给 summary_api
  5. 结果处理:
    • 成功:
      • 第一步:更新 AI 原始字段。将 API 返回的 JSON 数据填入 knowledges, methods, problem_summary 字段。这些字段始终反映 AI 的最新判断。

      • 第二步:更新人工审核字段 (写保护逻辑)

        • 检查该题目的 is_reviewed 字段状态
        • 场景 A (未审核, is_reviewed = False):将 AI 提取的结果 复制 (Copy) 一份给 updated_knowledges 和 updated_methods。此时认为 AI 结果即为当前最佳结果。
        • 场景 B (已审核, is_reviewed = True)跳过 对 updated_knowledges 和 updated_methods 的更新。绝对禁止 覆盖人工已经校对过的数据,仅更新 AI 原始字段供参考。
      • 第三步:更新状态。将 enrich_status 更新为 'done'清空 enrich_error。

    • 失败 (5xx/Timeout):
      • 触发重试(指数退避,最多 3 次)。
      • 若最终失败,更新状态 enrich_status = 'failed',并记录 error_msg

3.2 人工审核 (Human-in-the-Loop)

  • 审核逻辑: AI 的提取结果并不总是 100% 准确。系统信任链为:人工数据 > AI 数据
  • 数据流:
    1. 前端展示 updated_knowledges (初始值等于 AI 提取值)。
    2. 人工修改(增删改)。
    3. 调用 PUT /questions/{id}/review 接口保存。
    4. 系统更新 updated_atreviewer_id

3.3 知识库一致性 (Optional Advanced)

  • 需求: 虽然初期可以存自由文本的 Tag但为了检索准确建议引入“标准知识点树”。
  • 逻辑: 在保存 Tag 前,检查 Tag 是否在系统的 knowledge_tree 表中。如果不在,标记为“新词”,提示管理员审核。

4. 数据库设计 (PostgreSQL)

沿用模块二的 questions 表,本模块主要负责 UPDATE 操作。

4.1 Table: questions (字段更新)

本模块负责该表的 更新 (UPDATE) 操作。

  • 读取条件: WHERE enrich_status = 'pending'

  • 更新字段 (AI): knowledges, methods, problem_summary, enrich_status。

  • 更新字段 (人工): updated_knowledges, updated_methods, is_reviewed。

  • (完整表结构定义请参考“统一数据库设计规范”文档)


5. API 接口定义 (RESTful)

Base URL: /api/v1/enrichments

5.1 触发/重试打标

  • POST /trigger
  • Description: 手动触发一次批量打标(通常由定时任务调用,也可以人工触发重试失败任务)。
  • Body: {"retry_failed": true}
  • Response: {"triggered_count": 50}

5.2 提交人工审核结果

  • PUT /questions/{question_id}/review
  • Description: 教研人员提交修正后的知识点。
  • Body:
    {
      "knowledges": ["修正后的知识点1", "修正后的知识点2"],
      "methods": ["方法1"],
      "confirm": true // 标记 is_reviewed = true
    }
    
  • Response: 200 OK

5.3 获取待审核题目列表

  • GET /questions/review-queue
  • Query:
    • status: done (已AI打标等待人工)
    • is_reviewed: false
  • Response: 题目列表 (含 AI 提取的 Tag)。

6. 技术选型 (Vibe Coding Stack)

6.1 核心技术

  • HTTP Client: httpx (异步) 或 aiohttp
    • 理由: 相比 requests,异步客户端在 Celery Worker 中能支持更高的并发Event Loop适合 I/O 密集型任务。
  • Resilience (弹性): tenacity
    • 理由: Python 最好的重试库。用装饰器 @retry 就能实现指数退避,代码极简。
  • Rate Limiting: Redis + Lua Script 或 Celery 自带的 rate limit。
    • 理由: 防止把外部 summary_api 打挂。

6.2 代码结构示例 (Service Layer)

# services/enrichment_service.py
import httpx
from tenacity import retry, stop_after_attempt, wait_exponential

class SummaryAPIClient:
    def __init__(self, base_url: str, api_key: str):
        self.client = httpx.AsyncClient(base_url=base_url, headers={"Authorization": api_key})

    @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))
    async def get_summary(self, text: str):
        response = await self.client.post("/summarize", json={"text": text})
        response.raise_for_status()
        return response.json()

7. 模块间联动总结

到此为止,三个模块已经形成了一个完美的闭环:

  1. UDC-M (文档与转换):

    • Input: 用户上传 PDF/Docx。
    • Output: 永久存储原始文件 + 标准 Markdown (含 MinIO 图片链)。
    • Data: documents 表。
  2. QPES (题目解析):

    • Input: 读取 documents 里的 Markdown。
    • Action: 调用 DeepSeek 切分题目。
    • Output: 结构化题目。
    • Data: questions 表 (基础字段)。
  3. KES (知识增强):

    • Input: 读取 questions (Pending 状态)。
    • Action: 调用 Summary API + 人工审核。
    • Output: 完整的、带标签的题库。
    • Data: questions 表 (Tag 字段)。

部署建议 这三个模块可以部署在同一个代码仓库 (Monorepo) 中,共享数据库 Model 定义,但通过Docker Compose 拆分为不同的服务容器运行以便根据负载独立扩容例如UDC 扩容 GPU 节点KES 扩容 IO 密集型节点)。