科学工具
科学工具让世界更美好
让世界更美好

实时LLM语音对话工具 Unmute 安装部署和使用手册实时LLM语音对话工具 Unmute 安装部署和使用手册

Unmute是能赋予文本大语言模型(LLM)实时语音交互能力,通过Kyutai的语音转文本(STT)和文本转语音(TTS)模型将LLM包裹起来,实现用户通过语音输入,LLM生成文本响应,然后将文本响应朗读出来的全流程。Unmute强调低延迟,STT和TTS服务均经过优化,兼容任何文本LLM,用户可选择自托管LLM(如基于VLLM)或使用外部API。Unmute的架构由前端、后端、独立的STT、LLM和TTS服务以及Traefik路由组成,通过WebSocket实现浏览器与后端之间的实时音频和数据传输。项目支持多种部署方式,其中Docker Compose因其能简化多服务同时运行的复杂性而被推荐,支持多GPU部署以进一步优化语音处理延迟。Unmute提供了高度的可配置性,允许用户自定义角色语音和系统提示,通过基于OpenAI实时API的协议实现了前端的可替换性,为未来集成工具调用等高级功能奠定了基础。

工作原理概述

Unmute工作流程如下:

用户浏览器 → Traefik → 后端/前端;后端分别连接语音转文本(STT)、LLM、文本转语音(TTS)

具体步骤:

1、用户打开由前端提供服务的Unmute网站。

2、点击“连接”后,用户与后端建立websocket连接,实时来回传输音频和其他元数据。

3、后端通过websocket连接到语音转文本服务器,将用户的音频发送过去,并实时接收转录文本。

4、当语音转文本检测到用户停止说话,需要生成响应时,后端会连接到LLM服务器获取响应。我们使用VLLM托管自己的LLM,不过你也可以使用OpenAI或Mistral等外部API。

5、在生成响应的过程中,后端会将响应传输到文本转语音服务器进行语音合成,并将生成的语音转发给用户。

6、Traefik会将/api路径下的请求路由到后端,其余请求路由到前端。

部署方式

名称 GPU数量 机器数量 难度 有文档 Kyutai支持
Docker compose 1+ 1 非常简单
无Docker 1-3 1-5 简单
Docker swarm 1-约100 1-约100 中等

由于Unmute是一个复杂系统,需要同时运行多个服务,因此建议使用Docker Compose来运行Unmute。它能让你用一个命令启动或停止所有服务。因为这些服务都是Docker容器,所以你能获得可复现的环境,无需担心依赖问题。

LLM在Hugging Face Hub的访问设置

你可以使用任何LLM。默认情况下,Unmute使用Mistral Small 3.2 24B作为LLM(Gemma 3 12B也是个不错的选择)。这个模型可以免费使用,但需要你接受相关条款:

1、创建一个Hugging Face账号。

2、在Mistral Small 3.2 24B模型页面接受条款。

3、创建一个访问令牌。你可以使用细粒度令牌,只需授予“对所有你能访问的公共 gated 仓库内容的读取权限”即可。公开部署时不要使用具有写入权限的令牌。万一服务器被攻破,攻击者可能会获得你在Hugging Face上所有模型、数据集等的写入权限。

4、将令牌添加到~/.bashrc或类似文件中,格式为export HUGGING_FACE_HUB_TOKEN=hf_...your token here...

启动Unmute

确保你已经安装了Docker Compose。你还需要NVIDIA Container Toolkit,让Docker能访问你的GPU。要确认NVIDIA Container Toolkit安装正确,可以运行:

sudo docker run --rm --runtime=nvidia --gpus all ubuntu nvidia-smi

如果你使用meta-llama/Llama-3.2-1B(docker-compose.yml中的默认模型),16GB的GPU内存就足够了。如果遇到内存问题,打开docker-compose.yml,查找带有NOTE:的注释,那里有你可能需要调整的地方。

在有GPU的机器上运行:

# 确保环境变量中包含令牌:
echo $HUGGING_FACE_HUB_TOKEN  # 这里应该会输出hf_...之类的内容
docker compose up --build

多GPU使用

在Unmute.sh中,我们将语音转文本、文本转语音和VLLM服务器分别运行在不同的GPU上,与单GPU设置相比,这样能降低延迟。在单个L40S GPU上运行所有组件时,TTS延迟约为750ms,而在Unmute.sh上,延迟能降至约450ms。

如果有至少3个GPU可用,可以在sttttsllm服务中添加以下代码片段,确保它们在不同的GPU上运行:

stt: # tts和llm也类似
    # ...其他配置
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]

修改Unmute

以下是一些关于如何对Unmute进行特定修改的大致提示。

更改角色/声音

角色的声音和提示定义在voices.yaml中。这个配置文件的格式很直观。某些系统提示包含动态生成的元素。例如,“问答节目”的5个问题是从固定列表中随机预先选择的。这样的系统提示定义在unmute/llm/system_prompt.py中。

需要注意的是,该文件只在后端启动时加载,然后会被缓存,所以如果修改了voices.yaml中的内容,需要重启后端。

替换前端

后端和前端通过基于OpenAI实时API(“ORA”)的协议通过websocket通信。在可能的情况下,我们尽量匹配ORA格式,但也需要添加一些额外的消息,还有一些消息的参数经过了简化。我们会明确指出与ORA格式的不同之处,详见unmute/openai_realtime_api_events.py

关于WebSocket通信协议、消息类型和音频处理流程的详细信息,可参考浏览器-后端通信文档。

理想情况下,编写一个能同时与Unmute后端或OpenAI实时API通信的前端应该不难,但目前我们还未完全兼容。欢迎贡献代码!

前端是一个定义在frontend/中的Next.js应用。如果你想对比不同的前端实现,unmute/loadtest/loadtest_client.py中有一个Python客户端,这是我们用来测试Unmute延迟和吞吐量的脚本。

工具调用

这是一个常见需求,我们欢迎为Unmute添加工具调用功能的贡献!

可以研究vLLM如何实现工具调用,并修改docker-compose.yml中的vLLM调用,使用适当的参数。

在Unmute方面,修改unmute/unmute_handler.py中的_generate_response_task()。目前,llm.chat_completion()会逐个生成单词。这需要修改为还能生成工具调用并进行处理。

用Docker Swarm进行生产部署

如果你想了解我们如何部署和扩展unmute.sh,可以查看关于Swarm部署的文档。

开发Unmute

安装预提交钩子

首先安装pre-commit本身——你可能希望用pip install pre-commit在全局安装,而不是在虚拟环境或uv中,因为需要pre-commit可执行文件始终可用。然后运行:

pre-commit install --hook-type pre-commit

我们建议使用uv来管理Python依赖。以下命令假设你正在使用uv。

运行后端(开发模式,带自动重载)

uv run fastapi dev unmute/main_websocket.py

运行后端(生产模式)

uv run fastapi run unmute/main_websocket.py

运行负载测试

loadtest_client.py是一个连接到Unmute并模拟对话的脚本,用于测量延迟和吞吐量。

uv run unmute/loadtest/loadtest_client.py --server-url ws://localhost:8000 --n-workers 16