PracticeMate 架构总览
核心设计理念
PracticeMate 是一个 Rubric Runtime——换一份 YAML 即换整套陪练逻辑,架构不变。它不是「录视频等评分」的工具,而是「开一场陪练会话」的体验。用户点击的是「开始练习」,不是「开始录像」。录像只是会话的副产品,用于证据回放。
同一套架构支持多场景:OSCE 临床技能、实验操作、烹饪流程——只需替换 Rubric YAML 文件,无需改动代码。
系统中有两个 AI 角色各司其职:
| 角色 | 时机 | 语气 | 目标 |
|---|---|---|---|
| 端侧教练 | 操作中,实时 | 温和、即时、可打断 | 防错、养成习惯、正向激励 |
| 云端考官 | 结束后,异步 | 严谨、多维、有证据 | 定分、给改进路径 |
同一事件在两端呈现不同:端侧教练只说「注意按压深度」,云端考官写「按压质量扣 5 分,15.2s 处深度不足」。
承认不确定是产品哲学,不只是技术妥协。 当端侧教练置信度不足时,它会主动说「这里我不太确定,先记下来,练完再看」。低置信事件在 UI 中显示为「待考官确认」状态,而非隐藏。这让用户信任系统——它不会假装全知,但会诚实记录一切。
系统架构图
┌──────────────────────────────────────────────────────────────┐
│ iPhone App(教练) │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ 0. 练习仪式层(Ritual Layer) │ │
│ │ 3s 聚焦提示 → 深呼吸 + haptic + "进入急救状态" │ │
│ │ 阶段切换 → haptic + 教练语音里程碑播报 │ │
│ │ 结束时 → 亮点优先的即时复盘 │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────┐ ┌──────────────────┐ ┌────────────────┐ │
│ │ Camera │──→│ Camera Quality │──→│ Perception │ │
│ │ (1 fps) │ │ Gate (CQG) │ │ Planner │ │
│ │ │ │ │ │ (阶段感知调度) │ │
│ │ │ │ Swift + 轻量 CV │ │ │ │
│ │ │ │ 亮度/角度/遮挡 │ │ hybrid 切阶段 │ │
│ └──────────┘ └──────────────────┘ └───────┬────────┘ │
│ │ │
│ ┌──────────────────────────────────────┘ │
│ │ 只激活当前阶段的 2-3 个 signals │
│ ▼ │
│ ┌──────────────┐ ┌──────────────┐ ┌────────────────┐ │
│ │ MNN Runtime │──→│ Confidence │──→│ Coach Voice │ │
│ │ │ │ Router │ │ (教练语气) │ │
│ │ Qwen2.5-VL- │ │ │ │ │ │
│ │ 2B (INT4) │ │ high → 强提醒 │ │ Rubric 模板字串 │ │
│ │ [常驻] │ │ mid → 弱提示 │ │ alert_message │ │
│ │ │ │ low → 记录 │ │ confirm_message│ │
│ └──────────────┘ │ +标记 │ └────────────────┘ │
│ │ "待考官确认" │ │
│ └──────────────┘ │
│ │
│ events.jsonl(正负事实流) │
│ (本地落盘) │
│ │ │
│ ┌───────────────────────┴───────────────────────────────┐ │
│ │ Instant Recap(规则聚合即时复盘) │ │
│ │ 规则:按阶段统计 ✓/△/✗ 计数,亮点优先展示 │ │
│ │ "本次练习:安全 3✓ 操作 2✓1△ 收尾 2✓" │ │
│ │ [Qwen3-1.7B 按需加载,仅用于自然语言润色] │ │
│ │ [可选] 申请专家评分 → │ │
│ └───────────────────────┬───────────────────────────────┘ │
└──────────────────────────┼───────────────────────────────────┘
│ HTTPS (events.jsonl, < 100KB)
│ 视频不上云
▼
┌──────────────────────────────────────────────────────────────┐
│ Cloud(考官 — 全智评 API) │
│ │
│ ┌──────────┐ ┌──────────────────┐ ┌────────────────┐ │
│ │ Events │──→│ CCAE Engine │──→│ Report Builder │ │
│ │ Receiver │ │ (3-Phase) │ │ (考官语气) │ │
│ │ │ │ │ │ │ │
│ └──────────┘ │ Phase 1: 全扫 │ └───────┬────────┘ │
│ │ Phase 2: 批判 │ │ │
│ │ Phase 3: 仲裁 │ │ │
│ └──────────────────┘ │ │
│ │ │
│ 正向事件减少误判:signal_confirmed → 证据 │ │
│ Qwen-VL-Plus / Qwen3.5-Plus + rubric 全集 │ │
└──────────────────────────────────────────────────┼────────────┘
│
HTTPS (report.json) │
▼
┌──────────────────────────────────────────────────────────────┐
│ 练-评-教 三角闭环 │
│ │
│ Student App ──events.jsonl──→ Cloud Examiner │
│ ↑ │ │
│ │ report.json │
│ │ ▼ │
│ └──── 全智评 Web(教师端)←── 评分+证据链 │
│ 教师可审阅、可覆盖评分 │
└──────────────────────────────────────────────────────────────┘感知栈三层分离(Perception Stack)
端侧感知采用 L0/L1/L2 三层架构,每层有不同的技术栈和延迟特征:
| 层级 | 技术栈 | 延迟 | 用途 |
|---|---|---|---|
| L0 Camera Quality Gate | Swift + Core Image / Vision | < 30ms | 亮度/角度/遮挡/距离 |
| L1 Specialized CV | Swift Vision + 轻量规则 | < 50ms | 高频姿态信号(双手位置/按压姿态) |
| L2 VL Model | Qwen2.5-VL-2B + MNN | 500ms-2s | 语义理解类信号(按压深度/回弹/通气量) |
每个 edge_signal 在 rubric YAML 中标注 perception_level: L0 | L1 | L2,Perception Planner 据此路由到对应层级处理。L2 不可用时自动回退到 L1。详见 edge-runtime.md。
Coach Persona 参数化
Coach Voice 的人格由 rubric YAML 中的 coach_persona 配置驱动,支持三个参数维度:warmth(语气温暖程度 0-1)、interruptiveness(打断频率 0-1)、praise_frequency(正向反馈频率 0-1)。配合 Ritual 成熟度分级(first_time / daily / exam),系统自动调整仪式深度和教练语音频率。详见 edge-runtime.md。
数据流(Practice Ritual 生命周期)
0. 练习仪式层(Ritual Layer)
用户点击「开始练习」后,系统不直接跳入检测循环,而是先执行一个 3 秒的心理启动仪式:
- 聚焦提示:屏幕显示「深呼吸…进入急救状态」,配合 haptic 反馈节奏(吸气-呼气-开始)
- 目的:把用户从日常状态切换到练习状态,建立「认真对待」的心理暗示
- 阶段切换仪式:每次 phase_transition 触发时,教练用里程碑播报 + haptic 确认(如「准备阶段完成,做得不错,进入操作环节」)
- 结束仪式:练习结束时,优先展示做得好的地方(亮点优先),再提待改进项
这不是冥想 App——是一个心理启动协议,让每次练习都有仪式感和节奏感。
1. 机位引导 — Camera Quality Gate(CQG)
仪式层完成后,进入机位引导。CQG 是独立可演示的创新模块——把 ML 难题变成 onboarding 体验:
- AR 示意框提示「把手机架在实验台左前方,能拍到双手和台面」
- 实时画面质量检测:过暗 / 过曝 / 人脸太小 → 提示调整
- 纯 Swift + 轻量 CV 实现(Core Image + Vision framework),不依赖 VL 模型
- 质量不达标时可降级为「文字清单模式」(仍满足端侧本地交互要求)
- 通过后自动进入练习
CQG 的价值:即使没有后续 AI 陪练功能,单独的「智能机位引导」本身就是一个有价值的功能组件,可独立演示。
2. 阶段感知实时陪练(端侧教练)
Perception Planner 是端侧的一等公民,而非实现细节:
rubric.phases 定义练习阶段(环境评估 → 胸外按压 → 气道通气 → 循环延续)
│
▼
Perception Planner 维护当前阶段状态机
│
├── 每阶段只激活该阶段的 edge_signals(2–3 个)
│ → 降低误报、省电、叙事更清晰
│
├── Hybrid 三路阶段切换(见下文)
│
└── 每帧推理结果写入 events.jsonl
→ 包含正向确认(hand_position_correct)和违规(hand_position_wrong)两类感知栈三层分离(Perception Stack)(TD-015)
端侧感知不再是"一个 VL 模型做一切",而是三层独立运行:
- L0(Camera Quality Gate):Swift + Core Image,< 30ms,管画面质量(亮度/角度/遮挡)
- L1(Specialized CV):Swift Vision + 轻量规则,< 50ms,管高频姿态信号(双手位置/按压姿态)
- L2(VL Model):Qwen2.5-VL-2B + MNN,500ms–2s,管语义理解信号(按压深度/回弹/通气量)
三层独立降级:L2 不可用时 L1 仍保证安全检测可用,L0 始终可用保证基础引导。 每个 edge_signal 在 rubric YAML 中标注 perception_level,Perception Planner 据此路由。
Hybrid 阶段切换(三路容错)
阶段切换不依赖单一路径,而是三路并行保证可靠性:
| 优先级 | 路径 | 触发方式 |
|---|---|---|
| Primary | AI 自动检测 | transition_trigger 信号置信度达标 → 自动切换 |
| Fallback A | 用户手动 | 屏幕底部常驻大按钮「进入下一阶段」,用户随时可点 |
| Fallback B | 超时询问 | 超过 estimated_minutes 后教练主动问「要进入操作环节了吗?」 |
这样即使 AI 检测失败,用户体验也不会卡死在某个阶段。
Rubric Primitives(TD-016)
每个 edge_signal 被归类到五种 Rubric 原语之一,原语决定了信号的检测策略和教练响应方式:
| 原语 | 含义 | 典型信号 | 教练策略 |
|---|---|---|---|
safety_check | 安全类检查 | 环境安全/手套佩戴 | 立即提醒,不可忽略 |
step_sequence | 步骤顺序 | 呼叫120/AED到位 | 顺序提示,可延迟 |
equipment_state | 器材状态 | AED开机/电极贴片 | 状态监控,变化触发 |
motion_quality | 动作质量 | 按压深度与频率 | 实时反馈,连续评估 |
timing_window | 时间窗口 | 通气时间窗口 | 窗口内检测,单次判断 |
原语是跨学科复用的——CPR 的 safety_check 和化学实验的 safety_check 遵循相同的教练策略。
3. 置信度分层提醒(提醒光谱)
不做二元弹窗,做三层提醒光谱:
| 置信度 | alert_tier | 端侧教练行为 | 用户感知 |
|---|---|---|---|
| 高 (>0.8) | high | 强提醒 + haptic 震动 | 「确定有问题」 |
| 中 (0.6–0.8) | medium | 弱提示(角标 / 轻文案) | 「可能要注意」 |
| 低 (<0.6) | low | 只记 events,不打扰;UI 标记「待考官确认」 | 用户知道系统注意到了,但不确定 |
低置信事件不打扰用户,但诚实地标记「待考官确认」。教练会说:「这里我不太确定,先记下来,练完再看」。送到云端后由考官最终裁定。
Coach Voice 的文案来源于 Rubric YAML 中的 alert_message / confirm_message 模板字串,不经过 LLM 生成——保证延迟可控、语气一致。
4. 正负事实流(events.jsonl)
事件不只是「违规日志」,而是完整的正负事实流:
{"ts": 0.0, "event_type": "session_start", "signal": "session_began", "confidence": 1.0, "phase": "scene_assessment"}
{"ts": 3.2, "event_type": "signal_confirmed", "signal": "hand_position_correct", "confidence": 0.92, "phase": "scene_assessment", "alert_tier": "silent", "description": "双手位置正确"}
{"ts": 15.2, "event_type": "safety_violation", "signal": "scene_safety_skipped", "confidence": 0.87, "phase": "scene_assessment", "alert_tier": "high", "description": "未确认现场安全"}
{"ts": 42.0, "event_type": "step_completed", "signal": "response_check_done", "confidence": 0.78, "phase": "scene_assessment", "alert_tier": "silent", "description": "已确认意识与呼吸"}
{"ts": 45.0, "event_type": "phase_transition", "signal": "scene_assessment_to_chest_compression", "confidence": 0.85, "phase": "chest_compression", "description": "进入胸外按压阶段"}
{"ts": 120.0, "event_type": "step_completed", "signal": "compression_rate_stable", "confidence": 0.81, "phase": "chest_compression", "description": "按压频率稳定"}
{"ts": 125.0, "event_type": "phase_transition", "signal": "airway_ventilation_to_cycle_continuation", "confidence": 0.90, "phase": "cycle_continuation"}
{"ts": 180.0, "event_type": "session_end", "signal": "session_ended", "confidence": 1.0, "phase": "cycle_continuation"}正向事件的好处:云端 CCAE 可减少「没提到 ≠ 没做」的误判;端侧教练可以给正向反馈而不只是纠错。
events.jsonl 同时是「练-评-教」三角闭环的数据枢纽:学生端产出 → 云端考官消费 → 教师端(全智评 Web)审阅和覆盖。
5. 会话结束:Instant Recap(即时复盘)
用户点击「结束练习」后,端侧先给 Instant Recap(不依赖网络):
- 规则聚合:按阶段统计 ✓(完成)/ △(待确认)/ ✗(违规)计数
- 亮点优先:先展示做得好的地方,再列待改进项
- 示例:「准备阶段:安全 3✓;操作阶段:流程 2✓ 滴速 1△;收尾阶段:2✓」
- Qwen3-1.7B 按需加载(仅在此环节),用于将规则聚合结果润色为自然语言
- 这是「本次练习小结」,不是评分——语气温和、鼓励为主
- 底部显示「申请专家评分」按钮(可选,不强制上云)
Instant Recap ≠ 考官评分。它只做统计和鼓励,不做深度判断。
6. 可选:云端考官深度评分(Examiner)
用户主动选择后,events.jsonl 上传到云端:
- CCAE 三阶段评价(全扫 → 批判 → 仲裁)
- 使用完整 rubric(含 cloud_criteria 全集)
- 正向事件作为正面证据,减少「未提及 = 未做」误判
- 生成考官语气报告:严谨、多维、引用 evidence_ts
- 按实验阶段分段评价(phase_summary)
- 每个扣分项附带证据链:时间戳 + 信号 + 置信度
Examiner 与 Instant Recap 的分工:Instant Recap 是端侧秒出的鼓励性统计;Examiner 是云端深度的评判性评分。两层独立,互不依赖。
7. 报告渲染 + 证据回放
- 考官报告结构化展示:总分 + 各维度得分 + 阶段分段评价
- 点击扣分项 → 跳转本地视频对应时间点回看
- 低置信维度显示「待考官确认」标记 + 考官最终裁定结果
Replay / Live 双轨模式
系统支持两种运行模式,共享同一套 Rubric / Schema / UI:
| Replay Mode | Live Mode | |
|---|---|---|
| 事件来源 | 预录 events.jsonl 回放 | 实时 VL 推理产出 |
| 用途 | 产品演示、UI 开发、考官调试 | 正式练习 |
| Camera | 不需要 | 需要 CQG 通过 |
| 模型加载 | 不加载 MNN | 加载 VL-2B |
| UI 指示器 | 左上角显示"回放模式"标签 | 无额外标签 |
Replay Mode 让团队可以在没有真实摄像头场景的情况下完整验证 UI 流程、Instant Recap 逻辑、云端 Examiner 评分——加速开发迭代。切换方式:Rubric YAML 中设置 mode: replay 并指定 replay_events_path。UI 中提供透明的模式切换入口,用户始终能看到当前处于哪种模式。
端侧模型资源预算
| 模型 | 量化 | 大小 | 内存占用 | 加载策略 | 用途 |
|---|---|---|---|---|---|
| Qwen2.5-VL-2B | INT4 | ~1 GB | ~1.2 GB | 常驻(实时循环) | 视觉感知(帧→事件) |
| Qwen3-1.7B | INT4 | ~0.85 GB | ~1 GB | 按需加载(仅 Instant Recap) | 复盘文案自然语言润色 |
实时推理循环中 只加载 VL-2B。Coach Voice 文案直接读取 Rubric YAML 模板字串(alert_message / confirm_message),不经过语言模型,保证延迟 <100ms。Qwen3-1.7B 仅在练习结束后的 Instant Recap 环节按需加载,用完即释放内存。
峰值内存占用 ~2.2 GB(两模型同时在内存中的短暂窗口),iPhone 13+ (6GB) 可承载。
关键设计原则
- Rubric 即平台 — 换一份 YAML 即换整套陪练逻辑(信号、阶段、提醒文案),架构不变。同一个 Runtime 支持 CPR/BLS、OSCE、化学实验等任意场景。
- 承认不确定是产品哲学 — 低置信时教练主动说「不太确定」,UI 标记「待考官确认」,不隐藏短板也不假装全知。用户信任建立在诚实之上。
- events.jsonl 是端云之间的唯一契约 — 端侧教练不需要知道云端考官用什么模型评分;教师端通过同一份事件流审阅学生表现。
- 阶段感知 Perception Planner 是一等公民 — 不是实现细节,而是产品差异化:「我现在在帮你检查准备环节」
- 正负事实流 — 不只记违规,也记正向确认,让云端减少误判、让端侧能正向激励
- 置信度分层 UX — 把技术限制(检测不准)变成产品设计(提醒光谱),配合诚实哲学形成完整体验
- Camera Quality Gate 独立价值 — 把视角问题从 ML 难题变成 onboarding 体验;纯 Swift + 轻量 CV,可独立演示
- 视频永远不上云 — 隐私架构的核心卖点
- 专家评分是可选增值 — 端侧教练永远免费可用(Instant Recap 规则聚合),云端考官(Examiner CCAE)是用户主动选择的深度服务