资讯动态

端侧AI错题辅导落地实践:架构选型与推理优化

发布时间:2026/10/21 17:12:07 来源:尧图企业网站定制
去年我刚接手某个本地AI项目时甲方提的第一句话是“做错题辅导直接调大模型API不就行了为什么非要端侧”我没急着反驳。跑了一个月真机测试拍了三百多道错题在课后辅导班、卧室、上下学地铁这种真实场景里测答案很清楚调用云端API的方案在很多学生手上是撑不住日常使用的。信号不稳定、课堂集中提交导致的排队、每道题几秒甚至十几秒的转圈再加上家长对照片上传的天然警惕这些都不是“换个更大的模型”能解决的。于是我们转向了“本地AI错题辅导”这条路线识别、出题、解析、讲题尽量全部在设备端完成。这篇内容就是把当时从架构选型到端侧推理落地过程中踩过的坑和最终的选择原原本本拆给你看。我默认的读者是有一定客户端开发经验、理解“小程序”只是轻量宿主、想了解如何把真正的AI推理放到本地的人。如果你还在纠结“小程序到底能不能本地推理”我也会把这个问题一并回答掉。1. 为什么先谈“端侧”而不是“大模型”三个现实约束让我改了架构方案先说结论错题辅导这个场景端侧推理是刚需不是炫技。我越测越确信三个约束死死地卡住了“全部上云”的方案。第一个约束是网络环境。学生用错题App的高频时段恰好是网络质量最差的时段。晚自习教室几十台设备同时挤一个信号源校园图书馆、地下自习室、回家路上的地铁车厢这些地方要么信号弱要么干脆没网。我们的实测数据里光失败重试就占了请求总量的两成多。一个辅导工具学生正卡在哪道题上不去了结果它先转圈再报错这个体验基本等于劝退。端侧推理完全离线工作网络再烂识别和讲解都照常出结果。第二个约束是隐私。错题照片和普通风景照完全不同它天然包含了学生姓名、学校、班级、试卷来源这些信息。家长对“孩子作业照片被传到一个不知道藏在哪的服务器”这件事接受度越来越低。我接触的几所合作学校里有班主任直接把“不能用上传照片的App”写进班级公约。本地推理意味着照片文件不离开手机OCR识别和解题都在本机跑完这才是真正能拿出来和家长谈的隐私方案。第三个约束是成本。云端按次计费的模型单价看着不高但错题场景的使用量非常吓人。一个学生每天拍十道题一个班四十人一个年级八个班日调用量就是几千次。高峰期再叠加并发账单会成一个持续膨胀的无底洞。端侧模型是一次性部署跑一万次和跑一次的成本几乎一样。当然端侧也有替代不起的觉悟。我一开始就怕末尾本地小模型的数学推理能力确实不如云端大模型尤其面对多步证明题容易“一本正经地胡说”。所以设计目标不是“本地模型全知全会”而是把识别和标配讲解做扎实覆盖日常错题里七八成的高频题型难题才考虑做云端增强。把边界划清楚后端侧方案才真正立得住。2. 三道工序拆解拍照、读懂题意、生成讲解分别该选什么模型很多人做错题辅导第一反应是“找个多模态大模型图像输入答案输出”。我在评估过几类端侧视觉语言模型后果断拆成了三条独立的工序。拆的好处是每一步可以单独优化、单独替换出问题也好定位。具体拆成三道。2.1 工序一OCR把照片变成题干原文第一步是让设备“看懂”照片里写着什么。错题场景的OCR难点不在于单行文字而在于版面结构题目可能跨页、可能有配图、可能有手写批注、还可能有表格。我们最终采用的做法是“检测加识别”两段式先做文本区域的版面检测再做具体文字识别。这一道工序直接决定后面所有环节的上限OCR出错后面解析再准也没用。所以我把OCR质量卡得很严。实测标准是对印刷体题目文字识别准确率必须能达到95%以上对包含公式的题允许括号和上下标偶有偏差但核心数字和符号不能错。2.2 工序二语义理解把题干变成结构化信息拿到题干原文后模型要回答几个问题这是什么科目的题对应教材哪个知识模块一元二次方程、平行四边形、浮力、动量题目类型是选择、填空还是解答已知条件有哪些目标是什么这步我建议单独用一个轻量文本模型来做不需要很大的参数规模因为任务非常聚焦——它不是写作文而是做信息抽取和归类。相比视觉模型纯文本走的算子更简单在端侧的速度优势也更大。经过量化处理之后这一步在绝大多数手机上都能在半秒内完成。2.3 工序三讲解生成把结构化信息变成解题过程最后才是生成解题思路和步骤。很多人在这步犯了一个错误让模型“从图片直接写讲解”中间没有结构化信息约束输出经常牛头不对马嘴。我坚持先出结构化结果再喂给生成环节。给生成模型的输入是一段拼装好的模板Prompt包含题干文本、题目类型、知识点标签、学生年级。模型要做的是按步骤推导。为了控制质量和长度我会限制最大输出词元数并强制模型按“已知—求解—步骤—验证”的结构输出。生成模型是三者里参数规模最大的一个但也不需要顶到云端那种几千亿参数的体量。一亿到三四十亿参数区间、4比特量化后的模型已经能胜任绝大多数初中理科题和部分高中数学题的讲解。我把三道工序的参数定位整理成一张表方便你做选型时的参考工序模型形态参数量级量化后模型体积单次推理目标耗时文字检测与识别轻量视觉模型千万级60MB内0.5-1秒语义理解与分类小型文本模型0.5-1.5亿200MB内0.2-0.4秒解题与讲解生成中规模文本模型1-3亿300-800MB0.5-1.5秒三段式结构的另一个好处是容错清晰。OCR错了看检测结果就知道是拍摄角度问题还是模型问题讲解错了可以回看结构化抽取结果是否丢信息。要是只用一个端侧多模态大模型所有错误混在一起排查起来会非常痛苦。3. 整体架构与数据流六步链路里模型推理被放在哪个位置架构设计上我先把“小程序”这个概念摆正纯Web页面承载不了本地推理。端侧AI要走原生能力需要拿到CPU、NPU、内存的直接调度权。实际落地时我采用的是“轻量应用壳原生推理内核”的混合结构外层是类小程序的轻量界面内层是一个原生模块专门干AI推理和数据库存储。两套之间通过桥接层做异步通信。在这个结构下一次完整的错题辅导操作要经过六步链路每一步都有自己的任务和坑。第一步是图像采集。这一步往往被初学者忽略但它是体验的关键。我们做了自动取景框用边缘检测算法识别拍到的题目区域自动裁掉多余背景。手抖、反光、倾斜都在这一层做好预处理。第二步是图像预处理包括透视矫正、灰度化、对比度增强。这一步不求视觉上多好看只求OCR能吃得更准。第三步就是OCR识别。处理完的图像交给本地OCR模块产出题干原文和版面结构信息。第四步是关键的结构化理解把原文喂给理解模型产出学科、题型、知识点、已知条件、求解目标。第五步是讲解生成把理解模型产出的结构化信息和模板Prompt拼装后喂给生成模型流式产出解题步骤。第六步是落库与呈现。生成结果连同原图、OCR文本、结构化标签一起写入本地数据库同时根据知识点归属更新错题统计。界面上以“题干信息逐步解答知识点标签”的卡片形式呈现学生可以直接保存、标记和回顾。架构模块上我坚持了四层分离UI层只管展示、交互不知道模型存在。任务编排层负责六步链路的调度、超时处理、失败回退。服务层模型管理器、OCR服务、推理桥、本地存储接口。基础设施层推理引擎、SQLite数据库、文件系统。这种分层最直观的收益是我可以单独替换OCR模块而不影响其他层也可以把某个步骤的模型从本地方案切换成云端增强方案UI完全无感知。整个链路中推理桥层是最需要花心思的。它负责模型实例的加载与释放、控制并发、管理预热状态。错题辅导这个场景的并发量其实很低同一时刻最多一到两个推理任务但模型预热成本高、显存内存占用大管理不好就会出现“拍了一道题然后App直接被系统杀死”的惨剧。我把推理桥设计成单例模式所有模型实例由它统一管理启动时只加载小模型大模型按需加载用完即释放。4. 端侧推理工程落地引擎选型、量化取舍与上下文管理说到端侧推理很多人第一反应是“模型有多大、手机装不装得下”。实际上跑过一轮真机后你会发现最大的拦路虎根本不是体积而是推理引擎对算子、量化格式和内存回收的支持。这里把我的工程判断拆开讲。4.1 推理引擎选型看四点不是看跑分我评估移动端推理框架时不看官方在高端机上刷出来的跑分只看四个更实际的标准第一算子覆盖完整性。端侧模型里除了常规矩阵乘法和激活函数还有归一化、旋转位置编码、注意力计算这类结构。框架算子不全就意味着模型跑不起来或者要拆成几段算延迟直接翻倍。第二动态形状支持。错题文本长度变化很大模型输入不是固定尺寸框架必须支持动态张量形状这一点能筛掉一半候选。第三量化支持。必须是能跑的4比特量化推理不是只支持导出格式但真机上被反复回退成浮点。第四内存回收能力。推理结束后能不能立刻把池化内存归还给系统直接决定App会不会被杀后台。收尾一句选型阶段就该带着目标模型去框架里跑真机压测别只看示例程序里的Benchmark。4.2 量化取舍我为什么坚持“4比特为主敏感层例外”量化是端侧推理绕不开的坎。模型从32比特浮点位压到4比特整型体积剪到八分之一推理速度也能快不少但换来的可能是精度的轻微下降。错题辅导是教育场景讲解步骤错一个符号、错一个顺序都可能误导学生量化策略必须保守。我采用“感知量化和混合精度”结合的做法整体按4比特量化但对影响推理质量的少数层——特别是注意力输出的投影层和最后输出的计算层——保留更高精度。实际操作时先做一次全模型浮点推理收集各层权重分布找出离群值较多的层再做逐层量化的敏感度测试。这一步比较费时间但值得做。4.3 上下文管理错题场景不需要长篇对话很多端侧模型跑得慢不是因为模型大而是上下文开得太长。错题辅导的本质是单轮任务不是聊天。不存在的多轮对话所以我会把上下文窗口限制在一个很小的范围比如512词元足够容纳题干加一小段历史。这会让预填充阶段的计算量大幅下降生成阶段的键值缓存占用也直线减少。Prompt模板也要精修。我的是这样一个结构学科与年级定位、题干原文、结构化信息题型、知识点、已知条件、输出格式约束、语气约束。Prompt模板看似简单但它是本地模型输出质量提升最明显的杠杆之一。同一个模型模板写得好坏答案可读性差别很大。这里放一段我在推理桥层的TypeScript伪代码展示一次标准调用的骨架class InferenceBridge { static instance: InferenceBridge; private ocrModel?: any; private textModel?: any; private genModel?: any; async warmUp() { // 启动时只加载小模型生成模型按需加载 this.ocrModel await MobileInference.load(ocr_quant_v1, { precision: int8 }); this.textModel await MobileInference.load(text_struct_v1, { precision: int4 }); } async handleWrongQuestion(photoPath: string) { const taskRunner new TaskChain([ this.preprocess.bind(this, photoPath), this.runOCR.bind(this), this.understand.bind(this), this.generate.bind(this), this.saveToLocalDB.bind(this), ]); return taskRunner.run(); } private async runOCR(image: any) { // 返回题目文本 版面结构 const result await this.ocrModel.run(image); return result.text; } private async understand(text: string) { const prompt buildPrompt({ task: struct, text }); return this.textModel.run(prompt, { maxTokens: 128 }); } private async generate(structInfo: any) { const prompt buildPrompt({ task: solve, structInfo }); const engine await this.loadGenModelLazy(); return engine.generate(prompt, { maxTokens: 512, stream: true }); } }这里loadGenModelLazy是懒加载只有在需要生成讲解时才加载生成模型避免一进App就把几百MB模型全怼进内存导致低端机直接黑屏。生成过程中的流式输出也很关键。端侧模型单次完整生成要几百毫秒到一秒以上让我告诉你是什么体验如果必须全量生成完才显示学生面前就是一片空白加一个小圈圈转半秒以上。流式输出让第一个字在几百毫秒内就蹦出来然后一个字一个字地滚动显示用户感知到的延迟会少很多焦虑感也低了。这个体验投资非常值。5. 错题本的数据模型让“知识错误”真正可查询、可回顾错题辅导的核心资产不是模型而是积累下来的错题数据。学生持续用App两周本地就攒了几百道错题。如果没有一套好用的数据模型这些错题就是一堆死照片。这个模块必须一开始就设计对后面补数据模型是真的痛苦。我采用的是一张主表加多张关联表的结构。主表存每道错题的基本信息原始照片路径、OCR提取文本、题型、学科、知识点ID、错误原因类型、讲解内容、时间戳和状态。知识点和错因单独立表主表和它们多对多关联。一段核心的表结构设计建议直接用SQL表达CREATE TABLE wrong_questions ( id INTEGER PRIMARY KEY AUTOINCREMENT, photo_path TEXT NOT NULL, ocr_text TEXT, subject TEXT, problem_type TEXT, knowledge_point_id INTEGER, wrong_reason TEXT, solution_text TEXT, source_file_id INTEGER, status INTEGER DEFAULT 0, create_time INTEGER ); CREATE TABLE knowledge_points ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, chapter TEXT, difficulty INTEGER DEFAULT 1 ); CREATE TABLE wrong_reason_tags ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, description TEXT );为什么知识点必须单独建表而不是直接存字符串因为只有结构化之后才能做统计。有了这张表我可以轻易回答“这个学生哪些知识点错得最多”这类问题再根据错误频率给复习建议。而如果只存一段文本标签做统计时每次都要去分词和归一化痛苦不堪。关键还有个字段是status。我把它设为整型0表示待复习1表示已掌握2表示再刷一次。它驱动的是错题回顾机制。本地不需要做多复杂的间隔重复算法我实际用的只是一个简化版每道题录入后三天推一次复习提醒答对就置为已掌握答错就把状态重置回0。效果稳定代码也不复杂。对一个小程序端的工具来说够用了。数据导出的能力也不可少。本地数据是学生的资产我留了一个“导出错题本”的入口可以把结构化数据打包成通用格式发给老师。这是家教场景里很受欢迎的功能也让家长知道数据在本地、可控——不仅是隐私承诺而且是实际操作。6. 性能优化和设备兼容我的目标不是跑通而是感知不到延迟端侧推理有个反常识的地方单看每一项都挺快串在一起就容易让人等得不耐烦。OCR一秒钟理解三百毫秒生成八百毫秒加起来两秒多。两秒听起来不长但在一个高频操作里每道题都要两秒学生很快会烦躁。所以我把优化目标定得非常明确完整链路控制在1.5秒左右且用户第一眼看到反馈的时间不能超过500毫秒。按这个目标拆解后的各项预算如下链路环节预算耗时优化手段拍照与预处理100-200ms自动裁切加灰度化一次性完成OCR识别400-600ms轻量检测模型加小批量预测结构化理解200-300ms小模型加短上下文讲解生成400-600ms限制输出长度流式首字加速要把这些数字兑现我做了四件事。第一模型预热策略用户进入拍照页的瞬间后台就把OCR模型和文本理解模型加载好拍完照片直接推理省掉加载时间。第二图像预处理轻量化透视矫正直接抛给硬件加速之后立刻转灰度图减少后续算子的计算量。第三生成限制输出词数把默认回答死死压在200词元之内还设了停止符模型判断“步骤已完整”就会早停不再废话。第四内存的显式释放每次推理完成后立刻释放中间张量避免连续拍三四道题后内存水位飙升。设备兼容是另一个大坑。市面上的安卓设备从旗舰到千元机差异巨大同一个模型在不同机上的表现天差地别。我的处理方式是分档策略高端机型跑完整三段式推理中端机型跑OCR加小模型理解生成环节退化为模板填充低端机型则是只保OCR和结构化标签讲解改为预设模板按公式库填充。分档逻辑不是写死在代码里的而是通过一个远程开关来控制按需回退模型更新也不会导致老设备直接不可用。更底层的保障是崩溃兜底。推理引擎偶尔会碰到不支持的算子或资源不足在入口处做一层异常捕获一旦推理失败直接提示用户“当前设备暂不支持本地讲解可尝试云端增强”而不是干等着闪退。这个兜底教会了我很多次给用户一条退路比让他在loading圈里等一辈子强。7. 落地顺序、踩坑复盘和一些实在建议这类项目最忌讳一上来就做大而全的“全科错题AI助手”。我实际跑下来的顺序建议是这样。先做一个超级窄的MVP只支持初中数学只支持一元二次方程、函数单调性等十个高频错题题型模型只在高端机型上开放完整推理其他机型走本地OCR加云端API。为什么是初中数学因为初中理科题的解题步骤相对固定端侧小模型应付得了准确率容易达标。先定义这个范围后面的模型训练、模板设计和验收标准都有了一个清晰边界。MVP跑通后会遇到一个很有意思的现象用户反馈里有“这道题怎么解错了”的占比会明显下降取而代之的是“这道题步骤太简略我看不懂为什么这么做”。这时候才真正体现出错题辅导的核心需求——学生需要的不是标准答案而是“我错在哪、为什么错”。结构化数据里存放的错因标签就在这时候派上用场。录入错题时让学生顺手点一下错因“粗心算错”“概念混淆”“方法不当”“不会变通”。积累一段时间后按错因汇总给出复习建议比单纯按知识点汇总更有引导性。再回到本地和云端的边界问题。我最后的方案是“默认全部本地疑难自动提示”。本地模型对每道题产出一个置信分置信分高的直接展示讲解置信分低的提示“本机算力有限建议联网获取更权威解析”。这样既保住了大多数场景的离线能力和隐私也给真正的难题留了一条出路。用户不会觉得被一个笨模型耽误了。最后分享一个我反复吃的亏量化模型不是压得越小越好。我曾把生成模型压到3比特模型体积少了三成但讲解正确率掉了近二十个百分点尤其是涉及符号推导的题几乎全线崩溃。后来又花了大把时间回退到4比特混合精度方案。压缩带来的收益要放在整条体验链路中看省下的几百兆空间远远抵消不了错误率上升带来的口碑损失。端侧AI错题辅导真正的难点不在“端侧”而在想清楚“哪些必须端侧、哪些可以放云端、哪些干脆不做”。把这个问题想透模型选型、架构设计、性能优化都会自然有答案。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