编辑 | blame | 历史 | 原始文档

Roadmap(Current Architecture V5 + Capability Spec v1.0)

Date: 2026-09-18
评估与排序修订: phase-4-eval-and-roadmap.md(对照 Phase 1–4 代码缺口 + 家长端提前)。
输入(历史):phase-1-review.md · phase-2-review.md · phase-3-review.md · Capability Spec v1.0
粒度:架构与项目管理。不是 Coding Plan。
Phase 4 已实施(设备播放列表 + 后评估)。**下一编码阶段:Phase 7a 家长任务下发**(施工单 phase-7a-plan.md)。先 Dispatch,再 History;**不做计量 UI**。
语言包 / 离线词表仍见 Phase 6 / 6b / 7b。7a 双语场景只存并传递 language_pair,不换 MultiNet。
产品代际 / 多硬件版本(原 Phase V)改到最后:现网只有一款色宁设备,不挡演示。

原则:每完成一个 Phase → Completion Review → Architecture 更新 → Roadmap Review → 下一份 Phase Plan。
禁止把本文当成锁死到 Phase 9 的施工图。后面 Phase 只保证目标、边界与 对应的 Spec 能力 ID。



0. 冻结之后怎么切 Phase

Capability Spec 把系统分成三层:

Application        以后才无限扩展(教育 / 益智 / 陪伴 / 助手)
Task Runtime       尽快稳定,权威在 Server
Device Capability  语义已冻结:播 / 听 / VAD / speak 出声 / wait / loop / 指示 / 抢占

因此路线图不再按「再做 10 个 App」排列,而按:

1. 把已声明、固件尚未具备的原子能力补齐(只允许因此 OTA)
2. 把 Task Runtime 做成可归档、可查询
3. 把评估 / 调度 / 资源放到 Server
4. 用倒背 / 口算 / 接龙反证:新 App 零固件增量

原 V1.1「Phase 2 = type=task + Java 表 + 跟读 + 评分」仍然拆开。Spec 额外要求:

  • 运输可变(MCP / MQTT / detect 前缀),**语义集合不再为新 App 加命令种类**
  • loop(同一音频 N 次)在设备;branch(答对了吗) 只在 Server,且 仅 Task 声明为流内评估时才走进业务(倒背/接龙);跟读默认不走
  • 离线只保证可离线 Skill(播放);翻译/评估/接龙必须在线
  • 评估时机是 Task 属性(后评估 vs 流内),不是新传感器
  • 离线只保证可离线 Skill(播放);翻译/评估/接龙必须在线
  • SD 放资源;apps.json 不是离线业务引擎
  • record_clip v1 = 听流 + Server 归档;本地 WAV 上传是 v1.1
编号 一句话 Spec 主要验证 / 交付
Phase 1 薄 App Runtime 已完成:D15 设备 loop、D4 Mode 策略雏形、翻译走 Server
Freeze Capability Spec v1.0 文档冻结;不编码
Phase 2 用复读+跟读钉死事件与采集 已完成(见 phase-2-review.md):D1、D6、D7 v1、D8 v1 文本;另提前 D13 目录 /{app}/{task}/lessons
Phase 3 TaskInstance 持久化 已完成(见 phase-3-review.md):三表 + PUT/GET;GET 现为 server secret
Phase 4 跟读:清单循环 + 后评估 已完成(见 phase-4-eval-and-roadmap.md):设备本地播→听→下一句;metrics 不指挥喇叭
Phase 7a 家长任务下发 + 执行记录 下一编码:场景+参数;立即 vs 计划;本地全表、RTC 只写下一次。泛听≠跟读。History 后做、无 metrics
Phase 5 Server Scheduler 补救扫描 权威表已并入 7a-B;本阶段剩「设备已开机、云端到点再推一把」
Phase 6 App / 资源 + 在线 Locale D13 fetch;phrase pack;翻译/双语的 language_pair
Phase 4b 倒背 / 口算 / 接龙 流内评估 + 及时 speak;排在家长能看见跟读之后
Phase 6b 离线 Locale(可选 OTA) MultiNet/唤醒词表按 locale;**仅 ESP-SR 已有模型的语种(先 zh/en)**
Phase 7b 家长完整能力 语言对、PAUSE、长按退出、听原声完善
Phase 8 开发者 App 平台 Manifest 只能调已冻结 Skill
Phase 9 Subscription / Marketplace 账号,不改音频
Phase V 产品代际 + 端云兼容 最后做。 小智 AI 1 / 1-1 / 2;就这一款硬件时不开工

1. Phase 依赖图

Phase 1 薄 App Runtime                    ✅
    ↓
