7.7 KiB
7.7 KiB
产品需求文档:知识增强服务 (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 核心组件
- Enrichment Scheduler (调度器):
- 定时任务 (Celery Beat) 或 事件触发。
- 扫描
questions表中enrich_status = 'pending'的记录。 - 将任务推送到 Redis 队列。
- API Client Worker (执行器):
- 消费队列。
- 调用外部
summary_api。 - 关键特性: 实现流控 (Rate Limiting)、重试 (Retry) 和熔断机制。
- Review API (审核接口):
- 提供给前端/教研后台,用于人工修改知识点。
2.2 外部接口定义 (Mock Summary API)
假设外部接口契约如下(开发时需对接真实接口):
- Input:
{"question_text": "...", "answer": "..."} - Output:
{ "summary": "一道关于利用勾股定理求解直角三角形斜边的应用题", "knowledges": ["勾股定理", "直角三角形性质"], "methods": ["数形结合", "方程思想"] }
3. 功能需求详细说明
3.1 自动打标流程
- 任务获取: 查询
questions表,条件:enrich_status='pending'。 - 构建 Payload: 拼接
ocr_text(含公式/图片链接) 和answer_md。 - 调用 API: 发送 HTTP POST 请求给
summary_api。 - 结果处理:
- 成功:
- 将返回的 JSON 填入
knowledges,methods,problem_summary字段。 - 同时将这些值 Copy 一份给
updated_knowledges,updated_methods(作为人工审核的默认值)。 - 更新状态
enrich_status = 'done'。
- 将返回的 JSON 填入
- 失败 (5xx/Timeout):
- 触发重试(指数退避,最多 3 次)。
- 若最终失败,更新状态
enrich_status = 'failed',并记录error_msg。
- 成功:
3.2 人工审核 (Human-in-the-Loop)
- 审核逻辑: AI 的提取结果并不总是 100% 准确。系统信任链为:人工数据 > AI 数据。
- 数据流:
- 前端展示
updated_knowledges(初始值等于 AI 提取值)。 - 人工修改(增删改)。
- 调用
PUT /questions/{id}/review接口保存。 - 系统更新
updated_at和reviewer_id。
- 前端展示
3.3 知识库一致性 (Optional Advanced)
- 需求: 虽然初期可以存自由文本的 Tag,但为了检索准确,建议引入“标准知识点树”。
- 逻辑: 在保存 Tag 前,检查 Tag 是否在系统的
knowledge_tree表中。如果不在,标记为“新词”,提示管理员审核。
4. 数据库设计 (PostgreSQL)
沿用模块二的 questions 表,本模块主要负责 UPDATE 操作。
4.1 Table: questions (字段补充)
| 字段名 | 类型 | 说明 |
|---|---|---|
| ... | ... | (模块二已有的基础字段) |
problem_summary |
TEXT | 题目一句话摘要 (AI生成) |
knowledges |
JSONB | AI提取: ["k1", "k2"] |
methods |
JSONB | AI提取: ["m1"] |
updated_knowledges |
JSONB | 人工审核版 (应用层展示以此为准) |
updated_methods |
JSONB | 人工审核版 |
enrich_status |
VARCHAR | pending (待处理), processing, done, failed |
enrich_error |
TEXT | 调用外部API失败的错误日志 |
is_reviewed |
BOOLEAN | 是否经过人工确认 (默认 False) |
reviewer_id |
INT | 审核人ID |
reviewed_at |
TIMESTAMP | 审核时间 |
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就能实现指数退避,代码极简。
- 理由: Python 最好的重试库。用装饰器
- 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. 模块间联动总结
到此为止,三个模块已经形成了一个完美的闭环:
-
UDC-M (文档与转换):
- Input: 用户上传 PDF/Docx。
- Output: 永久存储原始文件 + 标准 Markdown (含 MinIO 图片链)。
- Data:
documents表。
-
QPES (题目解析):
- Input: 读取
documents里的 Markdown。 - Action: 调用 DeepSeek 切分题目。
- Output: 结构化题目。
- Data:
questions表 (基础字段)。
- Input: 读取
-
KES (知识增强):
- Input: 读取
questions(Pending 状态)。 - Action: 调用 Summary API + 人工审核。
- Output: 完整的、带标签的题库。
- Data:
questions表 (Tag 字段)。
- Input: 读取
部署建议: 这三个模块可以部署在同一个代码仓库 (Monorepo) 中,共享数据库 Model 定义,但通过Docker Compose 拆分为不同的服务容器运行,以便根据负载独立扩容(例如:UDC 扩容 GPU 节点,KES 扩容 IO 密集型节点)。