这次我们来看一个比较实际的边缘 AI 集成项目:在 reComputer Mini 这种小体积设备上,把 ASR(语音识别)、LLM(本地大模型对话)、TTS(语音合成)三个模块串成一条完全离线的语音助手链路。它和云端语音助手的最大区别是:从声音输入、文字理解到语音输出,全部在本机完成,不排队、不依赖云端服务,适合对隐私和延迟比较敏感的边缘场景。
这条链路本质上是一个三段式流水线:麦克风采集音频 → ASR 语音识别变成文本 → 本地大模型生成回复文本 → TTS 语音合成把回复读出来。听起来不复杂,真正落地时踩点主要集中在三处:模型选多大、推理用什么后端、模块之间怎么解耦。本文会围绕这三个问题展开,同时给出一套可以在 SSH 终端里直接验证的部署和测试流程。
如果你正在做离线语音助手、桌面语音盒子、本地大模型对话或边缘 AI 原型,这篇文章可以直接收藏。关键词可以先画一下:本地语音 LLM、ASR→LLM→TTS、离线语音助手、reComputer 小主机部署、本地大模型推理、语音合成接口。
1. 核心能力速览
| 能力项 | 说明 |
|---|---|
| 链路构成 | 音频采集 → ASR 语音识别 → LLM 对话 → TTS 语音合成 → 播放/保存 |
| 输入 / 输出 | 麦克风或音频文件输入;文本与音频输出 |
| 硬件平台 | reComputer Mini 等 Jetson 边缘设备,也可迁移到 x86/ARM 带声卡的 Linux 主机 |
| 推理方式 | 本地推理引擎 + ONNX/GGUF 模型,运行阶段不依赖云端 |
| 网络要求 | 首次部署需要下载模型,运行阶段可完全离线 |
| 接口扩展 | 三段能力可分别封装为 HTTP 服务,便于接入现有业务 |
| 批量任务 | 可对音频目录批量执行“识别 → 处理 → 合成”流水线 |
| 合规边界 | 录音、语音合成、版权素材使用都需要事先获得授权 |
表格里的参数我没有写死。这类链路高度依赖你实际选的模型、模型量化方式、音频采样率和推理后端,所以与其先给一组“看起来漂亮但没验证过”的数据,不如先把模块全部跑起来,再针对你的设备做一次基准记录。用同一个脚本、同一份测试音频、同一段提示词去测,数据才具有可比性。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 适用场景与使用边界
这套 ASR→LLM→TTS 链路适合哪类人?先把适用场景说清楚。
比较典型的是这几类:
- 对隐私敏感的语音助手:录音和对话记录只留在本机,不经过云端,适合办公环境、实验室、家庭网关类设备。
- 离线语音控制原型:在小主机上跑一个“说话 → 理解 → 执行”的闭环,验证智能硬件、桌面机器人、语音中控的可行性。
- 语音数据处理流水线:批量把一批音频转成文字,再让本地大模型做摘要、分类或意图识别,最后用 TTS 输出结果文件。
- 教学和学术验证:需要把 LLM、ASR、TTS 三块技术组合到同一个 demo 里的场景。
不适合的场景也要说清楚。如果产品要求高并发、超大模型、实时知识库、几十种方言识别,或者对合成音色的自然度要求达到播音级,那这类小主机和离线链路就不够。离线语音助手更适合做“限定领域 + 中等交互复杂度”的任务,不适合硬扛通用大模型服务。
使用边界这部分必须强调。语音类项目涉及录音、人声和版权素材,部署时至少要注意三条:
- 对录音对象要提前告知,获得同意之后再录,不要私下采集他人的声音。
- 语音合成尽量使用自己训练的音色、开源可商用音色或已获授权的音色,不要拿公众人物、他人声音做克隆。
- 开源模型和代码要确认许可证,是否允许商用、是否限制二次分发,以实际模型仓库的说明为准。
3. 架构设计与模块选型
3.1 整体链路设计
先看链路结构。用一句话描述就是:
text复制[麦克风/音频文件] -> [可选 VAD 断句] -> [ASR 识别文本] -> [LLM 生成回复] -> [TTS 合成音频] -> [播放/保存]
这里 VAD 是可选的语音活动检测,主要作用是过滤静音和噪声,让 ASR 只处理真正有人说话的部分,减少无效识别。如果只是先验证链路,可以跳过 VAD,直接把整段音频交给 ASR。
模块之间应该通过文本文件或中间变量解耦,而不是把 ASR、LLM、TTS 的代码写死成一个大函数。原因是替换方便:ASR 识别不准就换 ASR 模型,TTS 音色不满意就换 TTS 引擎,LLM 回复质量不行就换量化版本或推理后端。三段用公共的文本接口连接,排查问题时会非常清晰。
3.2 ASR 模块选型
离线语音识别在边缘设备上通常优先考虑 ONNX Runtime 或 sherpa-onnx 这类工具链。sherpa-onnx 是一个支持离线的语音识别/合成工具链,模型加载后直接在本地跑,CPU 和 GPU 都能用,对 Jetson 这类 ARM 平台兼容性也比较友好。部署时先确认模型是否支持中文,再确认采样率是 16kHz 还是 8kHz,因为采样率不匹配会直接影响识别结果。
如果中文识别率不满意,优先检查三点:音频是不是 16kHz 单声道;录音里有没有明显底噪;模型本身是不是中文优化版本。不要一上来就换更大的模型,先把音频输入质量拉高,很多时候收益比换模型更明显。
3.3 LLM 模块选型
边缘设备上的 LLM 一般选择 3B 到 8B 参数量的开源模型,配合量化后在 Jetson 上加载。量化和推理后端常见的有 llama.cpp、Ollama、llama-cpp-python。具体选哪一个,取决于你更看重命令行灵活性还是模型管理便利性。
模型选择可以参考公开模型榜单和社区口碑,比如 Open LLM Leaderboard 这类公开评测,也可以在本地跑几个固定问题判断生成质量。不要只盯着参数量,同样规模的模型因为训练数据和量化方式不同,实际效果差距可能很大。重要的是把“回复质量、首字延迟、内存占用”三个指标同时记录下来,才能判断当前模型适不适合你的设备。
3.4 TTS 模块选型
离线语音合成可以选择 Piper、sherpa-onnx TTS 等方案。这类工具会把输入文本直接合成为 wav 文件,CPU 就能运行,对显存压力很小。真正需要花时间的是音色自然度和多音字处理。
中文合成音色是否自然,和模型本身关系很大。使用时要一个一个音色试听,不要只看文档描述。有些引擎还支持语速、音量、说话人参数调整,测试时可以固定一组参数作为默认配置。
4. 环境准备与安装部署
4.1 系统环境检查
在 reComputer Mini 上动手之前,先确认四件事:JetPack SDK 版本、Python 版本、磁盘空间、音频设备。JetPack 是 Jetson 平台系统镜像的基础,包含 CUDA、cuDNN 等组件;如果 JetPack 版本和 PyTorch/ONNX Runtime 不匹配,后面会非常痛苦。
可以用以下命令做一个快速检查:
bash复制# 查看 L4T / JetPack 基础信息
dpkg-query --show nvidia-l4t-core
uname -a
# 检查 Python 版本
python3 --version
pip3 --version
# 检查磁盘空间,建议预留 20GB 以上
df -h
# 检查音频录音和播放设备
arecord -l
aplay -l
如果 arecord -l 看不到设备,说明系统没有识别到麦克风。可以先接 USB 声卡或带麦克风的 USB 音频设备,再重复执行检查。这一步建议在安装 Python 依赖之前完成,否则后面链路测试时才发现没录音设备,排查成本会高很多。
4.2 创建 Python 虚拟环境
不建议把依赖直接装到系统 Python 环境里,尤其是在 Jetson 这种系统里。用 venv 隔离才是更安全的方式。
bash复制python3 -m venv voice-llm
source voice-llm/bin/activate
# 确认当前环境
which python3
python3 --version
激活虚拟环境后,后续所有 pip 安装都在这个环境里进行。
4.3 安装 ASR / TTS 依赖
以下命令是常见路径,具体包名和版本需要以你实际使用的工具链官方文档为准。
bash复制pip install sherpa-onnx
pip install sounddevice numpy
# 如果系统缺少 PortAudio,需要先安装系统依赖
sudo apt-get update
sudo apt-get install -y libportaudio2
sounddevice 负责录音和播放,numpy 用于音频数据处理。如果你暂时不想用麦克风,只测音频文件,也可以先不装 sounddevice,直接用已有的 wav 文件做测试。
安装完可以验证一下:
bash复制python3 -c "import sherpa_onnx; print('sherpa-onnx ok')"
4.4 安装 LLM 推理后端
LLM 后端有两种路线:Ollama 走模型管理路线,llama.cpp 走编译和命令行路线。两条路线都能跑本地大模型,选一个顺手的即可。
Ollama 的安装方式是官方脚本,但在不同网络环境下可能失败。安装前确认你的网络可以访问对应资源,否则考虑用源码编译。
bash复制curl -fsSL https://ollama.com/install.sh | sh
ollama --version
llama.cpp 的通用编译流程是:
bash复制git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
make -j4
编译完成后,需要通过模型仓库下载你自己选择的 GGUF 模型文件,放到 models/llm/ 目录下。模型文件一般比较大,下载时要确认磁盘空间充足。
5. 链路组装与最小可运行脚本
5.1 推荐目录结构
建议先按下面的方式组织项目目录,把模型、输入、输出、脚本分开:
text复制voice-assistant/
├── models/
│ ├── asr/ # ASR 模型文件
│ ├── llm/ # LLM 模型文件
│ └── tts/ # TTS 模型文件与音色配置
├── input/ # 测试音频
├── output/ # 识别文本、回复文本、合成音频
├── scripts/
│ ├── asr_test.py
│ ├── llm_test.py
│ ├── tts_test.py
│ └── pipeline.py
└── logs/
目录分离的好处是:模型文件可以独立更新,不会污染代码;批量任务的输入和输出集中管理,日志和结果不会混在一起。
5.2 最小链路脚本模板
下面的脚本是一个链路骨架,用来把 ASR、LLM、TTS 串起来。方法内部需要按你实际安装的 SDK 替换,重点看模块间的连接方式。
python复制"""
离线语音助手最小链路脚本模板
流程:录音 / 读取音频 -> ASR 识别 -> LLM 生成回复 -> TTS 合成 -> 播放
"""
import os
import subprocess
import tempfile
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
OUTPUT_DIR = BASE_DIR / "output"
OUTPUT_DIR.mkdir(exist_ok=True)
def record_audio(duration: float = 5.0, samplerate: int = 16000) -> str:
"""
录音并保存为临时 wav。
这里用 sounddevice 示例,实际请根据你的录音方式调整。
"""
import sounddevice as sd
import numpy as np
import scipy.io.wavfile as wavfile
audio = sd.rec(int(duration * samplerate), samplerate=samplerate, channels=1, dtype="int16")
sd.wait()
tmp_path = OUTPUT_DIR / "record.wav"
wavfile.write(str(tmp_path), samplerate, audio)
return str(tmp_path)
def run_asr(audio_path: str) -> str:
"""
调用本地 ASR 引擎,返回识别文本。
这里用命令行示例,实际请替换为你的 ASR SDK 调用。
"""
result = subprocess.run(
[
"your_asr_cli", "--input", audio_path
],
capture_output=True,
text=True,
check=False,
)
text = result.stdout.strip()
return text
def run_llm(prompt: str) -> str:
"""
调用本地 LLM 推理后端,返回回复文本。
示例中先用环境变量占位,实际可以替换为 Ollama / llama.cpp / llama-cpp-python。
"""
reply = subprocess.run(
[
"your_llm_cli", "--prompt", prompt
],
capture_output=True,
text=True,
check=False,
).stdout.strip()
return reply
def run_tts(text: str) -> str:
"""
调用本地 TTS 引擎,合成音频并返回音频路径。
"""
out_path = OUTPUT_DIR / "reply.wav"
subprocess.run(
[
"your_tts_cli", "--text", text, "--output", str(out_path)
],
check=False,
)
return str(out_path)
def play_audio(audio_path: str) -> None:
"""
播放音频,实际可以根据平台使用 aplay / ffplay / sounddevice。
"""
subprocess.run(["aplay", audio_path], check=False)
def main() -> None:
# 第一步:录音
audio_path = record_audio(duration=5.0)
# 第二步:ASR 识别
user_text = run_asr(audio_path)
print("[ASR]", user_text)
# 第三步:LLM 生成回复
reply_text = run_llm(f"用户说:{user_text}\n请简短回复。")
print("[LLM]", reply_text)
# 第四步:TTS 合成并播放
reply_audio = run_tts(reply_text)
play_audio(reply_audio)
if __name__ == "__main__":
main()
这个脚本里所有 your_xxx_cli 都是占位。实际使用时,你先单独跑通 asr_test.py、llm_test.py、tts_test.py,确认三个模块各自都能输入输出,再把替换后的命令填进 pipeline.py。不要一开始就在完整链路里调试,否则无法判断是哪一个环节出了问题。
5.3 先手工验证,再自动化
我的建议是:第一天只做手工验证。准备一段 10 秒左右的清晰中文录音,先用 ASR 脚本识别,看文本输出是否准确;然后手动把这段文本交给 LLM,看回复是否合理;最后把回复文本交给 TTS,合成一段音频试听。三个环节都正常,再写自动执行脚本。这样每一步的边界都是清晰的,不会出现“链路跑通了但不知道哪里效果好哪里效果差”的情况。
6. 功能测试与效果验证
6.1 ASR 识别测试
ASR 的测试目标不是“能不能识别”,而是“识别到什么程度”。建议准备三组音频:
- 清晰普通话、语速中等、无背景噪音。
- 带轻微底噪的录音,模拟真实桌面环境。
- 较长句子,含标点和数字。
操作步骤:
- 将测试音频放到
input/目录。 - 运行 ASR 测试脚本,输出识别文本。
- 对照原文检查错字、多字、少字。
判断标准:
- 清晰音频的识别准确率是否满足你的业务要求。
- 带噪音频是否出现明显丢字。
- 长句是否保留了标点或句读停顿。
常见失败原因集中在采样率不匹配、模型语言不匹配、音频增益过高或过低。
6.2 LLM 对话测试
LLM 测试重点不是让它写作文,而是验证对话质量是否稳定。建议用一组固定问题:
- 你是谁?谁开发的?
- 请用一句话介绍你自己。
- 今天天气怎么样?(测试是否出现胡编)
- 讲个简短的笑话。
- 复述上一句内容。(测试多轮上下文处理)
操作步骤:
- 启动本地 LLM 后端。
- 在命令行发起单轮测试。
- 再测试多轮对话,看是否记住上下文。
判断标准:
- 回复是否简短、通顺。
- 是否出现明显幻觉。
- 上下文超过一定轮次后是否崩坏。
- 首字延迟是否符合预期。
如果回复质量不稳定,先降低 prompt 复杂度,再考虑更换模型或调整量化档位。小设备上跑大模型,本身需要在“效果”和“速度”之间做取舍。
6.3 TTS 合成测试
TTS 测试要重点听三个东西:音色自然度、中文多音字、长文本断句。
测试文本建议准备三组:
- 短句:你好,我是本地语音助手。
- 含数字:今天温度是 25 摄氏度,相对湿度 60%。
- 多音字:他正在银行里看一行动物,突然想起来了。
操作步骤:
- 运行 TTS 测试脚本,输入三组文本。
- 分别生成 wav 文件。
- 试听并记录问题。
判断标准:
- 短句是否清晰自然。
- 数字是否读得正确。
- 多音字是否出现明显错误。
- 长文本是否断句合理。
TTS 引擎的很多问题不是靠改代码能解决的,更快的路径是换一个音色模型或调整语速参数。测试过程务必记录当前使用的模型版本和音色配置,否则后面调优时容易迷失方向。
6.4 端到端链路测试
模块各自通过后,再跑完整链路。端到端测试建议从“音频文件输入”开始,而不是直接上麦克风。先用一段准备好的 wav 输入,看整条流水线能否输出语音回复;确认没问题后,再切换为麦克风录音输入。
判断链路成功的标准只有一个:输入一段语音,最终能听到机器合成的回复音频,并且回复内容与输入话题相关。失败时先定位到具体模块:能不能识别、能不能生成、能不能合成,逐个击破。
7. 接口 API 与批量任务
7.1 把链路封装成 HTTP 服务
命令行脚本跑通以后,如果希望把这个离线语音助手接到现有业务里,可以包一层 HTTP 接口。最简单的方式是用 FastAPI,把 ASR、LLM、TTS 分别暴露成三个接口,便于单独调用。
下面是一个最小服务骨架:
python复制"""
离线语音助手 HTTP 服务模板
启动:uvicorn voice_assistant_api:app --host 127.0.0.1 --port 8000
"""
from fastapi import FastAPI, File, UploadFile
import tempfile
app = FastAPI(title="Offline Voice Assistant API")
@app.post("/asr")
async def asr_endpoint(audio: UploadFile = File(...)):
"""
接收音频文件,返回识别文本。
实际需要将音频保存为临时文件,再调用本地 ASR 引擎。
"""
suffix = audio.filename.strip().split(".")[-1]
with tempfile.NamedTemporaryFile(suffix=f".{suffix}", delete=False) as tmp:
tmp.write(await audio.read())
tmp_path = tmp.name
text = "识别文本占位,请替换为真实 ASR 调用"
return {"text": text, "audio_path": tmp_path}
@app.post("/chat")
async def chat_endpoint(prompt: str):
"""
接收文本 prompt,返回 LLM 回复。
"""
reply = "本地大模型回复占位,请替换为真实 LLM 调用"
return {"reply": reply}
@app.post("/tts")
async def tts_endpoint(text: str):
"""
接收文本,返回合成音频路径。
"""
audio_path = "output/tts_result.wav"
return {"audio_path": audio_path}
启动服务:
bash复制pip install fastapi uvicorn python-multipart
uvicorn voice_assistant_api:app --host 127.0.0.1 --port 8000
注意 --host 不要随意设成 0.0.0.0,尤其是设备在局域网内时。只允许本机访问可以降低暴露面。
7.2 curl 调用示例
服务启动后,先用 curl 做一轮冒烟测试,确认接口能通。
合成接口示例:
bash复制curl -X POST http://127.0.0.1:8000/tts \
-H "Content-Type: application/json" \
-d '{"text": "你好,这是一个离线语音助手。"}'
对话接口示例:
bash复制curl -X POST "http://127.0.0.1:8000/chat?prompt=你好"
识别接口需要上传音频文件:
bash复制curl -X POST http://127.0.0.1:8000/asr \
-F "audio=@./input/test.wav"
接口能跑通后,就可以接到自己的前端、机器人程序或自动化脚本里。
7.3 批量任务流水线
批量任务不要让脚本一次读入全部音频,否则内存占用会快速上升。更稳妥的做法是遍历目录,一个一个处理,并为每个输出文件生成同名日志。
bash复制# 批量处理示例:把 input 目录下所有 wav 识别并合成回复
for f in input/*.wav; do
echo "processing $f"
python scripts/pipeline.py \
--input "$f" \
--output "output/$(basename "$f" .wav)_reply.wav"
done
如果需要更严格的批量控制,可以把输入目录、模型路径、采样率等参数写进一个 JSON 配置:
json复制{
"input_dir": "./input",
"output_dir": "./output",
"asr_model": "./models/asr",
"llm_model": "./models/llm",
"tts_model": "./models/tts",
"language": "zh",
"sample_rate": 16000
}
批量任务一定要加日志。每个文件的识别文本、LLM 回复、合成状态都写进日志,后续定位“哪个文件失败”时能直接查,不需要重跑整个目录。
8. 资源占用与性能观察
8.1 Jetson 平台的内存观察
reComputer Mini 这类 Jetson 设备和普通 PC 的观察方式不太一样。Jetson 使用统一内存架构,CPU 与 GPU 共享同一块内存,不能简单按“显存 8G、内存 8G”来分隔计算。模型加载后占用的实际上是统一内存中的一部分,观察时重点看整体内存使用量。
推荐用两个工具:
bash复制# tegrastats 实时查看 CPU、GPU、内存、功耗
sudo tegrastats
# jtop 更适合交互式观察
sudo apt-get install python3-jtop
sudo jtop
运行 pipeline 时另开一个 SSH 会话,持续观察资源占用。这样可以看出识别阶段、推理阶段、合成阶段分别在什么负载水平。
8.2 性能测试方法
准备一组固定测试集,内容包含三句话、三段语音、三次对话,然后记录:
- ASR 识别耗时:从输入音频到返回文本的时间。
- LLM 首字延迟:从输入 prompt 到返回第一个 token 的时间。
- LLM 总耗时:生成完整回复的时间。
- TTS 合成耗时:从输入文本到生成 wav 的时间。
- 端到端耗时:从录音结束到播放开始的全部时间。
- 峰值内存占用:运行过程中观察到的最高内存值。
记录三组数据后,再做模型替换或参数调整时,对比这些数据就能看出变化。不要只凭感觉说“好像变慢了”“好像占用高了”,用同一测试集的数据说话。
8.3 优化方向
如果资源占用偏高或响应太慢,优先尝试这几种手段:
- 将 LLM 换成更小参数的量化版本。
- 减少 LLM 输出最大长度,回复短一些,首字延迟会有改善。
- 在 ASR 前增加 VAD,过滤非语音段,减少无效识别。
- 批量任务设置每线程一个音频文件,避免同时处理多个文件导致内存打架。
- 关闭不需要的桌面进程或后台服务,把资源让给推理进程。
这些优化都不是免费的。换小模型可能损失回复质量,加 VAD 可能增加一些计算延迟,具体怎么取舍,还是要以你设备上的实测数据为准。
9. 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 录音设备找不到 | 系统未识别麦克风或声卡 | 检查 arecord -l |
更换 USB 声卡或检查权限 |
| ASR 识别结果为空 | 音频采样率不匹配或音频过短 | 打印音频时长、采样率 | 统一采样率为 16kHz 单声道 |
| 中文识别错字多 | 模型不是中文优化版 | 查看模型说明 | 换中文 ASR 模型 |
| LLM 回复很慢 | 模型过大或量化档位太高 | 观察内存占用 | 换小模型或换量化方式 |
| LLM 首字延迟长 | prompt 过长或输出长度限制过大 | 测试空 prompt 耗时 | 精简 prompt,缩短 max tokens |
| TTS 合成无声 | 播放设备输出错误或音频格式不兼容 | 检查 wav 是否能播放 | 换输出设备或重新合成 |
| 端口被占用 | 8000 端口被其他服务占用 | ss -tlnp 查看端口 |
换端口启动 uvicorn |
| 内存不足 | 同时加载多个大模型 | 查看 jtop 内存负载 |
分批加载,避免同时推理 |
| 批量任务卡住 | 单条音频处理超时没有重试机制 | 查看日志定位卡住的文件 | 增加超时退出和失败重试 |
实际排查时要形成一个习惯:先确认是哪一段的问题,再查配置。链路里三段互相连接,如果 ASR 输出就是错的,后面 LLM 和 TTS 再正确也没有意义。所以排错顺序永远是:输入 → ASR → LLM → TTS → 输出。
10. 最佳实践与下一步
10.1 工程化建议
第一遍跑通链路时,不要追求端到端完美效果。先用“最小编码”:最小模型、最短音频、最短回复,确认链路完整性,再逐步调优。很多人在第一步就下了超大模型,结果内存不够、速度太慢,最后连一次完整回复都没看到。
建议把这几点养成习惯:
- 模型文件、输入素材、输出结果、日志分目录管理,不使用散落的临时路径。
- 为 ASR、LLM、TTS 分别保留独立测试脚本,相当于给三个模块各做一次单测。
- 批量任务增加日志和失败重试,输出文件名保持可追溯。
- 接口服务默认只监听本机地址,不在无防护状态下暴露到公网。
- 模型和依赖的版本记录在 requirement 或配置文件中,方便重新部署。
- 涉及人脸、声音、版权素材的任务,必须确认授权后再处理。
10.2 最容易踩的坑
从链路角度排序,最容易踩的坑有三个:
第一个是音频采样率不一致。录音是 48kHz,ASR 模型用 16kHz,识别结果会明显变差。解决方法是录音时就固定采样率,或在 ASR 前统一重采样。
第二个是模型和推理后端不匹配。下载了一个 GGUF 模型,但 llama.cpp 版本太旧,加载失败或推理异常。解决方法是锁定模型仓库推荐的推理后端版本。
第三个是一个大脚本从头写到尾。ASR、LLM、TTS 混在一起,出了 bug 看不出是哪一段。解决方法始终是先分模块验证,再组装。
10.3 后续扩展方向
链路跑通后,后续可以很自然地往这几个方向扩展:
- 添加唤醒词检测,不需要手动按键。
- 在 ASR 前加 VAD,自动判断说话开始和结束。
- 用流式返回降低 LLM 回复的等待感。
- 增加多语言切换、多角色设定。
- 在 LLM 层加入工具调用能力,让语音助手能查本地文件、控制设备、执行简单任务。
这条链路的核心验证点,不是某个模型单点效果多好,而是设备能不能稳定地把“语音 → 文本 → 文本 → 语音”完整闭环跑起来。只要这个闭环稳定了,后续每一段都可以单独升级。
建议现在先做一件事:拿一段 10 秒的录音,分别跑通 ASR、LLM、TTS 三个测试脚本,把“识别准不准、回复快不快、声音自然不自然”三个问题记下来。这一步做完,你就知道下一步该优先调哪一段了。
