Files
digital_person/app/note/design_doc
2026-03-10 15:40:05 +08:00

256 lines
11 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

1. ## 🎯 当前使用的ASR模型
### 模型名称SenseVoice (RKNN版本)
### 模型架构:
- 编码器 : sense-voice-encoder.rknn - RKNN格式的神经网络模型
- 嵌入层 : embedding.npy - 词嵌入矩阵
- 分词器 : chn_jpn_yue_eng_ko_spectok.bpe.model - BPE分词模型
### 模型特点:
1. 多语言支持 - 支持中文、日文、粤语、英文、韩文
2. RKNN加速 - 针对RK3588等Rockchip芯片优化
3. ITN支持 - 启用了逆文本归一化Inverse Text Normalization提高数字/日期识别准确性
2. ## TTS模型信息
### 模型名称
Sherpa-ONNX VITS - 中文版本sherpa-onnx-vits-zh-ll
### 模型文件
位于 app/src/main/assets/tts_model/sherpa-onnx-vits-zh-ll/ 目录:
- model.onnx - ONNX格式的声学模型
- tokens.txt - 音素/字符映射表
- lexicon.txt - 发音词典
- phone.fst - 音素转换规则
- date.fst - 日期归一化规则
- number.fst - 数字归一化规则
- new_heteronym.fst - 多音字处理规则
3. ## VAD模型信息
### 模型名称
Silero VAD (Voice Activity Detection)
### 模型文件
- 文件路径: assets/vad_model/silero_vad.onnx
- 格式ONNX格式
4. 模型部署对比
模型 类型 格式 RKNN加速 推理设备 配置
ASR SenseVoice .rknn ✅ 是 NPU RKNN Runtime
VAD Silero VAD .onnx ❌ 否 CPU provider="cpu"
TTS Sherpa-ONNX VITS .onnx ❌ 否 CPU ONNX Runtime
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ AudioProcessor │────▶│ VadManager │────▶│ ASR Queue │
│ (录音+增益) │ │ (语音活动检测) │ │ (Channel队列) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
┌─────────────────────────┘
┌─────────────────┐
│ runAsrWorker │
│ (协程工作器) │
└─────────────────┘
┌─────────────────┐
│ SenseVoice │
│ (RKNN推理) │
└─────────────────┘
5. live2d, Haru的动作
由于没有官方文档基于Live2D模型的常见设计模式我建议以下映射
### 🎭 开心类情绪
- haru_g_m22 眯眼微笑
- haru_g_m21 跳动微笑
- haru_g_m18 手收背后微笑
- haru_g_m09 微微鞠躬
- haru_g_m08 深深鞠躬
### 😢 伤心类情绪
- haru_g_m25 - 扁嘴
- haru_g_m24 - 低头斜看地板,收手到背后
- haru_g_m05 扁嘴,张开双手
- haru_g_m16 双手捧腮,思考
### 😠 愤怒类情绪
- haru_g_m11 双手交叉,摇头,扁嘴
- haru_g_m04 双手交叉,点头
- haru_g_m03 双手交叉,点头
### 😌 平和类情绪
- haru_g_m15 双手交叉在胸前
- haru_g_m07 举起左手
- haru_g_m06 举起右手
- haru_g_m02 双手放到背后
- haru_g_m01 点头
### 😲 惊讶类情绪
- haru_g_m26 - 后退一步(适合:惊讶、吃惊)
- haru_g_m12 摆手,摇头
### 😕 困惑类情绪
- haru_g_m14 身体前倾,皱眉
- haru_g_m13 身体前倾,双手分开
### 害羞
- haru_g_m19 脸红微笑
### 担心
- haru_g_m20 手指点腮,思考,皱眉
### ❤️ 关心类情绪
- haru_g_m17 靠近侧脸
6. 其实可以抄一下讯飞的超脑平台的功能:
https://aiui-doc.xf-yun.com/project-2/doc-397/
7. 人脸检测使用的是RKNN zoo里的 retinaface模型转成了rknn格式并且使用了wider_face的数据集验证集进行了校准下载地址
https://www.modelscope.cn/datasets/shaoxuan/WIDER_FACE/files
8. 人脸识别模型是insightface的r18模型转成了rknn格式并且使用了 lfw 的数据集进行了校准,下载地址:
https://tianchi.aliyun.com/dataset/93864
9. 本地LLM用的是 rkllm 模型,由于内存限制,只能用较小的模型,如 Qwen3-0.6B-rk3588-w8a8.rkllm。
10. 数字人交互设计说明书(优化版)
核心原则
* 尊重用户:给用户足够的反应时间,不抢话,不催促。
* 主动但不打扰:用户沉默时适度引导,但不强行交互;数字人拥有独立的内心活动,即便无人交互也保持“生命感”。
* 个性化:记住每个用户的偏好、名字、对话历史,并据此调整问候和回应。
* 动作同步Live2D人物的表情与动作与当前状态、情绪、内心活动相匹配。
* 持续内心活动:数字人即使在没有用户时也会进行“回忆”或“思考”,并通过文字展现,用户可随时打断并询问想法。
状态定义
[空闲状态]:无人,数字人无内心活动(省电模式)。
[回忆状态]:无人,数字人正在根据记忆产生内心想法,通过表情表现。
[问候状态]:检测到用户,主动打招呼。
[等待回复状态]:问候后或对话间隙,等待用户回复。
[对话状态]:正在与用户交流,根据情绪调整动作。
[主动引导状态]:用户沉默但仍在画面中,数字人主动开启新话题。
[告别状态]:用户离开画面,数字人告别。
[空闲状态]
动作 haru_g_idle (待机动作)
检测到人脸 → 等待1秒让人脸稳定
[问候状态]
动作
- 认识用户: haru_g_m22 (高兴动作)
- 不认识: haru_g_m01中性动作
AI问候根据是否认识节日时间等因素个性化
启动20秒计时器
[等待回复状态]
动作 haru_g_m17
├─ 如果用户按下了麦克风按钮 → 进入[对话状态]
│ 动作 :根据对话情绪动态调整
│ - 开心: haru_g_m22 / haru_g_m21 / haru_g_m18 / haru_g_m09 / haru_g_m08
│ - 悲伤: haru_g_m25 / haru_g_m24 / haru_g_m05 / haru_g_m16
│ - 惊讶: haru_g_m26 / haru_g_m12
│ - 愤怒: haru_g_m04 / haru_g_m11 / haru_g_m04
│ - 平静: haru_g_m15 / haru_g_m07 / haru_g_m06 / haru_g_m02 / haru_g_m01
│ AI根据内容回应持续直到用户说“再见”
│ ↓
│ (用户离开)→ 进入[告别状态]
└─ 如果20秒内无回复
检查用户是否还在画面
├─ 如果还在 → [主动引导状态]
│ 动作 haru_g_m15 / haru_g_m07 (中性动作)
│ AI开启轻松话题如“我出一道数学题考考你吧1+6等于多少
│ 等待10秒
│ ↓
│ ├─ 回复 → 进入[对话状态]
│ └─ 没回复 → 换话题我们上完厕所应该干什么呀最多重复3次
│ 动作 haru_g_m22 / haru_g_m18
│ (重复尝试)→ 再次等待10秒
3次后仍无回复→ 回到[等待回复状态]
└─ 如果已离开 → [告别状态]
动作 haru_g_idle (告别后待机)
3秒后 → 回到[空闲状态]
[空闲状态] (长时间无人)
如果持续30秒无人 → 进入[回忆状态]
动作 haru_g_m15
回顾之前的聊天记录,生成想法,不发声,把想法显示在屏幕上
如果检测到人脸 → 立即中断回忆,进入[问候状态]
[回忆状态] 被用户询问“你在想什么?”
AI说出最近的想法如“我刚才在想上次你说你喜欢蓝色...”)
进入[问候状态]或直接进入[对话状态](根据用户后续反应)
[告别状态] (用户离开后)
动作 简短告别,用语音,→ 等待3秒 → 回到[空闲状态]
11. ## 用户类型区分
1. guest 用户
- 默认用户ID当没有检测到人脸时使用
- 在 Live2DChatActivity.kt 中初始化为 private var activeUserId: String = "guest"
- 表示未通过人脸识别的临时用户
2. face_ 用户
- 通过人脸识别生成的用户ID格式为 face_<数字>
- 在 FaceDetectionPipeline.kt 中生成: lastFaceIdentityId = match.matchedId?.let { "face_$it" }
- 表示通过人脸识别的正式用户
## 转换逻辑
当系统检测到人脸时,会触发以下流程:
1. 人脸检测 FaceDetectionPipeline 检测到人脸
2. 身份识别 FaceRecognizer 尝试识别用户身份
3. ID生成 :如果是新用户,生成新的 face_<数字> ID
4. 回调更新 :通过 onPresenceChanged 回调将 faceIdentityId 传递给 Live2DChatActivity
5. ID切换 Live2DChatActivity 中的 interactionController.onFacePresenceChanged 会调用 handler.onRememberUser(faceIdentityId, recognized)
6. 更新活跃用户 onRememberUser 方法会将 activeUserId 更新为 faceIdentityId
因此,当检测到人脸时, guest 用户会自动切换为 face_ 用户。
face_profiles 和 user_memory 表之间的关联是通过 ID转换 实现的,没有专门的关联表:
## 关联机制
1. ID转换规则
- face_profiles 表中的 id 字段(数字)→ 转换为 face_<id> 格式
- 例如: id=1 → face_1
- 这个转换在 FaceDetectionPipeline.kt 中实现: lastFaceIdentityId = match.matchedId?.let { "face_$it" }
2. 关联流程
- 系统检测到人脸后,从 face_profiles 表中查找匹配的记录,获取 id
- 将 id 转换为 face_<id> 格式的用户ID
- 这个用户ID被用作 user_memory 表中的 userId 字段
- 通过这个 userId ,两个表就建立了关联
12. 使用 adb shell 直接操作sqlite数据库
1. 进入设备 shell
adb shell
2. 找到应用数据库
# 进入应用数据目录
run-as com.digitalperson
# 进入数据库目录
cd databases
# 查看数据库文件
ls -la
3. 使用 sqlite3 命令查看数据库
bash
# 打开数据库
sqlite3 your_database.db # digital_human.db face_feature.db
# 在 sqlite3 提示符下执行命令:
.tables # 查看所有表
.schema table_name # 查看表结构
SELECT * FROM table_name; # 查询数据
.headers on # 显示列名
.mode column # 列模式显示
.quit # 退出