docs: M2.1 PRD 立项 + 团队沟通记录与状态同步
- 新增 docs/M2.1_PRD.md:语音数字生命 V1 产品需求文档(角色切换 + 语音回合 + 模型管理 + 双端交付) - 更新 CLAUDE.md:M2.1 立项状态、spike 结论、待处理项 - 更新 .showen/TEAM_CHAT.md:团队最新沟通记录 - 更新 souls/zhang-mingyuan.md、souls/zhang-wanlin.md:成员状态
This commit is contained in:
@@ -2861,3 +2861,153 @@ $ git status --short
|
|||||||
设备环境确认:时钟已正常(2026-07-03 15:07 CST),磁盘 18G 可用(35%)。showen_v2.service 单实例运行中(pid 1180, target/release)。
|
设备环境确认:时钟已正常(2026-07-03 15:07 CST),磁盘 18G 可用(35%)。showen_v2.service 单实例运行中(pid 1180, target/release)。
|
||||||
|
|
||||||
**M1.2 设备侧收尾完成,只差老板打 tag。**
|
**M1.2 设备侧收尾完成,只差老板打 tag。**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [2026-07-03] 张婉琳 → 陈逸飞:M2.1 PRD 完成
|
||||||
|
|
||||||
|
`docs/M2.1_PRD.md` v1.0 草案成文(未 commit,老板管提交)。范围:功能一 角色内容包切换 / 功能二 语音对话回合(App=话筒喇叭,设备=大脑和脸)/ 功能三 模型管理(老板 07-03 补充需求,已并入)/ NFR / V1 边界 / 17 条可演示验收 / 风险与素材方案建议 / V1→V2→V3 Roadmap。
|
||||||
|
|
||||||
|
**写前已核实的事实**:角色切换可完全复用现有 `GET /api/config/available` + `POST /api/config/switch`(routes.rs:411/448,含验证+热重载+失败不落盘),App 侧无语音能力(clients/flutter/PRD.md 确认),dog/cat 内容包结构确认(configs/*.json)。
|
||||||
|
|
||||||
|
**关键决策点(需 CEO/老板拍板)**:
|
||||||
|
1. **素材方案**:数字人/歌姬各需 idle/talk/greet/sleep 四状态片段(1920×1080/H.264/深底/首尾帧一致)。建议 A=AI 视频生成先试产(推荐)/ B=外包 / C=老板提供现成素材——需拍板
|
||||||
|
2. **角色元信息落地**:内容包新增 `character` 块(方案 A,推荐)受 deny_unknown_fields 影响需内核改 schema vs sidecar manifest(方案 B)——架构评审首议题,交王思远
|
||||||
|
3. **模型档位**:0.5B vs 2B 以张明远 spike 实测定;PRD 延迟/内存指标全部标注"待 spike 校准",未编造数字
|
||||||
|
4. **模型镜像源**:国内静态清单+自建镜像/OSS,清单维护责任人未定——需拍板
|
||||||
|
5. **歌姬不真唱**:V1 是"会聊天的歌姬人设",歌声合成明确排除,另立项——请确认口径
|
||||||
|
6. 中文优先还是中英双语;对话历史仅存手机本地(设备零留存,隐私卖点)——请确认
|
||||||
|
|
||||||
|
**老板补充需求已落位**:功能三 模型管理(清单/下载进度+校验+断点/切换/删除/存储配额/档位守门),设计动机写明 A733/4G 仅为最低档,验收第 14 条点名"换模型不重烧录/不重部署"。产品行为参照既有 plugin_repo/version_manager 模式,架构细节留给王思远。
|
||||||
|
|
||||||
|
## [2026-07-03] 张婉琳 → 陈逸飞:M2.1 PRD 补充二落位(客户端矩阵)
|
||||||
|
|
||||||
|
老板补充二("clients里的安卓app别忘了改,还有设备的网页控制端")已并入 `docs/M2.1_PRD.md`,新增独立第 5 章「客户端矩阵」,后续章节顺延(非功能→6 / 边界→7 / 验收→8 / 风险→9 / Roadmap→10,交叉引用已全部修正)。要点:
|
||||||
|
|
||||||
|
1. **双客户端同为交付对象**:安卓 App(clients/flutter,前文已覆盖)+ 设备内嵌 Web 控制端(routes.rs:1961 WEB_UI_HTML,`/` 直接服务)——Web 端必须新增角色切换 + 模型管理 + 文字对话三块界面
|
||||||
|
2. **Web 语音约束如实写明**:getUserMedia 需 HTTPS 安全上下文,设备纯 HTTP → V1 Web 不做录音,改做**文字输入对话**(文字→LLM→文字/TTS 音频,浏览器播音不受限),多出一个可演示入口且 LLM 链路可独立于 ASR 调试;自签 HTTPS 不入 V1
|
||||||
|
3. **功能×客户端对照表**(§5.3):角色切换/模型管理两端必做;录音对话 App 独占;文字对话 Web 必做、App 增强项;存量监控控制两端已有不动
|
||||||
|
4. **验收补 3 条**(#17 Web 切角色两端状态互通 / #18 Web 模型管理全流程 / #19 Web 文字对话+talk 联动+互斥),总验收 20 条
|
||||||
|
5. **风险表补 #11**:核实后修正一处事实——WEB_UI_HTML 实为 routes.rs:1961-2384 约 420 行高密度单行 HTML/JS("2000+ 行"是 routes.rs 全文件行数 2384);可维护性风险成立,建议王思远评审议 include_str! 拆独立 .html 或静态资源目录
|
||||||
|
|
||||||
|
未 commit(老板管提交)。
|
||||||
|
|
||||||
|
## [2026-07-03] 张婉琳 → 陈逸飞:M2.1 PRD 补充三落位(声音全部走客户端)
|
||||||
|
|
||||||
|
老板补充三("现在设备的扬声器麦克风没插入,尽量让对话和播放声音从网页和手机app实现")已并入 `docs/M2.1_PRD.md`,改动点位:
|
||||||
|
|
||||||
|
1. **§3.1 新增"声音归属铁律"**:TTS 回复音频一律返回发起请求的客户端播放(App/Web),设备本地不播放、不依赖任何音频硬件;设备角色收敛为 ASR/LLM/TTS 计算 + 画面状态联动。§3 标题与 §1 定位同步改为"客户端是话筒和喇叭";§3.3 画面联动、§6 稳定性行的"手机/App"措辞统一为"客户端(App/Web)"
|
||||||
|
2. **§5.2 重写**:Web 回复音频播放升为 **V1 必做**(浏览器 audio 无安全上下文限制,设备无扬声器时 Web 场景靠浏览器出声兜底);Web 录音降为**评估项/V1.5 增强候选**——技术路径已写明(自签 HTTPS 后 getUserMedia 可用,代价一次证书警告),不作 V1 验收硬指标
|
||||||
|
3. **§5.3 对照表重排**:拆出"录音(语音输入)"(App ✅ / Web 🔍 评估项)与"回复音频播放"(两端 ✅ 必做)两行
|
||||||
|
4. **§9 风险 #3 关闭重写**:"扬声器现场验证"事实已确认(未插入),改为"设备音频硬件未接入——V1 零影响;后续插 USB/3.5mm 麦克风扬声器则作为 V2 启动前置"
|
||||||
|
5. **§10 Roadmap**:V2 加前置条件"音频硬件接入后启动";V1 定位补"设备本地不出声"
|
||||||
|
6. **验收**:#19 Web 文字对话的回复音频浏览器播放改为 V1 必做;全表复查无任何"设备出声"条目(原本就全部落在客户端侧,#4 手机播放、#19 浏览器播放)
|
||||||
|
7. §7 边界 #1/#9 同步更新(设备直接对话的 V2 前置、Web 录音 V1.5 候选)
|
||||||
|
|
||||||
|
原始需求(老板三条补充原话)均已录入 §0 需求源头。未 commit(老板管提交)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [2026-07-03] 张明远 → 陈逸飞:M2.1 设备端本地 AI spike 报告(ASR→LLM→TTS 全链实测)
|
||||||
|
|
||||||
|
### 一句话结论
|
||||||
|
|
||||||
|
**能跑通,但"良好"(≤3s)在纯 CPU 上达不到。** 推荐 **0.5B 档(Qwen2.5-0.5B)+ 流式管线**,首音频延迟可压到 ~5s(可接受阈值边缘达标);1B 档只适合非实时场景;2B 档不可用。全程 showen_v2 服务 active,锁 2 大核推理时视频服务 CPU 只被挤压 8-13%。
|
||||||
|
|
||||||
|
### 0. 设备摸底(比档案强)
|
||||||
|
|
||||||
|
- **Radxa Cubie A7A / Allwinner A733**:8 核 big.LITTLE = 2×Cortex-A78@2.0GHz (cpu6-7) + 6×Cortex-A55@1.79GHz (cpu0-5),**均带 dotprod**,对 GGUF 量化推理友好;另有 NPU(thermal zone 可见,Phase 2 可探索)
|
||||||
|
- 内存 3.8G(基线可用 3.1G)/ 磁盘起始 17G 空闲 / 基线温度 50-54°C
|
||||||
|
- showen_v2 基线 CPU **132.3%**(60s 采样均值),内存 RSS ~98MB
|
||||||
|
- **apt 零安装**:git/cmake/gcc/curl/arecord 全数已存在
|
||||||
|
|
||||||
|
### 1. 工具链准备
|
||||||
|
|
||||||
|
- llama.cpp(build fdb1db8)cmake Release + GGML_NATIVE 编译成功(github 直连 git clone 被 TLS 掐断,ghfast.top 代理成功——**设备 github 直连不可靠,走镜像是必须项**)
|
||||||
|
- whisper.cpp 同法编译成功;piper 用官方 aarch64 release 二进制(github 直下 10KB/s 卡死,ghfast 秒下)
|
||||||
|
- 模型全部来自 hf-mirror.com,总下载 3.2GB(预算 5G 内)
|
||||||
|
|
||||||
|
**模型选型说明(老板点名 Gemma 0.5B/2B)**:Gemma 系没有 0.5B——用 **Gemma3-1B-it**(Gemma 最新代最小尺寸)占小档、**Gemma2-2B-it**(Gemma 系唯一 2B)占 2B 档、**Qwen2.5-0.5B-Instruct** 占 0.5B 档对照(该量级公认中文最强)。均 Q4_K_M 量化。
|
||||||
|
|
||||||
|
### 2. LLM 基准(视频服务运行中实测)
|
||||||
|
|
||||||
|
**线程数是生死线**(Qwen0.5B 扫描,llama-bench ±3 次重复):
|
||||||
|
|
||||||
|
| 线程 | pp128 t/s | tg64 t/s | 说明 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| **t=2(大核)** | 31.5 | **16.4** | 生成最快,对视频影响最小 ✅ |
|
||||||
|
| t=4 | 35.6 | 15.2 | |
|
||||||
|
| t=6 | 40.3 | 15.2 | |
|
||||||
|
| t=8(全核) | 37.4 | **7.2** | 生成崩一半,showen 被挤到 50.9% ❌ |
|
||||||
|
|
||||||
|
→ **结论:必须 t=2 锁大核。多线程在 big.LITTLE 上因同步拖尾反而更慢,还抢视频服务的核。**
|
||||||
|
|
||||||
|
**三模型基准表**(t=2,llama-bench r=3,误差 <2%):
|
||||||
|
|
||||||
|
| 模型 | 文件 | 峰值RSS | pp128 t/s | tg64 t/s | 50字回复(热) | showen 影响 |
|
||||||
|
|---|---|---|---|---|---|---|
|
||||||
|
| Qwen2.5-0.5B Q4_K_M | 469MB | 985MB@ctx4096 | 31.5 | 16.4 | ≈3.4s | 132→122%(-8%) |
|
||||||
|
| Gemma3-1B Q4_K_M | 806MB | 1447MB@ctx4096 | 16.6 | 8.2 | ≈6.2s | 132→120%(-9%) |
|
||||||
|
| Gemma2-2B Q4_K_M | 1.7GB | **3253MB@默认ctx** | 13.9 | 4.6 | ≈10.9s | 132→115%(-13%) |
|
||||||
|
|
||||||
|
- ⚠️ **Gemma2-2B 默认上下文峰值 RSS 3.25G,实测触发 swap 187MB**——2B 档若要用必须 `-c 1024` 限死,否则有拖垮整机风险
|
||||||
|
- 中文单回合实测(llama-cli 单轮+系统提示,含模型冷加载全 wall):Qwen 12.0s / Gemma3 22.1s / Gemma2 41.2s;冷加载占 5s/9s/20s → **正式方案必须模型常驻(llama-server)**
|
||||||
|
- 回复质量目测:Qwen0.5B 通顺但平淡;Gemma3-1B 流畅但事实性发散;Gemma2-2B 最准但太慢
|
||||||
|
- 温度:基准期间大核峰值 79°C(基线 54°C),未观察到降频引起的性能塌陷;测后 3 分钟回落 56°C
|
||||||
|
|
||||||
|
### 3. ASR(whisper.cpp,t=4,5.4s 中文样本)
|
||||||
|
|
||||||
|
样本:piper 合成的已知文本语音(可核对字错),另用 arecord 默认设备实录 5s 验证麦克风链路(**实录为环境音,无人在设备旁说话,如实标注**;tiny/base 对静音均产生幻觉文本,正式方案需 VAD 门限)。
|
||||||
|
|
||||||
|
| 模型 | 总耗时(冷) | 热推理 | 转写质量 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| tiny (75MB) | 3.7s | **≈2.2s**(encode 1.5 + decode 0.02) | 大意全对,错字:"散步"→"三部聖"、"咖啡"→"咖費",繁体输出 |
|
||||||
|
| base (142MB) | 7.4s | ≈5.7s(encode 3.3s) | 错字类似,标点更好 |
|
||||||
|
|
||||||
|
- whisper encode 是固定 30s 窗口成本,**语音再短 encode 也是 ~1.5s(tiny)**——这是 ASR 延迟下限
|
||||||
|
- 合成语音偏"干净",真实远场麦克风准确率会更低,转正前需真人实测
|
||||||
|
|
||||||
|
### 4. TTS(piper + zh_CN-huayan-medium,20字中文 ×3 轮)
|
||||||
|
|
||||||
|
- 20 字 → 4.0s 音频,**热推理 1.2s,RTF 0.30**(三轮稳定 0.30-0.33),进程冷启动另加 ~0.8s
|
||||||
|
- 音质试听 OK(huayan 女声,自然度中上);50 字回复 ≈10s 音频 → infer ≈3s,**分句流式合成可把首音频压到 <1s**
|
||||||
|
|
||||||
|
### 5. 端到端实测 + 驻留估算
|
||||||
|
|
||||||
|
**真实串联冷链实跑**(whisper→llama-cli→piper 三进程逐个冷启动,管道传文本):
|
||||||
|
|
||||||
|
| 链路 | ASR | LLM | TTS | 总计 |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| tiny + Qwen0.5B + piper | 3.06s | 12.31s | 2.61s | **17.98s** |
|
||||||
|
| tiny + Gemma3-1B + piper | 3.40s | 19.77s | 3.29s | **26.46s** |
|
||||||
|
|
||||||
|
**驻留服务热推理估算**(模型常驻内存,50 字回复,prompt≈45 token):
|
||||||
|
|
||||||
|
| 档位 | ASR | LLM(pp+tg) | TTS | 串行总计 | 流式首音频* |
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
| **Qwen0.5B** | 2.2s | 1.5+3.4s | 3.0s | **≈10s** | **≈5.0-5.6s** ⚠️边缘 |
|
||||||
|
| Gemma3-1B | 2.2s | 2.7+6.2s | 3.0s | ≈14s | ≈7.7s ❌ |
|
||||||
|
| Gemma2-2B | 2.2s | 3.2+10.9s | 3.0s | ≈19s | ❌ |
|
||||||
|
|
||||||
|
*流式 = LLM 边生成边分句送 TTS 边播放,首音频 = ASR + LLM 首句(~15tok) + TTS 首句;再叠加 sys prompt KV 预缓存(省 ~0.8s)与 VAD 截断可再压 0.5-1s
|
||||||
|
|
||||||
|
### 6. 结论与建议(给王思远架构 / CEO 排期)
|
||||||
|
|
||||||
|
1. **推荐档位:Qwen2.5-0.5B Q4_K_M + t=2 大核 + llama-server 常驻 + 流式分句 TTS**。延迟预期:首音频 4.5-5.5s("可接受"边缘),完整回合 ~10s。**"良好"(≤3s)纯 CPU 无解**,需 NPU(A733 自带,Phase 2 探索)或云端混合
|
||||||
|
2. **内存预算**:Qwen0.5B ctx1024 常驻 ~700MB + whisper tiny ~200MB + piper ~150MB ≈ **1.1GB**,设备 3.1G 可用装得下且不动 swap;**严禁默认 ctx**(4096/8192 会吃 1-3.3GB)
|
||||||
|
3. **对视频服务影响可控**:t=2 时 showen_v2 只降 8-13%(132%→115-122%),全程 active 无重启;瞬时最低 67.8% 出现在 ASR encode 段(t=4),若锁 ASR 也用 2 线程可再缓解。远程无法目测画面卡顿,建议转正前现场人眼确认一次
|
||||||
|
4. **风险**:① 0.5B 中文人设/事实性弱,靠 prompt 工程+限字数兜底,数字生命"人格"体验需产品侧评估;② whisper 对静音幻觉 + 真实麦克风远场衰减,必须加 VAD;③ 磁盘现剩 14G,模型+工具共占 3.5G,后续多模型热切换要做版本 GC;④ github 直连不可靠,部署脚本必须内置镜像回退
|
||||||
|
5. **备选路线**:Qwen3-0.6B(更新一代,需重测);ASR 可试 sherpa-onnx 流式(免 30s 窗口固定成本);TTS piper 已够用无需换
|
||||||
|
|
||||||
|
### 现场保留(~/ai_spike/,共 3.5G,磁盘余量 14G)
|
||||||
|
|
||||||
|
```
|
||||||
|
models/ 3.1G qwen2.5-0.5b/gemma-3-1b/gemma-2-2b Q4_K_M + ggml-tiny/base
|
||||||
|
llama.cpp/ 247M build fdb1db8,build/bin/llama-{cli,bench,server}
|
||||||
|
whisper.cpp/ 60M build/bin/whisper-cli
|
||||||
|
piper/ 136M aarch64 二进制 + zh_CN-huayan-medium
|
||||||
|
results/ 1.7M 全部原始数据:bench txt/采样 csv/对话输出/wav 样本
|
||||||
|
*.sh sampler/run_bench/run_dialog/asr_test/tts_test/e2e_test(可复跑)
|
||||||
|
```
|
||||||
|
|
||||||
|
apt 安装清单:**无**。未动项目代码/configs,未 commit(老板管提交)。设备遗留 2 个 zombie 为已知 unclutter 问题(待处理 #5),非本次产生。
|
||||||
|
|||||||
14
CLAUDE.md
14
CLAUDE.md
@@ -136,6 +136,20 @@ export PATH="/home/showen/.rustup/toolchains/stable-aarch64-unknown-linux-gnu/bi
|
|||||||
30. ~~**P0**: 设备端开机自启出现 3 个实例~~ ✅ 赵雨薇修复 (2026-07-02, 根因:3 个自启动入口叠加;仅保留用户级 showen_v2.service,其余移入 ~/autostart_backup_20260702/,重启验证进程==1)
|
30. ~~**P0**: 设备端开机自启出现 3 个实例~~ ✅ 赵雨薇修复 (2026-07-02, 根因:3 个自启动入口叠加;仅保留用户级 showen_v2.service,其余移入 ~/autostart_backup_20260702/,重启验证进程==1)
|
||||||
31. ~~**P0**: 设备端窗口非全屏~~ ✅ 赵雨薇修复 (2026-07-02, 根因:应用先于 kwin 启动,OpenCV 全屏调用空操作;ExecStartPre 等待 kwin + kwinrulesrc 强制全屏规则,重启验证 800x800 无边框)
|
31. ~~**P0**: 设备端窗口非全屏~~ ✅ 赵雨薇修复 (2026-07-02, 根因:应用先于 kwin 启动,OpenCV 全屏调用空操作;ExecStartPre 等待 kwin + kwinrulesrc 强制全屏规则,重启验证 800x800 无边框)
|
||||||
|
|
||||||
|
### M2.1 新立项(2026-07-03 老板拍板)
|
||||||
|
|
||||||
|
**语音数字生命 V1**。老板决策:**本地 AI 优先,云端接口预留**。范围:
|
||||||
|
1. 手机 App 遥控切换角色内容包(宠物猫狗/数字人/二次元歌姬),复用现有配置切换+remote_control 机制
|
||||||
|
2. 手机 App 录音上传 + 播放回复音频;设备本地跑 ASR(whisper.cpp)→ 小模型 LLM(0.5B~2B 量级,老板点名 Gemma 系,以设备实测为准)→ TTS(piper),响应时联动人物"说话"状态
|
||||||
|
3. LLM 后端做 trait 抽象,本地/云端可切换(云端接口预留不实现)
|
||||||
|
4. **模型管理(2026-07-03 老板补充)**:模型必须支持切换、下载、更换——不写死。因为设备硬件会变(未来可能上更强的板子跑更大模型),当前测试机只是全志 A733 4G 这一档。设计参照现有插件仓库/版本管理模式:模型清单 + 按设备能力选型 + 下载(国内镜像源)+ 校验 + 存储配额管理
|
||||||
|
5. **客户端矩阵(2026-07-03 老板补充)**:功能必须同时落到两个客户端——①clients/flutter 安卓 App;②设备内嵌网页控制端(routes.rs:1961 WEB_UI_HTML)。Web 端至少要有角色切换 + 模型管理;语音回合受浏览器安全限制(getUserMedia 需 HTTPS,设备是纯 HTTP)优先落 App,Web 端可用文字对话替代
|
||||||
|
6. 硬件事实:测试机为全志 A733(Linux ARM64, 4G 内存约 3.3G 可用),CPU 已被视频占 ~1.25 核;**老板确认(2026-07-03)扬声器/麦克风均未插入**(此前 arecord 有信号应为板载或浮空噪声)——**V1 音频 I/O 全部走客户端**:录音和播放在 App;网页端播放无障碍、录音需 HTTPS(自签证书列为评估项),文字对话保底;原 V2"设备直接对话"改为待硬件接入后再启动
|
||||||
|
|
||||||
|
7. **Spike 结论(2026-07-03 张明远实测,全表见 TEAM_CHAT.md)**:可行。设备实为 Radxa Cubie A7A(A733:2×A78@2.0G + 6×A55@1.8G)。推荐默认 **Qwen2.5-0.5B Q4**(16.4 t/s,50字回复 ~3.4s,RSS 985M);Gemma3-1B 可选档(8.2 t/s);**Gemma2-2B 本机不推荐**(RSS 3.25G 触发 swap)。硬约束:**推理必须 t=2 锁大核**(全核反而崩且挤死视频)、严禁默认上下文长度、部署脚本必须带镜像回退。ASR whisper tiny ~2.2s(需 VAD 防静音幻觉)、TTS piper RTF 0.3。端到端:串行热链 ~10s,**流式管线首音频 ~5s**(达标"可接受");≤3s 需 A733 的 NPU(Phase 2 路径)。现场保留 ~/ai_spike/ 3.5G 可复跑。
|
||||||
|
|
||||||
|
✅ PRD 完成(docs/M2.1_PRD.md,三轮修订含老板三条补充)+ Spike 完成。进行中:架构设计(王思远)。素材依赖:数字人/歌姬内容包需视频素材,先用现有猫狗包验证切换机制。
|
||||||
|
|
||||||
### 待处理
|
### 待处理
|
||||||
|
|
||||||
1. **[M1.2 收尾]** ✅ commit(老板 2a6e14b)→ ✅ 设备同步至 2a6e14b + cargo check 零 warning(周雅婷 2026-07-03,设备仅剩本地调参文件 configs/dog_state_machine.json 一处差异);**仅剩:老板打 tag(建议在 2a6e14b 上打 `m1.2`)**
|
1. **[M1.2 收尾]** ✅ commit(老板 2a6e14b)→ ✅ 设备同步至 2a6e14b + cargo check 零 warning(周雅婷 2026-07-03,设备仅剩本地调参文件 configs/dog_state_machine.json 一处差异);**仅剩:老板打 tag(建议在 2a6e14b 上打 `m1.2`)**
|
||||||
|
|||||||
312
docs/M2.1_PRD.md
Normal file
312
docs/M2.1_PRD.md
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
# M2.1 PRD — 角色切换 + 语音互动 V1
|
||||||
|
|
||||||
|
## 0. 文档信息
|
||||||
|
|
||||||
|
- 里程碑:M2.1(Phase 2 首个功能里程碑)
|
||||||
|
- 版本:v1.0(草案,待 CEO/老板评审)
|
||||||
|
- 作者:张婉琳(产品总监)
|
||||||
|
- 日期:2026-07-03
|
||||||
|
- 需求源头(老板原话,最高优先级):
|
||||||
|
> "先用本地跑,同时预留云端接口。先做一个可用手机遥控切换宠物模式以及数字人或者数字二次元歌姬之类的功能,同时通过手机app录音和播放实现设备响应,可以的话本地运行0.5B或者2B的gemma4"
|
||||||
|
>
|
||||||
|
> 补充一(2026-07-03):"要支持切换模型和模型下载更改,因为以后设备会变,只不过测试设备是4G的这款全志A733运行linux"
|
||||||
|
>
|
||||||
|
> 补充二(2026-07-03):"clients里的安卓app别忘了改,还有设备的网页控制端"
|
||||||
|
>
|
||||||
|
> 补充三(2026-07-03,关键事实):"现在设备的扬声器麦克风没插入,尽量让对话和播放声音从网页和手机app实现"
|
||||||
|
- 关联文档:`clients/flutter/PRD.md`(App 现状)、`docs/M1.2_TEST_PLAN.md`、`configs/dog_state_machine.json`(内容包现状)
|
||||||
|
- 性能基线依赖:设备端小模型 spike(张明远,llama.cpp + whisper.cpp + piper 实测)进行中,**本文所有延迟/资源数字凡标注"待 spike 校准"者均以 spike 报告为准,评审时统一回填**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 产品定位
|
||||||
|
|
||||||
|
数字生命窗口从"单一宠物循环播放"升级为 **"可切换角色 + 语音互动"的数字生命 V1**。
|
||||||
|
|
||||||
|
- **现状**:设备开机播放单一宠物(狗/猫)的预渲染视频状态机,手机 App 只能做播放控制、状态机触发、配网与配置管理。角色是"布景",不是"生命"。
|
||||||
|
- **升级后**:
|
||||||
|
1. 手机一键切换角色——宠物(狗/猫)、数字人、二次元歌姬,角色即内容包,随时更换"住在窗口里的生命";
|
||||||
|
2. 对着手机说话,角色"听懂并回答"——客户端是话筒和喇叭,设备是大脑和脸:设备本地完成 ASR → LLM(0.5B~2B 小模型,人设跟随角色)→ TTS 计算,**所有声音一律从手机 App / 网页端播出,设备本地不出声**(设备音频硬件未接入——老板补充三确认的事实),回合期间画面同步切换"说话"状态;
|
||||||
|
3. 模型即耗材、可管理——模型不烧死在系统里,手机可查看/下载/切换/删除设备上的推理模型,硬件升级换更大模型不换系统。
|
||||||
|
- **架构原则(老板明确要求)**:**先本地跑通,云端接口预留**。V1 全链路本地推理、不依赖公网;LLM 后端做成可配置(local/cloud),V1 只实现 local。
|
||||||
|
- **平台叙事**:角色内容包 = 状态机 JSON + 视频素材 + 角色人设,是本平台第一个"标准化内容单元",为 Phase 2 内容生态(第三方角色包分发)奠基。
|
||||||
|
- **交付面(老板补充二)**:安卓 App 与设备内嵌网页控制端**两个客户端同为 M2.1 交付对象**,功能覆盖差异见 §5 客户端矩阵。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 功能一:角色内容包切换
|
||||||
|
|
||||||
|
### 2.1 内容包定义
|
||||||
|
|
||||||
|
一个角色内容包由三部分组成:
|
||||||
|
|
||||||
|
| 组成 | 内容 | 现状 |
|
||||||
|
|------|------|------|
|
||||||
|
| 状态机 JSON | display / playlist / transition / playback / scenes.state_machine / remote_control(结构见 `configs/dog_state_machine.json`) | 已有(dog、cat 两包) |
|
||||||
|
| 视频素材组 | playlist 引用的一组预渲染 mp4 片段 | 狗/猫已有;数字人/歌姬待制作 |
|
||||||
|
| 角色元信息 + 人设(**M2.1 新增**) | 角色显示名、类型(pet/human/singer)、封面图、人设 prompt、回复风格参数、TTS 音色标识 | 无,需新增 |
|
||||||
|
|
||||||
|
**角色元信息落地方式(供架构师决策,产品倾向前者)**:
|
||||||
|
- 方案 A(推荐):在状态机 JSON 内新增 `character` 顶层块。注意:配置结构体已全面 `deny_unknown_fields`(commit 5770b70),旧解析器会拒绝新字段,**需内核侧同步扩展 schema**,这是本功能的工程依赖。
|
||||||
|
- 方案 B:内容包目录 + 独立 `manifest.json` sidecar。改动隔离但引入"包=目录"的新概念,迁移成本更高。
|
||||||
|
|
||||||
|
**内容包可移植性要求(新包必须遵守)**:现有 dog 包 playlist 使用仓库外相对路径(`../../宠物嵌入式开发视频2/...`),不可分发。新制作的内容包素材必须收敛到设备上约定目录(建议 `videos/<pack_id>/`),路径自包含,为后续内容包分发做准备。存量 dog/cat 包 V1 不强制迁移。
|
||||||
|
|
||||||
|
### 2.2 角色类型与必备状态集
|
||||||
|
|
||||||
|
| 角色 | 状态机 | 素材 | 人设风格 |
|
||||||
|
|------|--------|------|---------|
|
||||||
|
| 狗(已有) | 已有,11 状态 | 已有 | 拟声/简短俏皮("汪!"开头、短句、宠物口吻) |
|
||||||
|
| 猫(已有) | 已有 | 已有 | 拟声/简短俏皮(慵懒、傲娇) |
|
||||||
|
| 数字人(新) | 新建,见必备状态集 | **待制作** | 亲切助理型,自然口语 |
|
||||||
|
| 二次元歌姬(新) | 新建,见必备状态集 | **待制作** | 活泼元气,二次元语气词 |
|
||||||
|
|
||||||
|
**新角色必备状态集(V1 最小集,语音互动依赖)**:
|
||||||
|
|
||||||
|
| 状态 | 用途 | 素材要求 |
|
||||||
|
|------|------|---------|
|
||||||
|
| `idle` | 默认待机循环 | 可无缝循环(首尾帧一致),建议 5~15s |
|
||||||
|
| `talk` | 语音回合中"说话" | 口部/肢体有说话感,可无缝循环,建议 2~5s;V1 不要求口型对齐 |
|
||||||
|
| `greet` | 被切换到/被唤起时打招呼 | 一次性播放,建议 3~8s |
|
||||||
|
| `sleep` | 长时间无交互后休眠 | 可无缝循环,建议 5~15s |
|
||||||
|
|
||||||
|
存量宠物包无 `talk` 状态:V1 允许优雅降级(语音回合期间宠物包映射到既有互动状态如 `called_name`,或保持当前状态),不阻塞上线;后续补素材。
|
||||||
|
|
||||||
|
**素材统一规格**:
|
||||||
|
- 分辨率 1920×1080(与现有 render/output 配置一致),mp4 / H.264,25 或 30 fps
|
||||||
|
- 背景:纯黑或深色背景优先(全息显示依赖 brightness_adjust 背景抑制;如用 chroma key 需符合现有 hsv 配置能力)
|
||||||
|
- 角色形象跨片段严格一致(同一人物/服装/机位/光照)
|
||||||
|
- 循环类素材首尾帧一致,切换类素材起止均回到中立姿态,保证 fade 转场(0.5s)自然
|
||||||
|
|
||||||
|
### 2.3 App 侧交互
|
||||||
|
|
||||||
|
- **角色页(新增 Tab 或首页入口,交互稿定稿时定)**:角色卡片列表(封面图 + 名称 + 类型标签),当前角色卡片高亮标记"使用中"。
|
||||||
|
- **切换**:点卡片 → 二次确认(可选,首版可直接切)→ 切换中 loading 态 → 成功后卡片高亮迁移 + 首页当前角色信息同步更新。
|
||||||
|
- **数据来源**:切换机制复用现有 `GET /api/config/available` + `POST /api/config/switch`(服务端已具备:文件名校验 → 配置验证 → 写入激活 → ConfigReloadRequest 热重载)。现有 available 接口只返回文件名列表,**需扩展携带角色元信息**(显示名/类型/封面),扩展形式由工程定(enrich 现接口或新增 `/api/characters`)。
|
||||||
|
|
||||||
|
### 2.4 行为与体验指标
|
||||||
|
|
||||||
|
| 项 | 要求 |
|
||||||
|
|----|------|
|
||||||
|
| 切换耗时 | 点卡片 → 设备呈现新角色首帧:目标 ≤ 3s,上限 5s(超时 App 显示"切换超时,请检查设备") |
|
||||||
|
| 切换期间画面 | 不得黑屏挂死;允许短暂转场(fade/最后一帧定格) |
|
||||||
|
| 失败回退 | 目标配置验证失败 → 服务端拒绝(现有行为:400 + 激活配置不变),设备保持原角色,App 明确报错原因;热重载失败 → 依赖内核既有 AutoRollback 回滚到上一可用配置,App 通过 WS 状态感知并提示 |
|
||||||
|
| 状态一致性 | App 展示的"当前角色"以设备侧上报为准(available.active / WS 推送),不以本地点击乐观状态为准 |
|
||||||
|
| 切换副作用 | 切角色即切人设:对话上下文清空(见 3.5),语音回合若进行中则先完成或取消再切 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 功能二:语音对话回合(V1 = 客户端是话筒和喇叭,设备是大脑和脸)
|
||||||
|
|
||||||
|
### 3.1 回合模型
|
||||||
|
|
||||||
|
一次"回合"= 用户说一段话,角色回一段话。V1 只做回合制,不做流式、不做打断。
|
||||||
|
|
||||||
|
```
|
||||||
|
App:按住说话录音 → 松开上传 → 等待(思考中动画) → 播放设备返回的回复音频
|
||||||
|
设备:接收音频 → ASR 转写 → 本地 LLM 生成回复(人设 prompt 跟随当前角色) → TTS 合成 → 返回音频(+转写文本+回复文本)
|
||||||
|
画面:回合应答期间角色切 "talk" 状态 → 结束回 "idle"
|
||||||
|
```
|
||||||
|
|
||||||
|
**声音归属铁律(老板补充三)**:设备音频硬件(扬声器/麦克风)当前未接入。TTS 合成的回复音频**一律返回给发起请求的客户端播放**(App 或 Web,见 §5),设备本地不播放、不依赖任何音频输出/输入硬件。设备角色收敛为:**ASR / LLM / TTS 计算 + 人物画面状态联动**。
|
||||||
|
|
||||||
|
### 3.2 App 侧需求
|
||||||
|
|
||||||
|
- **对话页(新增)**:
|
||||||
|
- 底部"按住说话"大按钮:按住录音(波形/计时反馈),松开发送,上滑取消;单次录音上限 30s(超限自动截断发送并提示)
|
||||||
|
- 发送后"角色思考中"等待态,支持取消本回合
|
||||||
|
- 收到回复自动播放;播放器走手机扬声器/耳机
|
||||||
|
- **对话历史时间线**:按时间排列,我方气泡显示转写文本(可折叠原音频回放),角色气泡显示回复文本 + 可重播的回复音频;历史仅存手机本地(隐私设计,见 §6)
|
||||||
|
- **权限与异常**:麦克风权限引导;录音失败/上传失败/设备忙/超时均有明确可理解提示与重试入口
|
||||||
|
- **并发**:同一时刻只允许一个进行中回合;进行中时按钮置灰或排队提示
|
||||||
|
|
||||||
|
### 3.3 设备侧需求
|
||||||
|
|
||||||
|
- **新增语音回合 HTTP 接口**(具体 URL/编码由架构师定,行为要求如下):
|
||||||
|
- 输入:一段录音(建议 16kHz 单声道,格式工程定),附当前会话标识
|
||||||
|
- 输出:转写文本 + 回复文本 + 回复音频(三者 App 时间线都需要)
|
||||||
|
- 同一时刻只处理一个回合,忙时返回明确的"设备忙"错误(如 409)
|
||||||
|
- 全程本地推理:ASR(whisper.cpp 系)→ LLM(llama.cpp 系,0.5B~2B 档小模型,老板点名 gemma 系列优先,**最终模型与档位以 spike 实测为准**)→ TTS(piper 系)
|
||||||
|
- **人设注入**:LLM system prompt = 当前角色内容包的人设 prompt + 风格参数(最大回复长度、语气约束)。宠物 = 拟声/简短俏皮;数字人 = 亲切自然;歌姬 = 活泼元气。**角色人设是内容包的一部分**,切角色即切人设。
|
||||||
|
- **TTS 音色**:内容包元信息含音色标识,不同角色音色可区分(受限于 piper 中文音色可用性,最低要求:至少可用一款中文音色全角色共用,音色差异化作为增强项,以 spike 结论为准)。
|
||||||
|
- **画面联动**:回合应答开始 → 状态机切 `talk`;回合结束 → 回 `idle`。因 V1 音频在客户端(App/Web)播放,"说话画面"与客户端放音的对齐采用近似策略(按回复音频时长估算保持 talk 态,或由客户端回报播放完成,二选一由架构师定),对齐误差 ≤ 1.5s 可接受。角色包无 `talk` 状态时优雅降级(见 2.2),不报错。
|
||||||
|
- **上下文**:会话内保留滑动窗口短上下文(建议最近 3~5 回合,以 spike 内存数据定),存内存即可;切角色/重启即清空。**不做持久化**(V1 边界)。
|
||||||
|
|
||||||
|
### 3.4 云端预留(老板明确要求,验收必查)
|
||||||
|
|
||||||
|
- LLM 后端抽象为可配置项:`llm.backend = "local" | "cloud"`(含 cloud 的 endpoint/key 等预留字段)
|
||||||
|
- **V1 只实现 local**;配置为 cloud 时行为 = 明确报"暂未支持",不 panic 不静默
|
||||||
|
- 接口抽象层(trait/消息协议)在 V1 落地,保证 V2/V3 接云端时不动调用方
|
||||||
|
- ASR/TTS 是否同样抽象后端由架构师定,产品只强制 LLM 一层
|
||||||
|
|
||||||
|
### 3.5 回合与角色切换的互斥
|
||||||
|
|
||||||
|
- 回合进行中收到切换角色请求:拒绝并提示"角色正在回应,稍后再试"(或 App 侧先行禁用切换入口)
|
||||||
|
- 切换角色成功后:对话上下文清空,时间线插入系统分隔("已切换到 ×××"),历史记录保留(属手机本地数据)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 功能三:模型管理(老板补充需求,2026-07-03)
|
||||||
|
|
||||||
|
### 4.1 设计动机(必须写清楚的产品逻辑)
|
||||||
|
|
||||||
|
**设备硬件会演进,模型不能写死在固件里。** 当前测试机是全志 A733(4G 内存,Linux ARM64)——这只是**最低档位**,不是目标终点。同一套 ShowenV2 系统未来跑在更强的板子上时,应能直接下载并切换到更大的模型(如 0.5B → 2B → 更高档),获得更强的对话能力,而**不需要重新烧录或重新部署系统**。"模型能力档位与设备能力匹配"是本产品的长期竞争力:硬件卖点升级 = 角色变聪明,软件系统不动。
|
||||||
|
|
||||||
|
### 4.2 功能需求
|
||||||
|
|
||||||
|
模型(LLM,及后续 ASR/TTS 模型同理)作为设备上的可管理资产,支持:
|
||||||
|
|
||||||
|
| 能力 | 要求 |
|
||||||
|
|------|------|
|
||||||
|
| 可用模型清单 | 查看模型仓库清单:每个模型含名称、版本、文件尺寸、运行内存需求、**推荐设备档位**(如"4G 内存档可用 / 建议 8G 以上");同时展示已下载/未下载状态 |
|
||||||
|
| 下载模型 | 从**国内镜像源**下载;下载进度实时展示(百分比/速度);完成后完整性校验(哈希);失败可重试,**支持断点续传或失败后从断点重试**(二选一由工程定,不允许每次从零开始) |
|
||||||
|
| 切换模型 | 从已下载模型中选择一个作为当前推理模型并生效;切换期间语音功能短暂不可用需有明确状态提示,视频播放不受影响;切换失败自动回退到上一个可用模型 |
|
||||||
|
| 删除模型 | 删除已下载的旧模型释放空间;当前使用中的模型不可删除(或先强制切换);删除有二次确认 |
|
||||||
|
| 存储配额 | 设备磁盘有限(当前可用 18G),模型存储有配额概念:展示"模型已用空间 / 配额上限",下载前预检剩余空间不足则明确拒绝并引导删除旧模型 |
|
||||||
|
| 档位守门 | 下载/切换超出当前设备内存能力的模型时给出明确警告(可强制继续,标注"可能不稳定"),推荐档位默认高亮匹配当前设备的选项 |
|
||||||
|
|
||||||
|
### 4.3 App 侧交互:模型管理页
|
||||||
|
|
||||||
|
- 入口:设置页或角色/语音相关页内"模型管理"
|
||||||
|
- 页面内容:
|
||||||
|
- **当前模型**卡片:名称、档位、内存占用
|
||||||
|
- **设备资源水位**:磁盘(模型配额已用/剩余)、内存(总量/可用),让用户直观看到"我的设备还装得下什么"
|
||||||
|
- **可用模型列表**:每项显示尺寸/内存需求/推荐档位/状态(未下载 / 下载中+进度 / 已下载 / 使用中),操作按钮随状态变化(下载 / 取消 / 切换 / 删除)
|
||||||
|
- 下载过程可退出页面后台继续,回到页面恢复进度显示;下载失败有原因提示与重试按钮
|
||||||
|
|
||||||
|
### 4.4 与现有机制的关系
|
||||||
|
|
||||||
|
产品行为层面**参照项目已有的"插件仓库 + 版本管理"模式**(plugin_repo 下载安装、version_manager 版本切换/回滚/GC 保护当前版本):模型清单 ≈ 插件仓库索引,模型切换 ≈ 版本切换(先验证后生效、失败回退),删除保护 ≈ GC 的 protected 机制。是否复用同一套基础设施属架构决策,**留给王思远**;PRD 只约束上述外部行为一致性。
|
||||||
|
|
||||||
|
### 4.5 V1 边界(模型管理部分)
|
||||||
|
|
||||||
|
- 模型仓库源 V1 可以是静态清单(自建镜像/OSS 上的 index 文件),不做动态商店
|
||||||
|
- 不做模型自动更新推送;检查更新为手动触发
|
||||||
|
- ASR/TTS 模型 V1 允许随系统预置固定版本,仅 LLM 必须实现完整"清单/下载/切换/删除"闭环(ASR/TTS 纳入同一框架为增强项)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 客户端矩阵(老板补充需求二,2026-07-03)
|
||||||
|
|
||||||
|
### 5.1 两个客户端都是 M2.1 交付对象
|
||||||
|
|
||||||
|
| 客户端 | 位置 | M2.1 改动 |
|
||||||
|
|--------|------|-----------|
|
||||||
|
| 安卓 App | `clients/flutter` | 角色切换页(§2.3)+ 语音对话页(§3.2)+ 模型管理页(§4.3),前文已覆盖 |
|
||||||
|
| **设备内嵌网页控制端** | `src/plugins/http/routes.rs:1961` 的 `WEB_UI_HTML` 字符串常量,设备 `/` 与 `/index.html` 直接服务(routes.rs:162-172);现有能力:状态监控、播放控制、状态机触发、WiFi、配置编辑、视频管理 | **必须新增**:① 角色切换界面(角色列表 + 当前角色标识 + 一键切换,行为指标同 §2.4);② 模型管理界面(当前模型 / 资源水位 / 下载进度 / 切换 / 删除,行为同 §4.2);③ 文字对话 + **回复音频浏览器播放(V1 必做)**(见 5.2) |
|
||||||
|
|
||||||
|
两端共用同一套设备 API:一端发起的角色切换/模型下载,另一端可见状态同步(Web 通过既有 WS 推送或轮询回显)。Web 端体验标准允许低于 App(工具属性优先),但错误提示、进度反馈、危险操作二次确认不可缺。
|
||||||
|
|
||||||
|
### 5.2 Web 端语音的技术约束(如实声明)
|
||||||
|
|
||||||
|
- **播放不受限,V1 必做**:浏览器 `<audio>` 播放没有安全上下文限制。Web 端文字对话的回复**必须带语音播放**(回复文字 + TTS 回复音频在浏览器播出)——设备无扬声器(老板补充三),"角色的声音"在 Web 场景就靠浏览器播放兜底,这是 V1 硬指标。
|
||||||
|
- **录音受限,降为评估项**:浏览器 `getUserMedia` 麦克风权限要求 HTTPS 安全上下文(localhost 除外),设备当前为纯 HTTP —— 因此 **V1 录音语音回合只落 App,Web 端录音不作为 V1 验收硬指标**。
|
||||||
|
- **Web 录音的技术路径(V1.5 增强候选,评估项)**:设备配自签名 HTTPS 证书后 `getUserMedia` 即可用,代价是浏览器首次访问出现一次证书警告需用户确认。方案技术可行、体验有瑕疵,列为 V1.5 增强候选,是否做、何时做在 V1 交付后按用户反馈评估。
|
||||||
|
- **Web 端 V1 主路径:文字输入对话** —— 文字 → LLM(同一人设链路,跳过 ASR)→ 回复文字 + TTS 回复音频(浏览器播放)。既绕开录音限制,又多出一个可演示入口,还使 LLM/TTS 链路可独立于 ASR 单独调试。
|
||||||
|
- 画面联动与并发规则同 §3.3/§3.5:文字回合期间角色切 `talk`,与语音回合互斥(同一时刻全设备只有一个进行中回合)。
|
||||||
|
|
||||||
|
### 5.3 功能 × 客户端对照表
|
||||||
|
|
||||||
|
| 功能 | 安卓 App | Web 控制端 | 说明 |
|
||||||
|
|------|---------|-----------|------|
|
||||||
|
| 角色切换 | ✅ 角色卡片页 | ✅ 必须新增 | 同一套 `config/available` + `config/switch` API |
|
||||||
|
| 录音(语音输入) | ✅ 主路径 | 🔍 评估项(V1.5 候选,非 V1 验收项) | getUserMedia 需 HTTPS;自签证书方案见 §5.2 |
|
||||||
|
| 回复音频播放 | ✅ 必做 | ✅ **必做** | 设备无扬声器,声音一律客户端播出(§3.1 铁律);浏览器 `<audio>` 无限制 |
|
||||||
|
| 文字对话 | ➖ 增强项(可复用时间线 UI,非 V1 强制) | ✅ 必须新增 | 文字 → LLM → 回复文字 + TTS 音频播放,跳过 ASR |
|
||||||
|
| 模型管理 | ✅ 模型管理页 | ✅ 必须新增 | 同一套模型管理 API,含下载进度 |
|
||||||
|
| 状态监控/播放控制/状态机/WiFi/配置/视频 | ✅ 已有 | ✅ 已有 | M1 存量能力,本期不动 |
|
||||||
|
|
||||||
|
### 5.4 Web 端可维护性风险(前置声明)
|
||||||
|
|
||||||
|
`WEB_UI_HTML` 是嵌在 Rust 源码内的单文件 HTML 字符串常量(routes.rs:1961-2384,约 420 行高密度单行 HTML/JS,routes.rs 全文件已达 2384 行)。M2.1 要再塞入角色切换 + 模型管理 + 文字对话三块界面,继续以字符串常量方式堆积将迅速不可维护。**建议王思远在架构评审时议**:改为 `include_str!` 引入独立 `.html` 文件(编译期仍内嵌进二进制、零运行时成本、部署形态不变)或静态资源目录。PRD 不强制实现方式,只要求交付前解决可维护性问题(详见 §9 风险表 #11)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 非功能需求
|
||||||
|
|
||||||
|
| 维度 | 要求 |
|
||||||
|
|------|------|
|
||||||
|
| 回合延迟 | 松开录音 → 手机开始播放回复:**目标值待 spike 数据校准后回填**(产品期望:短语音(≤5s 说话、简短回复)体验可接受线 ≤ 5s、良好线 ≤ 3s,仅作 UX 参照,不作承诺;spike 若证明不可达则调整模型档位或预期,见 §9) |
|
||||||
|
| 分项预算 | ASR / LLM 首 token+生成 / TTS / 传输 各分项延迟以 spike 报告为准,PRD 评审时回填成正式指标表 |
|
||||||
|
| 离线可用 | 本地链路(角色切换 + 语音回合)在仅局域网、无公网环境下 100% 可用;断公网不得出现任何功能降级或报错 |
|
||||||
|
| 资源共存 | 测试机全志 A733(4G 内存,Linux ARM64,**最低档位基准机**)实测基线(2026-07-03):可用内存 3.3G、视频渲染已占 ~1.25 核。语音三模型(常驻或按需加载,策略以 spike 定)峰值内存预算初定 ≤ 2.5G(保留 ≥ 800M 余量,**以 spike 实测修正**);推理期间视频渲染不得出现可感知掉帧/卡顿,状态机触发仍需及时响应。更高档设备放宽预算由模型管理的档位机制承接(§4) |
|
||||||
|
| 模型落盘 | 模型文件占用设备磁盘(当前可用 18G),模型存储配额初定 ≤ 4G(含多模型共存),具体以选型定;配额行为见 §4.2 |
|
||||||
|
| 隐私(本地模式核心卖点) | 录音与对话内容**不出本地网络、不上云**;设备端不持久化用户录音与对话文本(处理完即弃);对话历史仅存用户手机本地,可一键清空;App 隐私文案明示"语音在你的设备上本地处理" |
|
||||||
|
| 稳定性 | 语音链路任何一环失败(ASR 空结果/LLM 超时/TTS 失败)都必须给发起请求的客户端(App/Web)返回结构化错误,不得拖垮视频主循环;连续失败不影响下一回合重试 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 不做什么(V1 边界)
|
||||||
|
|
||||||
|
1. **设备端麦克风/扬声器直接对话** — V2(老板补充三确认:设备扬声器/麦克风当前**未接入**;V1 全部声音走客户端,不依赖设备音频硬件;音频硬件接入后启动 V2,见 §10)
|
||||||
|
2. **唤醒词**("小狗小狗"类免手动唤起) — V3
|
||||||
|
3. **精细口型同步** — 不做;talk 状态只要求"在说话的感觉"
|
||||||
|
4. **多轮长上下文记忆的持久化** — 不做;仅会话内内存滑动窗口
|
||||||
|
5. 流式 ASR / 流式 TTS / 回合打断 — 不做,V1 纯回合制
|
||||||
|
6. 云端 LLM 的实际接入 — 只留接口不实现
|
||||||
|
7. 歌姬"真唱歌"(歌声合成) — 不做;歌姬 V1 是"会聊天的歌姬人设",唱歌能力另立项
|
||||||
|
8. 角色内容包的在线商店/分发 — Phase 2 后续里程碑
|
||||||
|
9. **Web 端录音语音对话** — 受 getUserMedia HTTPS 安全上下文限制(§5.2),V1 Web 用"文字对话 + 回复音频浏览器播放"替代;自签 HTTPS 解锁录音为 V1.5 增强候选(评估项,非 V1 验收)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 验收标准(可演示的用户旅程,逐条过)
|
||||||
|
|
||||||
|
1. 打开 App 进入角色页,看到 狗 / 猫 / 数字人 / 歌姬 至少 4 张角色卡片,当前角色卡片有"使用中"标记
|
||||||
|
2. 点击"歌姬"卡片 → 设备画面在目标时限内切换为歌姬 idle 循环 → App 当前角色标记同步更新为歌姬
|
||||||
|
3. 构造一个非法/损坏的内容包并尝试切换 → 设备保持原角色继续播放,App 显示明确错误原因
|
||||||
|
4. 在对话页按住说话:"你好,你叫什么名字?" → 松开 → 思考中动画 → 手机播出歌姬人设风格的语音回复;回合期间设备画面为 talk(或宠物包降级状态),结束后回到 idle
|
||||||
|
5. 对话历史时间线正确显示:我的转写文本 + 歌姬回复文本 + 回复音频可重播
|
||||||
|
6. 断开公网(仅保留局域网)重复旅程 2 和 4 → 全部成功,体验无差异
|
||||||
|
7. 切换到"狗"再问同一问题 → 回复风格明显变为拟声/简短俏皮,且时间线出现"已切换到狗"分隔、上下文已重置
|
||||||
|
8. 回合进行中再次按住说话或点击切换角色 → 被拒绝且有友好提示,不产生错乱
|
||||||
|
9. 语音回合全程观察设备画面 → 视频播放无可感知卡顿
|
||||||
|
10. 检查设备配置:`llm.backend` 配置项存在,切为 `cloud` 时得到"暂未支持"的明确响应(云端预留验收)
|
||||||
|
11. 设备端抽查:回合结束后无录音文件/对话文本落盘残留(隐私验收)
|
||||||
|
12. 打开模型管理页 → 看到当前模型、设备磁盘/内存水位、可用模型清单(含尺寸/内存需求/推荐档位标注)
|
||||||
|
13. 下载一个新模型 → 进度实时显示 → 完成后校验通过、状态变"已下载";中途断网 → 失败有提示,重试不从零开始
|
||||||
|
14. 切换到新下载的模型 → 语音回合使用新模型正常应答,视频播放全程不受影响;**全程不重新烧录/不重新部署系统**(老板点名验收项)
|
||||||
|
15. 删除一个未使用的旧模型 → 空间水位下降;尝试删除使用中的模型 → 被拒绝并提示
|
||||||
|
16. 磁盘配额不足时下载 → 被明确拒绝并引导删除旧模型
|
||||||
|
17. 浏览器访问设备 `http://<device-ip>:8080/` → Web 控制端可见当前角色并一键切换,设备画面切换成功,App 侧角色状态同步更新(两端一致性验收)
|
||||||
|
18. Web 控制端模型管理:查看当前模型与资源水位 → 下载新模型见实时进度 → 切换 → 删除旧模型,全流程可完成且与 App 侧状态互通
|
||||||
|
19. Web 控制端文字对话:输入文字 → 收到当前角色人设风格的回复文字 + **回复音频在浏览器内播放**(V1 必做,设备无扬声器由浏览器出声);回合期间设备画面 talk 联动,与语音回合互斥规则生效
|
||||||
|
20. 全部既有回归:147 项测试 + Flutter 测试继续全绿,零 warning
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 风险与依赖
|
||||||
|
|
||||||
|
| # | 风险/依赖 | 说明 | 应对 |
|
||||||
|
|---|----------|------|------|
|
||||||
|
| 1 | **数字人/歌姬素材从哪来**(最大外部依赖) | 每角色最少 4 状态 × 规格素材(§2.2),且跨片段角色一致性要求高 | 建议方案见下方"素材方案建议";**需老板拍板** |
|
||||||
|
| 2 | **spike 结论可能降档** | 2B 模型若延迟/内存超预算,降 0.5B 档甚至更小;ASR/TTS 模型同理 | PRD 指标留待回填;人设 prompt 按小模型能力设计(短、指令简单);回复长度上限收紧是首选降级手段 |
|
||||||
|
| 3 | 设备音频硬件未接入(~~扬声器现场验证~~ 已关闭:老板 2026-07-03 确认扬声器/麦克风未插入,无需再验证) | V1 全链路不依赖设备音频硬件(声音一律客户端播出,§3.1 铁律),**对 V1 零影响** | 若后续插入 USB/3.5mm 麦克风+扬声器,作为 V2(设备直接对话)的启动前置条件,届时再做接入验证 |
|
||||||
|
| 4 | CPU/内存争抢 | 视频渲染 ~1.25 核基础负载上叠加三模型推理 | spike 明确并发余量;必要时推理限核/降优先级;验收标准 9 兜底 |
|
||||||
|
| 5 | 配置 schema 演进 | `deny_unknown_fields` 下新增 `character` 块需内核同步改 schema,旧包/新包兼容策略要设计 | 列为内核工程依赖,架构评审首个议题(方案 A/B,§2.1) |
|
||||||
|
| 6 | piper 中文音色可用性 | 中文 TTS 音色质量/数量待验证 | spike 覆盖;最低验收线为"一款可懂中文音色",音色差异化降为增强项 |
|
||||||
|
| 7 | 存量包路径不可移植 | dog/cat 素材在仓库外相对路径 | 新包强制自包含目录规范;存量包 V1 不动,迁移列 backlog |
|
||||||
|
| 8 | App 录音权限与机型差异 | iOS/Android 麦克风权限、录音格式差异 | 沿用 BLE 权限引导的成熟模式;录音格式在 App 侧归一后上传 |
|
||||||
|
| 9 | 模型镜像源建设与维护 | 国内可达、带宽/存储成本、清单(index)维护责任人未定 | V1 用静态清单 + 自建镜像/OSS(§4.5);源地址做成可配置;**清单维护归属需老板/CEO 定** |
|
||||||
|
| 10 | 大文件下载对设备的冲击 | GB 级下载占带宽/磁盘 IO,可能影响视频播放与 HTTP 服务 | 下载限速/低优先级;沿用 M1.2 已解决的"上传流式化"经验(避免内存尖峰);下载中不允许同时切模型 |
|
||||||
|
| 11 | **Web 控制端可维护性** | `WEB_UI_HTML` 为嵌在 routes.rs 内的单文件 HTML 字符串常量(routes.rs:1961-2384,约 420 行高密度单行 HTML/JS,routes.rs 全文件已 2384 行),M2.1 需再加角色切换/模型管理/文字对话三块界面,继续内嵌堆积将不可维护 | **列王思远架构评审议题**:`include_str!` 拆独立 .html(编译期内嵌不变、部署形态不变)或静态资源目录;实现方式工程定,交付前必须解决(§5.4) |
|
||||||
|
|
||||||
|
### 素材方案建议(需老板拍板)
|
||||||
|
|
||||||
|
| 方案 | 优点 | 缺点 | 建议 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| A. AI 视频生成(可灵/即梦/Wan 等图生视频,先定角色立绘再批量生成状态片段) | 快、便宜、可迭代;一致性靠同一张立绘做参考帧可控 | 循环无缝性和动作质量需筛选返工;生成额度成本 | **推荐**:先各做 1 个角色 × 4 状态的试产验证管线 |
|
||||||
|
| B. 外包(Live2D/三维渲染工作室) | 质量与循环可控 | 周期长、贵、迭代慢 | 备选:A 试产不达标再启动 |
|
||||||
|
| C. 老板提供素材 | 零制作成本 | 是否存在、规格是否匹配未知 | 若老板有现成资源优先评估 |
|
||||||
|
|
||||||
|
**所需素材清单(无论哪种方案)**:数字人、歌姬各一套 —— idle / talk / greet / sleep 四状态片段,规格按 §2.2;每角色另需 1 张封面图(角色卡片用)+ 人设一句话设定(供撰写 persona prompt)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Roadmap 对齐
|
||||||
|
|
||||||
|
| 版本 | 定位(一句话) |
|
||||||
|
|------|---------------|
|
||||||
|
| **V1(本 PRD,M2.1)** | 手机遥控切换角色 + 客户端当话筒喇叭(设备本地不出声)的本地对话回合 + 模型可下载/切换(不重烧系统),App 与 Web 控制端双端交付,云端接口预留 |
|
||||||
|
| **V2** | 设备自带麦克风/扬声器直接对话,手机退为管理端(**前置条件:设备音频硬件接入后启动**——当前扬声器/麦克风未插入;接入后还需回声/拾音工程) |
|
||||||
|
| **V3** | 唤醒词免手动唤起 + 本地/云端 LLM 协同(本地兜底、云端增强),走向真正"常驻的数字生命" |
|
||||||
@@ -126,6 +126,16 @@
|
|||||||
- 在 `src/core/tests.rs` 增加 7 个回归测试,覆盖初始状态广播和 6 个自定义管理命令;保留旧生命周期测试并过滤新增状态广播事件
|
- 在 `src/core/tests.rs` 增加 7 个回归测试,覆盖初始状态广播和 6 个自定义管理命令;保留旧生命周期测试并过滤新增状态广播事件
|
||||||
- `cargo check --workspace --all-targets` 零 warning,`cargo test --workspace` 107/107 + 集成测试全绿
|
- `cargo check --workspace --all-targets` 零 warning,`cargo test --workspace` 107/107 + 集成测试全绿
|
||||||
|
|
||||||
|
## 个人经验 (2026-07-03 - M2.1 设备端本地 AI spike)
|
||||||
|
- Radxa Cubie A7A (Allwinner A733) = 2×A78@2.0G + 6×A55@1.8G 带 dotprod + NPU,不是老 A53 板子,量化推理能力远超预期
|
||||||
|
- **big.LITTLE 上 llama.cpp 线程数是生死线**:t=2 锁大核生成 16.4 t/s;t=8 全核反而崩到 7.2 t/s(ggml 同步屏障被小核拖尾)且把 showen_v2 挤到 50%——多线程≠更快
|
||||||
|
- llama-cli 默认上下文是内存杀手:Gemma2-2B 默认 ctx 峰值 RSS 3.25G 直接触发 swap;正式集成必须 `-c 1024` 限死
|
||||||
|
- whisper.cpp encode 是固定 30s 窗口成本(tiny ~1.5s),语音再短也省不掉,这是 ASR 延迟下限;对静音会幻觉出字幕,必须 VAD 前置
|
||||||
|
- piper zh_CN-huayan RTF 0.30 很稳,TTS 不是瓶颈;瓶颈排序 LLM > ASR > TTS
|
||||||
|
- 设备 github 直连 git clone 会被 TLS 掐断、release 直下 10KB/s:**ghfast.top 代理 + hf-mirror.com 是设备上拿代码/模型的唯一可靠路径**,部署脚本必须内置回退
|
||||||
|
- 测量方法论:无 GNU time 时用 /proc/<pid>/status 的 VmHWM 轮询取峰值 RSS;showen 影响用 /proc/stat+/proc/pid/stat 双点差分算瞬时 CPU%,比 top -bn1 首帧准
|
||||||
|
- llama-cli 参数坑:`--no-warmup`(双横线),`-no-warmup` 直接报错退出——远程 nohup 跑测试前先本地空跑一次参数
|
||||||
|
|
||||||
## 个人经验 (2026-07-03 - M1.2 集成测试返工教训)
|
## 个人经验 (2026-07-03 - M1.2 集成测试返工教训)
|
||||||
- `tests/m1_2_dynamic_plugin.rs` 目标机实跑暴露 2 个 warning(unused imports `Destination`/`Envelope` + 死函数 `manifest_with_caps`)——是我预写辅助函数/import 后测试改走 `register_dynamic_with_manifest` 路线留下的残留
|
- `tests/m1_2_dynamic_plugin.rs` 目标机实跑暴露 2 个 warning(unused imports `Destination`/`Envelope` + 死函数 `manifest_with_caps`)——是我预写辅助函数/import 后测试改走 `register_dynamic_with_manifest` 路线留下的残留
|
||||||
- 教训:**交付前必须对测试文件本身做死代码自查**(本机编译不了 aarch64 也要人工逐符号核对 import 和 helper 的使用点),不能只保证测试逻辑正确
|
- 教训:**交付前必须对测试文件本身做死代码自查**(本机编译不了 aarch64 也要人工逐符号核对 import 和 helper 的使用点),不能只保证测试逻辑正确
|
||||||
|
|||||||
@@ -120,6 +120,13 @@
|
|||||||
7. 产品上线后收集数据和反馈
|
7. 产品上线后收集数据和反馈
|
||||||
8. 迭代优化产品
|
8. 迭代优化产品
|
||||||
|
|
||||||
|
## 经验
|
||||||
|
- **2026-07-03 M2.1 PRD**:写 PRD 前先读代码核实能力边界,避免重复造轮子——角色切换直接复用已有 `/api/config/available` + `/api/config/switch`(含验证/热重载/失败不落盘),PRD 只定义行为与体验,不发明新机制
|
||||||
|
- 性能指标没有实测数据时一律标注"待 spike 校准",绝不编造数字;UX 期望值可写但注明"仅作参照,不作承诺"
|
||||||
|
- 配置结构体 `deny_unknown_fields` 意味着内容包 JSON 加新字段必须内核同步改 schema——产品定义信息需求,落地方案(schema 扩展 vs sidecar)留给架构师并在 PRD 里显式标注为工程依赖
|
||||||
|
- 老板中途补需求(模型管理):并入 PRD 时要写清设计动机(硬件会演进、A733/4G 只是最低档)并在验收标准里落成老板点名的可验证条目("换模型不重烧录")
|
||||||
|
- 涉及外部依赖(素材制作、镜像源维护)的开放问题必须在 PRD 和 TEAM_CHAT 中显式列出待拍板项,不能默默替老板做决定
|
||||||
|
|
||||||
## 记忆
|
## 记忆
|
||||||
- ShowenV2 是数字生命窗口平台,不局限于宠物
|
- ShowenV2 是数字生命窗口平台,不局限于宠物
|
||||||
- 插件架构是核心竞争力
|
- 插件架构是核心竞争力
|
||||||
|
|||||||
Reference in New Issue
Block a user