Capability Spec v1.0                      ✅ 文档
    ↓
Phase 2 钉死 D1 事件 + D6/D7/D8v1 采集    ✅
    ↓
Phase 3 TaskInstance 持久化               ✅
    ↓
Phase 4 跟读清单循环 + 后评估             ✅  设备执行列表;Server 只评估
    ↓
Phase 7a 家长任务下发                     ← 下一编码
    │  7a-A 固件:计划全表 + RTC 只写最近一次;开机到点也执行
    │  7a-B 云端任务表 + 场景 catalog + SYNC_SCHEDULE / 立即 START
    │  7a-C 小程序:场景参数 + 立即 / 周期
    │  7a-D 历史(文本+可选录音;无 metrics)
    ├─────────────┐
    ↓             ↓
Phase 5 到点补推  Phase 6 资源 + 在线 Locale
    │
    ↓
Phase 4b 倒背/口算/接龙(inline;禁止改跟读后评估模型)
    ↓
Phase 6b 离线 Locale(zh/en)
Phase 7b 家长完整(语言对 / PAUSE / 听原声)
    ↓
Phase 8 开发者平台
    ↓
Phase 9 订阅
    ↓
Phase V 代际/兼容                         最后;第二款硬件或摄像头 SKU 前才必须

必须串行: 1 → Freeze → 2 → 3 → 4 → 7a-A 固件(全表+下一次闹钟) → 7a-B 云端 → 7a-C 小程序。7a-D 历史不挡宣称 Dispatch Done。
7a 不依赖 4b / 6 / V。SD 已有 unit01 即可选课。家长任务数量 不是 10;ALARM_MAX_NUM 不准当上限。语言对可存 params,phrase pack 仍 Phase 6。
Phase 4b 依赖 4 的听窗/Instance,也依赖家长能看见结果(否则新 App 同样「只有喇叭」)。禁止为此改 C++。评估时机见下文「评估时机」表。
Phase V 不挡 7a / 4b / 5。 现网一款硬件;摄像头立项前再做握手字段。

Phase 6: 目录树与 ensure_app 已在 Phase 2 提前落地。本阶段做清单 / DOWNLOAD / resource_id,并做 在线 Locale。不要重做 mkdir。

Phase 6b: 仅当需要「没网也用德语/英语喊切换」时才 OTA 离线词表。德语等 没有 官方 MultiNet 的语种,离线入口保持 zh 或 en。

明确后置、不挡冻结宣称:

Spec 能力 最早 Phase
D11 wait 一等 Skill 4b 前可仍用 Server 延时;需要「播完停 800ms 再听」且不想云端睡时再下固件
D14 TASK_PAUSE/RESUME 5 或 7b 家长控制需要时
D8 v1.1 本地文件上传 会议纪要 / 律师询问产品化时;7a 不依赖
D9 长按退出 Task 可与口令退出并存;正式绑定放 7b
D10 indicate 逻辑态 有空再做;禁止塞进 DeviceState 迁移表
新 WS type=command 仅当 detect 前缀不够表达步进;**不加新语义**
在线 Locale / 语言对 Phase 6(phrase pack + pair);控制台 Phase 7b
摄像头 / 新传感器 Skill Phase V 之后;新 SKU = 小智 AI 2,禁止混进 1 的固件包
产品代际 hello 字段 Phase V,最后做;现网一款硬件不挡 7a

2. 各 Phase(Roadmap 级)

