一天造出拍照批改数学的AI家教:红笔圈错、多语言讲解

Somo用AI找出学生手写解题的第一处错误并用母语讲解,展示了教育AI的另一条产品路径。
Somo是一款与主流解题工具相反的数学家教应用:拍照上传手写过程,AI识别后圈出第一处出错的行,再用英语、斯瓦希里语或西班牙语讲解为什么错。作者在坦桑尼亚和纽约的英语学习者身上看到同一困境——学生数学没问题,卡在语言上,于是用一天时间做出原型。流程分拍照、诊断、确认、教学、检验五步,并强调人工确认以兜底模型读题盲区。工程上,文章详述了多模型自我验证、熔断加降级把诊断耗时从约116秒降到约10秒、Nimble检索真题配合pypdf抽取正文,以及Sentry trace抓到httpx分块超时漏洞。项目仍是原型,没有真实学生使用,测试题全部由作者自写。
大多数AI解题工具的目标是替你把答案算出来。开发者用一天时间做了个相反的东西:Somo(斯瓦希里语意为"课程")——一款拍照上传手写解题过程、由AI找出第一处出错的行、像老师一样用红笔圈出来,再用英语、斯瓦希里语或西班牙语讲解的数学家教。

为什么会有人做这个
作者在坦桑尼亚长大。当地小学用斯瓦希里语授课,升入中学后所有科目切换为英语,连NECTA全国统考都用一门你还在学习的语言作答。很多学生数学本身没问题,卡在语言上。到纽约后,他在英语学习者身上看到同样的困境。
这构成了Somo的问题意识:与其让AI直接解题,能不能让AI用学生"思考所用的语言",告诉他自己为什么错?作者用一天时间做出了原型来验证这个想法。
五步流程:从拍照到真题练习
Somo的使用流程被拆成五个明确动作:
- 拍照:拍下题目和自己的手写过程;
- 诊断:Gemini识别手写内容,返回结构化JSON,包含转录文本、考点、第一处错误行及错误原因,界面用红笔圈出那一行;
- 确认:Somo先展示"我读到的内容",由学生确认或纠正,之后才开始讲解;
- 教学:流式输出一段简短课程,涵盖知识点、错在哪里、生活化类比(菜市场秤、地铁票价)、用不同数字做的例题(避免直接泄题),以及考试中会用到的英文术语;
- 检验:回答一道题。答错则换一个更简单的解释和新类比;答对则进入真实历年真题练习。
AI工程里,可靠性才是大头
作者的核心体会是:提示词是最简单的部分,真正的工作都在它周围。
自我验证与人类兜底
系统会再做一次独立的模型调用,在看不到诊断结果的前提下重新解题。两次答案不一致时,学生看到的是"我不太确定有没有读对"。
但验证机制有盲区。作者测试的一张打印题因丢失格式,两次模型调用都以同样错误的方式读取,且彼此一致。这正是"人工确认"环节存在的理由:学生手上有纸,模型没有。
故障转移是功能,不是补丁
Gemini免费配额在开发中途耗尽。作者把所有调用收敛到一个函数:先试Gemini,遇到503/429重试一次,再降级到Claude,并加了熔断器——配额报错后60秒内跳过Gemini。诊断耗时从约116秒(等一个过载的模型)降到约10秒。
熔断器(Circuit Breaker)源自分布式系统,核心思想是当某个依赖连续失败时,主动“断开”对它的调用一段时间,而不是让每个请求都去撞同一个故障。Somo 的实现是:Gemini 报出配额或过载错误后,60 秒内直接跳过它,把请求交给 Claude。这样做的收益不只是省重试,而是把不可控的供应商抖动转换成可预期的响应时间——每个请求不再可能卡在过载模型上等待,整体耗时从约 116 秒降到约 10 秒。熔断器通常配合降级(fallback)使用:断路期间用备用供应商保底,恢复后再切回主路径,是 LLM 应用应对配额波动和限流的标准模式。
标签要诚实
流水线曾把一份英国练习卷标成"真实历年真题"。现在每道题都明确标注为历年真题、网络练习题或Somo自编题,跑题的问题会被拒绝。
在作者自测的三道手写题上,Somo都准确找到了出错行:一道除2错误、一道移项时漏掉负号、一道方程两边乘以了不同的数。作者特别说明:没有真实学生使用过,所有测试题都是他自己写的。
技术栈:三件套各司其职

