Files
ylhan bdd6bfb63d AI桌面陪伴助手:方案更新至 v2.4,代码剥离到独立仓库
代码剥离
- 助手本体、TTS 服务、P0 基准脚本、ESP32 固件移到 ~/workspace/ai-companion
  (独立 git 仓库),本目录只留方案、P0 报告与硬件记录
- 因此删除 esp32_smile_test.ino / esp32_touch_eyes.ino
- 同时移除已失效的 .gitignore(原本只为挡住模型体积,代码已搬走)

方案 v2.4 重大变更:架构从"单机"改为"服务器即助手、本地为客户端"
- 起因:实测 N5095 无 AVX2,跑不动可用的语音模型
- N5095 降为客户端/外设桥,只做 USB 接入、DoA、WebRTC 客户端
- 实施阶段表加进度列(P0/P1/P3/P4a 部分完成),新增三条验收要求
- 采购清单按实际到货更新,标出屏幕形态待确认(2.8寸 vs 原定1.28寸圆屏)

技术栈(实测更新)
- LLM:DeepSeek deepseek-flash(云端,必须关思考);本机 27B 已停用
- TTS:Qwen3-TTS 1.7B(服务器 3090);vits-zh-ll 因音色不满意被替换
- STT:Zipformer int8 未变,中文识别率仍是未闭合项

新增两份 P0 报告
- P0-Qwen3TTS报告.md:TTS 换型过程与实测
- P0-DeepSeek验证报告.md:四条路径验证

两份旧报告加了状态说明(结论仍有效但选型已变),
并修正了随代码移走而失效的引用与复现命令。
2026-09-15 11:08:56 +08:00

114 lines
5.2 KiB
Markdown
Raw Permalink 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.
# P0 验证报告 · DeepSeek API
日期:2026-09-14。机器:N5095 / Ubuntu 24.04.3 / Python 3.13.5。
脚本:`~/workspace/ai-companion/p0/verify_deepseek.py`。结果:**11/11 通过**。
复现:
```bash
set -a; . ~/.config/ai_assistant/env; set +a
cd ~/workspace/ai-companion && python3 p0/verify_deepseek.py
```
密钥存放:`~/.config/ai_assistant/env`(权限 600,不在项目目录内,不进版本管理)。
## 结论摘要
| # | 项目 | 结果 |
|---|---|---|
| 0 | 模型清单 | 仅 `deepseek-flash`、`deepseek-v4-pro` |
| 1a | 纯文本流式 | 可用 |
| 1b | 思考内容分离 | on 模式有 `reasoning_content`;off 模式无 |
| 1c | 首 token 延迟 | **P50 = 786ms,P95 = 1100ms**(N=8) |
| 2a | 流式工具调用 | 可用,参数 JSON 正确 |
| 2b | 工具结果回灌 | 可用 |
| 2c | 思考模式约束 | 开启时**必须回传 `reasoning_content`** |
| 3a | **图片输入** | **可用**,正确读出图中数字 |
| 4a | 中途断开(打断) | 无异常 |
| 4b | 超时 | 正确抛出 `TimeoutError` |
| 4c | 错误模型名 | HTTP 400,可作启动自检 |
## 逐条说明
### 1. 模型名:方案文档正确,Pipecat 默认值错误
`GET /v1/models` 实际返回:
```json
[{"id": "deepseek-flash"}, {"id": "deepseek-v4-pro"}]
```
- 方案文档 §2 记的 `deepseek-flash` **正确**。
- **Pipecat 的 `DeepSeekLLMService` 默认模型是 `deepseek-v4-flash`,该模型不存在**,直接用会 400。
实例化时必须显式覆盖为 `deepseek-flash`。
### 2. 思考模式必须显式关闭(重要)
`deepseek-flash` 默认开启思考模式。此时 API 要求**把上一轮 assistant 消息里的
`reasoning_content` 原样回传**,否则任何多轮对话与工具回灌都返回:
```
400 invalid_request_error: The `reasoning_content` in the thinking mode must be passed back to the API.
```
实测三种手工构造 assistant 消息的写法(`content=None` / `content=""` / 不带 tools)**全部 400**;
只有回传服务端返回的原始 assistant 消息才通过。
**影响**:多数框架的上下文层按 OpenAI 格式存储消息,不保留 `reasoning_content`——
一旦开启思考模式,Pipecat 的上下文管理与工具循环会持续踩这个坑。
**决定**:会话主路径传 `"thinking": {"type": "disabled"}`。两条理由:
1. 彻底消除 `reasoning_content` 回传要求,上下文层可安全裁剪消息;
2. 开启时**第一个流式 chunk 是 `reasoning_content` 而非 `content`**,若直接送 TTS 会念出思考过程。
关闭后两者合一,无需分流。
Pipecat 该服务的默认值恰好是 `DeepSeekThinkingConfig(type="disabled")`,与本结论一致。
若将来要开思考以提升回答质量,必须同时改造上下文层保证 `reasoning_content` 不丢。
### 3. 首 token 延迟
N=8,短问答,`thinking=disabled`:**P50 = 786ms,P95 = 1100ms**(min 515 / max 1100)。
对照方案 P1 验收目标"短问答结束到首段有声回复 P50≤2 秒、P95≤4 秒",
LLM 占约 0.8 秒,**余下约 1.2 秒预算**留给 STT 收尾判定 + TTS 首段合成。这个余量是否够,
取决于本地 TTS 的 RTF(待测,见下)。
注:thinking 开关对首包时间影响不大(约 700ms vs 718ms),但关闭后总耗时更短,因为不再生成思考 token。
### 4. 图片输入可用(P5 的意外好消息)
`deepseek-flash` 接受 `image_url` 的 base64 data URI,正确读出图中文字("7391")。
方案 §P5 的视觉问答不需要另找模型,按需抓拍 → 缩放 → base64 上传即可。
**未测**:视觉请求的 TTFT(预估显著长于纯文本)、大图 token 消耗、并发下的表现。
按需视觉是按次计费项,接 P5 时需单独测成本。
### 5. 工具调用链路完整
流式工具调用可用,`finish_reason="tool_calls"`,参数 JSON 正确。
回灌工具结果后模型能生成自然语言确认("客厅的灯已经打开了")。
这是 P5 米家控制的基础链路,已验证通畅。
**注意**:回灌时 `tool_call_id` 必须用服务端返回的真实值,assistant 消息必须用服务端返回的原始对象,不能手工构造。
### 6. 打断与超时
- **打断**(收到若干 chunk 后主动 close):无异常抛出,连接正常释放。对应方案"打断时取消旧回复生成"的客户端能力成立。
- **超时**:非流式长生成 + 2 秒预算,正确抛出 `TimeoutError`。
- 流式下 socket 超时不会因首包快而触发——**"打断"和"超时"必须分开实现检测**,不能只做一种。
### 7. 计费与缓存
`usage` 返回 `prompt_cache_hit_tokens` / `prompt_cache_miss_tokens`,实测命中 256/398。
系统提示词固定可吃到缓存,对月费有利。方案 §8 要求的费用统计应记录这两个字段。
## 遗留与未验证
- 视觉请求的延迟与 token 成本未测。
- 长上下文(多轮 + 记忆注入)下的延迟退化未测。
- 并发请求未测(多用户场景下的表现)。
- 本次仅验证 API 链路,**未接入 Pipecat、未写任何管线代码**。
- 本机 `github.com` / `huggingface.co` 直连不通,需走本地 mihomo 代理 `127.0.0.1:7890`
或国内镜像。DeepSeek API 直连正常,不需要代理。