Phase 2 — 冻结面验证:采集 + 完成事件 ✅

  1. Objective
    不是做一个新 App。用 已有 复读机 + 跟读 Demo,把 Spec 里尚未落地的三块钉进 Runtime:
    audio.completed/stopped(D1)、非 Chat 的 listen/句边界(D6/D7)、跟读归档 v1(D8)。
    完成事实: 见 phase-2-review.md。跟读改为 SD 一句一 MP3;订阅 App 可 mkdir 不烧录。

  2. Why Now
    Spec §20:这三项不补齐就不能宣称 Device 已冻结。跟读 Mode 已在线,继续堆倒背/口算只会在没有事件的底座上复制 Demo。

  3. Dependencies
    Phase 1 执行器、SHADOWING/PLAY_AUDIO 分流、Opus 听流、report、设备 repeat loop(D15,本阶段 不改)。

  4. Scope
    逻辑事件(运输:[skill_event],对应 Spec AUDIO_COMPLETED/STOPPED);TaskSession 文件;跟读 turn = prompt + asr + 可选 WAV;pytest。Mode 名代码里可仍叫 SHADOWING,文档对齐 Spec FOLLOW_READ。

  5. Out of Scope
    评分(S4)、Java 表、type=task、倒背/口算/接龙产品、SD 范读必修、wait Skill、TASK_PAUSE、record_clip 本地文件、apps.json 下发、新 DeviceState、MultiNet 加业务口令。

  6. Client
    复读结束上报完成/停止事件;不改 Opus;不把跟读句子表写进固件。

  7. Server
    Session + 跟读记轮次 + 吃事件后回 chat;ASR/LLM/翻译仍在 Server。

  8. Protocol
    不增加命令种类。 只把已声明的 Event 用现有 listen/detect 文本运过去。语义见 Spec §4–5。

  9. Database
    无新表。归档走现有 ai_agent_chat_audio(D8 v1)。

  10. API
    无新 REST。

  11. Data Flow
    见 phase-2-plan.md。跟读下一步由 Server 步进(D16),不是设备 loop。

  12. State Machine
    DeviceState 不动。InteractionMode:PLAY_AUDIO / SHADOWING(FOLLOW_READ) / 回 CHAT。

  13. Acceptance Criteria
    Spec §22 四条纪律 + 本文 Phase 2 验收:完成事件单次回聊、跟读 JSON 轮次完整、Chat/离线复读/翻译不回归。

  14. Risks
    回声当跟读;事件与 [app_task]chat 双招呼。

  15. Regression Risks
    复读双播、离线「切换模式」连云、Chat barge_in。

详细施工:phase-2-plan.md。


Phase 3 — TaskInstance Persistence ✅

  1. Objective
    中层 Task Runtime 可查询:Session JSON → ai_task_instance / ai_task_step / ai_task_event。不新增 Device Capability。
    完成事实: 见 phase-3-review.md。GET 走 server secret(非计划中的 oauth2)。未建空 score 列。跟读 prompt_text 仍是 SD 路径。

  2. Why Now
    Phase 2 字段已稳定,建表不会空。评估和调度需要主键。

  3. Dependencies
    Phase 2 TaskSession schema;D8 v1 report 管道。固件保持 Phase 2 bin。

  4. Scope
    manager-api 最小 DDL;TaskSession.save() upsert;只读 GET。Agent ≠ App。JSON 文件双写保留。

  5. Out of Scope
    评分算法、对象存储、家长 UI、新 WS type、设备缓存 instance_id、改 SD 布局。

6–10.
Client 零改动。Server Python 上报 + Java CRUD。协议不加新命令种类。音频挂 step 尽力而为。

  1. Acceptance
    一次跟读可在 API 查到 steps + 文本 + 可选 audio_id;manage_api 挂了语音仍可用。

14–15.
与 chat_history 双写但表分开;旧固件无 instance_id 必须兼容(id 只在云端)。

详细施工:phase-3-plan.md。验收:phase-3-test.md。


Phase 4 — 跟读:清单循环 + 后评估(定量) ✅

  1. Objective
    仅跟读这一类:预定 MP3 序列 + 定时录音。分析全部后置、定量、允许失败。设备不宣读对错。
    完成事实: 见 phase-4-eval-and-roadmap.md。步进在**设备播放列表**(一次 JSON 下发),不是逐句 MCP;后评估仍在 Server。

  2. Why Now
    跟读/打卡录音的价值在归档与事后看指标。若把云端比对绑在句间,喇叭会卡。

  3. Dependencies
    Phase 3 Instance;Phase 2 duration_ms 听窗。原文来自 txt 契约,**不能**用 prompt_text 路径。

  4. Scope(已落地)
    设备:listen_ratio × 墙钟播放时长;清单结束 playlist_completed。
    Server:ASR 不进 LLM;metrics[{method,value}];本地 wav + 同名 txt。无 passed、无当场 TTS 分数。

  5. Out of Scope
    倒背/接龙的及时反馈(4b);家长 UI(**7a**);S8 再播同一句;音素;租户。

  6. Client
    有 diff(播放列表 / 听窗)。禁止再改回「每句 MCP」。

  7. Acceptance
    说错/不说/API 挂了仍播下一句。语音回归已按锁定路径验收。

详细施工(历史):phase-4-plan.md(其中「固件零 diff / Server 时钟」已被代码修正,以评估报告为准)。


Phase 7a — 家长任务下发 + 执行记录 ← 下一编码

