从 Obsidian 笔记库剥离为独立仓库。规划文档与 P0 报告留在笔记库, 代码(助手本体、TTS 服务、P0 基准脚本、ESP32 固件)在此。 架构:服务器是助手,本地是客户端 - 助手本体跑在 cadadmin-server,N5095 只做 USB 外设桥与网络桥接 - 起因:实测 N5095 无 AVX2,跑不动可用的语音模型 当前技术栈 - LLM:DeepSeek deepseek-flash(云端,必须关思考) - TTS:Qwen3-TTS 1.7B(服务器 3090,独立 HTTP 服务) - STT:Zipformer 中英双语 int8(CPU,中文识别率未测) 实测:端到端 16/16 通过,首音延迟 1545ms (对比:本地 LLM + vits-zh-ll 是 179ms,但音色不满意——音质与延迟 在此硬件上此消彼长) 设计要点 - MemoryStore 接口按"可能远程"设计(全 async、可超时、可失败) - user_id / session_id / track_id 三者分开,人脸只作候选不自动切身份 - 记忆查询强制带 owner_user_id,无按 id 单独取的口子 - 自动抽取的记忆是"候选",默认不参与检索 - 异步写记忆绑定创建时的身份,不读"当前用户" - 引擎与传输解耦,只用文件音频即可端到端测试 模型与音频产物不进版本管理(1.1GB),由 download_models.sh 恢复
47 lines
1.7 KiB
Python
47 lines
1.7 KiB
Python
"""本机 Qwen3.8-27B(vLLM,OpenAI 兼容)。
|
||
|
||
实测数据(P0-本地LLM验证报告.md):
|
||
关思考 首 token 367ms / 完成 10 tokens
|
||
开思考 首 token 1390ms / 完成 187 tokens,且**回答被 max_tokens 截断**
|
||
(实测 200 预算下只吐出"我不"两个字)
|
||
|
||
开思考不只是慢——思考 token 会占用 max_tokens 预算。
|
||
语音场景 max_tokens 本来就要设小,所以这不是"慢一点"的取舍,是"说不出话"。
|
||
默认关闭。
|
||
|
||
约束:只接受一条 system 消息,多条返回 400。已在基类归一化。
|
||
视觉:本实例不支持("At most 0 image(s) may be provided"),
|
||
模型目录里没有视觉塔。视觉要走 llama.cpp + mmproj 那条线。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from typing import Sequence
|
||
|
||
from .base import LLMProvider
|
||
|
||
|
||
class LocalVLLMProvider(LLMProvider):
|
||
supports_vision = False
|
||
|
||
def _build_body(self, messages: list[dict], *, tools: Sequence[dict] | None,
|
||
max_tokens: int) -> dict:
|
||
body: dict = {
|
||
"model": self.cfg.model,
|
||
"messages": messages,
|
||
"stream": True,
|
||
"max_tokens": max_tokens,
|
||
"stream_options": {"include_usage": True},
|
||
}
|
||
# 关闭思考。这是本机部署实测唯一有效的方式
|
||
# (服务器上的 ctx_test.sh 也用同一写法)。
|
||
# 注意:即使关掉,响应里仍可能出现空的 reasoning 字段,属正常。
|
||
body["chat_template_kwargs"] = {"enable_thinking": self.cfg.thinking}
|
||
if tools:
|
||
body["tools"] = list(tools)
|
||
body["tool_choice"] = "auto"
|
||
return body
|
||
|
||
|
||
__all__ = ["LocalVLLMProvider"]
|