Files
note_sync/有趣的项目/AI桌面陪伴助手/P0-本地LLM验证报告.md
T
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

6.0 KiB
Raw Blame History

P0 验证报告 · 本地 Qwen3.8-27B

⚠️ 状态:该服务已于 2026-09-15 停用。 原因:用户要求换更强的语音模型(vits-zh-ll 音色不满意), 而 3090 只有 24GB——27B 的 vLLM 占 21.5GB,装不下 Qwen3-TTS。 决定让 LLM 走云端 DeepSeek,GPU 让给语音。见 P0-Qwen3TTS报告.md。

本报告的结论仍然有效(用于将来重启该服务,或评估其它本地 LLM): 关思考可让首 token 从 1390ms 降到 367ms;思考 token 会吃掉 max_tokens 预算; 只接受一条 system 消息;思考字段名与 DeepSeek 不同。

日期:2026-09-14。端点:http://192.168.0.20:18020/v1(vLLM,局域网 1.4ms)。 脚本:~/workspace/ai-companion/p0/verify_local_llm.py。结果:5/6 通过(未通过项为视觉,见 §5)。

复现:

set -a; . ~/.config/ai_assistant/env; set +a
cd ~/workspace/ai-companion && python3 p0/verify_local_llm.py

一、服务实况

方案文档假设 LLM 用 DeepSeek 云 API。实测发现局域网内已有可用服务:

项 值
服务 vLLM(不是 llama.cpp,服务器上两套都有)
模型 Qwen3.8-27B-W4A16-AutoRound-fast(4bit 权重,16bit 激活)
max_model_len 65536
思考解析 --reasoning-parser qwen3
到 N5095 延迟 1.4ms
视觉 不支持(见 §5)

二、思考模式:可关,且必须关

关闭方式(已实测有效):

"chat_template_kwargs": {"enable_thinking": false}

实测三种模式(同一个数学题,max_tokens=512):

模式 思考字数 完成 tokens 首 token(回答)
默认(不传) 168 214 527ms
enable_thinking=false 0 512 81ms
enable_thinking=true 289 239 620ms

开思考的代价不只是慢。看上面第二组数字:开思考时完成 tokens 只有 239, 而关思考是 512——因为思考 token 占用 max_tokens 预算。

在真实语音 prompt 上这个问题更严重(max_tokens=200):

模式 首 token(回答)P50 完成 tokens 中位 实际回答
关思考 367ms 10 「物流显示昨天已签收。」
开思考 1390ms 187 「我不」 ← 被截断

开思考时首 token 慢 3.8 倍,而且 200 的预算被思考吃光,回答只吐出两个字。

三、对比 DeepSeek 云 API

指标 本机 Qwen3.8-27B DeepSeek deepseek-flash
首 token(关思考) 367ms 786ms
网络延迟 1.4ms 含在 786ms 内
思考模式 可关(chat_template_kwargs) 可关(thinking),但字段名不同
视觉 ❌ 本实例不支持 ✅ 可用
费用 0(本地) 按 token 计费
数据 不出局域网 上传第三方

本机首 token 比云端快一倍多,因为省掉了网络往返与排队。

四、两个会改设计的集成约束

1. 思考内容的字段名不一致

后端 字段名
本机 vLLM reasoning
DeepSeek reasoning_content

适配层必须两个都认。只按 DeepSeek 的字段名写,会静默丢弃思考内容—— 不报错,但"把思考念出来"或"思考占用显示"这类问题会莫名其妙出现。

2. 只允许一条 system 消息

发送两条 system 消息直接 400:

System message must be at the beginning.

这推翻了原记忆设计。原方案打算"检索到的记忆作为一条独立 system message 注入", 在本机 vLLM 上会直接失败。

修正后的做法:保持唯一一条 system 消息,每轮重建:

system = 人设 + 规则 + 本轮检索到的记忆

这其实更干净,也和"注入的记忆每轮替换而非追加"的要求一致。

五、未通过项:视觉

本实例返回:

At most 0 image(s) may be provided in one prompt.

模型目录 Qwen3.8-27B-W4A16-AutoRound-fast/ 只有 safetensors 与 config, 没有视觉塔,是纯文本部署。

服务器上另有视觉能力:~/models/mmproj-F16.gguf(928MB)配合 llama.cpp 的 128k_vision.sh,以及 llama.cpp 的 --mmproj 参数。 但那是另一套服务,需要单独起。

影响:方案 §P5 的视觉问答在本端点不可用,需要么另起一个带 mmproj 的 llama.cpp 实例,要么走 DeepSeek。留到 P5 再定。

六、其余验证项

项 结果
工具调用(关思考) ✅ set_light({"room":"客厅","on":true})
纯文本流式 ✅
端点与模型清单 ✅

未测:取消/超时、长上下文退化、多客户端并发。

七、对 P1 延迟预算的影响

更新后的预算(用本机 LLM):

环节 耗时 来源
VAD 判定说完 200–500ms 估算,待实测
STT 冲刷 ≈0ms 实测
LLM 首 token 367ms 实测
TTS 首音(vits-zh-ll @服务器) 57–152ms 实测
网络 1.4–2ms 实测
合计 约 0.6–1.0 秒

方案 P1 目标 P50≤2 秒。余量超过一倍。

八、上下文建议

实测语音 prompt 约 406 tokens(人设 + 记忆 + 3 轮对话)。 建议按 4k tokens 设上限,超出时截断最旧的轮次:

  • system(人设 + 本轮记忆):400–800 tokens
  • 最近对话轮次:500–1000 tokens
  • 当前输入:~50 tokens

vLLM 服务端的 max_model_len=65536 是全局配置,不需要为助手改动 (那是共享服务)——短上下文靠客户端控制实际 prompt 长度即可。 短上下文不只省资源,还直接降低首 token 延迟,这对"回应及时"是关键。

九、工程陷阱记录

  1. 本机 vLLM 思考字段名是 reasoning,不是 reasoning_content(DeepSeek 的写法)。
  2. 只接受一条 system 消息,多条直接 400。
  3. 开思考会吃掉 max_tokens 预算,导致回答被截断。 语音场景下 max_tokens 本来就要设小,这个问题会被放大。
  4. N5095 上系统 python3 无 PIL,测试脚本要用 venv 里的解释器。