📚 教育技术方案 · v1.0

初中数学题库系统

本地化部署的私有题库 · 智能组卷 · 多维标签 · 一键导出

📅 2026 年 6 月 🎯 教师端 MVP 🛠️ Python + Vue + PostgreSQL 🤖 DeepSeek + 本地 OCR

💡 项目亮点 — 一张图看懂系统价值

从 Word/PDF 试卷到结构化题库,一键完成

📄
上传试卷
Word / PDF 文件
🤖
AI 切题
LLM 自动拆分题目 + 识别公式
🏷️
自动打标
知识点 + 难度 + 考点
🔍
向量去重
AI 判断重复题/相似题
✏️
人工校对
修正标签 / 补充解析
📚
题库存储
LaTeX + 图片 + 向量
📐
数学公式智能识别
支持 LaTeX 公式的 OCR 识别,输入图片自动输出可编辑的 LaTeX 源码。 支持分数、根号、上下标、积分等复杂公式,识别准确率 90%+。
pix2tex LaTeX 已验证
🧩
题目智能切分
整张试卷丢进去,AI 自动识别题号、拆分子问、分离答案。 选择题、填空题、解答题混合卷均可处理,输出结构化 JSON。
DeepSeek-V3 PyMuPDF
🔄
智能去重检测
基于题目语义向量(pgvector)判断重复题。 相似度 > 0.92 自动标记,人工确认后合并。 避免题库中积累大量"姐妹题"。
pgvector bge-m3 已验证
📋
多维标签体系
年级 × 知识点 × 考点 × 难度 × 题型 任意组合筛选。 树形知识点结构(人教版/北师大版),支持多父节点。 主次标签权重区分。
5维检索 树形KP 需人工建
🎯
智能组卷引擎
指定总分、难度分布、题型配比、必含/禁含知识点, AI 自动均衡抽题生成试卷。 支持生成 AB 卷、历史卷相似度检测。
分层贪心 约束规划 新功能
📤
一键导出多格式
同一试卷可导出:PDF( Typst 精美排版)、 Word(可二次编辑)、Markdown(在线分享)。 同时生成答案卷 + 解析卷。
Typst PDF Word

📝 组卷效果 — 输入约束,秒出试卷

组卷约束输入
总分: 100 分
题型分布:
  ├─ 选择题: 20 道
  ├─ 填空题: 10 道
  └─ 解答题: 5 道

难度比例:
  ├─ 易: 30%
  ├─ 中: 50%
  └─ 难: 20%

必含知识点:
  ├─ 一元二次方程
  └─ 圆的综合

作答时间: 120 分钟
填写约束 → 点击"生成" → 3秒出卷
九年级数学阶段测试卷
考试时间:120分钟 满分:100分 命题人:题库系统
一、选择题(本大题共 20 小题,每小题 3 分,共 60 分)
1. 若关于 $x$ 的一元二次方程 $x^2 - 3x + m = 0$ 有两个相等的实数根,则 $m$ 的值为(   )
A. $\dfrac{9}{4}$ B. $-\dfrac{9}{4}$
C. $\dfrac{3}{2}$ D. $-\dfrac{3}{2}$
2. 已知圆 $O$ 的半径为 5,圆心 $O$ 到直线 $l$ 的距离为 3,则直线 $l$ 与圆 $O$ 的交点个数为(   )
A. 0 个 B. 1 个
C. 2 个 D. 无法确定
...(共 20 题,选填部分略)
二、填空题(本大题共 10 小题,每小题 3 分,共 30 分)
21. 计算:$\sqrt{12} + \sqrt{27} = $
22. 若关于 $x$ 的方程 $x^2 - 4x + m = 0$ 无实根,则 $m$ 的取值范围是
三、解答题(本大题共 5 小题,共 50 分)
31.(8分)已知关于 $x$ 的一元二次方程 $x^2 - (m+2)x + 2m = 0$。
  (1)求证:该方程恒有两个不相等的实数根;
  (2)若该方程有一个根为 $x=1$,求 $m$ 的值及另一个根。
32.(10分)如图,$AB$ 是圆 $O$ 的直径,$C$ 是圆上一点,$\angle ABC = 30^\circ$,
  $OD \perp AC$ 于点 $D$。求证:$OD = \dfrac{1}{2} BC$。
✅ 自动排版 · ✅ 公式渲染 · ✅ 分值标注

📋摘要

本报告针对"为初中数学教师构建本地化结构化题库"的需求进行可行性分析,并给出完整的技术选型与实施方案。

