Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Reachy Mini + Local Voice Conversation: Full Deployment

A complete record of getting a fully local Chinese-English voice conversation pipeline running on a Reachy Mini Lite robot — from initial CPU attempt to a ROCm GPU-accelerated deployment.

License: CC-BY-4.0 ROCm PyTorch GPU 中文


What this is

In early June 2026, I assembled a Reachy Mini Lite robot — hardware took about 3 hours — then spent 2 days of free time debugging the pipeline, configuring the environment, and modifying the official Reachy Mini conversation app. The goal was simple: a fully local, real-time voice conversation in Chinese and English, with zero cloud API calls in the loop.

This repository documents the entire journey — installation, pitfalls, performance baselines, and the eventual working setup — so others with similar needs (local STS, AMD GPU + Linux, Reachy Mini integration) can skip the parts I had to figure out the hard way.

Key results

Metric Value
End-to-end perceived latency (steady state) ~1.0 s (user stops speaking → first synthesized audio)
ASR speed 35× real-time (Chinese, Paraformer-zh)
LLM first-token latency (steady state) 50 ms (Gemma-4-E4B-instruct)
TTS synthesis (steady state) Single-digit seconds
Chinese support ✅ Excellent ASR; TTS is English-leaning (use CosyVoice 2 for production)
Fully offline ✅ Zero cloud calls

Cold-start first request takes ~29 s (model load + TTS CUDA graph capture). The CLI does warmup internally at startup, but the first real user request still pays the full cold-start cost — see docs/03 §Performance Baseline.

The story

I followed the excellent Hugging Face blog "Local Reachy Mini Conversation" and the inspiring r/LocalLLaMA thread "Reachy Mini Goes Fully Local" as a starting point. My first attempt was CPU-only: Qwen3-TTS does not support AMD GPUs, so I switched to Kokoro. The pipeline ran, but the Reachy Mini app connected and then did absolutely nothing — no logs, no VAD, no audio. I wrote up the symptoms (the draft is preserved in docs/04 as a debugging reference).

Once I got my hands on an AMD Strix Halo 128G (Ryzen AI Max+ 395, Radeon 8060S iGPU, gfx1151) workstation, I re-researched ROCm compatibility, solved a series of AMD-specific issues, and ran the whole stack on GPU. That second pass is what this repo documents.

Along the way I also:

Requirements

  • GPU: AMD Strix Halo / Strix Point (gfx1151 / gfx1150), or any ROCm 7.13+ supported GPU. NVIDIA GPUs work for the pipeline itself, but the installation steps below are ROCm-specific.
  • OS: Fedora 44 (other modern Linux distros should work with minor adjustments)
  • RAM: 32 GB+ recommended (LLM loading needs ~8 GB VRAM)
  • Python: 3.12+ (managed with uv)
  • Robot (optional, only for Reachy Mini integration): Reachy Mini Lite, controlled via Reachy Mini Control

Quick start

The pipeline is set up in 5 steps, each with pinned versions to avoid the failures I hit during the 2-day debug. uv is the recommended venv+package manager — it handles resolution much better than venv + pip and is what the docs assume.

What you'll be installing (pinned)

Component Version Why this version
Python 3.12.13 Required by TheRock gfx1151 wheels
PyTorch (TheRock gfx1151 build) 2.10.0+rocm7.13.0a20260513 PyTorch.org's rocm7.1 wheels SIGSEGV on Strix Halo (Issue #2991). TheRock gfx1151 ships the VGPR fix
ROCm / HIP 7.13 First line with native gfx1151 support; do NOT set HSA_OVERRIDE_GFX_VERSION on this version
numpy 1.26.4 Force-downgraded for deepfilternet + torch 2.10 compat
packaging 23.2 Force-downgraded for deepfilternet 0.5.6
speech-to-speech 0.2.9 Pipeline framework
funasr 1.3.9 Paraformer-zh STT — Chinese CER 1.95 %, 120× real-time on GPU
qwen-tts 0.1.1 Qwen3-TTS backend
faster-qwen3-tts 0.2.6 TTS inference engine (ROCm gfx1151 verified)
deepfilternet 0.5.6 Audio denoising — + 1-line patch to df/io.py:9 for TheRock torchaudio 2.10 (one-time after every reinstall)
hf-transfer 0.1.9 HuggingFace fast downloader — mandatory for the TTS model download

