← 返回首页
Python 3.12 FastAPI React 18 / Vite TypeScript strict SQLAlchemy async SSE 实时推流 多模态 · 数据工程

🗂 多模态数据集工厂

mm_dataset_factory — 从 Word/DOCX 一键产出错题图像数据集,4 阶段流水线 + SSE 实时推流 + Skill-as-contract 交付架构

📄 完整技术文档(独立仓库) 系统架构、流水线内核、L1/L2/L3 错误体系、数据模型、SSE、API —— 中英双语,9 篇深入文档 + 截图。 前往文档仓库 →
📊 由本平台产出的评测基准 用这条流水线生产的数据,整理成了 EduFig-IC —— 面向理工科含图试题的分级图文一致性检测基准(L1/L2/L3,973 样本)。 查看 EduFig-IC →

项目概览

面向多模态模型(LMM/VLM)训练数据生产场景,本系统从 Word/DOCX 试卷文档自动提取含图题目, 经过 4 个流水线阶段最终产出可直接用于训练的错题图像数据集: JSON / JSONL / XLSX 标注文件 + 图片目录(zip 包)。 前后端分离架构,FastAPI 提供异步 REST API + SSE 实时推流,React/Vite 提供操作界面, 一条命令启动(python run.py)。

应用场景 LMM / VLM 错题训练数据构建 · 多模态评测基准制作 · 图文对数据集生产流水线

技术栈

Python 3.12 FastAPI(异步 REST + SSE) SQLAlchemy 2.x async(ORM) SQLite(持久化) React 18 TypeScript strict(禁 any) Vite(构建 + 开发代理) VLM API(图像理解) Text-to-Image API(图像生成) python-docx / Pillow(文档 / 图像处理)

4 阶段生产流水线

paper-structuring
文档解析 · 含图题目提取
vlm-error-planning
VLM 错误规划 · L1/L2/L3 分级
text2image-generation
AI 图像生成 · 错图替换
quality-gate
质量审查 · 导出数据集

架构