核心结论

  • 可行性:完全可行。当前大模型 + OCR + 向量数据库技术已成熟,能覆盖 80% 以上的自动化需求
  • 推荐技术栈:Python FastAPI + Vue 3 + PostgreSQL + DeepSeek API + Typst
  • 核心难点:数学公式识别、题目自动切分、多维标签体系设计
  • 预估工时:8-10 周可达到生产可用状态
  • 预估成本:云端 LLM 调用约 50 元/千题,零服务器投入

1可行性评估

时机、技术、成本三方面均已具备,核心瓶颈在"标签体系"和"公式识别"的工程化落地。

✅ 优势
• 大模型对中文数学题理解成熟
• PaddleOCR、pix2tex 等开源 OCR 工具已可用
• 本地化部署成本可控
• 数据完全自主可控,教学资源安全
⚠️ 难点
数学公式识别是最大瓶颈
• 题目自动切分需 LLM 二次加工
多维标签需要本地化标准体系
去重需向量检索支持
排版美观影响最终交付

2技术栈

所有选型均优先考虑中文生态友好 + 数学场景适配 + 长期可维护

2.1 后端

类别选型理由
语言Python 3.11+LLM 生态最全、解析库丰富
框架FastAPI异步高性能、自动生成 OpenAPI 文档
ORMSQLAlchemy 2.0(异步)成熟稳定、迁移工具完善
迁移Alembic数据库版本管理
任务队列Celery + Redis处理耗时的 PDF 解析、AI 切题
LLM SDKopenai(兼容 DeepSeek/Qwen)一套接口对接多家

2.2 前端

类别选型理由
框架Vue 3 + TypeScript + Vite国内生态成熟、SSR/CSR 灵活
UI 库Naive UI中文文档好、组件丰富、TS 优先
状态PiniaVue 3 官方推荐
编辑器Tiptap + KaTeX支持 LaTeX 公式实时预览
HTTPofetch / axios简洁、拦截器完善

2.3 数据与 AI

选型用途
主数据库PostgreSQL 16 + pgvector结构化数据 + 题目向量
缓存/队列Redis分页缓存、Celery 队列
主 LLMDeepSeek-V3 API切题、打标、解析生成(性价比王)
备用 LLM智谱 GLM-4 / 通义 Qwen-Max主备切换
本地 LLMOllama + Qwen2.5-14B完全离线备用
Embeddingbge-m3 / text-embedding-v3题目向量化、去重

2.4 文档解析

场景工具备选
Word (.docx)python-docx
文字型 PDFPyMuPDF (fitz)pdfplumber
扫描型 PDF / 图片PaddleOCRTesseract
数学公式pix2tex (LaTeX-OCR)MathPix API(付费但准)
几何图形原图存储 + 文本描述Qwen2.5-VL 多模态

2.5 排版输出

格式主选转换链路
PDF(主)Typst(强烈推荐)Typst 直出 / Pandoc + LaTeX
Wordpython-docx公式转 OMML 或图片
MarkdownJinja2 模板直出公式用 $...$ / $$...$$
通用互转PandocMD ↔ Word ↔ PDF
💡 Typst 是排版救赎

相比 LaTeX,Typst 学习曲线平缓、编译秒级、公式渲染极其美观。一个 .typ 文件就能生成专业级数学试卷。强烈建议优先掌握。官网:typst.app

3系统架构

采用"本地为主 + 云端模型为辅"的混合架构,数据完全自主可控。

┌─────────────────────────────────────────────────┐ │ 前端:Vue 3 + Naive UI + Tiptap │ ├─────────────────────────────────────────────────┤ │ 后端:FastAPI(Python 3.11+) │ │ ┌────────────┬────────────┬────────────┐ │ │ │ 文档解析 │ LLM 编排 │ 排版导出 │ │ │ └────────────┴────────────┴────────────┘ │ ├─────────────────────────────────────────────────┤ │ 任务队列:Celery + Redis │ ├─────────────────────────────────────────────────┤ │ 数据层 │ │ • PostgreSQL + pgvector(题目+向量) │ │ • 本地文件存储(图片、源文件) │ ├─────────────────────────────────────────────────┤ │ 外部服务:DeepSeek / Qwen / GLM API │ └─────────────────────────────────────────────────┘

4数据库设计

核心 9 张表,结构化标签 + 向量检索双引擎,新增媒体资源管理表支持图片去重与复用。

4.1 核心表概览

knowledge_points
知识点字典(树形结构)
如:一元二次方程 → 判别式
questions
题目主表(含题干、答案、解析、向量)
question_knowledge
题目-知识点多对多关联
sources
来源文件(Word/PDF 原始试卷)
papers
试卷配置(含组卷规则 JSONB)
paper_questions
试卷-题目关联(含分值、顺序)
🖼️
media_resource — 媒体资源表(图片/公式/附件)
统一管理所有二进制素材,支持 MD5 去重、一图多题复用
🔗
question_media — 题目-媒体关联表
解耦存储:一张示意图可用于多个题目,通过关联表实现

4.2 题目表核心字段

CREATE TABLE questions (
    id BIGSERIAL PRIMARY KEY,
    stem TEXT NOT NULL,                    -- 题干(LaTeX/Markdown)
    stem_html TEXT,                        -- 渲染后 HTML(缓存)
    question_type VARCHAR(20),             -- choice/fill/solution/proof
    difficulty SMALLINT DEFAULT 3,         -- 1-5
    answer TEXT,
    analysis TEXT,                         -- 解析
    source_id BIGINT REFERENCES sources(id),
    source_page INT,
    checksum VARCHAR(64),                  -- 内容 hash(去重辅助)
    embedding VECTOR(1024),                -- pgvector 向量
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW(),
    is_active BOOLEAN DEFAULT TRUE
);

CREATE INDEX idx_questions_embedding ON questions
    USING ivfflat (embedding vector_cosine_ops);

4.7 媒体资源管理(图片 / 公式 / 附件)

Word/PDF 试卷中的图片素材采用对象存储 + 数据库路径映射方案,支持 MD5 去重和题目-图片解耦。