Base install skips flash-attn. The optional high-performance Qwen3-TTS path is documented in docs/06.

Step 1 — ROCm + PyTorch (TheRock gfx1151)

# Create venv with uv
uv venv ~/.venvs/sts --python 3.12
source ~/.venvs/sts/bin/activate

# Install PyTorch from TheRock gfx1151 index — NOT PyTorch.org
uv pip install --index-url https://rocm.nightlies.amd.com/v2/gfx1151/ \
  torch torchaudio torchvision

Verify:

python3 -c "
import torch
assert torch.cuda.is_available(), 'ROCm not working'
assert 'gfx1151' in torch.cuda.get_arch_list(), 'Wrong wheel index'
x = torch.randn(100, 100, device='cuda')
print('ROCm + PyTorch OK:', torch.cuda.get_device_name(0))
"

Full ROCm troubleshooting: docs/01 — ROCm gfx1151 PyTorch Install.

Step 2 — STT, TTS, denoise

# Main pipeline + STT/TTS backends (skip deepfilternet — installed separately below)
uv pip install "speech-to-speech[paraformer]" funasr qwen-tts \
  faster-qwen3-tts hf-transfer

# Audio denoising — needs two force-downgrades to coexist with torch 2.10
uv pip install "deepfilternet==0.5.6"
# Then apply the torchaudio 2.10 compat patch (one-time, after every reinstall).
# See docs/03 §7 for the sed command.

Why these picks (full comparison table in docs/02):

  • STT: Paraformer-zh — Chinese CER 1.95 % (vs SenseVoice 2.96 %, faster-whisper 5.14 %), 120× real-time on GPU, built-in VAD + punctuation
  • TTS: Qwen3-TTS — the only TTS I verified working on ROCm gfx1151. Kokoro works but is CPU-only and English-leaning
  • Denoise: DeepFilterNet 0.5.6 — best quality; RNNoise is faster but lower quality

Step 3 — LLM backend

The pipeline expects an OpenAI-compatible LLM endpoint — point it at any local LLM server (e.g. llama-server from llama.cpp, vLLM, SGLang, or any other) and it works. The default URL in sts_start.sh is http://127.0.0.1:8101/v1 — adjust --responses_api_base_url to match yours.

The actual setup deployed in this project is llama-swap (OpenAI-compatible HTTP proxy) fronting lemonade (lemonade-sdk/lemonade, AMD-optimized inference backend for Strix Halo iGPU / Ryzen AI NPU) — that's what the performance numbers below were measured against. If you use a different stack, the LLM performance will naturally differ but the pipeline itself doesn't care.

After benchmarking 7 models, Gemma-4-E4B-instruct is the steady-state TTFT champion (50 ms). Full numbers in docs/03 §Tuning §1.

Step 4 — Launch

git clone https://github.com/kamjin3086/reachy-mini-sts-pipeline.git
cd reachy-mini-sts-pipeline
STS_LLM_MODEL=Gemma-4-E4B-instruct ./scripts/sts_start.sh
# → WebSocket: ws://0.0.0.0:8765/v1/realtime

If your LLM server or port differs, override it with environment variables instead of editing the script:

STS_LLM_BASE_URL=http://127.0.0.1:8101/v1 \
STS_LLM_MODEL=your-model-name \
STS_WS_PORT=8765 \
./scripts/sts_start.sh

There are only two supported launch paths:

Path Command Use when
Stable make start or ./scripts/sts_start.sh You want the simplest working setup
Fast Qwen3-TTS make start-fast or ./scripts/sts_start_qwen3_openai_fastapi_flash.sh You want better Qwen3-TTS runtime throughput and can accept slower warmup

Offline startup and the high-performance environment are covered in docs/06.

Production starts with Paraformer live transcription disabled so partial Chinese subtitles are not sent to the LLM as repeated user turns. To enable live subtitles, first patch the installed handler:

python3 scripts/patch_paraformer_live_transcription.py
# then switch sts_start.sh from --no_enable_live_transcription to --enable_live_transcription

sts_start.sh sets these ROCm env vars (do not set HSA_OVERRIDE_GFX_VERSION — see TROUBLESHOOTING.md):