┌─────────────────────────────────────────────────────────┐ │ 前端层 (React 18 + Vite) │ │ 任务列表 / 样本浏览 / 规划详情 / 实时进度 / 数据集导出 │ │ useTaskEvents() Hook ← SSE /api/events │ └──────────────────────┬──────────────────────────────────┘ │ HTTP port 8000 (5173 → proxy) ┌──────────────────────▼──────────────────────────────────┐ │ FastAPI 主服务 (apps/api/) │ │ │ │ /api/tasks/* 任务 CRUD + 阶段状态 │ │ /api/runs/* 执行流水线阶段 │ │ /api/samples/* 样本查询 / 筛选 │ │ /api/datasets/* 导出 JSON/JSONL/XLSX/zip │ │ /api/events SSE 实时事件流 │ │ /api/settings 系统配置 │ │ /static/* 任务产物静态文件(StaticFiles 白名单) │ └──────────────────────┬──────────────────────────────────┘ │ ┌──────────────────────▼──────────────────────────────────┐ │ 基础设施层 │ │ SQLAlchemy async + SQLite (tasks / sample_states) │ │ asyncio EventBus (SSE 进程内广播) │ │ 文件系统 data/tasks/{task_id}/ │ │ images/ · extraction_debug/ · planning/ · generated/ │ └─────────────────────────────────────────────────────────┘

技术深度

① 阶段一:文档结构化(paper-structuring)

读取 Word/DOCX 文档,以"小题"为粒度(一小题一条 Sample)提取内容。 规则:仅保留含图小题,无图小题跳过。 图片按题内重新编号(img_01img_02 …), 题目文本保留图占位符 <img_01> 形式,便于后续阶段追踪图文对应关系。 图片落盘到 tasks/{task_id}/images/,文件名格式 q0001_img_01.png。 同时生成调试产物:提取文本、imageMap JSON、原始图片备份。

关键字段(Sample):sample_no · source_file · question_no · subject · question_type · question_text · image_count · image_map

② 阶段二:VLM 错误规划(vlm-error-planning)与 L1/L2/L3 三级错误体系

调用 VLM API 分析每道含图题目,对每个样本固定输出 3 行规划(L1 / L2 / L3):

L1 · 换图错配
引用其他题目的图片,构造图文内容不一致的错题。不启用"生成后评估"闭环,直接换图。
L2 · 参数不匹配
图可改,题图参数冲突(如长度与角度矛盾)。触发"生成后评估"闭环:VLM 校验数值锚点(numeric / symbolic / structural)一致性后决策 pass / repair / regenerate。
L3 · 逻辑无解
图可改,题图组合无解。需附 unsolvable_reason。同样进入评估闭环,达到轮次上限转 machine_reject

文本补全(text_enrichment)机制:当 L2/L3 计划涉及"修改图中数值"但题文中缺失对应数值锚点时, 先执行受控文本补全并合并进该行导出的 question_text,再评估。 不允许将补全任务下推给图像生成阶段口头声明,确保数据一致性。

规划产物:planning/plan_eval_report.jsonl(含 severity / decision / judge_trace)+ questions_prompt_plan.xlsx/.jsonl

③ 阶段三:图像生成(text2image-generation)

questions_prompt_plan.jsonl 为输入,对每条 L2/L3 规划调用 Text-to-Image API 生成替换图片; L1 直接在任务图片库内选图替换,不走生成 API。 生成结果落盘到 tasks/{task_id}/generated/,记录对应 sample_no + error_level。

④ SSE 进程内事件总线(asyncio EventBus)

每个流水线阶段的 runner 通过 EventBus.publish(Event) 广播进度事件, SSE 路由 /api/events 为每个订阅客户端维护独立的 asyncio.Queue, 实现进程内零延迟广播。前端通过 useTaskEvents() Hook 订阅并自动重连, 实时展示每题的处理状态与进度数字。

Runner ──publish()──→ EventBus._subscribers: set[asyncio.Queue] └──→ Queue(client_1) ──→ SSE /api/events └──→ Queue(client_2) ──→ SSE /api/events Frontend useTaskEvents() ←── EventSource → auto-reconnect + keepalive(15s)

⑤ 数据模型(SQLAlchemy async ORM)

TaskORM SampleStateORM task_id (PK, str) id (PK, autoincrement) title task_id (FK → tasks) current_stage sample_no (idx) created_at stage (paper-structuring / vlm-error-planning / …) updated_at status (idle / running / done / failed / machine_reject) └── sample_states[] updated_at (cascade delete) [UQ: task_id + sample_no + stage]

阶段进度由前端聚合 SampleState.status 计算(total / done / failed / machine_reject), 无需额外进度表。所有 ORM 操作均通过 async with session 异步执行,保证吞吐。

⑥ SKILL.md 作为功能交付契约

每个功能模块对应一份 SKILL.md,严格定义: 支持动作(create_task / run_task / list_samples / export_dataset)、 输入字段约束、输出字段规范(success / data / errors / meta)、 阶段产物路径与格式。这使 AI Coding Agent 可以按契约验收功能,而非凭经验猜测接口行为。

工程亮点 deliverable(交付物)与 process(过程文档)严格目录隔离;TypeScript strict 模式全面禁 any;Python 类型注解完整 + from __future__ import annotations 保证向前兼容。

⑦ 导出格式

质量门控通过后,支持多格式导出:

  • JSON / JSONL — 标准多模态训练数据格式
  • XLSX — 人工审核与修订
  • images.zip — 所有生成图片打包
  • StaticFiles 白名单确保只有已知安全路径可通过 /static/* 访问

API 端点

GET /api/tasks 任务列表(含阶段进度聚合) POST /api/tasks 新建任务(上传 Word 文档) GET /api/tasks/{id} 任务详情 + artifacts URL POST /api/runs/{id}/start 启动 / 继续流水线到指定阶段 GET /api/samples/{id} 分页查询样本 GET /api/samples/{id}/filter 按学科 / 题型 / 错误级别筛选 GET /api/datasets/{id} 导出数据集(JSON/JSONL/XLSX/zip) GET /api/events SSE 实时事件流 GET /api/settings 系统配置(LLM / 存储路径) GET /health 健康检查

截图

任务列表
① 任务列表 — 含真实数据、阶段状态
结构化
② 结构化 — 文档解析,含图题目逐条展示
VLM 规划
③ VLM 错误规划 — L1/L2/L3 三级规划
生图
④ AI 生图 — L1 换图 / L2·L3 生成批跑
导出
⑤ 导出 — 产物列表 + 一键生成 zip
新建任务
⑥ 新建任务 — 上传 Word、设定学科与题型

提示词工程与 LLM 架构

规划阶段是提示词工程的核心。未使用 LangChain,而是自研薄封装 (httpx + OpenAI 兼容 Chat Completions + .prompt 模板 + Pydantic), 以换取对提示词、JSON 容错、多供应商适配的完全掌控。

  • 形态:确定性工作流为骨架,规划阶段内嵌 planner–judge(LLM-as-Judge)自我修正闭环(pass / repair / regenerate / machine_reject)。
  • 提示词分层:角色 → 输入槽 → 目标 → 分级选参策略 → 等级硬边界(l2 仅参数层 / l3 必须结构层)→ 三要素写作约束(定位锚点 + 具体画法 + 可视验收)→ 正反例 → JSON 字段白名单。
  • 控制手段:system 强制 JSON、温度分档(抽取/评审 0.0、planner 0.2)、judge 先产出 alignment_table 再裁决、关闭 thinking。
  • 生图 prompt:固定「局部编辑」前缀 + 题干 + 图中参数 + planner 改图指令;原图随请求上传;L1 / text 不调生图。
  • 多层兜底:JSON 三级容错、planner 正则 guard、judge 异常当 regenerate、轮次耗尽 best-of 择优、生图重试 + 指数退避、provider 自动切 DashScope。
  • Few-shot:l2 / l3 / judge 提示内嵌正例 + 反例(标注"仅学风格,勿原样复述")。
完整拆解(每条 prompt 原文、planner–judge 控制流图、兜底清单)见文档仓库 10 · 提示词工程与 LLM 架构

核心亮点

  • 4 阶段流水线覆盖从文档解析到数据集导出的全链路,支持按阶段重试
  • L1/L2/L3 三级错误规划体系 + "生成后评估"闭环,保证数据质量
  • asyncio EventBus + SSE 实时推流,前端零轮询展示逐题处理进度
  • SKILL.md 契约驱动开发,AI Agent 可按契约验收功能
  • SQLAlchemy async ORM + SQLite,全异步无阻塞
  • TypeScript strict 全面禁 any,Python 类型注解完整

相关链接

📄 完整文档仓库(Markdown · 中英双语) GitHub 主页