import os import subprocess import sys def setup_dependencies(): """Install NeMo and pin transformers in the right order to satisfy gradio 6.20's huggingface-hub>=1.2 requirement while still ending up on transformers 5.3.0 (which the Gepard checkpoint needs). Why not put nemo-toolkit in requirements.txt? NeMo's ``nemo-toolkit[tts]==2.4.0`` pulls in ``transformers<=4.52`` (which resolves to 4.51.x), and that requires ``huggingface-hub<1.0`` — conflicting with gradio 6.20's ``huggingface-hub>=1.2`` at build time so pip refuses to resolve. We install nemo-toolkit itself at runtime with ``--no-deps`` instead. All of NeMo's OTHER [tts] dependencies (librosa, soundfile, omegaconf, matplotlib, seaborn, einops, kornia, lhotse, lightning, peft, torchmetrics, datasets, …) are pre-installed at build time from requirements.txt — the complete list minus the conflicting transformers pin (source: pypi.org/pypi/nemo-toolkit/2.4.0/json). So installing nemo with --no-deps doesn't miss anything import-time. Order is load-bearing: 1. transformers==5.3.0 with --no-deps — forces the runtime onto the Qwen3.5 backbone version the Gepard checkpoint was trained on. Combined with the pre-installed hub>=1.2, satisfies gradio 6.20. 2. nemo-toolkit[tts]==2.4.0 with --no-deps — installed on top of transformers 5.3.0 without re-resolving its declared (conflicting) transformers<=4.52 constraint. 3. numpy<2.0 — keep the NeMo/codec stack on numpy 1.x. Idempotent: writes a sentinel file so the install only runs once per container. """ os.environ["OMP_NUM_THREADS"] = "4" sentinel = "/tmp/deps_installed" if os.path.exists(sentinel): return pip = [sys.executable, "-m", "pip", "install", "--no-cache-dir"] try: # 1. Pin the transformers + hub versions gradio 6.20 needs, before # NeMo gets a chance to downgrade them. --no-deps because we # already have these libraries installed at compatible versions. print("Pinning transformers==5.3.0 + hub>=1.2 (no-deps) ...") subprocess.check_call(pip + [ "--no-deps", "transformers==5.3.0", "huggingface-hub>=1.2,<2.0", ]) # 2. Install NeMo on top without re-resolving dependencies. Its # declared transformers<=4.52 / hub<1.0 would conflict; with # --no-deps the resolver doesn't see those constraints. print("Installing nemo-toolkit[tts]==2.4.0 (no-deps) ...") subprocess.check_call(pip + ["--no-deps", "nemo-toolkit[tts]==2.4.0"]) # 3. Cap numpy so a transitive bump doesn't break the NeMo/codec # stack, which is built against numpy 1.x. print("Capping numpy<2.0 ...") subprocess.check_call(pip + ["numpy<2.0"]) with open(sentinel, "w") as f: f.write("done") except Exception as e: print(f"Dependencies setup error: {e}") raise