Spaces:
Sleeping
Sleeping
Enable Zero GPU coach backend
Browse files- coach.py +29 -1
- requirements.txt +7 -10
coach.py
CHANGED
|
@@ -30,6 +30,23 @@ from dotenv import load_dotenv
|
|
| 30 |
|
| 31 |
load_dotenv()
|
| 32 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
# ---------------------------------------------------------------------------
|
| 34 |
# Backend selection
|
| 35 |
# ---------------------------------------------------------------------------
|
|
@@ -301,8 +318,14 @@ def _chat_router(messages: list[dict]) -> str:
|
|
| 301 |
return resp.choices[0].message.content
|
| 302 |
|
| 303 |
|
|
|
|
| 304 |
def _chat_local(messages: list[dict]) -> str:
|
| 305 |
-
"""One JSON-mode round trip to the locally-loaded GGUF model.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 306 |
llm = _get_local_llm()
|
| 307 |
resp = llm.create_chat_completion(
|
| 308 |
messages=messages,
|
|
@@ -317,6 +340,11 @@ def _chat_local(messages: list[dict]) -> str:
|
|
| 317 |
def preload() -> None:
|
| 318 |
"""Force-load whichever backend we're configured for. Safe to call twice."""
|
| 319 |
if BACKEND == "local":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 320 |
_get_local_llm()
|
| 321 |
else:
|
| 322 |
# Router path doesn't really preload — but probe the token now so we
|
|
|
|
| 30 |
|
| 31 |
load_dotenv()
|
| 32 |
|
| 33 |
+
# Zero GPU detection. spaces.GPU is a no-op decorator when not on Zero GPU
|
| 34 |
+
# hardware, but we still want to know whether we're running there so we can
|
| 35 |
+
# skip the eager startup preload (the GPU isn't allocated at import time).
|
| 36 |
+
ZERO_GPU = bool(os.environ.get("SPACES_ZERO_GPU"))
|
| 37 |
+
try:
|
| 38 |
+
import spaces # type: ignore
|
| 39 |
+
_HAS_SPACES = True
|
| 40 |
+
except ImportError:
|
| 41 |
+
_HAS_SPACES = False
|
| 42 |
+
class _SpacesShim:
|
| 43 |
+
@staticmethod
|
| 44 |
+
def GPU(*_a, **_kw):
|
| 45 |
+
def deco(fn):
|
| 46 |
+
return fn
|
| 47 |
+
return deco
|
| 48 |
+
spaces = _SpacesShim() # type: ignore
|
| 49 |
+
|
| 50 |
# ---------------------------------------------------------------------------
|
| 51 |
# Backend selection
|
| 52 |
# ---------------------------------------------------------------------------
|
|
|
|
| 318 |
return resp.choices[0].message.content
|
| 319 |
|
| 320 |
|
| 321 |
+
@spaces.GPU(duration=120)
|
| 322 |
def _chat_local(messages: list[dict]) -> str:
|
| 323 |
+
"""One JSON-mode round trip to the locally-loaded GGUF model.
|
| 324 |
+
|
| 325 |
+
On Zero GPU the GPU is allocated for the duration of this call; the model
|
| 326 |
+
is loaded on first invocation and cached for subsequent calls within the
|
| 327 |
+
same process.
|
| 328 |
+
"""
|
| 329 |
llm = _get_local_llm()
|
| 330 |
resp = llm.create_chat_completion(
|
| 331 |
messages=messages,
|
|
|
|
| 340 |
def preload() -> None:
|
| 341 |
"""Force-load whichever backend we're configured for. Safe to call twice."""
|
| 342 |
if BACKEND == "local":
|
| 343 |
+
if ZERO_GPU:
|
| 344 |
+
# GPU isn't allocated at import time on Zero GPU; defer the load
|
| 345 |
+
# to the first @spaces.GPU call (slower first turn, works at all).
|
| 346 |
+
print("[coach] Zero GPU detected — deferring model load to first call.")
|
| 347 |
+
return
|
| 348 |
_get_local_llm()
|
| 349 |
else:
|
| 350 |
# Router path doesn't really preload — but probe the token now so we
|
requirements.txt
CHANGED
|
@@ -9,14 +9,11 @@ praat-parselmouth==0.4.7
|
|
| 9 |
phonemizer==3.3.0
|
| 10 |
python-dotenv==1.2.2
|
| 11 |
pocket-tts==2.1.0
|
| 12 |
-
# Local coach backend (COACH_BACKEND=local).
|
| 13 |
-
#
|
| 14 |
-
#
|
| 15 |
-
|
| 16 |
-
#
|
| 17 |
-
# For local Mac dev: the regular PyPI wheel auto-uses Metal — you
|
| 18 |
-
# don't need this extra index, but it's harmless.
|
| 19 |
-
# For NVIDIA GPU Spaces: swap "cpu" → "cu121" (or your CUDA version)
|
| 20 |
-
# in the URL below.
|
| 21 |
-
--extra-index-url https://abetlen.github.io/llama-cpp-python/whl/cpu
|
| 22 |
llama-cpp-python==0.3.28
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
phonemizer==3.3.0
|
| 10 |
python-dotenv==1.2.2
|
| 11 |
pocket-tts==2.1.0
|
| 12 |
+
# Local coach backend (COACH_BACKEND=local). CUDA 12.1 wheel for Zero GPU.
|
| 13 |
+
# Local Mac dev uses the regular PyPI wheel (Metal). For CPU-tier Spaces,
|
| 14 |
+
# swap "cu121" back to "cpu".
|
| 15 |
+
--extra-index-url https://abetlen.github.io/llama-cpp-python/whl/cu121
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
llama-cpp-python==0.3.28
|
| 17 |
+
|
| 18 |
+
# Zero GPU runtime
|
| 19 |
+
spaces
|