mirror of
https://github.com/jamiepine/voicebox.git
synced 2026-09-29 07:05:14 -07:00
fix: ROCm setup for Linux AMD GPUs (#817)
* Fix ROCm setup for Linux AMD GPUs - Ensure Docker ROCm builds resolve PyTorch packages from the ROCm wheel index so later dependency installs do not replace them with CUDA wheels. - Move ROCm device group handling to a runtime entrypoint that joins the groups owning /dev/kfd and /dev/dri, avoiding distro-specific render/video GID defaults. - Leave HSA_OVERRIDE_GFX_VERSION unset by default in the ROCm compose overlay so newer RDNA GPUs can use native ROCm detection. - Add Linux GPU detection to the Unix setup recipe so AMD systems install ROCm torch wheels and NVIDIA systems install CUDA wheels before backend dependencies. * docs(changelog): add Linux ROCm setup entry * fix(setup): pin ROCm torch wheels and prefer NVIDIA over amdgpu - Install torch/torchaudio from the ROCm index only, before the pooled requirements install, so a plain PyPI (CUDA) wheel can't outrank +rocm - Detect NVIDIA before AMD and gate ROCm on /dev/kfd, so hybrid AMD+NVIDIA hosts get CUDA instead of ROCm
This commit is contained in:
@@ -5,6 +5,17 @@
|
|||||||
|
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
|
||||||
|
- **ROCm setup works on Linux AMD systems.** Docker ROCm builds now keep PyTorch
|
||||||
|
on the ROCm wheel index during dependency installation, so later installs do
|
||||||
|
not replace it with CUDA wheels. The ROCm compose overlay no longer assumes
|
||||||
|
Ubuntu render/video group IDs; the container joins the groups that own the GPU
|
||||||
|
device nodes at startup. Native Linux setup now picks ROCm wheels for AMD GPUs
|
||||||
|
and CUDA wheels for NVIDIA GPUs before installing backend dependencies.
|
||||||
|
|
||||||
## [0.5.0] - 2026-04-22
|
## [0.5.0] - 2026-04-22
|
||||||
|
|
||||||
**The Capture release.** Voicebox stops being just a voice-cloning studio and becomes a full AI voice studio. Hold a key anywhere on your machine, speak, release — the transcript lands in the focused text field. Flip the primitive around and any MCP-aware agent — Claude Code, Cursor, Spacebot — speaks back through an on-screen pill in one of your cloned voices. A local LLM sits between the two, so transcripts come out clean and voice profiles can carry a personality that reshapes what the agent says before it gets spoken.
|
**The Capture release.** Voicebox stops being just a voice-cloning studio and becomes a full AI voice studio. Hold a key anywhere on your machine, speak, release — the transcript lands in the focused text field. Flip the primitive around and any MCP-aware agent — Claude Code, Cursor, Spacebot — speaks back through an on-screen pill in one of your cloned voices. A local LLM sits between the two, so transcripts come out clean and voice profiles can carry a personality that reshapes what the agent says before it gets spoken.
|
||||||
|
|||||||
+12
-35
@@ -45,18 +45,16 @@ RUN pip install --no-cache-dir --upgrade pip
|
|||||||
|
|
||||||
COPY backend/requirements.txt .
|
COPY backend/requirements.txt .
|
||||||
|
|
||||||
# ROCm version to pull PyTorch wheels for. Default is 6.3 (supports RDNA1/2/3).
|
# ROCm wheel index. Default 6.3 (RDNA1/2/3); set ROCM_VERSION=7.2 for RDNA4.
|
||||||
# Set ROCM_VERSION=7.2 for RDNA 4 (RX 9000 series) support.
|
|
||||||
ARG ROCM_VERSION=6.3
|
ARG ROCM_VERSION=6.3
|
||||||
|
|
||||||
# When building the ROCm variant, install the ROCm-enabled PyTorch wheels
|
# For ROCm, make the PyTorch ROCm index primary so every install below resolves
|
||||||
# first so that the subsequent requirements.txt install sees them as already
|
# torch to ROCm wheels instead of the default CUDA build.
|
||||||
# satisfying the torch/torchaudio constraints and leaves them in place.
|
|
||||||
# The CPU path skips this step and installs torch from PyPI as before.
|
|
||||||
RUN if [ "$PYTORCH_VARIANT" = "rocm" ]; then \
|
RUN if [ "$PYTORCH_VARIANT" = "rocm" ]; then \
|
||||||
pip install --no-cache-dir --prefix=/install \
|
pip install --no-cache-dir --prefix=/install \
|
||||||
torch torchaudio \
|
--index-url "https://download.pytorch.org/whl/rocm${ROCM_VERSION}" \
|
||||||
--index-url "https://download.pytorch.org/whl/rocm${ROCM_VERSION}"; \
|
torch torchaudio && \
|
||||||
|
printf '[global]\nindex-url = https://download.pytorch.org/whl/rocm%s\nextra-index-url = https://pypi.org/simple\n' "$ROCM_VERSION" > /etc/pip.conf; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
|
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
|
||||||
@@ -69,37 +67,17 @@ RUN pip install --no-cache-dir --prefix=/install \
|
|||||||
# === Stage 3: Runtime ===
|
# === Stage 3: Runtime ===
|
||||||
FROM python:3.11-slim
|
FROM python:3.11-slim
|
||||||
|
|
||||||
# Re-declare ARG inside the stage (Docker scoping requirement).
|
# Create non-root user; the entrypoint joins GPU device groups at runtime.
|
||||||
ARG PYTORCH_VARIANT=cpu
|
|
||||||
|
|
||||||
# ROCm device access requires the container user to belong to the render
|
|
||||||
# and video groups. GIDs are parameterised to match the host; Ubuntu 22.04+
|
|
||||||
# defaults are used here. Override via env vars (docker-compose.rocm.yml
|
|
||||||
# passes them through automatically):
|
|
||||||
# export RENDER_GID=$(getent group render | cut -d: -f3)
|
|
||||||
# export VIDEO_GID=$(getent group video | cut -d: -f3)
|
|
||||||
ARG RENDER_GID=992
|
|
||||||
ARG VIDEO_GID=44
|
|
||||||
RUN if [ "$PYTORCH_VARIANT" = "rocm" ]; then \
|
|
||||||
groupadd -f -g ${RENDER_GID} render && \
|
|
||||||
groupadd -f -g ${VIDEO_GID} video; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create non-root user for security
|
|
||||||
RUN groupadd -r voicebox && \
|
RUN groupadd -r voicebox && \
|
||||||
useradd -r -g voicebox -m -s /bin/bash voicebox
|
useradd -r -g voicebox -m -s /bin/bash voicebox
|
||||||
|
|
||||||
# ROCm: add voicebox user to render+video so it can open /dev/kfd and /dev/dri.
|
|
||||||
RUN if [ "$PYTORCH_VARIANT" = "rocm" ]; then \
|
|
||||||
usermod -aG render,video voicebox; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Install only runtime system dependencies
|
# Install only runtime system dependencies (gosu drops root in the entrypoint)
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
ffmpeg \
|
ffmpeg \
|
||||||
curl \
|
curl \
|
||||||
|
gosu \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Copy installed Python packages from builder stage
|
# Copy installed Python packages from builder stage
|
||||||
@@ -115,9 +93,6 @@ COPY --from=frontend --chown=voicebox:voicebox /build/web/dist /app/frontend/
|
|||||||
RUN mkdir -p /app/data/generations /app/data/profiles /app/data/cache \
|
RUN mkdir -p /app/data/generations /app/data/profiles /app/data/cache \
|
||||||
&& chown -R voicebox:voicebox /app/data
|
&& chown -R voicebox:voicebox /app/data
|
||||||
|
|
||||||
# Switch to non-root user
|
|
||||||
USER voicebox
|
|
||||||
|
|
||||||
# Expose the API port
|
# Expose the API port
|
||||||
EXPOSE 17493
|
EXPOSE 17493
|
||||||
|
|
||||||
@@ -125,5 +100,7 @@ EXPOSE 17493
|
|||||||
HEALTHCHECK --interval=30s --timeout=10s --retries=3 --start-period=60s \
|
HEALTHCHECK --interval=30s --timeout=10s --retries=3 --start-period=60s \
|
||||||
CMD curl -f http://localhost:17493/health || exit 1
|
CMD curl -f http://localhost:17493/health || exit 1
|
||||||
|
|
||||||
# Start the FastAPI server
|
# Entrypoint joins GPU groups then drops to the voicebox user
|
||||||
|
COPY --chmod=755 scripts/rocm-entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||||
|
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
||||||
CMD ["uvicorn", "backend.main:app", "--host", "0.0.0.0", "--port", "17493"]
|
CMD ["uvicorn", "backend.main:app", "--host", "0.0.0.0", "--port", "17493"]
|
||||||
|
|||||||
+8
-36
@@ -1,24 +1,11 @@
|
|||||||
|
---
|
||||||
# ROCm (AMD GPU) overlay for Voicebox
|
# ROCm (AMD GPU) overlay for Voicebox
|
||||||
#
|
#
|
||||||
# Usage:
|
|
||||||
# docker compose -f docker-compose.yml -f docker-compose.rocm.yml up --build
|
# docker compose -f docker-compose.yml -f docker-compose.rocm.yml up --build
|
||||||
#
|
#
|
||||||
# Prerequisites on the host:
|
# Requires ROCm drivers on the host:
|
||||||
# 1. ROCm drivers installed — https://rocm.docs.amd.com/projects/install-on-linux
|
# https://rocm.docs.amd.com/projects/install-on-linux
|
||||||
# 2. Current user in the 'render' and 'video' groups:
|
# RDNA4 (RX 9000): export ROCM_VERSION=7.2 (default 6.3 covers RDNA1-3).
|
||||||
# sudo usermod -aG render,video $USER (then log out/in)
|
|
||||||
#
|
|
||||||
# If the render/video GIDs on your host differ from the Ubuntu 22.04 defaults
|
|
||||||
# (render=992, video=44), export them before running compose so the build arg
|
|
||||||
# and group_add values both stay in sync automatically:
|
|
||||||
# export RENDER_GID=$(getent group render | cut -d: -f3)
|
|
||||||
# export VIDEO_GID=$(getent group video | cut -d: -f3)
|
|
||||||
# docker compose -f docker-compose.yml -f docker-compose.rocm.yml up --build
|
|
||||||
#
|
|
||||||
# ROCm version (ROCM_VERSION):
|
|
||||||
# Default is 6.3 (supports RDNA1/2/3). For RDNA 4 (RX 9000 series) use 7.2:
|
|
||||||
# export ROCM_VERSION=7.2
|
|
||||||
# docker compose -f docker-compose.yml -f docker-compose.rocm.yml up --build
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
voicebox:
|
voicebox:
|
||||||
@@ -26,39 +13,24 @@ services:
|
|||||||
context: .
|
context: .
|
||||||
args:
|
args:
|
||||||
PYTORCH_VARIANT: rocm
|
PYTORCH_VARIANT: rocm
|
||||||
# These build args read from env vars so a single export covers both the
|
|
||||||
# Dockerfile group creation and the runtime group_add below.
|
|
||||||
RENDER_GID: ${RENDER_GID:-992}
|
|
||||||
VIDEO_GID: ${VIDEO_GID:-44}
|
|
||||||
ROCM_VERSION: ${ROCM_VERSION:-6.3}
|
ROCM_VERSION: ${ROCM_VERSION:-6.3}
|
||||||
|
|
||||||
# Pass the AMD GPU device nodes into the container.
|
|
||||||
# /dev/kfd — ROCm compute interface (required for GPU inference)
|
|
||||||
# /dev/dri — DRM render nodes (required for display/memory access)
|
|
||||||
devices:
|
devices:
|
||||||
- /dev/kfd
|
- /dev/kfd
|
||||||
- /dev/dri
|
- /dev/dri
|
||||||
|
|
||||||
# Grant access to the render and video groups so the non-root user
|
|
||||||
# inside the container can open the GPU device nodes.
|
|
||||||
# These reference the same env vars used in build.args above so a
|
|
||||||
# single export keeps Dockerfile groups and runtime group_add in sync.
|
|
||||||
group_add:
|
|
||||||
- "${RENDER_GID:-992}" # render
|
|
||||||
- "${VIDEO_GID:-44}" # video
|
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
# HSA_OVERRIDE_GFX_VERSION forces the ROCm runtime to treat the GPU as a
|
# HSA_OVERRIDE_GFX_VERSION forces the ROCm runtime to treat the GPU as a
|
||||||
# specific GFX version when auto-detection fails or the GPU is newer than
|
# specific GFX version when auto-detection fails or the GPU is newer than
|
||||||
# the ROCm release. app.py sets 10.3.0 (RDNA2) by default; override here
|
# the ROCm release. app.py sets 10.3.0 (RDNA2) by default; override here
|
||||||
# for your GPU family:
|
# for your GPU family:
|
||||||
# RDNA4 / RX 9000 series: 12.0.0 (requires ROCM_VERSION=7.2)
|
# RDNA4 / RX 9000 series: 12.0.0
|
||||||
|
# (requires ROCM_VERSION=7.2)
|
||||||
# RDNA3 / RX 7000 series / Strix Halo: 11.0.0
|
# RDNA3 / RX 7000 series / Strix Halo: 11.0.0
|
||||||
# RDNA2 / RX 6000 series: 10.3.0
|
# RDNA2 / RX 6000 series: 10.3.0
|
||||||
# RDNA1 / RX 5000 series: 10.1.0
|
# RDNA1 / RX 5000 series: 10.1.0
|
||||||
# Vega / GCN5: 9.0.0
|
# Vega / GCN5: 9.0.0
|
||||||
- HSA_OVERRIDE_GFX_VERSION=11.0.0
|
- HSA_OVERRIDE_GFX_VERSION=${HSA_OVERRIDE_GFX_VERSION:-}
|
||||||
|
|
||||||
# Tune the ROCm memory allocator to reduce fragmentation during
|
# Tune the ROCm memory allocator
|
||||||
# multi-engine inference (TTS + STT + LLM running concurrently).
|
|
||||||
- PYTORCH_HIP_ALLOC_CONF=garbage_collection_threshold:0.8,max_split_size_mb:512
|
- PYTORCH_HIP_ALLOC_CONF=garbage_collection_threshold:0.8,max_split_size_mb:512
|
||||||
|
|||||||
@@ -43,6 +43,26 @@ setup-python:
|
|||||||
fi
|
fi
|
||||||
echo "Installing Python dependencies..."
|
echo "Installing Python dependencies..."
|
||||||
{{ pip }} install --upgrade pip -q
|
{{ pip }} install --upgrade pip -q
|
||||||
|
if [ "$(uname)" = "Linux" ]; then
|
||||||
|
torch_index=""
|
||||||
|
if [ -e /proc/driver/nvidia/version ] || [ -d /sys/module/nvidia ]; then
|
||||||
|
echo "Detected NVIDIA GPU — installing CUDA PyTorch..."
|
||||||
|
torch_index="https://download.pytorch.org/whl/cu128"
|
||||||
|
elif [ -e /dev/kfd ]; then
|
||||||
|
if [ -n "${VOICEBOX_ROCM_VERSION:-}" ]; then
|
||||||
|
rocm_ver="$VOICEBOX_ROCM_VERSION"
|
||||||
|
elif lspci 2>/dev/null | grep -qi "Navi 4"; then
|
||||||
|
rocm_ver=7.2
|
||||||
|
else
|
||||||
|
rocm_ver=6.3
|
||||||
|
fi
|
||||||
|
echo "Detected AMD GPU — installing ROCm PyTorch (rocm${rocm_ver})..."
|
||||||
|
torch_index="https://download.pytorch.org/whl/rocm${rocm_ver}"
|
||||||
|
fi
|
||||||
|
if [ -n "$torch_index" ]; then
|
||||||
|
{{ pip }} install torch torchaudio --index-url "$torch_index"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
{{ pip }} install -r {{ backend_dir }}/requirements.txt
|
{{ pip }} install -r {{ backend_dir }}/requirements.txt
|
||||||
# Chatterbox pins numpy<1.26 / torch==2.6 which break on Python 3.12+
|
# Chatterbox pins numpy<1.26 / torch==2.6 which break on Python 3.12+
|
||||||
{{ pip }} install --no-deps chatterbox-tts
|
{{ pip }} install --no-deps chatterbox-tts
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
# Join whatever groups own the mounted GPU nodes so /dev/kfd and /dev/dri work
|
||||||
|
# on any host (no RENDER_GID/VIDEO_GID needed), then drop to the app user.
|
||||||
|
for dev in /dev/kfd /dev/dri/render*; do
|
||||||
|
[ -e "$dev" ] || continue
|
||||||
|
gid=$(stat -c %g "$dev")
|
||||||
|
grp=$(getent group "$gid" | cut -d: -f1)
|
||||||
|
[ -n "$grp" ] || {
|
||||||
|
grp="gpu$gid"
|
||||||
|
groupadd -g "$gid" "$grp"
|
||||||
|
}
|
||||||
|
usermod -aG "$grp" voicebox
|
||||||
|
done
|
||||||
|
exec gosu voicebox "$@"
|
||||||
Reference in New Issue
Block a user