Files
voicebox/backend
Jamie PineandGitHub d61e884104 fix(offline): patch transformers mistral-regex check to survive HF failures (#530)
* fix(offline): patch transformers mistral-regex check to survive HF failures

transformers 4.57.x's `PreTrainedTokenizerBase._patch_mistral_regex` calls
`huggingface_hub.model_info(repo_id)` unconditionally during any non-local
tokenizer load to probe for Mistral-family models. The call raises on
`HF_HUB_OFFLINE=1`, on network outages, and on slow/blocked HF endpoints,
and transformers doesn't catch any of it — the exception bubbles out of
`from_pretrained` and kills the load for unrelated engines (Qwen TTS,
Qwen CustomVoice, TADA, etc.).

0.4.2's load-time `force_offline_if_cached` guard walked straight into
this trap: on cached online users it flipped `HF_HUB_OFFLINE=1` and
converted a healthy load into a hard crash. 0.4.3's inference-path guard
masked it; #524 removed the inference guard in 0.4.4, and users updating
to 0.4.4 started hitting the same error on the load path instead
(#526).

Fix:
- Wrap `_patch_mistral_regex` so any exception from the inner HF
  metadata check is swallowed and the tokenizer is returned unchanged.
  Voicebox never loads Mistral models, so the regex rewrite this check
  gates is a no-op for us; matches the success-path behavior for
  non-Mistral repos (tokenization_utils_base.py:2503).
- Drop the `force_offline_if_cached` wraps from every load path
  (pytorch_backend Qwen + Whisper, qwen_custom_voice_backend,
  mlx_backend Qwen + Whisper). With the mistral patch in place they
  provide zero value and only risk re-introducing the same class of
  bug. Helper and its unit tests stay — still correct for targeted
  future use.
- Add `backend/tests/test_offline_patch.py` covering
  OfflineModeIsEnabled / ConnectionError suppression, success
  pass-through, idempotence, and the missing-method no-op path.

Fixes #526.

* fix(offline): install mistral-regex patch for non-MLX backends

The previous commit left the patch wired only through ``mlx_backend.py``'s
existing import of ``hf_offline_patch``. On Windows/Linux/CUDA users who
never load the MLX backend (everyone who hit #526), the patch module was
never imported, so ``patch_transformers_mistral_regex`` never ran and the
crash persisted.

Hoist the import into ``backends/__init__.py``. Every backend imports from
this package, so the module-level patch install runs before any
``from_pretrained`` call regardless of which engine the user picks.

Caught by CodeRabbit and Cursor Bugbot on #530.
2026-04-21 22:01:29 -07:00
..
2026-04-21 04:28:09 -07:00

Voicebox Backend

FastAPI server powering voice cloning, speech generation, and audio processing. Runs locally as a Tauri sidecar or standalone via python -m backend.main.

Running

# Via justfile (recommended)
just dev:server

# Standalone
python -m backend.main --host 127.0.0.1 --port 17493

# With custom data directory
python -m backend.main --data-dir /path/to/data

The server auto-initializes the SQLite database on first startup. Models are downloaded from HuggingFace on first use.

Architecture

backend/
  app.py                  # FastAPI app factory, CORS, lifecycle events
  main.py                 # Entry point (imports app, runs uvicorn)
  config.py               # Data directory paths and configuration
  models.py               # Pydantic request/response schemas
  server.py               # Tauri sidecar launcher, parent-pid watchdog

  routes/                 # Thin HTTP handlers — validation, delegation, response formatting
  services/               # Business logic, CRUD, orchestration
  backends/               # TTS/STT engine implementations (MLX, PyTorch, etc.)
  database/               # ORM models, session management, migrations, seed data
  utils/                  # Shared utilities (audio, effects, caching, progress tracking)

Request flow

HTTP request
  -> routes/        (validate input, parse params)
  -> services/      (business logic, database queries, orchestration)
  -> backends/      (TTS/STT inference)
  -> utils/         (audio processing, effects, caching)

Route handlers are intentionally thin. They validate input, delegate to a service function, and format the response. All business logic lives in services/.

Key modules

services/generation.py -- Single run_generation() function that handles all three generation modes (generate, retry, regenerate). Manages model loading, voice prompt creation, chunked inference, normalization, effects, and version persistence.

services/task_queue.py -- Serial generation queue. Ensures only one GPU inference runs at a time. Background tasks are tracked to prevent garbage collection.

backends/__init__.py -- Protocol definitions (TTSBackend, STTBackend), model config registry, and factory functions. Adding a new engine means implementing the protocol and registering a config entry.

backends/base.py -- Shared utilities used across all engine implementations: HuggingFace cache checks, device detection, voice prompt combination, progress tracking.

database/ -- SQLAlchemy ORM models with a re-exporting __init__.py for backward compatibility. Migrations run automatically on startup.

Backend selection

The server detects the best inference backend at startup:

Platform Backend Acceleration
macOS (Apple Silicon) MLX Metal / Neural Engine
Windows / Linux (NVIDIA) PyTorch CUDA
Linux (AMD) PyTorch ROCm
Intel Arc PyTorch IPEX / XPU
Windows (any GPU) PyTorch DirectML
Any PyTorch CPU fallback

Detection is handled by utils/platform_detect.py. Both backends implement the same TTSBackend protocol, so the API layer is engine-agnostic.

API

90 endpoints organized by domain. Full interactive documentation available at http://localhost:17493/docs when the server is running.

Domain Prefix Description
Health /, /health Server status, GPU info, filesystem checks
Profiles /profiles Voice profile CRUD, samples, avatars, import/export
Channels /channels Audio channel management and voice assignment
Generation /generate TTS generation, retry, regenerate, status SSE
History /history Generation history, search, favorites, export
Transcription /transcribe Whisper-based audio-to-text
Stories /stories Multi-track timeline editor, audio export
Effects /effects Effect presets, preview, version management
Audio /audio, /samples Audio file serving
Models /models Load, unload, download, migrate, status
Tasks /tasks, /cache Active task tracking, cache management
CUDA /backend/cuda-* CUDA binary download and management

Quick examples

# Generate speech
curl -X POST http://localhost:17493/generate \
  -H "Content-Type: application/json" \
  -d '{"text": "Hello world", "profile_id": "...", "language": "en"}'

# List profiles
curl http://localhost:17493/profiles

# Stream generation status (SSE)
curl http://localhost:17493/generate/{id}/status

Data directory

{data_dir}/
  voicebox.db             # SQLite database
  profiles/{id}/          # Voice samples per profile
  generations/            # Generated audio files
  cache/                  # Voice prompt cache (memory + disk)
  backends/               # Downloaded CUDA binary (if applicable)

Default location is the OS-specific app data directory. Override with --data-dir or the VOICEBOX_DATA_DIR environment variable.

Code quality

Linting and formatting are enforced by ruff, configured in pyproject.toml. See STYLE_GUIDE.md for conventions.

just check-python       # lint + format check
just fix-python         # auto-fix lint issues + reformat
just test               # run pytest

Dependencies

Runtime dependencies are in requirements.txt. macOS-only MLX dependencies are in requirements-mlx.txt. Dev tools (ruff, pytest) are installed automatically by just setup-python.