产品:选场景填参数;可立即执行(临时,最高优先)或存为周期计划。设备存全表,RTC 只写最近一次。先下发,后看记录;无计量 UI。对外 泛听(旧称复读机)/ 跟读。
详细见 phase-4-eval-and-roadmap.md §5.2。施工单:phase-7a-plan.md。

  1. Objective
    家长按场景创建任务(泛听/跟读:课文、遍数、结束后关机或回对话;双语:中英/中法/中日…;对话可带时长)。立即下发马上跑;计划任务到点跑。软关机后从本地表挑下一最近时刻写入唯一硬件闹钟。History:跟读句文本+录音;对话类聊天。不展示相似度。

  2. Why Now
    把计划 1:1 塞进 ALARM_MAX_NUM=10 撑不住「每小时整点聊 10 分钟」这类周期。DS3231 本来就只编程下一次。现网唯一 pending 会被覆盖;已开机到点不执行;课文写死。

  3. Dependencies
    Phase 1 START_APP_TASK / 软关机 / Alarm1;Phase 3 Instance;Phase 4 播放列表。不依赖 4b/6/V。

  4. Scope
    7a-A 本地 schedule 全表 + recompute_next_alarm;7a-B ai_parent_task + SYNC_SCHEDULE + 立即 START;7a-C 场景表单;7a-D 历史。

  5. Out of Scope
    metrics;课文 DOWNLOAD;倒背口算;新 WS type;改锁定热路径;用 10 限制条数。

  6. Device
    允许 OTA:计划文件、只写 Alarm1、duration 墙钟、on_complete。禁止新 DeviceState。课文不进固件。

  7. Acceptance(Dispatch)
    立即跟读可打断计划;≥15 条计划含 hourly 全量在设备、芯片只有最近一次;软关机唤醒进正确场景;结束后重算下一闹钟。History 不挡 Dispatch Done。


Phase V — 产品代际 + 端云版本匹配 (最后做)

2026-09-18: 现网只有一款硬件。本阶段 不挡 7a / 5 / 4b。摄像头 SKU 或第二款板子立项前再开工。
现状结论(2026-09-02 核对代码,仍成立):**没有「小智 AI 1 / 1-1 / 2」代际,也没有兼容矩阵。**
施工单以后写 phase-v-plan.md。

  1. Objective
    把三套独立的编号钉死,并在连接时对上:
    产品代际(小智 AI 1 / 1-1 / 2)≠ 固件 semver(OTA 包)≠ 协议/能力集(Server 决定开哪些业务)。
    Server 对过旧设备降级或引导 OTA;对过新设备拒绝未知能力,而不是 silently 当聊天。

  2. Why Now
    不加摄像头也可以出 1-1(跟读/Task Runtime 已是大功能面)。不加代际字段,OTA 只能按板型比 2.2.6 vs 1.0.0 两个对不上的数字,Server 无法判断「这台有没有相机 MCP、能不能跑 cap.v1.1 的跟读听窗」。

  3. Dependencies
    现网已有:OTA 上报 application.version + board.type;WS hello version(帧格式 1/2/3)+ features.mcp|aec;MQTT snlp/v1 + header "1.0";manager-api Liquibase 日期 changeset。
    不依赖 Phase 4 完成。摄像头硬件不在本阶段。

  4. 编号模型(冻结语义,实现可后写)

product.generation     1 / 2 / 3        硬件族。1=现网音箱;2=加摄像头(或其它新传感器)
product.revision       0 / 1 / 2        同代硬件上的软件大改。对外:小智 AI 1、小智 AI 1-1、小智 AI 2
firmware.semver        1.4.2            每一次可 OTA 的 bin;只升这个数字去升包
capability.set         cap.v1 / v1.1    与 Spec 修订对齐(播/听/跟读听窗/…);新 App 不加 cap 号
protocol.ws            1                已有 hello.version,只为二进制帧;禁止拿它当产品代际
protocol.mqtt          snlp/v1          topic 大改才升 v2;header.version 只升破坏性字段
server.release         2026.09.x 或 semver    xiaozhi-server + manager-api 同发
api.rest               /xiaozhi/v1/     破坏性 REST 才 /v2/;旧路径保留到兼容窗结束

对外称呼:

对外 generation revision 含义
小智 AI 1 1 0 现网:无摄像头,当前能力面
小智 AI 1-1 1 1 同一块硬件,能力集或业务面大改(例如 Task Runtime 成为默认)
小智 AI 2 2 0 新硬件(摄像头等);固件包与 1.x 分轨,禁止烧到对方板上
  1. 现状缺口(对照代码,不要假装已有)
