Skip to content

Phase 0 公开边界

本页描述的是待实现的产品与架构设计。除非对应 Spike 明确标为“已完成”,性能数字均为设计目标或验收阈值,不是实测结果;当前也没有上线产品、真实用户或效果指标。

Edge Runtime 架构(iOS 端) ​

PracticeMate 的核心感知与教练循环运行在用户设备上,保证离线可用、低延迟反馈。


核心角色 ​

Edge Runtime 负责三件事:

  1. 实时感知:摄像头画面 → VL 模型推理 → 结构化信号
  2. 教练反馈:rubric 模板文案驱动的即时语音提示
  3. 会话管理:阶段切换、仪式层、即时复盘

所有推理在设备端完成,不依赖网络。


模型配置 ​

模型用途大小加载策略
Qwen3-VL-4B-Instruct-MNN视觉关键帧感知(唯一常驻模型)模型文件不进 Git,运行时从 Application Support 读取会话开始时加载,全程常驻
Qwen3-1.7B按需加载(Recap 润色)~1.0 GB仅在 Instant Recap 需要自然语言润色时按需加载,否则不加载

单模型优先原则(TD-012/024):视觉检测循环只加载固定 revision 的 taobao-mnn/Qwen3-VL-4B-Instruct-MNN。Coach Voice 的文案来自 Rubric YAML 的模板字符串(alert_message / confirm_message),不经过 LLM 生成。Qwen3-1.7B 仅在用户结束练习后、需要对 Instant Recap 做自然语言润色时才按需加载;如果设备内存不足或模型不可用,Recap 退回规则聚合。


MNN 集成 ​

使用固定版本 MNN 3.6.0 做端侧推理:

  • 量化:INT4 量化,平衡精度与内存占用
  • 线程:Swift actor 串行管理模型加载和推理,调用方异步等待,不阻塞主线程
  • 帧采样:不逐帧推理,按 rubric 定义的 detection_interval(通常 2-5 秒)采样关键帧
  • 模型位置:从 Application Support/Models/Qwen3-VL-4B-Instruct-MNN 读取,framework、模型权重和本机路径均不进入 Git
  • mmap profile:显式使用 4096 MB;缓存 namespace 绑定 backend、模型 revision 与 mmap 大小,防止不同候选共用旧缓存
  • 输出门:模型只产生 observation;严格 JSON、signal 白名单和枚举值校验通过后才能构造 PracticeEvent
  • 后端状态:arm64 Simulator CPU 垂直切片已通过;4B Simulator Metal 输出乱码并 fail closed,未通过;真机未测试

Camera Quality Gate(摄像头质量门控) ​

把 ML 难题变成 onboarding 体验。

Camera Quality Gate 是独立可交付价值——即使 VL-4B spike 失败,CQG 仍然完整可用。它使用 Swift + 轻量级 CV(亮度/角度/遮挡检测),不依赖 VL 模型。

检测项 ​

检测项方法阈值
亮度CIAreaAverage 取平均亮度> 0.3(0-1 归一化)
角度VNDetectHumanBodyPoseRequest 关键点对称性偏转 < 15°
遮挡关键点可见性置信度核心关键点 > 0.6
距离人体边界框占画面比例20%-80% 画面高度

流程 ​

摄像头预览 → [亮度检测] → [角度检测] → [遮挡检测] → [距离检测]
                ↓ 任一不通过
          语音引导 + 视觉提示("请往后退一步")
                ↓ 全部通过
          ✅ 进入练习仪式层

CQG 独立可演示:打开 App → 对准摄像头 → 实时看到检测反馈 → 调整到合格。这本身就是一个有价值的 onboarding 体验。


感知栈三层分离(Perception Stack)(TD-015) ​

端侧感知不是"一个模型做所有事",而是三个独立层级,各自有不同的技术栈和延迟特征:

层级技术栈延迟用途降级行为
L0 Camera Quality GateSwift + Core Image / Vision< 30ms亮度/角度/遮挡/距离始终可用
L1 Specialized CVSwift Vision + 轻量规则< 50ms高频姿态信号(双手位置/按压姿态检测)L2 不可用时兜底
L2 VL ModelQwen3-VL-4B-Instruct-MNN + MNN 3.6.04096 MB mmap;2–5s 关键帧调度;真机延迟待测首切片仅判断 hand_position_correct不可用或输出非法时记为 unknown

层级协作流程 ​

摄像头帧
    │
    ▼