后端是FastAPI加Server-Sent Events做流式输出,前端是一个单文件移动界面,视觉上模仿学校练习本:网格纸、红色页边线、老师批注用手写体。
Gemini:结构化输出的关键
gemini-flash-latest承担多模态硬活。关键点是结构化输出——不做自由文本解析,诊断结果直接用Pydantic schema校验。因为error_step是一个真实字段,界面才知道该圈哪一行。Gemini还负责流式讲解和生成检验题。
Gemma 4(gemma-4-26b-a4b-it,走同一个Gemini API)负责高频低风险任务:判分、判断两个答案是否等价("x = 4"和"4")。它快且便宜,适合对每个答案都跑的检查。
结构化输出(Structured Output)指模型被约束为按预定义的数据模式返回结果,而不是自由生成文本。开发者用 Pydantic 定义 schema,Gemini 通过 function calling 或 response schema 参数把输出强制映射到该结构,字段类型、必填项都会在模型侧校验。对 Somo 这类应用,这决定了系统的可编程性:只有当 diagnostic 结果里存在 error_step 这种明确的整数字段,前端才能知道该在第几行画红圈;如果换成一段自然语言,就必须再写一层脆弱的解析逻辑,容易在模型措辞变化时崩掉。结构化输出还让下游校验、缓存和重试变得确定,是多模态模型接入生产流水线的关键一步。
Nimble:把"多练"变成"练真题"
课程开始时,后台任务让Nimble在实时网络上搜索该考点的历年试卷,优先官方站点。美国学生拿到的是NY Regents题库,官方站点无结果时再搜开放网络。
Nimble找对了文档:坦桑尼亚考试委员会2017至2023年的官方数学试卷和考官报告。但PDF类结果只返回约300–700字符的摘要,里面根本没有题目。解决办法是把Nimble当作发现器:遇到短PDF结果时,Somo下载文件,用pypdf抽取最多20000字符(并行处理五份试卷),再由Gemini挑出一道原文逐字出现、且考查同一考点的题目。NECTA的《考生题目作答分析》报告意外成了金矿,因为它逐字引用了每道考题。
第一个真实成果来自NECTA CSEE 2023基础数学试卷的一道矩阵应用题,展示时带考试印章和来源链接。结果按模糊主题匹配缓存到磁盘,每个主题只搜一次。
Sentry:抓到一个日志看不见的bug
所有对Gemini、Gemma、Claude和Nimble的调用都是Sentry span,后台任务各自成事务。每次Gemini到Claude的降级也会抛出warning issue,issue列表变成了一份"何时为何切换供应商"的时间线。
真正的收获是trace瀑布图暴露的一个bug:某次历年题搜索中,一台NECTA服务器花3.6分钟才发出一个PDF。代码里设了12秒超时,但httpx是按数据块计时的,慢速滴流的服务器永远触发不了。修复方式是对整个下载设硬性截止时间,最坏情况从约4分钟降到约30秒。作者坦言,这个bug从日志里根本看不出来。Sentry设置了send_default_pii=False,不发送学生照片或提示词文本。

httpx 的超时是分块粒度的,这一点与很多人的直觉相反。它默认在读取响应体时对每个数据块分别计时,而不是对整个下载过程设一个总截止时间。这意味着如果服务器以非常慢的速度持续滴流数据块——每块都刚好不超过超时阈值——请求可以拖上几分钟也不触发超时。这类问题在普通日志里几乎不可见,因为每次读取都“成功”,没有报错,只是整体耗时异常。修复方式是对整个下载显式设置总超时(或使用 httpx.Timeout 的 read/write/connect 细分加外层 deadline),把最坏情况从约 4 分钟压到约 30 秒。这也说明 trace 瀑布图的价值:它把慢请求拆成 span,才能看出时间花在哪一段。
一天黑客松的真实体验
项目诞生于一场一日制MLH黑客松。作者没有队伍也没有点子,上午用来头脑风暴,因自身背景锁定教育方向,其余时间都在构建。
他印象最深的三件事:
- 和编码智能体一起造东西:先用Gemini CLI,中途触发用量上限后转向Claude。工作方式随之改变——时间花在设计决策和用手写题实测上,写样板代码的时间变少了。
- 赞助商演讲真有价值:原本没打算用Nimble,听完演讲才决定接入,最后成了最自豪的功能。
- 真实世界的摩擦:场地wifi让手机连不上笔记本、Gemini配额耗尽、政府服务器极慢——每一件都逼出了更好的设计。
下午5点截止,他在3:45冻结功能,然后写README、录demo,赶在最后几分钟提交。
值得借鉴的三点
Somo的价值不在"又一个AI解题器",而在于它展示了一条不同的产品路径:不替学生做题,而是定位错误并解释原因。这个定位对语言门槛高的教育场景尤其有意义。
工程层面有三点可复用:一是多模型自我验证加人类确认,比单纯提高提示词质量更有效;二是熔断加降级的故障转移设计,把不可控的供应商波动转化为可预期的响应时间;三是可观测性不能只靠日志,trace能抓到httpx分块超时这类隐蔽问题。
当然,项目仍是原型:没有真实学生参与,测试样本全部由作者自写,多语言教学效果也尚未经过教学实验验证。作者对"标签诚实"和"人工确认"的强调,恰恰说明了AI教育工具现阶段最该保持的克制。
背景补充
PDF 文本抽取与网页抓取不同,PDF 内部是按页面和字体位置存储的绘图指令,而不是语义化 HTML。pypdf 这类库通过解析内容流,把可提取的文本按页拼回来,但遇到扫描件、复杂排版或加密文件时可能抽不到或抽乱。Somo 的策略是先用 Nimble 做发现,拿到短摘要式结果后,再自己下载原始 PDF,用 pypdf 抽取最多 20000 字符,并并行处理多份试卷,最后由 Gemini 从抽取文本中挑出与考点匹配的题目。这种做法把“搜索服务”和“内容获取”解耦:搜索负责找到正确文档,抽取负责拿到正文,核对原文逐字出现则保证题目没有被改写或截断。
相关推荐

Workbuddy零基础入门:桌面AI智能体如何落地工作流
Workbuddy桌面AI智能体零基础教程解读:从安装、积分领取到文件管理与自动化工作流搭建,对比CodeX的适用场景与成本差异,帮助职场人完成从AI提问者到AI管理者的思维转变。

OpenAI智能体新栈:计算机操作、决策API与超速工作流
OpenAI Dev Day发布智能体新栈:Computer Use操作速度超越普通人,Decisions API基于Luna实现极低延迟分类,Agents API开放同源计算机操作能力,GPT-6.1 Sol成本仅为Astra七分之一。本文梳理核心更新、实测数据与开发者落地要点。

梁文峰开源推理框架DeepInfo,硬刚美国禁令
DeepSeek在开源模型后再开源推理框架DeepInfo,包含GPU/CPU交叉流水线、小模型预判大模型复核、华为昇腾与英伟达芯片全面适配等技术,直面美国联邦禁令。本文解析其对AI产业落地的意义与开源策略。