层 现在有什么 缺什么
终端产品号 system.h 里 APP_FIRMWARE_VERSION "1.0.0" 几乎不 bump;CMake PROJECT_VER "2.2.6" 是上游仓库号;User-Agent 是 BOARD_NAME/esp_app.version 没有 product.generation/revision;1 和 1-1 无法区分
WS 握手 hello:version=1 + features.{mcp,aec} + 音频参数 不报固件、不报代际、不报 cap_set;Server 不拒不匹配
OTA 按 板型 比 semver,新则给下载 URL 不按产品代际分轨;不检查 Server 最低 cap;1.0.0 vs 2.2.6 两套数字并存
MQTT snlp topic v1、header "1.0" 写死 无协商;无能力位
Server config.yaml xiaozhi.version: 1;manager-api 靠日期 SQL 无 server.release;REST 无兼容窗;无「此 Server 支持的 generation 范围」
业务匹配 MCP 工具列表运行时发现 没有「这台 gen1 永远不要 vision」的矩阵;新 API 默认所有旧设备都能打
  1. Scope
  • 设备 OTA JSON + WS hello 增补(不改旧字段含义):product_generation、product_revision、firmware、capability_set。
  • Server 维护一张 compat 矩阵(哪一档 Server 接受哪一档设备;过旧 → 只开旧业务或下发 OTA;过新/未知 cap → 拒绝或忽略未知 MCP)。
  • manager-api:固件包绑定 (board_type, generation),禁止 gen2 包推给 gen1。
  • REST:现有 /task/instance 视为 v1;破坏性变更走新路径或带 Accept-Version,旧客户端有兼容窗。
  • 文档:一张表写清「小智 AI 1 最低 Server」「Server x 最低固件」。
  1. Out of Scope
    摄像头驱动、vision MCP 实现、把 cap_set 当 App 商店、为每个 App 升 generation、把 hello.version 改成 2 来表示 1-1。

  2. Protocol
    只加字段,不加新 WS type。 旧固件不带这些字段时:Server 视为 小智 AI 1 / revision 0 / cap.v1,保持现网能连。
    匹配发生在 hello 与 OTA check,不在每句 ASR。

  3. Client / Server 匹配规则(产品语义)

连接时
  Device  →  generation + revision + firmware + cap_set
  Server  →  查矩阵:
      未知 generation          → 拒绝或只开 CHAT
      cap_set < server.min     → 引导 OTA;OTA 前只跑 cap 交集(例如没有跟读听窗就当 PLAY_AUDIO)
      cap_set > server.max     → Server 忽略未知能力,不崩溃
      generation=1 无 camera   → 永不下发 vision 工具
      generation=2             → 允许 vision;固件包与 1 分轨

同一硬件出 1-1:只升 product.revision + capability_set + firmware.semver,**不**升 generation。
新传感器:升 generation,新 board_type,新 OTA 目录。

  1. Acceptance
  • 现网未改字段的固件仍能连当前 Server(默认 1.0 / cap.v1)。
  • 控制台能看到设备是 1 还是 1-1,OTA 不会把 gen2 bin 推给 gen1。
  • hello 日志能打印两端的 generation / cap_set / 采用的交集。
  • 文档有兼容矩阵;破坏性 REST 有旧路径或明确截止日期。
  1. Risks
    把业务版本和协议版本混成一个数;1-1 误当成必须换机;Server 静默吞掉未知字段导致「以为支持摄像头」。

  2. Regression Risks
    hello 加字段导致旧 Server 解析失败(必须忽略未知键);OTA 板型字符串与 generation 不一致导致升错包。


评估时机(Task 声明,后续 4b 施工单再细化)

不是新 Device 能力。Manifest / Task JSON 标明 assessment.timing:

timing 听窗结束后 代表 实现阶段
deferred 立刻下一步;metrics 后台可晚到 跟读、故事复述、打卡录音 Phase 4
inline 先 Server 评估,**再** speak 反馈,然后下一题 倒背数字、成语接龙、口算 Phase 4b

共同点:判题只在 Server;设备只收到已有 speak / play_audio;固件无 if correct、无 JUDGE。
差别:跟读可以评估失败仍往下播;倒背若评估失败应 speak「没听清」之类再进入下一题,**不能**把反馈拖到家长事后打开 App 才算完成这一回合。

倒背示例(Server 编排,可后补进 4b-plan):

speak 数字,间隔 ~1s(Server 睡或以后 D11 wait)
speak「开始」
listen 固定时长
ASR + parser → metrics(对了几个、准确率)
speak 反馈(及时、可含定量,如「倒对了 4 个」)
下一题或结束

成语接龙:听完用户一句 → Server 判是否合法接龙 → 马上 speak 下一成语或纠错提示。同样是 inline。

口算:默认同 inline(对/错或报出正确答案属于业务流)。若某练习模式只要交卷后看报表,再在 Task JSON 改成 deferred。


