做 AI 批改时我们讨论了很久一个问题:AI 给的分数,算不算数?如果算,出了错谁负责?如果不算,那 AI 的价值在哪?
最后的结论是:AI 负责写草稿,教师负责拍板。而且这个边界不是写在产品说明里,是写在数据模型里的。
草稿写进扩展列,不碰业务状态
学习记录表有明确的业务状态列(submitted / reviewed 等)和分数列。AI 的输出不写进这些列,而是写进 attributes 这个 JSONB 扩展列。
ai 域 — 草稿写入扩展列
01// 草稿挂在扩展属性上,业务状态列不动02record.attributes["ai_feedback"] = {03 "score": 82,04 "comment": "第二问的推导跳了一步,建议补上边界条件…",05 "model": "glm-4",06 "generated_at": "2026-06-25T10:12:03Z",07 "draft": true08}0910// 终审仍走教师既有的 feedback 接口11POST /tv1/teacher/homeworks/{hid}/feedback整班批改要能部分失败
一个班几十份作业,不能因为第 7 份超时就整批回滚。所以批量接口分块处理,单份失败不中断整批,逐条返回错误,下次自动重试——已有草稿的会被跳过,不重复烧 Token。
- 只处理 submitted 状态,已终审的不再生成草稿
- 已有草稿的自动跳过,避免重复调用模型
- 单份失败逐条报 error,不影响同批其它作业
- 分块处理,单批上限 100,防止一次请求拖垮模型服务
未配置时优雅降级
没配置 LLM 端点时,AI 批改接口返回 501,其余功能完全不受影响。这条设计让「想试 AI 的客户」和「完全不想接 AI 的客户」可以跑同一个版本。
AI 提速的部分我们尽量做满,但「谁对结果负责」这件事,我们不交给模型。