MomsVoiceAI / runtime_config.py
minhahwang's picture
refactor: runtime config, Q&A flow module, storage paths, and cleanup
397b4ac
Raw
History Blame Contribute Delete
1.91 kB
"""Runtime paths and shared execution controls for the Space."""
import os
import tempfile
import threading
import warnings
from pathlib import Path
APP_ROOT = Path(__file__).resolve().parent
def _usable_root(path: Path, *, warn: bool = False) -> Path | None:
try:
path.mkdir(parents=True, exist_ok=True)
probe = path / ".write_probe"
probe.write_text("ok", encoding="utf-8")
probe.unlink(missing_ok=True)
return path
except OSError as exc:
if warn:
warnings.warn(f"Runtime storage path is not writable: {path} ({exc})")
return None
def _select_storage_root() -> Path:
configured = (
os.environ.get("MOMSVOICE_STORAGE_DIR")
or os.environ.get("SPACE_STORAGE_DIR")
)
candidates: list[tuple[Path, bool]] = []
if configured:
candidates.append((Path(configured).expanduser(), True))
candidates.extend([
(Path("/data") / "momsvoice", False),
(APP_ROOT, True),
(Path(tempfile.gettempdir()) / "momsvoice", True),
])
for candidate, warn in candidates:
usable = _usable_root(candidate, warn=warn)
if usable is not None:
return usable
raise RuntimeError("No writable runtime storage path is available.")
STORAGE_ROOT = _select_storage_root()
VOICE_PROFILE_DIR = STORAGE_ROOT / "Voice_Profile"
AUDIO_CACHE_DIR = STORAGE_ROOT / "audio_cache"
SAMPLE_SOUNDS_DIR = STORAGE_ROOT / "sample_sounds"
for _path in (VOICE_PROFILE_DIR, AUDIO_CACHE_DIR, SAMPLE_SOUNDS_DIR):
_path.mkdir(parents=True, exist_ok=True)
# Serializes GPU-heavy model calls across Gradio events and background pregen
# threads. This keeps the Space responsive under hackathon demo traffic.
GPU_INFERENCE_LOCK = threading.RLock()
def gradio_allowed_paths() -> list[str]:
return [
str(APP_ROOT / "assets"),
str(SAMPLE_SOUNDS_DIR),
]