Phase 4b — 冻结验收集(倒背 / 口算 / 接龙)· 流内评估

  1. Objective
    三个代表 Task 只加 Server Task / Parser / Prompt。其中倒背、接龙(及默认口算)必须是 inline:听窗结束就要评估并出声反馈,**禁止**做成跟读那样的后评估。

  2. Why Now
    跟读只覆盖「录完继续」。规则型/游戏型回合若不及时反馈,产品就不是那个 App。

  3. Dependencies
    Phase 4 的听窗、Instance、metrics 字段。另增:听窗结束 → await 短评估 → speak(仍不改固件)。

  4. Scope
    倒背:间隔出题 → 「开始」→ 录音窗 → 立刻报对了几个/准确率。
    接龙:用户说完 → 立刻合法性与下一提示。
    口算:默认同 inline。
    出题 TTS 语言 = device.locale(无则 zh)。Parser 仍产出定量 metrics[];反馈文案由 Server 生成后 speak,不是固件模板。

  5. Out of Scope
    新 Mode、新 DeviceState、MultiNet 业务词、新 WS、JUDGE 命令、难度引擎产品化、小程序、phrase pack、把跟读改回流内纠错。

  6. Client
    禁止改 C++。

  7. Acceptance
    倒背一轮:录音结束后 数秒内 设备说出评估结果,再出下一题或结束。断评估服务时有超时兜底 speak,不得死等。固件 git diff 为空。

施工单:以后写 phase-4b-plan.md(本文件只钉时机差异)。

Phase 5 — Server Scheduler(补救扫描)

  1. Objective
    权威任务表已在 7a-B ai_parent_task。本阶段补:设备已开机但本地闹钟漏触发时,云端按分钟再推 START_APP_TASK。RTC 仍只负责「下一次」唤醒。

  2. Why Now
    7a 完成后「每天准时」仍可能两边漏一刀;云扫描是对账,不是日历真相的第二份拷贝。

  3. Dependencies
    7a-B plan 表;Phase 1 START_APP_TASK。

  4. Scope
    到期扫描;同一 plan+同一分钟幂等一次;跳过正在跑的 mqtt_immediate。

  5. Out of Scope
    再做一张平行日历;Device 上的复杂 Plan DSL。若 7a J5 已落地,本阶段可标部分完成。

  6. Protocol
    复用已有 MQTT 命令,不新增种类。PAUSE/RESUME 若做,必须是 Spec D14,不是第五套协议。


Phase 6 — App / Resource Management(D13)+ 在线 Locale

  1. Objective
    资源权威在 Server;设备只缓存文件。同时落地 设备默认语言(在线半) 与 翻译/双语的可替换语言对。

  2. Why Now
    跟读换标准音、多 App 音频,不能靠手工拷 SD。词表若继续写死中文,德语机联网后仍只能喊「开始跟读」。

  3. Dependencies
    Phase 3。不依赖 4b、不依赖 6b 固件。现网 ai_agent.language / lang_code 可先当 Chat 语种来源。

  4. Scope — 资源
    清单 / DOWNLOAD / resource_id。可选缓存 manifest。设备仍只执行 skills[]。

  5. Scope — Locale(在线,本阶段必须做)
    见下文 「语言模型」。phrase pack、device.locale、翻译/双语 language_pair。热路径:ASR 文本用该 locale 的 enter_phrases 匹配;TTS 进场语用该 locale;Chat 系统提示与音色跟 locale。

  6. Out of Scope
    App Store;把判题 JSON 当固件逻辑;德语离线唤醒(6b / 可能永久做不到);Phase 4 时钟重做。


Phase 6b — 离线 Locale(可选 OTA)

  1. Objective
    没网时,唤醒词与系统级口令(切换入口 / 复读机 / 回 Chat)与 device.locale 一致。**不是新 Device 能力种类**(Spec:MultiNet 词表可配)。

  2. Why Now / 为何单独
    ESP-SR 的 WakeNet / MultiNet 按语种出模型。中文口令是拼音音素;英语是另一套 MN;官方 没有 德语 MultiNet 可预期。把「烧一套德语句表」塞进 Phase 6 会假装离线德语已经存在。

  3. Scope
    NVS locale;从 assets 加载该语种的 wake + 系统命令表。v1 只承诺 zh 与 en(有模型才做)。切换仍只允许系统级词,禁止把「开始跟读」写进固件。

  4. Out of Scope
    为泰/法/德训练唤醒模型(产品/数据项目,不是编码 Phase);运行时从云下载声学模型进 PSRAM(除非以后单独立项)。

  5. 接受现实
    locale=de-DE 的设备:在线菜单/Chat 可以是德语;离线唤醒可以仍是英文或中文 SKU,直到有模型。文档必须写清,不要当 bug。