📦 存储结构
question_images/ — 题干配图
option_images/ — 选项图片
analysis_images/ — 解析图片
formula_images/ — 公式截图
文件名:{uuid}_{用途}_{关联ID}.{ext}
✅ 关键设计
• MD5 去重:相同图片只存一份
• 解耦关联:一图可用于多题
• 分级 URL:配图可 CDN 加速
• 尺寸记录:便于前端自适应渲染
-- 媒体资源表(统一管理所有二进制素材)
CREATE TABLE media_resource (
    id            BIGSERIAL PRIMARY KEY,
    uuid          VARCHAR(36) UNIQUE NOT NULL,
    original_name VARCHAR(255) NOT NULL,
    storage_path  VARCHAR(512) NOT NULL,
    access_url    VARCHAR(512),
    file_size     BIGINT NOT NULL,
    mime_type     VARCHAR(50) NOT NULL,
    md5_hash      VARCHAR(32),
    width         INT,
    height        INT,
    source        VARCHAR(50) DEFAULT 'upload',
    created_at    TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_media_md5 ON media_resource(md5_hash)
    WHERE md5_hash IS NOT NULL;

-- 题目-媒体关联表(解耦:一张图可用于多个题目)
CREATE TABLE question_media (
    id            BIGSERIAL PRIMARY KEY,
    question_id   BIGINT NOT NULL REFERENCES questions(id) ON DELETE CASCADE,
    media_id      BIGINT NOT NULL REFERENCES media_resource(id) ON DELETE CASCADE,
    usage_type    VARCHAR(20) NOT NULL,  -- stem/option/analysis/attachment
    display_order INT DEFAULT 0,
    alt_text      VARCHAR(255),
    created_at    TIMESTAMPTZ DEFAULT NOW(),
    UNIQUE (question_id, media_id, usage_type)
);

5项目结构

前后端分离、模块化分层、模板与代码分离。

math-bank/
├── backend/
│   ├── app/
│   │   ├── api/                    # FastAPI 路由
│   │   ├── core/                   # 配置、日志、安全
│   │   ├── models/                 # SQLAlchemy 模型
│   │   ├── schemas/                # Pydantic
│   │   ├── services/
│   │   │   ├── parser/             # 文档解析(pdf/docx/ocr)
│   │   │   ├── llm/                # LLM 客户端 + Prompts
│   │   │   ├── tagger/             # 自动打标
│   │   │   ├── dedup/              # 向量去重
│   │   │   └── exporter/           # Word/PDF/MD 导出
│   │   ├── db/
│   │   └── main.py
│   ├── alembic/
│   ├── tests/
│   └── pyproject.toml
├── frontend/
│   ├── src/
│   │   ├── views/
│   │   │   ├── QuestionBank/      # 题库浏览/编辑
│   │   │   ├── PaperBuilder/      # 组卷
│   │   │   ├── Importer/          # 试卷导入
│   │   │   └── KnowledgeTree/     # 知识点管理
│   │   ├── components/
│   │   │   ├── MathEditor.vue     # Tiptap + LaTeX
│   │   │   ├── QuestionCard.vue
│   │   │   └── TagSelector.vue
│   │   ├── api/
│   │   └── stores/
│   ├── package.json
│   └── vite.config.ts
├── templates/                      # 排版模板
│   ├── typst/                      # Typst 模板(主)
│   └── word/                       # Word 模板
├── data/
│   ├── sources/                    # 原始试卷
│   ├── images/                     # 题目图片
│   └── exports/                    # 导出文件
└── docker-compose.yml

6核心模块

四个核心模块构成系统的"AI 流水线"。

6.1 题目切分(最关键)

SPLIT_PROMPT = """你是初中数学题目切分专家。
输入是一份试卷的纯文本(可能含 LaTeX 公式 $...$),
需要切分成独立题目。

要求:
1. 准确识别每道题的题号
2. 分离题干、选项(小问)、答案、解析
3. 保留 LaTeX 公式原样
4. 几何题保留 [图:description] 占位

输出严格 JSON:
{
  "questions": [
    {
      "number": "1",
      "stem": "题干文字...",
      "options": ["A. ...", "B. ..."],
      "sub_questions": [{"label": "(1)", "stem": "..."}],
      "answer": "...",
      "analysis": "...",
      "knowledge_points": ["一元二次方程", "求根公式"],
      "difficulty": 3
    }
  ]
}"""

6.2 PDF 解析流程

  1. PyMuPDF 提取文字 + 图片位置
  2. 扫描型 PDF 走 PaddleOCR
  3. 公式片段识别用 pix2tex 转 LaTeX
  4. 几何图直接保留原图,文字里插入 [图:hash] 占位
  5. 拼接后送 LLM 二次切题

6.3 自动打标

打标策略

基于本地知识点字典(如"人教版"),LLM 从字典中选最匹配的 1-3 个标签。Prompt 包含完整字典和题型示例,确保输出稳定。

6.4 向量去重

async def find_duplicates(question_text: str, threshold=0.92):
    embedding = await embed(question_text)
    sql = text("""
        SELECT id, stem,
               1 - (embedding <=> :vec) AS similarity
        FROM questions
        WHERE 1 - (embedding <=> :vec) > :threshold
        ORDER BY embedding <=> :vec
        LIMIT 5
    """)
    return await db.execute(sql, {"vec": embedding, "threshold": threshold})
去重阈值经验值

• > 0.95:几乎肯定是同题
• 0.85 - 0.95:可能是"姐妹题"(同模板换数字)
• < 0.85:基本无关

6.7 智能组卷模块

智能组卷本质是带约束的随机抽样,目标是在限定条件下生成一套均衡的试卷。

6.7.1 组卷约束输入

约束类型示例说明
总分要求100 分最终试卷总分数
难度分布易 30% / 中 50% / 难 20%各难度题目占比
题型配比选择 20 / 填空 10 / 解答 5各题型题目数量
知识点覆盖必含 [101, 102],禁含 [205]强制包含 / 排除的知识点
作答时间120 分钟按题型均耗时估算

6.7.2 算法对比

算法优点缺点推荐场景
贪心算法 实现简单、速度快 难以保证整体均衡 生产环境首选
遗传算法 全局搜索能力强 计算量大、参数调优复杂 复杂约束优化
约束规划(CP-SAT) 硬约束精确求解 需 OR-Tools 依赖 精确约束组卷

6.7.3 推荐算法:分层贪心 + 知识点约束检查

class SmartPaperGenerator:
    """分层贪心智能组卷生成器"""

    def generate(self, constraint: PaperConstraint) -> list[Question]:
        # 1. 按题型+难度分桶
        buckets = self._group_by_type_and_difficulty()

        # 2. 按题型贪心抽取
        selected = []
        for qtype, count in constraint.type_distribution.items():
            diff_counts = self._distribute_difficulty(count, constraint.difficulty_ratio)
            for diff, diff_count in diff_counts.items():
                candidates = buckets.get((qtype, diff), [])
                picked = self._pick_randomly(candidates, diff_count)
                selected.extend(picked)

        # 3. 知识点覆盖校验(缺必含则替换)
        selected = self._ensure_knowledge_coverage(selected, constraint)

        # 4. 禁知识点过滤
        selected = self._exclude_forbidden_kps(selected, constraint)

        # 5. 分配分值(使总分为目标总分)
        selected = self._allocate_scores(selected, constraint.total_score)
        return selected

    def _ensure_knowledge_coverage(self, selected, constraint):
        """确保必含知识点被覆盖,缺则替换"""
        if not constraint.required_kps:
            return selected
        covered = set()
        for q in selected:
            covered.update(q.knowledge_points)
        for kp_id in constraint.required_kps:
            if kp_id not in covered:
                replacement = self._find_replacement(selected, kp_id, constraint)
                if replacement:
                    weakest = min(selected, key=lambda q: len(
                        set(q.knowledge_points) & set(constraint.required_kps)))
                    selected[selected.index(weakest)] = replacement
        return selected

6.7.4 智能组卷扩展功能

历史卷相似度检测
与近 3 次考试的雷同率检测,题目不应重复出现
AB 卷生成
同一约束生成两份不同的卷,适用于 A/B 测试
预估时长计算
按题型平均耗时估算总时长,确保符合考试时间
卷内雷同检测
生成后用向量检索检测卷内相似题目,避免重复
API 设计

POST /api/papers/generate
输入:总分、题型分布、难度比例、必含/禁含知识点
输出:生成后的试卷详情(含题目列表、分值、预估时长)

7实施路线

5 个阶段、约 8-10 周可达到生产可用。

阶段 1:基础架子 1-2 周
• FastAPI + Vue 项目骨架
• 数据库表 + Alembic
• 题目/标签/试卷 CRUD API
• 简单前端列表页
阶段 2:录入与检索 3-4 周
• Tiptap + KaTeX 富文本编辑器
• 知识点树形管理
• 多条件组合检索
• 手动录入 200 道题跑通流程
阶段 3:文档导入 5-7 周
• Word/PDF 解析管道
• LLM 切题 + 自动打标
人工校对界面
• 题目图片、公式关联
阶段 4:组卷与导出 8-9 周
• 组卷规则引擎
• Typst / Word / Markdown 模板
• 一键导出试卷 + 答案 + 解析
阶段 5:智能增强 10 周+
• 向量去重、相似题推荐
• 配套解析自动生成
• 错题本预备(学生端)

8关键建议

🎯 1. 标签体系第一

动手前先把 7-9 年级数学知识点整理成树。可以参考人教版 / 北师大版目录。这是整个系统的骨架,AI 帮不了您,必须您自己定。

🎯 2. 不要追求 100% 自动化

"LLM 切题 + 人工校对"是最稳妥方案。AI 处理 80% 体力活,您花 20% 时间校对质量。自动打标的 5-10% 误差也靠人工修正。

🎯 3. 公式录入用 LaTeX

前端 KaTeX 实时预览,所见即所得。比 Word 公式编辑器快 10 倍。一旦习惯,回不去。

🎯 4. Typst 强烈建议

LaTeX 的现代替代品。编译秒级、公式漂亮、模板即代码。组卷导出首选。

🎯 5. 先跑通最小闭环

建议马上开始的 3 件事:
① 建数据库 + 写题目 CRUD API(半天)
② 前端列表 + Tiptap 编辑器(一天)
③ 手动录入 50 道题,跑通"录入→检索→导出"(一天)
跑通后再加 PDF 解析、LLM 切题。

9成本估算

项目一次性投入月度成本
云端 LLM API(DeepSeek)50-200 元(看题量)
本地部署(可选)5000-10000 元(GPU 服务器)电费 ~100 元
自己开发1-2 人月工时
找人定制开发3-8 万元

典型场景:首次导入 1000 道题,预计 DeepSeek 调用成本 30-50 元,之后日常使用更低。

🚀下一步行动

从最小闭环开始,逐步迭代。

  1. 本周:搭项目骨架(FastAPI + Vue + Docker Compose)
  2. 第 2 周:手动录入 50-200 道题,跑通"录入→检索→导出 Markdown"
  3. 第 3-4 周:建知识点体系 + Tiptap 编辑器集成
  4. 第 5 周起:接入 Word/PDF 解析 + LLM 切题
  5. 第 8-9 周:组卷引擎 + Typst 模板 + 三格式导出

📌 核心提醒

技术方案和工具都已经成熟,真正的难点不在技术,而在您自己梳理清楚"标签体系"和"组卷规则"。这两件事想明白了,剩下的 80% AI 都能干。