L0: Camera Quality Gate(始终运行)
    │ 画面合格
    ▼
L1: Specialized CV(高频姿态信号)
    │ 双手位置/按压姿态等 < 50ms 快速检测
    │ 如果 L2 不可用,L1 结果直接写入 events.jsonl
    ▼
L2: VL Model(语义理解信号)
    │ 按 detection_interval 采样(2-5s)
    │ 仅处理 L1 无法覆盖的信号
    ▼
events.jsonl

每个 edge_signal 在 rubric YAML 中标注 perception_level: L0 | L1 | L2,Perception Planner 据此决定用哪层处理。


练习仪式层 ​

仪式层为练习提供心理节奏感,让用户从"打开 App"过渡到"进入专注状态"。

进入仪式(Camera Quality Gate 通过后) ​

  • 3 秒聚焦提示:haptic 震动 + Coach Voice 播报 rubric.ritual.focus_prompt(如"深呼吸,准备进入急救状态")
  • 倒计时动画(3-2-1),结束后正式开始第一阶段
  • 目的:给用户一个明确的"开始"信号,区分准备和练习

阶段过渡仪式 ​

  • 每次阶段切换时:haptic 震动 + Coach Voice 播报当前阶段的 rubric.phases[].transition_feedback
  • 短暂过渡动画(0.5 秒),让用户意识到阶段已切换
  • 见下方"混合阶段切换"详细流程

结束仪式 ​

  • 练习结束时:Instant Recap 优先展示亮点(rubric.ritual.recap_priority = highlights_first)
  • 先正向反馈,再改进建议,保持积极收尾

Coach Persona 参数化(TD-019) ​

Coach Voice 的"人格"不再硬编码,而是由 rubric YAML 中的 coach_persona 配置驱动:

参数范围说明默认值
warmth0.0–1.0语气温暖程度0.8
interruptiveness0.0–1.0打断频率0.5
praise_frequency0.0–1.0正向反馈频率0.7

Persona 路由逻辑 ​

信号产出 → 查 coach_persona 参数
    │
    ├─ interruptiveness < 阈值 → 静默记录(不播报)
    ├─ praise_frequency < 阈值 → 跳过正向确认播报
    └─ warmth 影响模板选择 → 高 warmth 选鼓励性模板,低 warmth 选事实性模板

Ritual 成熟度(TD-019) ​

仪式层根据 maturity_level 自动调整深度:

级别专注引导Coach 语音操作提示
first_time3 秒完整引导高频(每个信号)显示
daily1 秒精简中频(仅 high/medium)隐藏
exam无静默(纯记录)隐藏

混合阶段切换(三路并行)(TD-013) ​

阶段切换支持三条路径并行,确保不论 AI 检测是否准确,用户始终能顺畅推进练习。

三条路径 ​

路径 A — AI 自动检测(主路径)

  • VL-4B 从画面中检测到 rubric 定义的 transition_trigger 条件
  • 自动触发阶段切换 + haptic 震动 + Coach Voice 播报 transition_feedback
  • transition_source: ai_detected

路径 B — 用户手动推进(常驻兜底)

  • 屏幕上始终显示大号"进入下一阶段"按钮
  • 用户随时可以点击手动推进,不需要等 AI 判断
  • transition_source: user_manual

路径 C — 超时提醒(时间兜底)

  • 如果当前阶段已超过 rubric 定义的 estimated_minutes
  • Coach Voice 播报 rubric 中的 timeout_prompt(如"这个阶段已经练习了 5 分钟,要继续还是进入下一步?")
  • 用户确认后切换,或选择继续当前阶段
  • transition_source: timeout

流程图 ​

┌─────────────────────────────────────────────────────┐
│                 当前阶段进行中                        │
│                                                     │
│  ┌──────────┐  ┌──────────────┐  ┌──────────────┐   │
│  │ 路径 A   │  │   路径 B     │  │   路径 C     │   │
│  │ AI 检测  │  │  手动按钮    │  │  超时提醒    │   │
│  │ trigger  │  │  用户点击    │  │  estimated   │   │
│  │ 命中     │  │ "下一阶段"   │  │  _minutes    │   │
│  └────┬─────┘  └──────┬───────┘  └──────┬───────┘   │
│       │               │                │            │
│       └───────────────┼────────────────┘            │
│                       ▼                             │
│            phase_transition 事件                     │
│         { phase_id, transition_source }             │
│                       │                             │
│                       ▼                             │
│         haptic + transition_feedback 语音            │
│                       │                             │
│                       ▼                             │
│              进入下一阶段                            │
└─────────────────────────────────────────────────────┘