Phase 7b — Parent Task Management(完整)

  1. Objective
    小程序在 7a 之上:改 Schedule;**设置设备默认语言与翻译/双语语言对**;PAUSE;听原声完善。

  2. Dependencies
    Phase 7a + Phase 5 + Phase 6。6b 不是前提:控制台改 locale 后,在线立即生效。

  3. Scope
    UI。D9 长按退出若未做可一并。语言对只能选 App Manifest 声明的 supported_pairs。

  4. Out of Scope
    开发者平台、支付、在小程序里训练唤醒词、硬件代际管理。


Phase 8 — Developer App Platform

  1. Objective
    第三方 Task JSON 只能引用 Spec 已冻结 Skill。校验失败即拒。

  2. Dependencies
    Phase 6;InteractionMode 集合稳定。

  3. Out of Scope
    GPIO、设备脚本引擎、新传感器。


Phase 9 — Subscription / Marketplace

账号与权益。不改 Opus,不上情绪诊断。


语言模型(评估结论;实现落在 6 / 6b / 7)

分三层,不要混成「一个 language 字段搞定唤醒和翻译」。

层 是什么 例子 难度
A 设备默认语言 device.locale 开机 Chat、进场 TTS、在线场景口令、无语言对的 App(倒背、口算、故事复述) zh-CN / en-US / de-DE 在线:**容易**(Server phrase pack + 已有 ai_agent.language)。离线唤醒/口令:**不容易**,见 6b
B App 语言对 language_pair 翻译、双语对话的可替换选项 翻译 th↔fr;对话 en↔de 容易,纯 Server;一个 App + 参数,不要每种语言对一个 app_id
C 资源内容语言 音频 MP3/txt 本身 英语跟读课永远是英文音频 跟 lesson 包走,不跟 locale。德语机练英语跟读:菜单德语、喇叭音频英语

功能 1 好不好做:

  • 联网后的中文改德语 Chat / 「切换模式」菜单 / 「开始跟读」的德语同义句:把 runtime.py 硬编码词表换成 locales/{locale}/phrases.json,hello 时带上 device.locale。**工作量中等、风险低,Phase 6。**
  • 开机离线就用德语喊唤醒、喊「复读机」:必须换 WakeNet + MultiNet 模型与音素格式。中文现网是拼音编译进 system.h。英语官方 MN 可做第二套 assets。**德语没有现成 ESP-SR 模型时,离线入口做不到**,只能在线。不要承诺「改一个配置全世界离线德语」。
  • 工厂 SKU(出厂烧中文机 / 英文机)比运行时热切换离线模型容易得多。运行时切换 locale:在线立刻生效;离线要 6b 且仅 zh/en。

功能 2 怎么配:

不要再复制 english_translation / english_conversation 两个 App 名。Manifest:

app_id: translation
  default_pair: ["zh","en"]          # 设备 locale 为 zh 时的缺省
  supported_pairs: [["zh","en"],["th","fr"],["en","de"], ...]
  instance.options.language_pair     # 家长/控制台覆盖

app_id: bilingual_chat
  default_pair: ["zh","en"]
  supported_pairs: [["zh","en"],["en","de"], ...]
  语义:用户说 lang_a → 只答 lang_b,反之

翻译机:未指定时仍可 auto 检测,目标语取 pair 的另一侧或 target_lang。
缺省 pair 的推导:[device.locale 的主语言, 机构配置的 L2],没有 L2 则 zh-en。

倒背 / 故事复述 / 口算:只有 A,TTS 与听窗提示用 device.locale。不要给它们配 language_pair。

权威: device.locale 在 manager-api(绑定/出厂);Agent.language 与其对齐,避免两套打架。xiaozhi-server 连接时读取,固件 NVS 只服务 6b 离线。设备 仍然没有 tenant_id。

禁止: 为每种语言对改 C++;把「开始跟读」的德语写进固件;Phase 4 做 Locale。


3. 跨端依赖(Command / Event / State)

对齐 Spec §4–5。每个 Phase 必须同时有 Server→Device 与 Device→Server,禁止单端表。

Phase 2
  Device  AUDIO_COMPLETED|STOPPED  ──detect──►  Server
  Device  listen 流 + VAD          ────────►  Server ASR / D8 v1 report
  Server  SPEAK / PLAY_AUDIO / 回 CHAT ──tts/mcp──► Device
  Server  ensure_app dirs          ──MCP/MQTT──► Device mkdir(运输,非新能力)

