-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcompose.yml
More file actions
156 lines (144 loc) · 7.47 KB
/
Copy pathcompose.yml
File metadata and controls
156 lines (144 loc) · 7.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
name: persona-forge
# Minimal setup:
# - Create .env if you need to override defaults:
# HF_TOKEN="your token repo is gated" # if needed
# REF_AUDIO_PATH=/path/to/reference.wav # optional default voice
# REF_TEXT="exact transcript reference audio" # optional override; Whisper drafts by default
# PERSONA_FORGE_IMAGE=ghcr.io/nmorgowicz-org/persona-forge:latest # pull published image instead of building
# - Then:
# docker compose up -d persona-forge # pulls PERSONA_FORGE_IMAGE if set, else builds :local
# docker compose up --build persona-forge # force a local build from source
# The default backend (pocket_tts) needs no export step. Only run the export
# below if you switch TTS_BACKEND=openvino for the accelerated Qwen path:
# docker compose run --rm --profile export export (once, to generate IR)
# All other knobs are optional and should be left at defaults.
# Common model/volume settings (used by both persona-forge and export)
x-model-environment: &model-environment
MODEL_SIZE: ${MODEL_SIZE:-1.7B}
REF_TEXT: ${REF_TEXT:-}
REF_TEXT_AUTO: ${REF_TEXT_AUTO:-whisper}
HF_TOKEN: ${HF_TOKEN:-}
MODEL_REVISION: ${MODEL_REVISION:-}
# Capacity baked into the IR at export time; changing it requires re-export.
TTS_MAX_SPEECH_SECONDS: ${TTS_MAX_SPEECH_SECONDS:-}
# Container-side runtime paths (docs/plans/20260829-no_more_docker_architecture.md §4).
# These are the persona_forge.paths resolvers' highest-precedence inputs, distinct from
# the host-side Compose bind-mount variables (MODEL_CACHE_PATH, OV_DATA_PATH, etc. above/
# below) — never confuse the two. Fixed to match the mounts so native/non-Docker runs and
# the container agree on every default except the root.
MODEL_CACHE_CONTAINER_PATH: /root/.cache/huggingface/hub
OV_DATA_DIR: /ov
VOICE_LIBRARY_DIR: /voices
SEGMENT_LIBRARY_DIR: /segments
REF_AUDIO: /voice/reference.wav
HF_TOKEN_FILE: /app/.hf_token
OV_CACHE_DIR: /ov/cache
x-model-volumes: &model-volumes
- ${MODEL_CACHE_PATH:-./data/model}:/root/.cache/huggingface/hub:rw
- ${OV_DATA_PATH:-./data/ov}:/ov:rw
services:
persona-forge:
# Local builds: docker compose up --build creates :local.
# Production: set PERSONA_FORGE_IMAGE to a pinned GHCR SHA or version tag.
image: ${PERSONA_FORGE_IMAGE:-persona-forge:local}
build:
context: .
# Phase A6f: uncomment to layer Intel iGPU userspace (compute-runtime + Level-Zero) into
# the image. Off by default so the canonical CPU image is unaffected (D3).
# args:
# INSTALL_ACCEL_SYSLIBS: "1"
container_name: persona-forge
restart: unless-stopped
# Phase A6f: Intel iGPU passthrough example (uncomment to enable). Also requires:
# - build.args.INSTALL_ACCEL_SYSLIBS=1 above (system libs)
# - environment.GPU_FAMILY=intel-xpu below (triggers A6e's first-boot torch-xpu install
# into the accel-venv volume + A6d's fp64-emu env)
# - the container's user in the host's `render` group (or run privileged) so
# /dev/dri/renderD128 is actually openable, not just visible
# devices:
# - /dev/dri:/dev/dri
# group_add:
# - "44" # render group GID — check `getent group render` on the host, it varies
ports:
- "${PERSONA_FORGE_PORT:-8318}:8318"
environment:
<<: *model-environment
# Core behavior. pocket_tts is the product default: it is self-contained
# (no IR export needed) and drives the built-in voice catalog + voice
# cloning the UI is built around. Set TTS_BACKEND=openvino for the
# accelerated Qwen path once you have run the export (see below).
TTS_BACKEND: ${TTS_BACKEND:-pocket_tts}
# Pocket-TTS artifact sourcing (TTS_BACKEND=pocket_tts only). auto (default):
# verified cache, then the ungated LunaHR mirror, then the gated official
# repo (needs HF_TOKEN), degrading to built-in-only if all sources fail.
POCKET_TTS_MODEL_SOURCE: ${POCKET_TTS_MODEL_SOURCE:-auto}
# Verified artifact cache directory; defaults to <MODEL_CACHE_PATH>/pocket-tts.
POCKET_TTS_ARTIFACT_DIR: ${POCKET_TTS_ARTIFACT_DIR:-}
TZ: ${TZ:-America/Detroit}
# Phase A6/A6d-e: which torch wheel family the entrypoint resolves/installs. `auto`
# (default) detects via torch-independent PCI/device-node probes; only meaningful
# combined with the Intel iGPU passthrough example above. `cpu` (explicit or detected)
# never installs anything extra.
GPU_FAMILY: ${GPU_FAMILY:-auto}
# LOW_RAM_MODE=1 is recommended on typical 10-15 GiB hosts:
# enables idle unload + malloc tuning so the container can coexist
# with other services without hogging memory.
LOW_RAM_MODE: 1
# Serve the built web UI at /. Set to 0 to run API-only.
FRONTEND_ENABLED: 1
# VoiceDesign (used for POST /voice_design).
# These must match whatever was used during export.
VOICE_DESIGN_MODEL_SIZE: ${VOICE_DESIGN_MODEL_SIZE:-1.7B}
VOICE_DESIGN_MODEL_REPO: ${VOICE_DESIGN_MODEL_REPO:-}
VOICE_DESIGN_MAX_SPEECH_SECONDS: ${VOICE_DESIGN_MAX_SPEECH_SECONDS:-}
# Forced-aligner hardening (Precise/Auto prosody). The portable CPU provider and
# five-second warm p95 budget are the load-bearing defaults.
ALIGNER_MODEL_PATH: ${ALIGNER_MODEL_PATH:-}
ALIGNER_PROVIDERS: ${ALIGNER_PROVIDERS:-CPUExecutionProvider}
ALIGNER_LATENCY_BUDGET_SECONDS: ${ALIGNER_LATENCY_BUDGET_SECONDS:-5}
ALIGNER_IDLE_UNLOAD_SECONDS: ${ALIGNER_IDLE_UNLOAD_SECONDS:-120}
GENERATION_REPAIR_BUDGET_SECONDS: ${GENERATION_REPAIR_BUDGET_SECONDS:-5}
volumes:
- ${MODEL_CACHE_PATH:-./data/model}:/root/.cache/huggingface/hub:rw
- ${OV_DATA_PATH:-./data/ov}:/ov:rw
- ${REF_AUDIO_PATH:-./data/reference.wav}:/voice/reference.wav:ro
- ${VOICE_LIBRARY_PATH:-./data/voices}:/voices:rw
# Phase A6e: persists the first-boot per-family torch install (e.g. torch-xpu) across
# container recreation. Harmless/unused when GPU_FAMILY resolves to cpu.
- accel-venv:/opt/accel-venv
- ${SEGMENT_LIBRARY_PATH:-./data/segments}:/segments:rw
mem_limit: ${TTS_MEMORY_LIMIT:-10G}
memswap_limit: ${TTS_MEMORY_SWAP_LIMIT:-11G}
stop_grace_period: 45s
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:8318/health"]
interval: 30s
timeout: 10s
retries: 5
# Qwen first-run downloads and model initialization can take several
# minutes, especially on native Apple Silicon or a cold HF cache.
# Keep this aligned with the image healthcheck's 10-minute allowance.
start_period: 10m
# Unified export service: exports both Base and VoiceDesign IR in one run.
export:
image: ${PERSONA_FORGE_IMAGE:-persona-forge:local}
build:
context: .
command: ["python", "scripts/export.py"]
profiles: [export]
environment:
<<: *model-environment
# Tell export.py to run both targets (Base + VoiceDesign) in one shot.
EXPORT_TARGET: both
OV_OUTPUT_ROOT: /ov
# VoiceDesign settings (must match persona-forge service)
VOICE_DESIGN_MODEL_SIZE: ${VOICE_DESIGN_MODEL_SIZE:-1.7B}
VOICE_DESIGN_MODEL_REPO: ${VOICE_DESIGN_MODEL_REPO:-}
VOICE_DESIGN_MAX_SPEECH_SECONDS: ${VOICE_DESIGN_MAX_SPEECH_SECONDS:-}
volumes: *model-volumes
# FP32 export + INT4/INT8 quantization is memory-intensive.
# On a 15 GiB box, stop persona-forge before running this to avoid OOM.
mem_limit: ${EXPORT_MEMORY_LIMIT:-13G}
memswap_limit: ${EXPORT_MEMORY_SWAP_LIMIT:-14G}
volumes:
accel-venv: