学习工作赛道 LingoQuest - 手机里的私人英语教练,AI 全驱动完全离线

学习工作赛道 LingoQuest — 把端侧大模型塞进手机,做一台随时在线的英语教练

LingoQuest 是我在这次参赛期间开发的一款 Android 英语学习 App Demo。一句话说清它的特点:核心 AI 能力——大模型对话、语音识别、语音合成、发音评分——全部跑在手机本地,不联网也能完整使用。

它面向两类人:一类是 K12 学生,初高中生备考场景;一类是职场人士,商务英语提升。一套引擎,两种配置,入境时确定画像(ProfileType),内容优先级和 UI 风格跟着走,但核心引擎(SRS / ASR / TTS / LLM)完全相同。

先说说这个东西长什么样

首页没有底部导航栏。这是我纠结了很久的决定。打开 App 第一屏直接就是"今天该做的事"——一张 MissionCard 巨卡占据视觉中心,上面是今天的开口任务和一个带脉冲光环的麦克风按钮;往下依次是 AI 教练面板(BriefingCard 实时数据 + LLM 打磨过的文本)、说话能力四维卡(发音准确 / 流利度 / 反应速度 / 开口自信)、NextSpeak 软引导卡片。AI 决定你下一步去哪,单屏单任务,不嵌套弹窗。

这个 Demo 目前实现了以下核心功能模块:

  1. AI 情景对话 —— 端侧 Qwen3 驱动的场景化口语练习,实时语法纠错。Thinking / Non-Thinking 双模式调度:实时对话走 Non-Thinking(延迟优先),对话复盘、写作批改、深度诊断、任务排序、每日简报走 Thinking(质量优先,超时延长到 60s),词卡造句走 Non-Thinking(速度优先)。三层降级链:MNN 本地 → 云端 API → 规则引擎。

  2. 发音评分 Pipeline —— 完整链路从录音到音素级纠错:录音 → ASR 转写(含词级时间戳)→ DTW 动态时间规整 → CMU Pronouncing Dictionary → PhonemeSimilarity → 综合评分(准确度 50% + 流利度 30% + 韵律 20%)→ LLM 生成中文纠错建议。它能明确告诉用户"音素 /θ/ 需要加强练习"。

  3. 词汇复习 —— FSRS-5 算法(Free Spaced Repetition Scheduler v5),三组件记忆模型(Stability / Difficulty / Retrievability),4 档评分(Again / Hard / Good / Easy),目标保持率 0.9,最长间隔 365 天。3D 翻转卡片,开口锁机制。

  4. 即兴说(FreeTalk) —— AI 给话题,1 分钟讲话,评估流利度 / 词汇丰富 / 反应速度。

  5. 影子跟读(Shadow) —— 听一句立刻复述,AI 对比打分,逐词高亮匹配。

  6. 学习统计 —— 总时长 / 已学单词 / 连续天数 / XP,本周柱状图,技能分布,等级进度。

  7. 模型管理 —— LLM / ASR / TTS 模型下载管理,设备分档推荐,优先级链可视化。

技术栈简单交代一下:Kotlin 1.9.24 全 Compose UI 单 Activity;端侧 LLM 用 MNN-LLM 自编译 JNI(C++),跑 Qwen3 Dense 系列 INT4 量化(0.6B 约 400MB 约 12 tok/s,1.7B 约 1.1GB 约 10 tok/s);语音统一用 sherpa-onnx 框架(ASR + TTS + VAD),4 种音色(US_FEMALE / US_MALE / UK_FEMALE / UK_MALE),流式 TTS 配合 LLM 流式输出;数据库 Room v8 共 15 张表带迁移链;DI 用 Hilt 2.50;整体 Clean Architecture 五层分层(UI / Domain / Engine / Data / DI)。

为什么花大力气做端侧

灵感其实来自一个很具体的场景:地铁上没信号,想练两句英语,App 直接弹"网络连接失败"。更早之前我注意到一个矛盾——市面上的英语 App 把 AI 当卖点,但 AI 全在云端,离线就是个壳;而另一方面,Qwen3 这种 0.6B 的小模型 INT4 量化后才 400MB 出头,在中端机上能跑到 12 tok/s,对对话场景已经够用了。

我想验证一件事:能不能把"私人英语教练"这件事完整地塞进手机,不依赖云端。这带来的不只是"能离线用",还有隐私——语音数据、学习数据全在设备上,不出门。这对学生家长和注重隐私的职场用户是个实打实的卖点。

痛点其实是三层叠加的:

  • 无网环境(地铁、教室、飞机)下 AI 功能直接瘫痪
  • 语音数据上传云端,不少用户有顾虑
  • 传统 App 功能列表太长,打开就是选择焦虑,不知道今天该学什么

第三点催生了"首页即课堂"这个设计理念,也是我踩过弯路才想明白的。最早的版本我做了一个 ExploreGrid 功能网格,把所有模块铺在首页,看着丰富,结果数据很难看——打开率低,停留时间短,选择焦虑严重。后来砍掉网格,改成 AI 决定下一步的强引导模式,MissionCard 麦克风点进去就是今天该做的任务,效果立竿见影。这个教训让我更坚定一件事:学习产品不能让用户做选择题,AI 该替用户做决策,规则引擎只在 AI 不可用时兜底。

怎么体验

为了让评审直观感受产品形态和核心交互,我做了个交互式 HTML 演示页面,浏览器打开就能体验,不用装 App。

HTML 演示覆盖 8 个场景:

  • 首页:MissionCard 任务卡 + AI 教练面板 + 说话能力四维卡,能直接感受到"首页即课堂"的强引导交互
  • AI 情景对话:模拟端侧 Qwen3 的流式输出和实时语法纠错,以及 Thinking / Non-Thinking 双模式切换
  • 发音评分:模拟录音 → 评分结果展示,包括音素级错误定位(比如提示 /θ/ 需加强练习)
  • 词汇复习:FSRS-5 的 4 档评分交互和 3D 翻转卡片
  • 即兴说:AI 给话题 + 倒计时 + 录音评分
  • 影子跟读:双波形对比 + 逐词高亮匹配
  • 学习统计:柱状图 + 雷达图 + 等级进度
  • 模型管理:设备分档 + 三层降级链可视化

附件里是 Zip 打包的 HTML 文件,解压后用浏览器打开即可。

LingoQuest-Demo-v2.zip (20.6 KB)

在 TRAE 里是怎么造出来的

整个 Demo 从 PRD 到架构设计、功能实现、Bug 修复,全程用 TRAE IDE 辅助开发。挑几个关键节点说。

产品需求与架构设计这块,我先把"首页即课堂"“AI 全驱动”"隐私优先"这几个设计理念在对话里讲清楚,让它理解我不想要一个功能堆砌的 App,而是一个 AI 决策、单屏单任务的产品。最终生成的 PRD 走到 v4.2,配套 Clean Architecture 五层分层方案(UI / Domain / Engine / Data / DI)。这步很重要,因为后面所有功能的分层位置——该放 ui 还是 domain 还是 engine——都靠这个架构约束,避免了后期代码乱窜。

端侧 AI 引擎集成是最硬核的部分。MNN-LLM 的 JNI 桥接(llm_mnn_jni.cpp)是自编译的,CMake 里开了 MNN_LOW_MEMORY 和 MNN_CPU_WEIGHT_DEQUANT_GEMM 两个针对低内存设备的优化开关。模型下载子系统我设计了一套完整状态机:ActivationCoordinator 是唯一状态真相源,持有 Map<ModelKey, ModelState>,支持 reconcileFromDisk(App 重启后从磁盘重建状态,这对升级存活很关键,不会因为重启就丢失已下载模型的校验状态);DownloadEngine 负责 HTTP Range 断点续传;IntegrityVerifier 做 SHA256 校验;ModelDownloadService 是前台 Service(foregroundServiceType=dataSync)保活后台下载。设备分档逻辑:LOW(≤4GB)推 0.6B,MID(6-8GB)推 1.7B,HIGH(≥8GB)推 1.7B 多线程。

**LLM 治理(Phase 6)**也花了不小功夫。LlmGateway 做限流、超时、降级路由;LlmResponseCache 持久化响应缓存;LlmMetricsLogger 记延迟 / 结果 / token / 模式指标,带 24h 滑动窗口;LlmHealthMonitor 负责熔断与降级触发。对话安全用了 DialogInputGuard / DialogOutputGuard / LlmOutputSanitizer 三层护栏,比如过滤掉 <think> 标签这类内部输出。场景化 Prompt 拼装靠 PromptTemplates / ScenarioPromptBuilder / UserContextBuilder,ChatHistoryManager 管理对话上下文窗口,DeepDiagnosisService 在模型就绪后异步生成深度诊断。

发音评分 Pipeline这块,核心是 PronunciationScorerImpl:ASR 转写带词级时间戳后,用 DTWAligner 做动态时间规整对齐,再过 PhonemeSimilarity 算音素相似度,CMU 词典查音素序列,最后 FluencyCalculator 算停顿、RhythmCalculator 算重音节奏,综合评分按准确度 50% + 流利度 30% + 韵律 20% 加权。用户主动触发时 LLM 生成中文纠错解释。

踩坑的部分

有几个印象比较深,值得单独说。

第一个是 TTS 并发崩溃。 sherpa-onnx 的 JNI 层不是线程安全的,并发调 generateAudio 会静默失败——不报错,不抛异常,就是没声音。排查了好一阵,日志里啥都没有,最后定位到是并发访问 JNI 资源,加 Mutex 串行化解决。这种静默失败最坑,因为你看不到任何异常堆栈,只能从"该出声的地方没出声"反推。

第二个是 Error 类型捕获的问题。 UnsatisfiedLinkError 和 OOM 都属于 Error 不是 Exception,我一开始写的 catch(e: Exception) 根本捕获不到,模型加载失败或者内存吃紧时直接崩到主进程。改成 catch(e: Throwable) 才稳。MNNAdapter 加载 .so 失败时的降级路径就是靠这个兜住的——捕获到 UnsatisfiedLinkError 后平滑降级到 Cloud / Fallback。

第三个是 LLM 降级到英文模板的尴尬。 早期规则引擎用的是英文模板,有次模型没就绪走了降级,用户问"今天该学什么",AI 回了句 “Good point!”。这体验直接崩了。后来改用中文规则引擎 AdvisorRuleFallback,降级场景也能说人话、给出可执行的学习建议。

第四个前面提过,首页从 ExploreGrid 自由探索改成强引导。 这个不是 bug,是产品设计上的弯路。功能网格铺开看着丰富,实际选择焦虑严重、打开率低。砍掉之后让 AI 决定下一步,数据立刻好转。这让我意识到,AI 全驱动不只是技术上把 LLM 接进来,产品形态也要配合——把"选择权"从用户手里收走,交给 AI,反而体验更好。

关键对话 Session ID

  • 【.2355573270522090:6975274f9414d8f8e72e5746b89c6dfa_6a2823d003e621a1ea8963e1.6a28245703e621a1ea8963e4.6a282457974411f8cb8f8095:Trae CN.T(2026/6/9 22:33:59) — 架构设计 / PRD 编写】
  • 【.2355573270522090:137463eabae6589ee5094d50320759bb_6a2ad51f62d1dca300c2db7f.6a2ad56b62d1dca300c2db81.6a2ad56b592c06113efbc6e5:Trae CN.T(2026/6/11 23:34:03) — tts集成】

写在最后

这个 Demo 想验证的是:端侧 AI 已经能撑起一个有深度的英语学习产品——带 FSRS-5 记忆算法、发音音素级纠错、模型治理、三层降级链的工程级实现。0.6B 的小模型在手机上跑到 12 tok/s,配合流式 TTS 和 DTW 音素对齐,离线也能做出像样的私人英语教练体验。核心功能已经跑通,后续还会继续打磨。

TRAE 在整个开发流程里承担了从需求到实现到修复的主线角色,尤其是 JNI 桥接和算法实现这种容易踩坑的部分,AI 辅助排查确实省了大量时间。如果你也在做端侧 AI 落地的项目,欢迎交流。

报名帖链接:【(LingoQuest——装进口袋的端侧AI英语私教)】

1 个赞