Phase 3  ✅
  Server  TaskSession JSON         ──HTTP upsert──►  manager-api Instance
  无新 Device 能力;设备不持有 instance_id

Phase 4  ✅
  Server  一次 JSON playlist           ──MCP──► Device
  Device  本地播→听窗→下一句
  Device  听流(旁路 ASR/report)     ──► Server 后评估 metrics
  Device  playlist_completed          ──detect──► Server 回 CHAT
  跟读:分析失败不挡下一句;无 JUDGE

Phase 7a
  小程序  场景任务(立即/计划)         ──HTTP──► manager-api
  立即    START_APP_TASK mqtt_immediate ──MQTT──► Device
  计划    SYNC_SCHEDULE 全表           ──MQTT──► Device schedule.json
  Device  挑最近一次                    ──Alarm1──► 唤醒/到点 StartAppTask
  7a-D    GET instance / chat          ──oauth2──► 文本+可选录音
  无新 WS type;无 metrics UI

Phase 4b
  Device  听流                       ──► Server ASR + parser(inline,短超时)
  Server  SPEAK 反馈 / 下一题        ──► Device
  仍无 JUDGE、无固件 if correct;评估在业务流内,不能拖到后评估

Phase 5
  Server  TASK_START               ──MQTT──► Device
  Device  TASK_STARTED/COMPLETED   ──ack/event──► Server

Phase 6
  Server  FETCH                    ──DOWNLOAD──► Device SD
  Device  PLAY_AUDIO(resource)     ──event──► Server

Phase V(最后)
  Device  hello/OTA 带 generation+revision+cap_set  ──► Server 矩阵
  Server  交集业务 / 引导 OTA / 拒未知 SKU          ──► Device
  旧固件缺字段 = 当前这一款 SKU;不加新 WS type

4. Master Plan / Spec 对照

长期目标 Roadmap
Device 能力冻结 Freeze 文档 + Phase 2 补事件/采集
Task Runtime 在 Server P2 Session → P3 Instance ✅ → P4 后评估 ✅ → P4b 流内评估
新 App 不改 C++ P4b 三个代表 Task 验收
跟读语音对象 P2 D8 v1 → P3 挂 step → P4 本地 wav/txt → P6 标准音下载
Scheduler P7a 任务全表 + 设备只写下一闹钟;临时优先于计划;P5 到点补推可选
App ≠ Firmware 贯穿;P6 资源、P8 沙箱
设备默认语言 / 语言对 P6 在线 pack + pair;P6b 离线 zh/en;P7b 控制台;P4b 继承 locale
产品代际 / 端云匹配 Phase V,最后;现网一款硬件视为当前 SKU
家长可见练习 P7a 场景任务下发 + 7a-D 历史(无分数);语言对已作为双语参数;PAUSE P7b
心理陪伴 / 主持人 无新硬件;复用 listen/speak + Server Memory
Subscription P9

5. 刻意不做进近期的事项

来自 Spec §17 与 §21:

  • 为成语/口算/接龙改 C++ 或加 MultiNet 业务口令
  • 把 branch(if correct) 放进固件
  • 合并 Xiaozhi MQTT 与 snlp(改运输 ≠ 加能力,但不作为近期项目)
  • 把 apps.json 当离线权威引擎
  • Phase 2 做 wait Skill、TASK_PAUSE、本地 WAV 上传、indicate 大改
  • Phase 2 拆微服务 / 对象存储 / 情绪分析 / 临床诊断
  • 一次性写死 Phase 5–9 的类名与 REST 路径
  • 把业务 App 切换词写入固件(系统级仅 Chat + 离线复读 + 「切换模式」总入口)
  • 在 Phase 4 引入租户 / tenant_id(最早缝在 Phase 6,产品化 Phase 7b)
  • 在 Phase 4 做多语言 / 把德语唤醒写进固件
  • 为每种翻译语言对新增一个 app_id 或新 WS type
  • 用一个数字同时表示产品代际、固件 semver 和协议版本
  • 把摄像头固件包按 semver 推给无摄像头的小智 AI 1
  • 在 Phase 4 / 7a 做兼容矩阵 / 改 hello 字段(放到 Phase V,最后)
  • 在 7a 之前做倒背/口算/接龙或课文 DOWNLOAD 平台

下一编码阶段: 只打开 phase-7a-plan.md。跟读/泛听热路径与欢迎词/翻译/中英锁定。先 7a-A「全表 + 只写下一次闹钟」,不要再做 10 槽一对一。History 与 metrics 后置。