Skip to content

Commit 30ac7be

Browse files
authored
feat(runtime): Pocket TTS cloning status fix, mount checks, and env simplification (#117)
Overview Integrates Pocket TTS as a hotswappable, live-configurable TTS backend (TTS_BACKEND=pocket_tts), and makes related reliability, observability, and DX improvements across runtime, frontend, Docker compose, and docs. Key highlights: - Pocket TTS wired end-to-end: model loading, generation, voice states, caching, invalidation, and UI. - Mount/runtime health checks: /health now reports volumes, paths, and Pocket TTS status. - MODEL_DTYPE control: backend-aware dtype selection with bf16/float32 safety. - TTS_DIAG watchdog: hard timeout on stuck generation (especially pytorch+bfloat16), with optional bf16→float32 auto-fallback. - REF_TEXT optional: service starts without a reference transcript; Whisper auto-drafts it if REF_AUDIO is mounted. - Unified export target: single compose service exports both Base and VoiceDesign IR. - Centralized frontend state: Zustand store for health, swap, runtime config, and speak-page state. - Simplified .env.example and ENV_REFERENCE for new users. Changes Runtime: - Added Pocket TTS as a first-class backend (TTS_BACKEND=pocket_tts). - New src/qwen3_tts/pocket_tts_runtime.py with: - load_pocket_tts_model, generate_pocket_tts, build_default_voice_state, get_pocket_tts_voice_state. - invalidate_voice_state, unload_pocket_tts. - Post-EOS tail trimming and FRAMES_AFTER_EOS support. - Caching and fallback for voice_state to avoid redundant re-encoding. - _run_generate has a dedicated Pocket TTS branch using its own voice_state resolution. - TTS_BACKEND is now one of: openvino | pytorch | pocket_tts; switching is supported via runtime config without restarting. - Added MODEL_DTYPE: - openvino: pinned to bfloat16 (user cannot break it). - pytorch / pocket_tts: configurable (float32 / bfloat16); defaults float32. - On backend switch (e.g., openvino → pytorch), dtype is auto-corrected to avoid unsafe bf16 on CPU. - Added mount health checks: - On startup: validates REF_AUDIO, /voices, /segments, HF cache, OV dir, and /app writability; logs [MOUNT] warnings. - health_state() now includes a "mount" object reflecting these statuses. - Added Pocket TTS health metadata (language, voice_cloning_available, status message). - TTS_DIAG unified and hardened: - TTS_DIAG is no longer OpenVINO-only; applies across backends. - Hard timeout watchdog on generate_voice_clone: - Uses a background watchdog thread with periodic logging. - Fails cleanly with RuntimeError when exceeding TTS_DIAG_GEN_TIMEOUT. - pytorch+bfloat16: - Tighter max_new_tokens cap (160 by default) to avoid hung decode. - Optional auto-fallback to float32 (TTS_DIAG_BF16_AUTO_FALLBACK=1/true), now opt-in only. - Added "mounted reference" as a first-class voice: - On startup, ensure_mounted_ref_voice registers REF_AUDIO as voice vd_000000000001. - Idempotent by SHA256; marked "Mounted" in VoiceSelector. - HF_TOKEN handling: - Removed from live config (no longer editable via RuntimeConfigPage). - Config precedence: HF_TOKEN env → HF_TOKEN_FILE → /app/.hf_token. - Missing or empty token file no longer raises; treated as not-set. - ASR and REF_TEXT: - Graceful handling when faster_whisper is not installed: logs a warning instead of crashing. - REF_TEXT is now optional. When REF_AUDIO is mounted but REF_TEXT is unset, Whisper auto-drafts a transcript (REF_TEXT_AUTO=whisper). - New transcribe_reference_audio() in asr_check.py for bootstrap transcription when no expected_text. - Runtime persists sample_text_source (env/whisper/user/unused/none) and ASR metadata on the mounted reference voice. - Voice library tracks per-voice needs_review and asr fields; UI shows transcript review status. Docker / Compose: - Unified export service: - Export can now run both Base and VoiceDesign in one pass (EXPORT_TARGET=both). - Removed separate export-voice-design service from compose.yml. - compose.yml: - Added healthcheck to qwen3-tts service. - Set LOW_RAM_MODE=1 and FRONTEND_ENABLED=1 as recommended defaults. - REF_AUDIO_PATH and REF_TEXT no longer required; REF_TEXT_AUTO=whisper defaults when REF_AUDIO is present. - Simplified comments and layout. - .env.example: - Greatly simplified for new users; REF_AUDIO_PATH and REF_TEXT marked optional. Frontend: - Integrated Pocket TTS into: - RuntimeConfigPage: pocket_tts backend option + live tunable knobs (temperature, LSD decode steps, EOS threshold, noise clamp, frames after EOS). - SpeakPage: uses centralized Zustand speak state (speakAudioUrl, speakIsGenerating, etc.). - AppShell: one-time fetch to initialize runtime config + Pocket TTS status. - HealthStatusBanner: fixed clipping and improved truncation; now mounted in AppShell. - New PocketTTSWarningBanner: - Shows when backend is pocket_tts but voice cloning is unavailable until the user accepts the Hugging Face license. - Centralized Zustand store: - Health, swap, and runtime config moved from per-page hooks into store.ts. - useSwapStatus now consumes store.swapInProgress instead of doing its own polling. - VoiceSelector: - Labels mounted reference voice with a "Mounted" badge. - Adds "Review" badge for voices needing transcript review. - VoiceLibraryPage: - Shows transcript source badge (Whisper draft, User edited, Startup override). - Displays amber review callout when ASR flags issues. - Shows Whisper draft transcript when it differs from the stored sample_text. Docs: - New docs/architecture/pocket_tts_integration.md with integration design. - New docs/plans for voice manipulation, speak tab enhancements, and TTS audio style pipeline. - ENV_REFERENCE.md simplified; REF_AUDIO/REF_TEXT marked optional; REF_TEXT_AUTO documented. - README.md updated with Pocket TTS and simplified setup guidance. - HOW_TO_RUN and FRONTEND_OVERVIEW updated to reflect new defaults and pocket_tts backend. Tests: - New tests/tier1_unit/test_pocket_tts_runtime.py: - Covers load, generate, voice_state resolution, cache invalidation, unload, and HF gate error handling. - New tests/tier1_unit/test_run_generate.py: - Regression test for _run_generate non-TTS_DIAG path (catches watchdog/local-scope regressions). - Updated test_model_config.py: - Aligned with new MODEL_DTYPE behavior and HF_TOKEN graceful degradation. New / relevant env vars Key new or changed: - TTS_BACKEND: now accepts pocket_tts in addition to openvino / pytorch. - MODEL_DTYPE: float32 | bfloat16; controls Torch dtype for pytorch/pocket_tts (pinned to bf16 for openvino). - TTS_DIAG_BF16_AUTO_FALLBACK: 1 | true to enable auto bf16→float32 fallback on pytorch timeout. - TTS_DIAG_GEN_TIMEOUT: seconds before watchdog kills stuck generation (default 180; 120 for pytorch+bf16). - TTS_SYSTEM_MAX_NEW_TOKENS_PYTORCH_BF16: cap for max_new_tokens when pytorch+bf16 (default 160). - POCKET_TTS_TEMP, POCKET_TTS_LSD_DECODE_STEPS, POCKET_TTS_EOS_THRESHOLD, POCKET_TTS_NOISE_CLAMP, POCKET_TTS_FRAMES_AFTER_EOS: live-tunable Pocket TTS knobs via runtime config. - EXPORT_TARGET: new allowed value both (exports Base + VoiceDesign in one run). - REF_TEXT_AUTO: whisper (default) | 0; auto-drafts REF_TEXT from REF_AUDIO when unset. Testing / validation Validated (branch locally, on dockermisc1): - Docker build: single image builds with pocket-tts==2.1.0 included. - /health: - Reports mount statuses, pocket_tts block (when applicable), and runtime config. - TTS_BACKEND=pocket_tts: - Loads Pocket TTS model (with valid HF_TOKEN). - Generates speech; respects temperature, EOS threshold, etc. - Voice library and mounted reference voice work as expected. - invalidate_voice_state clears cached state on voice deletion. - TTS_BACKEND=openvino and pytorch: - Existing behavior preserved; no regressions in generation, health, idle unload, or runtime config. - MODEL_DTYPE: - openvino: always bf16. - pytorch/pocket_tts: honors MODEL_DTYPE, safe defaults on backend switch. - TTS_DIAG watchdog: - On long-running or stuck generation with TTS_DIAG=1, watchdog logs progress and fails with timeout instead of hanging. - Frontend: - Pocket TTS appears in RuntimeConfigPage backend dropdown. - SpeakPage, VoiceLibraryPage, HealthStatusBanner, and RuntimeConfigPage render without errors. Notes - Pocket TTS currently lives under TTS_BACKEND=pocket_tts; swapping backends at runtime is supported but is considered advanced. - Pocket TTS voice cloning requires accepting terms at https://huggingface.co/kyutai/pocket-tts with the HF account used by the container. - The bf16 auto-fallback (TTS_DIAG_BF16_AUTO_FALLBACK) is opt-in and intentionally conservative; it mutates global state mid-request and is not for casual use. BEGIN_COMMIT_OVERRIDE feat(runtime): integrate Pocket TTS as hotswappable backend with generation, voice states, and live knobs feat(runtime): add MODEL_DTYPE control with backend-aware safety and bf16→float32 auto-correction on swap feat(runtime): add mount health checks (REF_AUDIO, /voices, /segments, HF cache, OV dir) and /health mount/pocket_tts reporting feat(runtime): unify TTS_DIAG across backends and add watchdog with hard timeout; tighter pytorch+bf16 token cap; opt-in bf16→float32 auto-fallback feat(runtime): register mounted REF_AUDIO as first-class "Mounted reference" voice; show "Mounted" badge in VoiceSelector fix(runtime): gracefully handle missing faster_whisper instead of crashing at import fix(runtime): gate bf16→float32 auto-fallback and cache fallback voice_state feat(docker): unified export service with EXPORT_TARGET=both for Base + VoiceDesign; simplified compose.yml and .env.example feat(frontend): add Pocket TTS options and tuning controls to RuntimeConfigPage; PocketTTSWarningBanner for cloning unavailability refactor(frontend): centralize health, swap, runtime config, and speak-page state in Zustand store; refactor SpeakPage and useSwapStatus docs: simplify ENV_REFERENCE and .env.example for new users; add pocket_tts_integration architecture doc test: add test_pocket_tts_runtime and test_run_generate for watchdog/watchdog-regression and Pocket TTS behaviors feat(frontend)(runtime)(docs): make REF_TEXT optional via Whisper auto-draft and add transcript review status END_COMMIT_OVERRIDE
1 parent 06fd976 commit 30ac7be

35 files changed

Lines changed: 4174 additions & 713 deletions

.env.example

Lines changed: 33 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,36 @@
1-
# ── Required (set these before first use) ─────────────────────────────────────
2-
REF_AUDIO_PATH=/absolute/path/to/reference.wav
3-
REF_TEXT=Exact transcript of the reference audio
4-
MODEL_SIZE=1.7B
5-
6-
# ── Recommended (most real deployments should set) ────────────────────────────
7-
# QWEN3_TTS_IMAGE=ghcr.io/nmorgowicz-org/qwen3-tts-openvino:<sha>
8-
# LOW_RAM_MODE=1
9-
10-
# ── Service ───────────────────────────────────────────────────────────────────
11-
# QWEN3_TTS_PORT=8318 # Host port for the service
12-
# TZ=UTC # Log timestamps (UTC recommended for multi-timezone access)
13-
# FRONTEND_ENABLED=1 # Serve the web UI at / (set 0 for API-only deployments)
14-
15-
# ── Memory limits ─────────────────────────────────────────────────────────────
16-
# TTS_MEMORY_LIMIT=10G # Serving container cgroup memory limit (raise on larger hosts)
17-
# TTS_MEMORY_SWAP_LIMIT=11G # Serving container cgroup memory+swap limit
18-
# EXPORT_MEMORY_LIMIT=13G # Export container limit (stop serving first on 15 GiB hosts)
19-
# EXPORT_MEMORY_SWAP_LIMIT=14G # Export container swap limit
20-
21-
# ── Advanced (tune only if you have a reason; see HOW_TO_RUN.md for details) ──
22-
23-
# CPU threading: set to your physical core count (not hyperthreads) for best latency.
24-
# OV_INFERENCE_THREADS=6
25-
26-
# OpenVINO dynamic quantization: 0=disabled, 32=default, 64=faster with slightly
27-
# lower accuracy. Useful on very constrained hosts where a small latency gain matters.
28-
# OV_DYNAMIC_QUANT_GROUP_SIZE=32
1+
# Minimal Qwen3-TTS OpenVINO example.
2+
# Copy this to .env and edit the values you need.
3+
# For full reference, see docs/ENV_REFERENCE.md
294

30-
# OpenVINO compiled kernel cache directory. Leaving this default eliminates 60–120s
31-
# of JIT recompilation on every restart or idle-unload reload. Set to empty string to disable.
32-
# OV_CACHE_DIR=/ov/cache
5+
# Optional default voice -------------------------------------------------
6+
# If set, this WAV is mounted and promoted to the Voice Library.
7+
# REF_TEXT is optional; by default Whisper drafts it automatically.
8+
# REF_AUDIO_PATH=/absolute/path/to/reference.wav
9+
# REF_TEXT=Exact transcript audio
10+
# REF_TEXT_AUTO=whisper
3311

34-
# Idle unload: set to N seconds to free the model after inactivity (e.g. 1800 = 30 min).
35-
# LOW_RAM_MODE=1 sets this automatically. Reload is transparent but adds ~5–30s latency.
36-
# IDLE_UNLOAD_SECONDS=0
12+
# HF_TOKEN is required only if the checkpoint is gated in your environment.
13+
# HF_TOKEN=hf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
3714

38-
# OPENVINO_KEEP_CODEC_ENCODER: set to 0 only if you'll never use VoiceDesign / voice library
39-
# / cloning any voice_id besides the one startup reference voice (e.g. a single-voice deployment).
40-
# - 1 (default): keeps codec resident; enables cloning any voice_id immediately, at a cost of ~0.3 GiB.
41-
# - 0: frees ~0.3 GiB after startup; uncached voice_id will fail with an error.
42-
# OPENVINO_KEEP_CODEC_ENCODER=1
43-
44-
# TTS_MAX_SPEECH_SECONDS: max duration for a single request, baked into IR at export time.
45-
# Is a latency/safety cap, not a memory lever. Changing it requires re-exporting.
46-
# Default 64 is appropriate for most uses.
47-
# TTS_MAX_SPEECH_SECONDS=64
48-
49-
# Rollback backend: set to 'pytorch' to run without OpenVINO IR (slower, useful if IR fails).
50-
# TTS_BACKEND=pytorch
51-
52-
# Hugging Face token: required if the checkpoint is gated for your environment.
53-
# Never log or commit this.
54-
# HF_TOKEN=
55-
56-
# Pin a specific Hugging Face revision; must match exported IR metadata.
57-
# MODEL_REVISION=
58-
59-
# Silence trim: trim leading/trailing silence from output audio. Useful if output
60-
# sounds too short or is missing final consonants. Set SILENCE_TRIM=0 to disable.
61-
# SILENCE_TRIM=1
62-
# SILENCE_TRIM_THRESH=0.01 # Silence threshold (fraction of peak amplitude)
63-
# SILENCE_TRIM_PAD_MS=30 # Padding kept after detected silence boundary
64-
65-
# ── VoiceDesign ────────────────────────────────────────────────────────────────
66-
# After Base export, run: docker compose run --rm export-voice-design
67-
# VOICE_DESIGN_MODEL_SIZE=1.7B
68-
# VOICE_DESIGN_MODEL_REPO=
69-
# VOICE_DESIGN_MAX_SPEECH_SECONDS=20 # Capacity baked into the VoiceDesign IR at export time
15+
# ── Recommended defaults ──────────────────────────────────────────────────────
16+
MODEL_SIZE=1.7B
17+
TTS_BACKEND=openvino
18+
19+
# ── Data paths (override only if you need non-default locations) ────────────────
20+
# MODEL_CACHE_PATH=/var/data/autopirate/qwen3-tts/model
21+
# OV_DATA_PATH=/var/data/autopirate/qwen3-tts/openvino
22+
# VOICE_LIBRARY_PATH=/voices
23+
# SEGMENT_LIBRARY_PATH=/segments
24+
25+
# ── Advanced / tuning ─────────────────────────────────────────────────────────
26+
# For full reference and all available options, see docs/ENV_REFERENCE.md.
27+
28+
# LOW_RAM_MODE=1 # Recommended on 10–15 GiB hosts; enables idle unload and malloc tuning
29+
# FRONTEND_ENABLED=1 # Serve the web UI at / (0 = API-only)
30+
# VOICE_DESIGN_MODEL_SIZE=1.7B # For VoiceDesign (run export-voice-design after Base export)
31+
32+
# TTS_MAX_SPEECH_SECONDS=64 # Max speech length per request (requires re-export if changed)
33+
# SILENCE_TRIM=1 # Trim silence from output (0 = disable)
34+
# IDLE_UNLOAD_SECONDS=1800 # Free model after N seconds of inactivity (0 = disabled)
35+
# OV_INFERENCE_THREADS=6 # Use physical core count for best latency
36+
# TTS_BACKEND=pytorch # Rollback to CPU-only PyTorch if OpenVINO fails

Dockerfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ p.write_text(t)"
8181
RUN python -m pip install -r requirements/requirements-openvino.txt && \
8282
python -m pip install -r requirements/requirements-export.txt
8383

84+
# Pocket TTS: lightweight CPU TTS backend
85+
RUN python -m pip install -r requirements/requirements-pocket-tts.txt
86+
8487
COPY src/ src/
8588
COPY scripts/ scripts/
8689
COPY --from=frontend-build /frontend/dist frontend/dist

README.md

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,31 +20,21 @@ contains the export tooling.
2020
No authentication or TLS. Keep port 8318 on a trusted network or behind an authenticated reverse
2121
proxy (see SECURITY.md).
2222

23-
## Quick start
23+
## Getting started
2424

25-
Requirements: Linux AMD64, Docker Compose, Intel CPU, at least 10 GiB RAM for the service, a
26-
reference WAV, and its exact transcript.
25+
Prerequisites:
2726

28-
```bash
29-
cp .env.example .env
30-
# Edit .env: set REF_AUDIO_PATH and REF_TEXT. MODEL_SIZE=1.7B is recommended.
27+
- Docker and Docker Compose
28+
- Optional: a reference WAV file for a default cloned voice
3129

32-
docker compose run --rm export
33-
docker compose up -d qwen3-tts
34-
curl -fsS http://localhost:8318/health
35-
```
30+
Steps:
3631

37-
Generate:
32+
1. Copy `.env.example` to `.env`; set `HF_TOKEN` only if your selected models are gated. Optional: set `REF_AUDIO_PATH` for a default voice; Whisper drafts its transcript automatically.
33+
2. `docker compose up --build qwen3-tts`
34+
3. Run once to generate model artifacts: `docker compose run --rm --profile export export`
35+
4. Open `http://localhost:8318`
3836

39-
```bash
40-
curl -sS http://localhost:8318/v1/audio/speech \
41-
-H 'Content-Type: application/json' \
42-
-d '{"input":"Hello from Qwen three TTS.","response_format":"mp3"}' \
43-
-o output.mp3
44-
```
45-
46-
For full deployment details, environment variables, VoiceDesign setup, streaming, and memory
47-
tuning, see [HOW_TO_RUN.md](docs/HOW_TO_RUN.md).
37+
For advanced configuration, environment variables, and tuning, see [docs/ENV_REFERENCE.md](docs/ENV_REFERENCE.md).
4838

4939
## Model profiles
5040

compose.yml

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
name: qwen3-tts-openvino
22

3+
# Minimal setup:
4+
# - Create .env if you need to override defaults:
5+
# HF_TOKEN="your token repo is gated" # if needed
6+
# REF_AUDIO_PATH=/path/to/reference.wav # optional default voice
7+
# REF_TEXT="exact transcript reference audio" # optional override; Whisper drafts by default
8+
# - Then:
9+
# docker compose up --build qwen3-tts
10+
# docker compose run --rm --profile export export (once, to generate IR)
11+
12+
# All other knobs are optional and should be left at defaults.
13+
14+
# Common model/volume settings (used by both qwen3-tts and export)
315
x-model-environment: &model-environment
416
MODEL_SIZE: ${MODEL_SIZE:-1.7B}
5-
REF_TEXT: ${REF_TEXT:?Set REF_TEXT to the exact reference-audio transcript}
17+
REF_TEXT: ${REF_TEXT:-}
18+
REF_TEXT_AUTO: ${REF_TEXT_AUTO:-whisper}
619
HF_TOKEN: ${HF_TOKEN:-}
720
MODEL_REVISION: ${MODEL_REVISION:-}
8-
# Must match between `export` and `qwen3-tts` — it selects which capacity-keyed IR file
9-
# gets built and which one gets loaded. Unset uses the 64s default (unchanged behavior).
21+
# Capacity baked into the IR at export time; changing it requires re-export.
1022
TTS_MAX_SPEECH_SECONDS: ${TTS_MAX_SPEECH_SECONDS:-}
1123

1224
x-model-volumes: &model-volumes
@@ -15,7 +27,7 @@ x-model-volumes: &model-volumes
1527

1628
services:
1729
qwen3-tts:
18-
# Local builds: `docker compose up --build` creates the :local tag automatically.
30+
# Local builds: docker compose up --build creates :local.
1931
# Production: set QWEN3_TTS_IMAGE to a pinned GHCR SHA or version tag.
2032
image: ${QWEN3_TTS_IMAGE:-qwen3-tts-openvino:local}
2133
build:
@@ -26,61 +38,57 @@ services:
2638
- "${QWEN3_TTS_PORT:-8318}:8318"
2739
environment:
2840
<<: *model-environment
41+
# Core behavior
2942
TTS_BACKEND: ${TTS_BACKEND:-openvino}
3043
TZ: ${TZ:-America/Detroit}
31-
LOW_RAM_MODE: ${LOW_RAM_MODE:-0}
32-
# Serves the built frontend/ static export at / (see src/qwen3_tts/app.py). Set to 0 to
33-
# run this container as an API-only service with no web UI.
34-
FRONTEND_ENABLED: ${FRONTEND_ENABLED:-1}
35-
# Must match the export-voice-design service below — selects which VoiceDesign IR tree
36-
# this container swaps into for POST /voice_design (see src/qwen3_tts/voice_design.py).
44+
45+
# LOW_RAM_MODE=1 is recommended on typical 10-15 GiB hosts:
46+
# enables idle unload + malloc tuning so the container can coexist
47+
# with other services without hogging memory.
48+
LOW_RAM_MODE: 1
49+
50+
# Serve the built web UI at /. Set to 0 to run API-only.
51+
FRONTEND_ENABLED: 1
52+
53+
# VoiceDesign (used for POST /voice_design).
54+
# These must match whatever was used during export.
3755
VOICE_DESIGN_MODEL_SIZE: ${VOICE_DESIGN_MODEL_SIZE:-1.7B}
3856
VOICE_DESIGN_MODEL_REPO: ${VOICE_DESIGN_MODEL_REPO:-}
3957
VOICE_DESIGN_MAX_SPEECH_SECONDS: ${VOICE_DESIGN_MAX_SPEECH_SECONDS:-}
4058
volumes:
4159
- ${MODEL_CACHE_PATH:-./data/model}:/root/.cache/huggingface/hub:rw
4260
- ${OV_DATA_PATH:-./data/ov}:/ov:rw
43-
- ${REF_AUDIO_PATH:?Set REF_AUDIO_PATH to the reference WAV file}:/voice/reference.wav:ro
61+
- ${REF_AUDIO_PATH:-./data/reference.wav}:/voice/reference.wav:ro
4462
- ${VOICE_LIBRARY_PATH:-./data/voices}:/voices:rw
4563
- ${SEGMENT_LIBRARY_PATH:-./data/segments}:/segments:rw
4664
mem_limit: ${TTS_MEMORY_LIMIT:-10G}
4765
memswap_limit: ${TTS_MEMORY_SWAP_LIMIT:-11G}
4866
stop_grace_period: 45s
67+
healthcheck:
68+
test: ["CMD", "curl", "-sf", "http://localhost:8318/health"]
69+
interval: 30s
70+
timeout: 10s
71+
retries: 5
72+
start_period: 120s
4973

74+
# Unified export service: exports both Base and VoiceDesign IR in one run.
5075
export:
51-
# Same single image as the service above; only the command differs.
5276
image: ${QWEN3_TTS_IMAGE:-qwen3-tts-openvino:local}
5377
build:
5478
context: .
5579
command: ["python", "scripts/export.py"]
5680
profiles: [export]
5781
environment:
5882
<<: *model-environment
83+
# Tell export.py to run both targets (Base + VoiceDesign) in one shot.
84+
EXPORT_TARGET: both
5985
OV_OUTPUT_ROOT: /ov
60-
volumes: *model-volumes
61-
# The FP32 export + INT4/INT8 quantization needs more headroom than serving; the 1.7B
62-
# INT4 export can OOM at the 10G serving limit. Stop the serving container before exporting
63-
# on the 15 GiB box — never run a 13G export and a 10G serve concurrently (OOM).
64-
mem_limit: ${EXPORT_MEMORY_LIMIT:-13G}
65-
memswap_limit: ${EXPORT_MEMORY_SWAP_LIMIT:-14G}
66-
67-
export-voice-design:
68-
# Same image/command as `export`; EXPORT_TARGET selects the VoiceDesign checkpoint and
69-
# its separate /ov/<size>-voicedesign/... output tree (see scripts/export.py, VOICE_DESIGN
70-
# section of docs/dev/architecture/voice_design.md). Independent from the `export` service so a
71-
# VoiceDesign export never overwrites a Base export for the same size.
72-
image: ${QWEN3_TTS_IMAGE:-qwen3-tts-openvino:local}
73-
build:
74-
context: .
75-
command: ["python", "scripts/export.py"]
76-
profiles: [export]
77-
environment:
78-
HF_TOKEN: ${HF_TOKEN:-}
79-
EXPORT_TARGET: voice_design
86+
# VoiceDesign settings (must match qwen3-tts service)
8087
VOICE_DESIGN_MODEL_SIZE: ${VOICE_DESIGN_MODEL_SIZE:-1.7B}
8188
VOICE_DESIGN_MODEL_REPO: ${VOICE_DESIGN_MODEL_REPO:-}
8289
VOICE_DESIGN_MAX_SPEECH_SECONDS: ${VOICE_DESIGN_MAX_SPEECH_SECONDS:-}
83-
OV_OUTPUT_ROOT: /ov
8490
volumes: *model-volumes
91+
# FP32 export + INT4/INT8 quantization is memory-intensive.
92+
# On a 15 GiB box, stop qwen3-tts before running this to avoid OOM.
8593
mem_limit: ${EXPORT_MEMORY_LIMIT:-13G}
8694
memswap_limit: ${EXPORT_MEMORY_SWAP_LIMIT:-14G}

0 commit comments

Comments
 (0)