教育软件开发不能靠好意愿驱动,系统必须能解释每一个学习者进度决策,并通过测试验证边界。作者分享了在 Scholarium 学习引擎开发中发现的关键工程原则。
完整作品与配套文件
当天的简短播客
当天的简短播客
今天就是那种让编程不再浪漫的日子。
不是因为项目变得不再有意义。恰恰相反,它变得意义重大,以至于代码开始拒绝一切捷径。每一个脆弱的假设都会暴露出来。每一句动听的话,都必须转化为一种状态、一条规则、一项测试、一道边界,或者一个系统日后能够解释的决策。
我今天完成的文章是关于 Scholarium Teach 的。它是 SecuredMe Education 套件中的一个以音节为先的学习引擎。但更深层的启示并不只与音节有关,而是关乎这样一个现实:当儿童、语言难度、无障碍、隐私和 AI 同时汇聚到一个系统中时,究竟该如何构建教育软件。
今天最大的教训简单而残酷:
良好的教育意图不是证据。漂亮的界面不是证据。模型给出的答案也不是证据。如果系统无法解释为什么让学习者进入下一阶段,它就没有资格假装自己衡量了学习成果。
这正是外界往往看不到的编程工作。
编程不只是编写函数。编程还意味着决定软件可以知道什么、可以推断什么、必须拒绝什么,以及哪些事情必须始终由人类负责。

Python 并不是今天最难的部分。
真正困难的是把一种直觉转化为足够诚实、可以接受检验的东西。
最初的想法很有力量:先从儿童能够听见并发音的音节开始,再要求他们处理孤立的字母。构建一套音节表(silabario)。让学习者先听、先读、先组合,之后再书写。图片只能作为辅助,不能成为让儿童无需解码就能猜出答案的线索。
这个想法有温度,也有教学价值,背后还有真实经验的支撑。
但如果我把这个想法编码成一条定律,系统就会变得危险。不是出于恶意,也不是什么戏剧性的灾难,只是悄无声息地犯错。软件会开始声称“这个孩子已经掌握了当前步骤”,但孩子可能只是认出了图片、刚听完声音便立即复述出来,或者过度依赖了提示。
于是,这项工作变成了一场外科手术。
我必须把人类的教育意图与可执行契约分离开来:
以音节为先的方法应当成为一项带版本的 policy,而不是普遍真理;
音节表应当成为由可教学内容块、前置条件、来源和限制构成的图;
界面可以简化学习者的体验,但引擎必须精确保留语言关系;
图片可以帮助理解语境,但不能在解码任务中泄露答案;
音频可以观察信号质量,但不能对人作出诊断;
AI 可以解释、辅助和起草内容,但不能掌控学习者的 canonical state。
这就是那些艰苦而琐碎的工作。这才是真正的工作。
“做一个教人阅读的应用。”这句话说起来很容易。
真正的工作是:什么是音节块?需要什么证据才能解锁书写?如果学习者能够复述,却无法在稍后回忆起来,该怎么办?如果麦克风噪声很大呢?如果学习者使用了另一种回答方式呢?如果模型提供商明天发生变化呢?如果同一次尝试被提交了两遍呢?如果教师需要质疑系统给出的结果呢?
到了这里,软件才真正变得严肃。
今天,我推动 Scholarium Teach 从一个美好的愿景,向一套可以接受审查的架构迈进了一步。
最终完成的文章记录了这样一套系统:学习者的进度不由语言模型掌控。Scholarium 负责维护 canonical state。一个确定性的 Python 引擎接收先前状态、内容版本、事件和 policy,然后返回一份结构化 receipt。产品负责验证并持久化这份 receipt。
如果明天向引擎输入相同的状态和相同的尝试,就必须得到相同的决策。不是相似的感觉,不是一份概率性的解释,而是完全相同的决策。
我还明确了周边系统各自扮演的角色:
D1 仍是学习者 checkpoint 和 receipt 的事务性 source of truth;
Python 负责计算决策,但不能成为隐藏的第二份记忆;
PostgreSQL 可以用于编目语言包及其版本;
TimescaleDB 适合存储经过授权的时序事件,而不是假装自己是整个学习系统的大脑;
CodeProject.AI 可以成为可选的观察层,但不能成为教学法的权威;
Synthia Scholarium 负责追踪 provenance 和 transformation,但不参与表决什么是真相;
Google Drive 可以归档所有者侧的材料,但不应成为课堂运行时依赖。
这其中涉及大量边界划分工作。它不如“AI 将自动教会儿童”那样吸引眼球,却负责任得多。
说实话,我为此感到自豪。
我之所以自豪,是因为这项工作没有假装自己已经完成。它现在拥有了足够清晰的结构,可以接受测试。这才是更好的里程碑。

最触动我的时刻,是意识到系统必须有能力说“不”。
不,这张图片泄露了太多信息。
不,这个在引导下得出的答案不能证明已经掌握。
不,这段音频的噪声太大,无法作出判断。
不,这个数据集很有意思,但没有获得课堂使用许可。
不,这张由 AI 生成的卡片不能在未经编译、审核和 provenance 追踪的情况下进入 canonical learning path。
不,不能仅仅因为一种交互模态失败,就把这个孩子简化成一个分数。
这不是消极,而是工程上的尊重。
一个严肃的教育系统并不会因为总是让学习者前进而获得信任。它值得信任,是因为它知道什么时候应该停留、放弃判断、进入审核流程,或者请求人类作出决定。
这或许是我今天学到的最重要的一课:
在 AI 辅助学习工具中,最重要的功能或许不是生成,而是给出理由并拒绝。
有理由的拒绝可以保护学习者,也可以保护教师、家长和项目本身,避免项目作出夸大的承诺。它还能保护未来版本的代码,使其不必继承一个谎言。
总有那么一个时刻,最初的兴奋会迎面撞上实现的现实。
你从一个愿景开始。然后代码要求你为事物命名。接着数据库要求你定义 schema。隐私要求你设置限制。无障碍要求你提供替代方案。研究要求你保持谦逊。最后,部署会追问:如果 20 名学习者同时使用低功耗设备访问,系统会怎样?
到了这里,我不得不慢下来。
我希望这个系统充满生命力。但我也必须接受这样一个事实:课堂工具必须在一系列乏味的约束下运行——稳定的状态、可重放的决策、有界的事件、不囤积原始语音、不让隐藏的模型掌握权威、不伪造“已经掌握”的结果,也不能神奇地依赖某个浏览器 AI 模型。
4 GiB 内存的 Chromebook 很重要。安静可靠的 fallback 很重要。平平无奇的 receipt 很重要。不可逾越的硬边界也很重要。
这正是多年来编程改变我的地方。早些时候,我希望引擎令人惊叹。现在,我希望它能够承担责任。
这是另一种值得自豪的事。
如果你正在使用 AI 构建产品,尤其是教育产品,不要一开始就问模型能够做多少事情。
先问这些问题:
什么是 source of truth?
什么可以重放?
什么必须由人类审核?
哪些数据绝不应该存储?
哪些事情可以由模型解释,但不能由模型决定?
哪些事情可以由引擎决定,但只能依据明确声明的 policy?
系统不确定时应该怎么办?
学习者进入下一阶段之前,需要什么证据?
这些问题并不是官僚主义,而是信任的骨架。
今天我再次认识到,构建真正的软件,不是让机器表现得信心十足,而是迫使机器始终待在契约规定的范围之内。
这值得为之自豪。
Scholarium Teach 音节引擎并不是在声称某一种方法已经被证明更优。它是一套用于研究和构建的架构。它让我们能够把经得起辩护的内容编码实现,把仍需测试的部分隔离开来,并禁止产品假装知道自己并不知道的事情。
这是今天得到的最清晰成果。
而在软件领域,有时,一道真正有效的边界就是第一次真正的胜利。

如需采取进一步措施,你可以考虑屏蔽此人和/或举报滥用行为。