export GPU_MAX_ALLOC_PERCENT=100                    # Full UMA allocation
export GPU_MAX_HEAP_SIZE=100                        # Cap HIP heap
export TORCH_ROCM_AOTRITON_ENABLE_EXPERIMENTAL=1    # AOTriton perf

Steady-state perceived latency: ~1.0 s (user stops speaking → first synthesized audio). For Reachy Mini integration, see the forked conversation app: kamjin3086/reachy_mini_conversation_app. For app development with live source edits, see the pip install -e . tip in docs/04.

Documentation

Document Purpose When to read
docs/SCRIPTS.zh.md Script index, environment-variable overrides, common Make commands Before running or changing scripts
docs/MAINTENANCE.zh.md Maintenance rules, experiment records, pre-commit checks Before extending this repo
docs/01 — ROCm gfx1151 PyTorch Install ROCm 7.13 + TheRock gfx1151 wheels + PyTorch First-time deployment
docs/02 — STS Pipeline Install speech-to-speech installation + STT/TTS/LLM selection rationale After doc 01
docs/03 — Runtime Status & Tuning Detailed status, tuning notes, and known issues When debugging internals
docs/04 — Reachy Mini Debug Journey The original "nothing happens" debugging record When Reachy Mini connection fails
docs/05 — Qwen3-TTS Realtime Test Report Real Chinese TTS, inline instruction, and Realtime tool-call results When tuning Chinese conversation
docs/06 — Runtime Paths & Offline Startup The two supported launch paths, offline cache behavior, and flash-attn environment checks Before running or sharing the setup
TROUBLESHOOTING.md Quick symptom → fix lookup When something breaks
README.zh.md This document in Chinese 中文读者

Benchmarking

# Common command entrypoint
make help

# End-to-end pipeline benchmark
python3 scripts/bench_sts_pipeline.py --quick

# LLM TTFT comparison across models
python3 scripts/bench_llm_models.py

After benchmarking 7 LLM models, Gemma-4-E4B-instruct is the steady-state TTFT champion (50 ms). NPU-accelerated models were actually slower. Full data in docs/03 §Tuning §1.

Component selection

Component Choice Alternatives considered Why
ASR Paraformer-zh (FunASR) SenseVoice, faster-whisper Best Chinese CER (1.95%)
LLM Gemma-4-E4B-instruct GPT-OSS-20B, Qwen3.6-35B-A3B Steady-state TTFT king
TTS Qwen3-TTS (CustomVoice) Kokoro, CosyVoice 2 ROCm compatibility verified
LLM backend Any OpenAI-compatible server (e.g. llama-server, vLLM, SGLang) The pipeline only needs an OpenAI-compatible HTTP endpoint. The actual deployed setup is llama-swap (proxy) + lemonade (inference); see §Step 3
Denoising DeepFilterNet 0.5.6 RNNoise High quality, patched for torchaudio 2.10

Known issues & workarounds

  • MPS bug: speech_to_speech/paraformer_handler.py:56 calls torch.mps.empty_cache() unconditionally and crashes on ROCm/CUDA. One-line sed fix provided.
  • HSA override side effect: HSA_OVERRIDE_GFX_VERSION=11.0.0 actually triggers hipErrorInvalidImage on ROCm 7.13 (TheRock). Just remove it.
  • DeepFilterNet + torchaudio 2.10: df/io.py references torchaudio.backend.common which TheRock 2.10 doesn't ship. try/except fallback patch provided.
  • flash-attn on gfx1151: keep it out of the base venv. For the verified optional path, see docs/06.

Full list: docs/03 §Known Issues, TROUBLESHOOTING.md.

Related repositories

Acknowledgments

License

Documentation and scripts in this repository are released under CC-BY-4.0 — free to copy, modify, and use commercially, as long as attribution is preserved. If you build something better on top of this, a PR or an issue link back is appreciated.

Third-party software mentioned in this repo retains its own license — see the LICENSE file for the breakdown.

About

End-to-end deployment of a fully local speech-to-speech conversation pipeline (STT + LLM + TTS) on Reachy Mini Lite, accelerated on AMD Strix Halo (gfx1151) via ROCm 7.13 / TheRock. Includes install guides, performance baselines, and a debug record.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages