☰
从一次性答疑到持续学习系统:四层架构与工程实践
2026/10/20 14:55:52 网站建设 项目流程

1. 从答疑到系统:这个项目到底在解决什么问题

1.1 一个被大多数人忽略的学习断层

先说说我为什么会关注到这个方向。过去两年,我身边不少做教育产品的朋友都在做同一件事:把大模型接进学习场景。最常见的做法就是做一个对话框,用户输入问题,模型给出解答,然后就没有然后了。这种模式我称之为“一次性答疑”——问完即走,下次再来又是从零开始。

问题出在哪?出在学习这件事本身不是一次性的。一个学生在某个知识点上卡住,往往不是因为他缺那一句解释,而是因为他缺一个持续追踪、反复强化、逐步加深的机制。一次性答疑解决的是“此刻不懂”,但解决不了“下次还忘”“换个场景就不会用”“不知道自己到底哪里薄弱”这些更深层的问题。

Learning Accelerator 这个项目,核心思路就是把这个断层补上。它不是一个答疑工具,而是一套持续学习系统。所谓持续,体现在三个层面:第一,系统会记住你问过什么、错在哪里、哪些概念反复出现;第二,它会根据这些记录主动安排后续的练习和回顾;第三,它会随着你的水平变化动态调整内容的难度和侧重点。

适合谁来参考?如果你正在做教育类产品、企业内部培训系统、或者个人知识管理工具,这套思路都可以直接借鉴。哪怕你只是想给自己搭一个学习助手,里面的设计逻辑同样适用。

1.2 为什么“持续”比“智能”更难做

很多人以为接入一个大模型就万事大吉了,实测下来完全不是这么回事。大模型本身很聪明,但它的聪明是“无状态”的——每次对话对它来说都是全新的,它不记得你上周问过什么,也不知道你三个月前在哪个概念上栽过跟头。

要做到持续,你需要额外构建几层东西:一层是记忆层,负责存储和检索学习历史;一层是诊断层,负责从历史中识别薄弱点和知识盲区;一层是调度层,负责根据诊断结果安排下一步该学什么、练什么;最后还有一层是反馈层,负责把新的学习结果写回记忆,形成闭环。

这四层里,最容易被低估的是诊断层。因为“识别薄弱点”这件事,远比想象中复杂。一个人做错一道题,可能是因为概念不清,可能是因为计算失误,也可能只是因为题目表述绕。如果不加区分地全部归为“这个知识点没掌握”,后续的练习安排就会失准,学生会被大量无效练习淹没,体验直线下降。

注意:诊断层的设计一定要区分“知识性错误”和“操作性错误”,前者需要重新讲解和强化练习,后者只需要提醒注意即可。混在一起处理是很多学习系统的通病。

2. 系统架构拆解:四层结构怎么落地

2.1 记忆层:不只是存对话记录

记忆层最容易犯的错误就是把它做成一个简单的日志表,把每次问答原样存下来。这样做短期没问题,但时间一长,数据量膨胀,检索效率急剧下降,而且原始对话里大量冗余信息会干扰后续的诊断。

我的做法是结构化存储。每次交互后,系统会提取几个关键字段:涉及的知识点标签、用户的回答质量评分、错误类型分类、时间戳、以及一个简短的上下文摘要。原始对话可以保留,但只作为归档,日常检索走结构化字段。

具体来说,知识点标签采用层级结构,比如“数学-代数-一元二次方程-求根公式”。这样做的目的是支持不同粒度的检索——有时候你需要看某个大类的整体掌握情况,有时候你需要精确到某个具体公式的熟练度。

错误类型分类我建议至少分四类:概念理解错误、计算/操作错误、审题偏差、以及完全不会。这四类对应的后续动作完全不同。概念错误要回炉重讲,计算错误要加练基础运算,审题偏差要做专项的读题训练,完全不会则要从头教起。

存储方案上,如果数据量在百万级以内,用关系型数据库加标签索引就足够了。再往上走,可以考虑引入向量数据库做语义检索,但那是后话,初期不要过度设计。

2.2 诊断层:从数据到洞察的关键一跃

诊断层的核心任务是把记忆层里的原始数据转化成可操作的结论。这里我踩过最大的坑就是试图用一套规则打天下。早期我写了一大堆 if-else 来判断“如果连续三次同一知识点出错就标记为薄弱”,结果发现误报率很高。

后来改成两层诊断:第一层用统计方法做粗筛,第二层用模型做精判。粗筛阶段,系统会计算每个知识点的错误率、最近错误时间、错误类型的分布。如果某个知识点的错误率超过阈值,或者最近一次错误在短时间内反复出现,就进入精判队列。

精判阶段,系统会把该知识点相关的所有历史记录(包括题目、用户答案、正确答案、错误类型)打包成一个上下文,交给模型做一次综合分析。模型需要回答几个问题:这个用户的错误模式是什么?是概念不清还是熟练度不够?建议的下一步动作是什么?

这里有个细节很关键:精判不要每次都做,太耗资源。我的策略是粗筛命中后才触发精判,而且同一个知识点的精判结果会缓存一段时间,除非有新的错误记录进来才重新计算。

实操心得:诊断结果一定要给用户看,而且要用人话解释。比如“你在‘求根公式’这个点上最近五次练习错了三次,其中两次是符号搞反,建议先复习一下判别式的正负判断”。这种具体的反馈比“你的一元二次方程掌握度是 62%”有用得多。

2.3 调度层:学什么、练什么、什么时候复习

调度层是整个系统里最像“老师”的部分。它要根据诊断结果决定下一步给用户推送什么内容。这里涉及三个维度的决策:内容类型(讲解/练习/复习)、难度等级、以及时间安排。

内容类型的选择相对直接:概念错误推讲解,计算错误推基础练习,审题偏差推读题专项,完全不会推从零开始的引导式教学。难度等级则要根据用户的历史表现动态调整,我采用的是一个简化的 Elo 评分机制,每个知识点维护一个用户能力值和一个题目难度值,每次作答后双方都更新,下一题选择难度略高于用户当前能力值的题目,保持“跳一跳够得着”的状态。

时间安排上,我参考了间隔重复的基本思路,但不是照搬 Anki 那套固定间隔。因为学习场景和背单词不一样,知识点之间有依赖关系,不能孤立地安排复习。我的做法是维护一个知识图谱,当某个前置知识点的掌握度下降时,会自动触发后续知识点的复习提醒。

调度层还有一个容易被忽略的功能:冲突消解。当多个知识点同时被诊断为薄弱时,系统不能一股脑全推给用户,那样只会让人崩溃。我的策略是优先级排序,优先处理“前置依赖多”和“最近错误频繁”的知识点,其他的排队等待。

2.4 反馈层:闭环的关键在“写回”

反馈层做的事情看起来简单——把用户的新表现写回记忆层。但这里有个设计难点:写回的数据格式必须和记忆层的结构一致,否则诊断层下次读取时会出问题。

我的做法是定义一套标准的事件模型。每次用户完成一次交互,系统生成一个标准事件对象,包含用户 ID、知识点标签、交互类型、结果评分、错误类型、时间戳等字段。这个事件对象先进入一个消息队列,由消费者异步写入记忆层。这样做的好处是解耦,即使记忆层暂时不可用,事件也不会丢失。

反馈层还有一个高级玩法:元反馈。也就是系统对自己的诊断和调度效果做评估。比如,如果系统判断某个知识点薄弱并安排了练习,但用户后续在该知识点上的表现没有改善,那就说明诊断或调度可能出了问题,需要调整策略。这个机制我目前还在迭代中,但初步效果不错,能捕捉到一些明显的误判。

3. 核心环节实操:从零搭建一个最小可用版本

3.1 技术选型与依赖准备

如果你要自己搭一套,我建议从最小可用版本开始,不要一上来就追求大而全。技术栈上,后端用 Python 的 FastAPI 就够,数据库用 PostgreSQL 加一个标签索引扩展,模型调用走标准的 API 接口。前端随意,甚至可以先不做前端,用命令行或者简单的网页表单验证核心逻辑。

依赖方面,除了常规的 Web 框架和数据库驱动,你需要一个任务队列来处理异步的诊断和调度计算。我用的是 Celery 加 Redis,轻量且成熟。向量检索初期不需要,等数据量上来了再考虑。

环境准备上,我建议用 Docker Compose 把数据库、Redis、应用服务编排在一起,这样本地开发和部署环境一致,省去很多麻烦。配置文件里把模型 API 的密钥、数据库连接串、队列地址都做成环境变量,不要硬编码。

3.2 数据模型设计:五张核心表

最小可用版本我建议先建五张表:用户表、知识点表、交互记录表、诊断结果表、调度任务表。

用户表很简单,存基本信息和能力评分。知识点表存层级化的知识点,每个知识点有一个唯一标识、名称、父节点标识、以及一个难度基准值。交互记录表存每次问答的结构化数据,包括用户、知识点、题目内容、用户答案、正确答案、结果评分、错误类型、时间戳。

诊断结果表存每次诊断的输出,包括用户、知识点、诊断结论、建议动作、置信度、生成时间。调度任务表存待执行的学习任务,包括用户、知识点、任务类型、计划时间、执行状态。

这五张表的关系是:交互记录驱动诊断,诊断结果驱动调度,调度任务执行后产生新的交互记录,形成闭环。建表时注意加好索引,交互记录表按用户加知识点加时间建复合索引,诊断结果表按用户加知识点建索引,调度任务表按计划时间加状态建索引。

3.3 诊断逻辑的实现细节

诊断逻辑我分成两个函数来实现。第一个是粗筛函数,输入是用户 ID 和知识点 ID,输出是一个布尔值表示是否需要精判。实现上就是查交互记录表,计算最近 N 次交互的错误率和错误类型分布,如果错误率超过阈值或者某种错误类型占比过高,就返回真。

第二个是精判函数,输入是用户 ID、知识点 ID 和该知识点的历史交互记录,输出是一个诊断结论对象。实现上是把历史记录格式化成一段文本,拼接到提示词里,调用模型 API,解析返回的 JSON 结果。

提示词的设计很关键。我的模板大致是这样的:先说明角色和任务,然后给出知识点的定义和常见错误类型,接着附上用户的历史记录,最后要求模型输出一个 JSON,包含诊断结论、建议动作、置信度三个字段。实测下来,明确要求 JSON 输出能大幅减少解析失败的情况。

注意:模型返回的 JSON 偶尔会有格式问题,比如多一个逗号或者少一个引号。一定要加一层容错解析,解析失败时降级到规则引擎的结论,不要直接报错。

3.4 调度算法的参数计算

调度算法的核心是一个优先级评分函数。我给每个待处理的知识点算一个分数,分数越高越优先处理。评分公式我设计成三个因子的加权和:错误严重度、前置依赖数、最近活跃度。

错误严重度就是最近一段时间该知识点的错误率,归一化到 0 到 1 之间。前置依赖数是指该知识点被多少个其他知识点依赖,这个值越大说明它越基础,越应该优先解决。最近活跃度是指该知识点最近一次交互距今的时间,越近说明用户刚接触过,趁热打铁效果更好。

三个因子的权重我一开始拍脑袋设成 0.5、0.3、0.2,后来根据实际效果调整到 0.4、0.35、0.25。调整的依据是观察用户完成调度任务后的改善率,改善率高说明权重合理。这个权重没有绝对标准,不同学科、不同用户群体可能不一样,建议做成可配置的。

难度选择上,我用一个简化的 Elo 公式。用户当前能力值记为 R,题目难度记为 D,预期正确率 P 等于 1 除以 1 加 10 的 D 减 R 次方。每次作答后,如果答对,R 增加 K 乘以 1 减 P,如果答错,R 减少 K 乘以 P。K 值我取 32,这是国际象棋 Elo 的经典取值,实测在学习场景下也够用。

3.5 闭环验证:怎么知道系统真的有效

系统搭好了,怎么验证它真的有用?我设计了三个指标来跟踪。第一个是知识点掌握度的提升速度,对比使用系统前后,用户在相同知识点上的错误率下降曲线。第二个是学习任务的完成率,如果调度层安排的任务用户经常跳过,说明任务安排不合理。第三个是长期留存,看用户是否愿意持续使用,这个最能说明问题。

验证方法上,我建议做 A/B 测试。一组用户用完整的持续学习系统,另一组只用一次性答疑,对比两组在相同知识点上的表现差异。样本量至少要几百人,周期至少四周,否则统计显著性不够。