phase_transition 事件统一包含 transition_source 字段(ai_detected / user_manual / timeout),用于后续数据分析和 rubric 优化。


Perception → Planner 循环 ​

首个视觉垂直切片只运行 Qwen3-VL-4B-Instruct-MNN:

摄像头帧(按 detection_interval 采样)
    │
    ▼
Qwen3-VL-4B-Instruct-MNN 推理
    │
    ▼
严格输出:{ signal: "hand_position_correct", observation: "yes|no|unknown" }
    │
    ├─ schema 与白名单通过 → 构造 PracticeEvent
    └─ JSON 非法 / signal 越界 / 图片缺失 / 输出含糊 → unknown
                              │
                              ▼
                 confidence=0, alert_tier=low
                              │
                              ▼
                     待考官确认,不强提醒

Coach Voice 文案流程:

  1. VL-4B 输出白名单 observation,而不是 assertion 或校准概率
  2. 解析器通过后构造低等级 PracticeEvent
  3. ConfidenceRouter 将其送入待考官确认;首切片不直接播报医疗强提醒

Spike-002 的 Simulator 多图预验证进一步表明,严格 JSON 并不等于语义可靠:20 张公开 CPR 训练照片虽有 20/20 合法 JSON,但输出集中为 17 个 yes,且讲师只做手势、没有手接触胸部的画面仍被判断为 yes。增加生成模型自报 visibility 或拆成 visibility-only 第一问都没有形成区分度。因此 hand_position_correct 当前不是已启用的产品检测信号,只保留软件垂直切片和考官确认边界;不接 Live UI、自动阶段推进或强提醒。

生成式模型自报的 confidence 不是校准概率,不能直接套用下面面向已校准事件的置信分层。只有后续完成标注集、校准和医疗安全门后,才可提升路由等级。


置信度分层 UX(诚实哲学 TD-011) ​

这是信任设计,不是技术妥协。用户值得知道 AI 什么时候确定、什么时候不确定。

置信度UI 表现Coach Voice 示例设计意图
≥ 0.8(高)实时标注 + 即时语音反馈"注意保持眼神交流"(rubric alert_message)确信时果断提醒
0.5-0.8(中)静默记录,Recap 中以 △ 标记(不触发实时语音)不确定时不干扰练习
< 0.5(低)静默记录 + "待考官确认"徽章"这里我不太确定,先记下来,练完再看"坦诚不确定,邀请人工复核

设计哲学:与其假装全知全能然后翻车,不如坦诚告诉用户"这个我拿不准"。低置信度检测标记为"待考官确认",既保留了信息,又不会误导用户。这种诚实反而建立信任——用户知道当 AI 说"确定"的时候,是真的确定。


会话结束:教练即时复盘(Instant Recap) ​

Instant Recap 采用规则聚合生成,不依赖 LLM,确保飞行模式下 100% 可用。

生成流程 ​

会话事件流
    │
    ▼
按阶段分组聚合
    │
    ├─ signal_confirmed 事件 → 计数 ✓
    ├─ medium_confidence 事件 → 计数 △
    └─ low_confidence / violation 事件 → 计数 ✗
    │
    ▼
按 rubric.ritual.recap_priority 排序
    │
    ├─ highlights_first: 先展示 ✓(positive_notes),再展示改进建议
    │
    ▼
生成 per-phase 摘要

输出格式示例 ​

📋 练习复盘

阶段 1:开场白(2分30秒)
  ✓ 眼神交流保持良好(8/10 次检测确认)
  △ 手势幅度待确认(3 次中置信度)
  ✗ 语速偏快(2 次检测到)

阶段 2:主体论述(5分10秒)
  ✓ 站姿稳定(全程确认)
  ✓ 与听众互动自然
  △ 有 1 处停顿较长(待考官确认)

总体:✓ 12 项确认 | △ 4 项待确认 | ✗ 2 项需改进

可选:自然语言润色 ​

如果设备内存允许(6GB+)且用户未处于飞行模式,可按需加载 Qwen3-1.7B 对规则聚合结果做自然语言润色:

  • 将结构化摘要转化为更自然的教练语气段落
  • 添加鼓励性开头和具体改进建议
  • 这是锦上添花,不是必需品——规则聚合版本已经完整可用

