woke_tutor v3:让 AI 生成内容进入可验证的教学系统¶
woke_tutor 面向 AI 教师、机器人陪练和自适应学习场景生成多用途题库,并提供可以直接运行的选择题互动教学页面。
我没有把它设计成“输入一句话,模型返回一批题”的脚本。核心目标是回答一个更工程化的问题:随机的模型输出,怎样经过规划、校验、存储、发布和运行时权限控制,变成可以反复消费的教学数据?
一个题池,多个题库视图¶
v3 将数据分成三个层次:
flowchart TB
Project[教学项目] --> Knowledge[共享知识模型]
Project --> Pool[共享题池 · 单一真值来源]
Pool --> Diagnostic[诊断题库]
Pool --> Guided[引导教学]
Pool --> Practice[分层练习]
Pool --> Remediation[易错纠偏]
Pool --> Assessment[阶段测评]
题目只保存一份,各题库通过 question_ids 建立成员关系。这样同一道题被练习和纠偏共同使用时,不会出现两份答案和解析逐渐不一致的问题。
当前 V1 主动限制为单选题与多选题。这不是能力不足的包装,而是协议边界:题型变化会同时影响规划、校验、判分、前端组件、语音脚本和测试,因此必须通过新协议版本演进。
确定性程序与生成模型的职责分工¶
整个流程分为五个阶段:
| 阶段 | 执行者 | 主要产物 |
|---|---|---|
| 规格化 | Python + 用户 | 项目规格、知识点 |
| 规划 | Python | 精确题量的任务列表 |
| 生成 | Claude / Codex | 每批 8—12 道结构化题目 |
| 校验与修复 | Python | 共享题池、失败记录 |
| 发布 | Python | 各题库 JSON、manifest、catalog |
题量分配使用最大余数法,把知识点、难度、题型和互动模式的权重转换成精确整数任务。模型不能修改 task_id、知识点、难度和题型,只补充题干、选项、答案、解析、提示与互动策略。
这种分工让失败可以定位到任务:已经校验通过的题目不回滚,只有失败任务重新进入生成。任务达到最大次数后进入 failed,系统不会静默无限重试。
校验不是只验证 JSON 语法¶
结构合法只是最低要求。当前本地校验还包括:
- 单选题恰好一个正确选项,多选题至少两个;
- Markdown 数学公式的
$成对闭合; - 至少两级提示和完整机器人互动字段;
- SHA-256 精确题干指纹与归一化近似重复检测;
- 朗读稿中的数字、正负号、运算符、括号和单位保留;
- 作答前答案泄露与浏览器公开结构递归检查。
模型返回值先经过解析和业务校验,再由 Python 原子写入项目文件。模型本身没有项目写权限,从边界上避免“模型声称写入成功,但文件并不存在”。
互动教学:后端判分,按状态解锁¶
浏览器首次拿到的题目只包含题干、公开选项、展示规则和当前可用的朗读片段 ID。以下内容始终留在服务端,直到教学策略允许公开:
- 正确选项与
grading_spec; - 答案和完整解析;
- 典型错误模式;
- 未解锁的提示与语音片段。
互动运行时支持 correct、partial、incorrect 和 deferred 四种反馈。诊断与测评不立即泄露结果,引导与纠偏则按尝试次数逐步开放提示。
同一 attempt_no 和同一选择重复提交时返回原结果,不重复计分;相同序号提交不同选择时返回 409 idempotency_conflict。幂等性在这里不仅是接口规范,也直接保护学习记录的可信度。
语音链路与降级¶
题目朗读被拆成 opening、stem、option、feedback、hint、answer 和 explanation 等独立片段。MiniMax TTS 的缓存键包含模型、音色、语速、文本和音频参数,任一输入变化都会产生新的内容哈希。
API Key 只从后端环境变量读取,浏览器通过 session_id + qid + segment_id 请求当前已解锁片段。语音服务超时或失败时,教学流程退化为完整文字,不阻止学生继续作答。
测试结果¶
2026 年 8 月 20 日在本地执行 python -m pytest tests -q:66 项测试全部通过,耗时 1.60 秒。测试覆盖:
- 规格模型、题量规划和多题库流水线;
- Claude / Codex JSON 解析与失败信息;
- 存储、原子创建、旧协议拒绝;
- 题目校验、公式语义与重复检测;
- 互动协议、幂等冲突、测评延迟反馈;
- 答案隔离、受限音频访问和本地 HTTP API;
- TTS 内容哈希、TLS 校验与缓存。
我从这个项目学到的¶
AI 应用的可靠性不能靠“更强的提示词”兜底。真正稳定的部分来自模型外部:输入契约、任务状态、失败预算、权限边界、可追溯日志和自动化测试。模型可以富有创造性,系统必须保持确定性。