我自己跑下来的初步结果是:使用完整系统的用户,在薄弱知识点上的错误率下降速度比对照组快约 40%,任务完成率在 70% 左右,四周留存率比对照组高约 25 个百分点。当然这个数据因场景而异,仅供参考。

4. 常见问题与排查技巧实录

4.1 诊断不准:模型总说“概念不清”怎么办

这是最常见的问题。模型倾向于把所有错误都归为“概念不清”,因为这是最安全的结论。解决办法是在提示词里给出明确的分类标准和示例,并且要求模型在输出时附上判断依据。如果依据不充分,就降级到规则引擎的结论。

另一个技巧是引入用户反馈。在诊断结果展示给用户后,加一个“这个判断准确吗”的按钮,用户点“不准确”时,把这条记录标记出来,定期人工审查,用来优化提示词。我靠这个机制把诊断准确率从最初的 60% 左右提升到了 85% 以上。

4.2 调度任务堆积:用户被任务淹没

早期版本我犯过一个错误:诊断出薄弱点就立刻生成任务,结果用户一打开系统看到几十个待办任务,直接关掉不用了。后来改成每日任务上限,默认最多推三个,用户完成后再推新的。同时把任务按优先级排序,只展示最紧急的几个。

还有一个细节:任务要有“跳过”和“稍后提醒”选项。用户跳过时记录原因,如果某个任务被大量跳过,说明调度策略有问题,需要调整。我通过分析跳过原因,发现很多任务是难度设置过高导致的,调整 Elo 参数后跳过率明显下降。

4.3 模型调用成本失控:怎么省钱

持续学习系统比一次性答疑的模型调用频率高得多,成本是个现实问题。我的省钱策略有三条:第一,粗筛用规则,只有精判才调模型,这样能过滤掉大部分不必要的调用。第二,精判结果缓存,同一个用户同一个知识点在短时间内不重复诊断。第三,批量处理,把多个知识点的诊断请求合并成一次调用,减少 API 往返开销。

实测下来,这三条策略能把模型调用量降低到原来的三分之一左右,而诊断质量几乎没有下降。如果你用的是按 token 计费的接口,还可以在提示词上做压缩,去掉冗余的说明文字,只保留必要信息。

4.4 冷启动问题:新用户没有历史数据

新用户刚进来时,记忆层是空的,诊断层无从下手。我的做法是做一个简短的初始测评,十到十五道题,覆盖主要知识点,快速建立初始的能力画像。测评题目难度要有梯度,从易到难,这样能更准确地定位用户水平。

测评结果直接写入记忆层,作为第一批诊断依据。同时给新用户一个默认的学习路径,不依赖诊断结果,先按知识图谱的顺序推进,等积累了一定交互数据后再切换到个性化调度。这个过渡期一般需要三到五天,取决于用户的使用频率。

4.5 常见问题速查表

问题现象可能原因排查方向解决建议
诊断结论总是“概念不清”提示词分类标准不明确检查提示词中的分类示例补充具体示例,要求输出判断依据
用户大量跳过任务任务难度过高或数量过多查看跳过率和任务难度分布调整 Elo 参数,设置每日上限
模型调用成本过高精判触发过于频繁统计精判调用次数和缓存命中率优化粗筛阈值,加强缓存
新用户无数据可用冷启动缺少初始画像检查是否有初始测评增加简短测评,设置默认路径
知识点掌握度不更新反馈层写回失败检查消息队列和写入日志修复队列消费,增加重试机制
调度任务时间冲突知识图谱依赖未处理检查前置依赖计算逻辑引入拓扑排序,按依赖顺序调度

最后分享一个小技巧:在诊断结果里加一个“置信度”字段,低于某个阈值时,系统不自动生成任务,而是推给用户一个“需要更多练习来确认”的提示。这样既避免了误判导致的无效任务,又给了用户一个合理的解释。我实测下来,这个机制能显著提升用户对系统的信任感。

这个项目后续还可以这样扩展:把知识点图谱做成可视化的,让用户看到自己的掌握度分布和进步轨迹;引入社交元素,让用户之间可以互相出题和批改;以及把调度层开放出来,允许老师或培训管理者手动调整任务优先级。这些方向我都在陆续尝试,有新的心得再分享。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询