如果 Qwen3-1.7B 不可用,用户看到的就是规则聚合版本,无降级感知。


Uncertainty Ledger(不确定性账本)(TD-017) ​

Instant Recap 底部新增"不确定项"折叠区,将散落在 events.jsonl 中的低置信事件产品化为一个清晰的列表。

展示逻辑 ​

events.jsonl 中 alert_tier == "low" 的事件
    │
    ▼
按时间排序,提取:时间戳 + 信号描述 + 教练备注
    │
    ▼
Instant Recap 底部折叠区:
    "不确定项(3 项)"
    ├─ 0:42 天平可能未归零 — "这个角度我看不清"
    ├─ 1:15 滴速可能偏快 — "不太确定,先记下来"
    └─ 2:30 废液处理待确认 — "这里需要考官看一下"
    │
    [一键请考官裁定] ← 选中项随 events.jsonl 上传

Uncertainty Ledger 不是"隐藏不确定",而是"展示诚实"——这是 PracticeMate 与竞品的核心差异化。


电源管理 ​

策略实现
帧采样而非逐帧按 detection_interval 采样,通常 2-5 秒/帧
推理间歇休眠非采样期间 MNN 线程挂起
屏幕亮度练习中自动降低非关键区域亮度
热管理监控 ProcessInfo.thermalState,过热时拉长采样间隔

目标:30 分钟练习消耗 < 15% 电量(iPhone 13 基准)。


内存管理 ​

当前没有真机 Instruments 峰值收据,不能再用估算表宣称具体设备“无压力”。4B Simulator CPU 连续 10 次只记录到完成时 physical footprint 从 256,022,024 B 到 260,675,128 B,区间最大 263,624,248 B;这不是峰值。4B Simulator Metal 单次完成时采样为 2,730,040,544 B 且输出乱码,因此不能作为可用后端。

真机恢复测试后必须分别记录冷启动峰值、10 次循环后的驻留变化、memory warning、jetsam 和热状态;任一失败都保持 Live UI 关闭。


降级策略 ​

故障场景降级行为用户感知
VL-4B 推理超时(> 5s)跳过当前帧,下一采样点重试当前 observation 记为 unknown
输出非法、越界或含糊fail closed 为 unknown,固定走 low tier待考官确认,不触发强提醒
Metal 输出异常回退到已验证的 CPU 后端;仍保留原始错误收据反馈频率可能降低
VL-4B 加载失败仅运行 Camera Quality Gate + 手动阶段切换 + 计时器提示"AI 教练暂不可用,手动模式练习"
L1 CV 检测降级L2 不可用时,L1 独立覆盖安全类信号安全检测可用,语义类信号暂停
Qwen3-1.7B 不可用Instant Recap 用规则聚合(默认行为)无降级感知——规则聚合就是默认输出
热节流拉长 detection_interval(如 2s → 5s)反馈频率略降,但不中断
内存压力释放非关键缓存;极端情况暂停推理提示"内存不足,暂停 AI 检测"
摄像头被遮挡暂停检测 + 语音提示"摄像头被遮挡了"明确提示

核心原则:VL-4B 是唯一关键模型。Qwen3-1.7B 不可用 = 默认行为(规则聚合),不算降级。Camera Quality Gate 独立于模型,始终可用。


Spike 验证计划 ​

Spike验证目标成功标准
S-1: CQG 独立演示Swift + Vision 框架实现四项检测亮度/角度/遮挡/距离实时反馈,无模型依赖
S-2: MNN + VL-4B 端侧推理Qwen3-VL-4B-Instruct-MNN 在目标 iPhone 上推理p95 ≤ 5s、无 jetsam、峰值内存可接受;当前仅 Simulator CPU 通过软件门
S-3: 结构化输出解析VL-4B observation → 严格 JSON → 白名单 signal固定输入 10 次合法率 100%;任意非法输出 fail closed
S-4: Coach Voice 模板播报rubric 模板文案 → AVSpeechSynthesizer延迟 < 200ms(信号到语音开始)
S-5: 阶段切换三路并行AI 检测 + 手动按钮 + 超时提醒三路均能触发 phase_transition 事件
S-6: Instant Recap 规则聚合事件流 → 按阶段分组 → 格式化输出飞行模式下完整生成,< 500ms
S-7: Qwen3-1.7B 按需加载会话结束时加载 → 润色 → 卸载加载 < 5s,润色 < 3s,卸载释放内存
Jason Xun judges & accepts · AI assists