| |
| """Pre-warm the Modal-hosted models before a live demo / judging run. |
| |
| The flagship Space calls ONE Modal endpoint for everything — the LLM (+vision/OCR), |
| STT (Whisper) and TTS (Veena). With scale-to-zero the first request after idle pays |
| a cold start (GGUF + model load) that can take a minute or two. Run this ~2 minutes |
| before filming so the first real turn the judge sees is instant. |
| |
| Usage |
| ----- |
| uv run python scripts/prewarm.py # uses DUKAAN_*_BASE_URL / config |
| uv run python scripts/prewarm.py https://<ws>--dukaan-llm-serve.modal.run |
| |
| It exercises the three inference paths (a 1-token completion, a short STT call, a |
| short TTS call) through the normal dukaan client code, so it warms whatever the env |
| points at — Modal in production, or a local llama-server in dev. Read-only: it |
| records nothing to any database. |
| """ |
| from __future__ import annotations |
|
|
| import os |
| import sys |
| import time |
|
|
|
|
| def _route_to(base: str) -> None: |
| """Point LLM/STT/TTS at one Modal base URL (modal_app.py serves all three).""" |
| base = base.rstrip("/") |
| if base.endswith("/v1"): |
| base = base[:-3] |
| os.environ["DUKAAN_LLM_BASE_URL"] = base + "/v1" |
| os.environ["DUKAAN_STT_BASE_URL"] = base + "/stt" |
| os.environ["DUKAAN_TTS_BASE_URL"] = base + "/tts" |
|
|
|
|
| def _timed(label: str, fn) -> bool: |
| t0 = time.perf_counter() |
| try: |
| fn() |
| print(f" [ok] {label:<4s} {time.perf_counter() - t0:6.1f}s") |
| return True |
| except Exception as e: |
| print(f" [FAIL] {label:<4s} {time.perf_counter() - t0:6.1f}s {type(e).__name__}: {e}") |
| return False |
|
|
|
|
| def main() -> int: |
| if len(sys.argv) > 1: |
| _route_to(sys.argv[1]) |
|
|
| |
| import numpy as np |
|
|
| from dukaan import config, llm, stt, tts |
|
|
| print("Pre-warming Dukaan models") |
| print(f" LLM : {config.LLM_BASE_URL}") |
| print(f" STT : {config.STT_BASE_URL or '(local, in-process)'}") |
| print(f" TTS : {config.TTS_BASE_URL or '(local, in-process)'}") |
| print() |
|
|
| sr = 16000 |
| silence = np.zeros(sr // 2, dtype=np.float32) |
| ok = [ |
| _timed("llm", lambda: llm.complete("namaste", max_tokens=1)), |
| _timed("stt", lambda: stt.transcribe((sr, silence))), |
| _timed("tts", lambda: tts.synthesize("नमस्ते, दुकान साथी तैयार है।")), |
| ] |
|
|
| print() |
| if all(ok): |
| print("All warm — safe to start the demo.") |
| return 0 |
| print("Some endpoints did not warm — check the Modal app is deployed with min_containers>=1.") |
| return 1 |
|
|
|
|
| if __name__ == "__main__": |
| raise SystemExit(main()) |
|
|