从 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 恢复
53 lines
2.0 KiB
Bash
Executable File
53 lines
2.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# 下载 P0 基准所需模型。走 hf-mirror.com(本机 huggingface.co 直连不通)。
|
|
# 可重复执行:已存在且大小正确的文件会跳过。
|
|
set -uo pipefail
|
|
|
|
ROOT="$(cd "$(dirname "$0")" && pwd)"
|
|
MIRROR="${HF_MIRROR:-https://hf-mirror.com}"
|
|
STT_REPO="csukuangfj/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20"
|
|
TTS_REPO="csukuangfj/sherpa-onnx-vits-zh-ll"
|
|
|
|
STT_DIR="$ROOT/models/stt"
|
|
TTS_DIR="$ROOT/models/tts"
|
|
WAV_DIR="$ROOT/wavs"
|
|
mkdir -p "$STT_DIR" "$TTS_DIR" "$WAV_DIR"
|
|
|
|
fetch() { # fetch <repo> <remote-path> <local-path>
|
|
local repo="$1" remote="$2" local="$3"
|
|
mkdir -p "$(dirname "$local")"
|
|
local url="$MIRROR/$repo/resolve/main/$remote"
|
|
local expect
|
|
expect=$(curl -sIL "$url" | grep -i '^content-length' | tail -1 | tr -d '\r' | awk '{print $2}')
|
|
if [ -f "$local" ] && [ -n "$expect" ] && [ "$(stat -c%s "$local")" = "$expect" ]; then
|
|
printf ' skip %-45s %s\n' "$(basename "$remote")" "(已完整)"
|
|
return 0
|
|
fi
|
|
printf ' get %-45s %s\n' "$(basename "$remote")" "${expect:+$((expect/1048576))MB}"
|
|
curl -sL --retry 3 --retry-delay 2 -o "$local.part" "$url" || { echo " FAILED"; return 1; }
|
|
mv "$local.part" "$local"
|
|
}
|
|
|
|
echo "=== STT: 流式 Zipformer 中英双语 int8 ==="
|
|
for f in tokens.txt bpe.model \
|
|
encoder-epoch-99-avg-1.int8.onnx \
|
|
decoder-epoch-99-avg-1.int8.onnx \
|
|
joiner-epoch-99-avg-1.int8.onnx; do
|
|
fetch "$STT_REPO" "$f" "$STT_DIR/$f"
|
|
done
|
|
for w in 0.wav 1.wav 2.wav 3.wav; do
|
|
fetch "$STT_REPO" "test_wavs/$w" "$WAV_DIR/stt_$w"
|
|
done
|
|
|
|
echo "=== TTS: VITS zh-ll ==="
|
|
for f in model.onnx tokens.txt lexicon.txt date.fst number.fst phone.fst new_heteronym.fst \
|
|
dict/jieba.dict.utf8 dict/hmm_model.utf8 dict/idf.utf8 \
|
|
dict/pos_dict/char_state_tab.utf8 dict/pos_dict/prob_emit.utf8 dict/pos_dict/prob_trans.utf8; do
|
|
fetch "$TTS_REPO" "$f" "$TTS_DIR/$f"
|
|
done
|
|
|
|
echo
|
|
echo "=== 结果 ==="
|
|
du -sh "$STT_DIR" "$TTS_DIR" "$WAV_DIR" 2>/dev/null
|
|
echo "下载完成。"
|