Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
Commit ·
14ce963
1
Parent(s): 1ba7218
lets try running on different gpu machines
Browse files- EVALUATION_SCALING.md +6 -5
- remote_job_images.example.json +1 -1
- remote_jobs.py +18 -7
- scripts/run_hf_remote_job.py +86 -2
EVALUATION_SCALING.md
CHANGED
|
@@ -48,19 +48,20 @@ When enabled, the queue worker **does not** call `run_evaluation` inside the Spa
|
|
| 48 |
| `FFASR_REMOTE_JOBS` | `1` / `true` to enable Hub Job dispatch. |
|
| 49 |
| `FFASR_REMOTE_EVAL_REPO_URL` | Git URL cloned inside the job (required unless `FFASR_REMOTE_JOB_COMMAND` is set). |
|
| 50 |
| `FFASR_REMOTE_EVAL_GIT_BRANCH` | Branch for clone (default `main`). |
|
| 51 |
-
| `FFASR_REMOTE_JOB_IMAGE` | Default Docker image if no `remote_job_images.json` match (default `
|
| 52 |
-
| `FFASR_REMOTE_JOB_FLAVOR` | Hub Job hardware flavor (default `
|
| 53 |
| `FFASR_REMOTE_JOB_NAMESPACE` | Optional Hub namespace for the job. |
|
| 54 |
| `FFASR_REMOTE_JOB_TIMEOUT` | Job timeout (Hub format). |
|
| 55 |
| `FFASR_REMOTE_JOB_MAX_WAIT_S` | Max seconds to poll for terminal state (default `14400`). |
|
| 56 |
| `FFASR_REMOTE_JOB_POLL_S` | Poll interval seconds (default `10`). |
|
| 57 |
| `FFASR_REMOTE_JOB_COMMAND` | Optional JSON array of strings: full command override for `run_job`. |
|
| 58 |
-
| `FFASR_REMOTE_WORKER_DEVICE` | Passed into the job as `FFASR_DEVICE` (default `
|
| 59 |
| `FFASR_REMOTE_WORKER_DISABLE_ZEROGPU` | Passed as `FFASR_DISABLE_ZEROGPU` (default `1`). |
|
|
|
|
| 60 |
|
| 61 |
**Per-model Docker images**: copy [remote_job_images.example.json](remote_job_images.example.json) to `remote_job_images.json` in the repo root. Longest matching prefix key wins; use `"default"` as fallback.
|
| 62 |
|
| 63 |
-
**Job entrypoint**: [scripts/run_hf_remote_job.py](scripts/run_hf_remote_job.py) runs `run_evaluation`, builds the artifact, and uploads it with `HF_TOKEN` (passed as a Hub Job secret).
|
| 64 |
|
| 65 |
---
|
| 66 |
|
|
@@ -90,6 +91,6 @@ Do not execute **untrusted** `pip install` lines from users on shared infrastruc
|
|
| 90 |
|
| 91 |
## Suggested evolution path
|
| 92 |
|
| 93 |
-
1. **Now**: FIFO queue + CSV lock + ZeroGPU **or** fixed CPU (`FFASR_DEVICE` / `FFASR_DISABLE_ZEROGPU`) **or** Hub Jobs (`FFASR_REMOTE_JOBS=1`).
|
| 94 |
2. **Next**: richer job metadata in CSV (remote ids, artifact paths); optional webhooks when remote workers finish.
|
| 95 |
3. **Later**: split UI and workers entirely (multiple runners, priority tiers).
|
|
|
|
| 48 |
| `FFASR_REMOTE_JOBS` | `1` / `true` to enable Hub Job dispatch. |
|
| 49 |
| `FFASR_REMOTE_EVAL_REPO_URL` | Git URL cloned inside the job (required unless `FFASR_REMOTE_JOB_COMMAND` is set). |
|
| 50 |
| `FFASR_REMOTE_EVAL_GIT_BRANCH` | Branch for clone (default `main`). |
|
| 51 |
+
| `FFASR_REMOTE_JOB_IMAGE` | Default Docker image if no `remote_job_images.json` match (default CUDA PyTorch: `pytorch/pytorch:2.6.0-cuda12.4-cudnn9-devel`). |
|
| 52 |
+
| `FFASR_REMOTE_JOB_FLAVOR` | Hub Job hardware flavor (default `l4x1` — NVIDIA L4, 1× GPU per [Hub Jobs](https://huggingface.co/docs/huggingface_hub/guides/jobs)). |
|
| 53 |
| `FFASR_REMOTE_JOB_NAMESPACE` | Optional Hub namespace for the job. |
|
| 54 |
| `FFASR_REMOTE_JOB_TIMEOUT` | Job timeout (Hub format). |
|
| 55 |
| `FFASR_REMOTE_JOB_MAX_WAIT_S` | Max seconds to poll for terminal state (default `14400`). |
|
| 56 |
| `FFASR_REMOTE_JOB_POLL_S` | Poll interval seconds (default `10`). |
|
| 57 |
| `FFASR_REMOTE_JOB_COMMAND` | Optional JSON array of strings: full command override for `run_job`. |
|
| 58 |
+
| `FFASR_REMOTE_WORKER_DEVICE` | Passed into the job as `FFASR_DEVICE` (default `auto`: CUDA in GPU jobs, else CPU). |
|
| 59 |
| `FFASR_REMOTE_WORKER_DISABLE_ZEROGPU` | Passed as `FFASR_DISABLE_ZEROGPU` (default `1`). |
|
| 60 |
+
| `FFASR_REMOTE_SKIP_OPTIONAL_PIP` | If `1` / `true`, the remote worker skips allowlisted `pip install` for optional stacks (NeMo, Qwen ASR). |
|
| 61 |
|
| 62 |
**Per-model Docker images**: copy [remote_job_images.example.json](remote_job_images.example.json) to `remote_job_images.json` in the repo root. Longest matching prefix key wins; use `"default"` as fallback.
|
| 63 |
|
| 64 |
+
**Job entrypoint**: [scripts/run_hf_remote_job.py](scripts/run_hf_remote_job.py) optionally installs missing **allowlisted** dependencies (e.g. `nemo_toolkit[asr]` for Parakeet-style ids, `qwen-asr` for Qwen ASR ids) when imports fail, then runs `run_evaluation`, builds the artifact, and uploads it with `HF_TOKEN` (passed as a Hub Job secret).
|
| 65 |
|
| 66 |
---
|
| 67 |
|
|
|
|
| 91 |
|
| 92 |
## Suggested evolution path
|
| 93 |
|
| 94 |
+
1. **Now**: FIFO queue + CSV lock + ZeroGPU **or** fixed CPU/CUDA in-process (`FFASR_DEVICE` / `FFASR_DISABLE_ZEROGPU`) **or** Hub Jobs on GPU (`FFASR_REMOTE_JOBS=1`, default flavor `l4x1` + CUDA image).
|
| 95 |
2. **Next**: richer job metadata in CSV (remote ids, artifact paths); optional webhooks when remote workers finish.
|
| 96 |
3. **Later**: split UI and workers entirely (multiple runners, priority tiers).
|
remote_job_images.example.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
{
|
| 2 |
-
"default": "
|
| 3 |
"coherelabs/": "your-registry/cohere-asr-eval:pin",
|
| 4 |
"ibm-granite/": "your-registry/granite-speech-eval:pin"
|
| 5 |
}
|
|
|
|
| 1 |
{
|
| 2 |
+
"default": "pytorch/pytorch:2.6.0-cuda12.4-cudnn9-devel",
|
| 3 |
"coherelabs/": "your-registry/cohere-asr-eval:pin",
|
| 4 |
"ibm-granite/": "your-registry/granite-speech-eval:pin"
|
| 5 |
}
|
remote_jobs.py
CHANGED
|
@@ -7,8 +7,8 @@ Environment (Space / operator):
|
|
| 7 |
|
| 8 |
- ``FFASR_REMOTE_JOBS`` — ``1`` / ``true`` to route queue worker through Hub Jobs.
|
| 9 |
- ``HF_TOKEN`` — token with permission to run jobs and read/write the results bucket.
|
| 10 |
-
- ``FFASR_REMOTE_JOB_IMAGE`` — Docker image for the job (default
|
| 11 |
-
- ``FFASR_REMOTE_JOB_FLAVOR`` — hardware flavor (default ``
|
| 12 |
- ``FFASR_REMOTE_JOB_NAMESPACE`` — optional Hub namespace/user for the job (default: token owner).
|
| 13 |
- ``FFASR_REMOTE_JOB_TIMEOUT`` — job timeout string/int (optional).
|
| 14 |
- ``FFASR_REMOTE_EVAL_REPO_URL`` — git clone URL for this repo inside the job (required unless
|
|
@@ -17,7 +17,7 @@ Environment (Space / operator):
|
|
| 17 |
|
| 18 |
Per-model Docker image: optional JSON file ``remote_job_images.json`` in the repo root::
|
| 19 |
|
| 20 |
-
{"cohere/": "org/cohere-asr-image:tag", "default": "
|
| 21 |
|
| 22 |
Longest key match wins; ``default`` fallback.
|
| 23 |
"""
|
|
@@ -32,6 +32,11 @@ from typing import Any
|
|
| 32 |
from huggingface_hub import HfApi
|
| 33 |
from huggingface_hub._jobs_api import JobInfo, JobStage
|
| 34 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
_IMAGE_MAP_CACHE: dict[str, str] | None = None
|
| 36 |
|
| 37 |
|
|
@@ -85,7 +90,7 @@ def resolve_job_image(model_id: str) -> str:
|
|
| 85 |
if default_map:
|
| 86 |
return default_map
|
| 87 |
env_img = os.environ.get("FFASR_REMOTE_JOB_IMAGE", "").strip()
|
| 88 |
-
return env_img or
|
| 89 |
|
| 90 |
|
| 91 |
def _default_bash_command() -> list[str]:
|
|
@@ -99,7 +104,7 @@ def _default_bash_command() -> list[str]:
|
|
| 99 |
"cd \"$WORKDIR\" && "
|
| 100 |
"python -m pip install --no-cache-dir -U pip && "
|
| 101 |
"python -m pip install --no-cache-dir -r requirements.txt && "
|
| 102 |
-
"export FFASR_DEVICE=${FFASR_DEVICE:-
|
| 103 |
"python scripts/run_hf_remote_job.py"
|
| 104 |
)
|
| 105 |
return ["bash", "-lc", script]
|
|
@@ -130,7 +135,10 @@ def submit_eval_job(
|
|
| 130 |
api = HfApi(token=token)
|
| 131 |
image = resolve_job_image(model_id)
|
| 132 |
namespace = os.environ.get("FFASR_REMOTE_JOB_NAMESPACE", "").strip() or None
|
| 133 |
-
flavor =
|
|
|
|
|
|
|
|
|
|
| 134 |
timeout_raw = os.environ.get("FFASR_REMOTE_JOB_TIMEOUT", "").strip()
|
| 135 |
timeout: int | float | str | None
|
| 136 |
if not timeout_raw:
|
|
@@ -164,7 +172,10 @@ def submit_eval_job(
|
|
| 164 |
"FFASR_SPACE_JOB_ID": space_job_id,
|
| 165 |
"FFASR_REMOTE_ARTIFACT_PATH": artifact_path,
|
| 166 |
"FFASR_BUCKET_ID": bucket,
|
| 167 |
-
"FFASR_DEVICE": os.environ.get(
|
|
|
|
|
|
|
|
|
|
| 168 |
"FFASR_DISABLE_ZEROGPU": os.environ.get("FFASR_REMOTE_WORKER_DISABLE_ZEROGPU", "1"),
|
| 169 |
"FFASR_REMOTE_EVAL_REPO_URL": eval_repo,
|
| 170 |
"FFASR_REMOTE_EVAL_GIT_BRANCH": eval_branch,
|
|
|
|
| 7 |
|
| 8 |
- ``FFASR_REMOTE_JOBS`` — ``1`` / ``true`` to route queue worker through Hub Jobs.
|
| 9 |
- ``HF_TOKEN`` — token with permission to run jobs and read/write the results bucket.
|
| 10 |
+
- ``FFASR_REMOTE_JOB_IMAGE`` — Docker image for the job (default CUDA PyTorch image for GPU eval).
|
| 11 |
+
- ``FFASR_REMOTE_JOB_FLAVOR`` — hardware flavor (default ``l4x1``). See ``HfApi.list_jobs_hardware``.
|
| 12 |
- ``FFASR_REMOTE_JOB_NAMESPACE`` — optional Hub namespace/user for the job (default: token owner).
|
| 13 |
- ``FFASR_REMOTE_JOB_TIMEOUT`` — job timeout string/int (optional).
|
| 14 |
- ``FFASR_REMOTE_EVAL_REPO_URL`` — git clone URL for this repo inside the job (required unless
|
|
|
|
| 17 |
|
| 18 |
Per-model Docker image: optional JSON file ``remote_job_images.json`` in the repo root::
|
| 19 |
|
| 20 |
+
{"cohere/": "org/cohere-asr-image:tag", "default": "pytorch/pytorch:2.6.0-cuda12.4-cudnn9-devel"}
|
| 21 |
|
| 22 |
Longest key match wins; ``default`` fallback.
|
| 23 |
"""
|
|
|
|
| 32 |
from huggingface_hub import HfApi
|
| 33 |
from huggingface_hub._jobs_api import JobInfo, JobStage
|
| 34 |
|
| 35 |
+
# Defaults for L4 GPU Hub Jobs (override with FFASR_REMOTE_JOB_* / remote_job_images.json).
|
| 36 |
+
_DEFAULT_REMOTE_JOB_IMAGE = "pytorch/pytorch:2.6.0-cuda12.4-cudnn9-devel"
|
| 37 |
+
_DEFAULT_REMOTE_JOB_FLAVOR = "l4x1"
|
| 38 |
+
_DEFAULT_REMOTE_WORKER_DEVICE = "auto"
|
| 39 |
+
|
| 40 |
_IMAGE_MAP_CACHE: dict[str, str] | None = None
|
| 41 |
|
| 42 |
|
|
|
|
| 90 |
if default_map:
|
| 91 |
return default_map
|
| 92 |
env_img = os.environ.get("FFASR_REMOTE_JOB_IMAGE", "").strip()
|
| 93 |
+
return env_img or _DEFAULT_REMOTE_JOB_IMAGE
|
| 94 |
|
| 95 |
|
| 96 |
def _default_bash_command() -> list[str]:
|
|
|
|
| 104 |
"cd \"$WORKDIR\" && "
|
| 105 |
"python -m pip install --no-cache-dir -U pip && "
|
| 106 |
"python -m pip install --no-cache-dir -r requirements.txt && "
|
| 107 |
+
"export FFASR_DEVICE=${FFASR_DEVICE:-auto} FFASR_DISABLE_ZEROGPU=${FFASR_DISABLE_ZEROGPU:-1} && "
|
| 108 |
"python scripts/run_hf_remote_job.py"
|
| 109 |
)
|
| 110 |
return ["bash", "-lc", script]
|
|
|
|
| 135 |
api = HfApi(token=token)
|
| 136 |
image = resolve_job_image(model_id)
|
| 137 |
namespace = os.environ.get("FFASR_REMOTE_JOB_NAMESPACE", "").strip() or None
|
| 138 |
+
flavor = (
|
| 139 |
+
os.environ.get("FFASR_REMOTE_JOB_FLAVOR", _DEFAULT_REMOTE_JOB_FLAVOR).strip()
|
| 140 |
+
or _DEFAULT_REMOTE_JOB_FLAVOR
|
| 141 |
+
)
|
| 142 |
timeout_raw = os.environ.get("FFASR_REMOTE_JOB_TIMEOUT", "").strip()
|
| 143 |
timeout: int | float | str | None
|
| 144 |
if not timeout_raw:
|
|
|
|
| 172 |
"FFASR_SPACE_JOB_ID": space_job_id,
|
| 173 |
"FFASR_REMOTE_ARTIFACT_PATH": artifact_path,
|
| 174 |
"FFASR_BUCKET_ID": bucket,
|
| 175 |
+
"FFASR_DEVICE": os.environ.get(
|
| 176 |
+
"FFASR_REMOTE_WORKER_DEVICE", _DEFAULT_REMOTE_WORKER_DEVICE
|
| 177 |
+
).strip()
|
| 178 |
+
or _DEFAULT_REMOTE_WORKER_DEVICE,
|
| 179 |
"FFASR_DISABLE_ZEROGPU": os.environ.get("FFASR_REMOTE_WORKER_DISABLE_ZEROGPU", "1"),
|
| 180 |
"FFASR_REMOTE_EVAL_REPO_URL": eval_repo,
|
| 181 |
"FFASR_REMOTE_EVAL_GIT_BRANCH": eval_branch,
|
scripts/run_hf_remote_job.py
CHANGED
|
@@ -9,24 +9,107 @@ Environment (set by the Space when dispatching ``remote_jobs.submit_eval_job``):
|
|
| 9 |
- ``FFASR_BUCKET_ID``, ``HF_TOKEN`` — bucket write access.
|
| 10 |
- ``FFASR_SPACE_JOB_ID`` — optional correlating id from the Space queue.
|
| 11 |
|
| 12 |
-
Also respects ``FFASR_DEVICE`` / ``FFASR_DISABLE_ZEROGPU`` (
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
|
| 14 |
Repo root must be the current working directory (after git clone in the job).
|
| 15 |
"""
|
| 16 |
|
| 17 |
from __future__ import annotations
|
| 18 |
|
|
|
|
| 19 |
import io
|
| 20 |
import json
|
| 21 |
import os
|
|
|
|
| 22 |
import sys
|
| 23 |
-
import
|
| 24 |
|
| 25 |
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 26 |
if ROOT not in sys.path:
|
| 27 |
sys.path.insert(0, ROOT)
|
| 28 |
|
| 29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
def main() -> int:
|
| 31 |
from evaluation.remote_artifact import ARTIFACT_SCHEMA_VERSION, build_artifact
|
| 32 |
from evaluation.runtime import apply_cpu_thread_settings_once
|
|
@@ -58,6 +141,7 @@ def main() -> int:
|
|
| 58 |
|
| 59 |
try:
|
| 60 |
_log(f"run_hf_remote_job: model_id={model_id!r} family_id={family_id!r}")
|
|
|
|
| 61 |
result = run_evaluation(model_id, family_id=family_id, progress_cb=None)
|
| 62 |
artifact = build_artifact(
|
| 63 |
model_id=model_id,
|
|
|
|
| 9 |
- ``FFASR_BUCKET_ID``, ``HF_TOKEN`` — bucket write access.
|
| 10 |
- ``FFASR_SPACE_JOB_ID`` — optional correlating id from the Space queue.
|
| 11 |
|
| 12 |
+
Also respects ``FFASR_DEVICE`` / ``FFASR_DISABLE_ZEROGPU`` (GPU Hub Jobs: ``auto`` uses CUDA when available).
|
| 13 |
+
|
| 14 |
+
Optional preflight (before ``run_evaluation``):
|
| 15 |
+
|
| 16 |
+
- ``FFASR_REMOTE_SKIP_OPTIONAL_PIP`` — if ``1``/``true``, skip targeted ``pip install`` for NeMo / Qwen ASR.
|
| 17 |
|
| 18 |
Repo root must be the current working directory (after git clone in the job).
|
| 19 |
"""
|
| 20 |
|
| 21 |
from __future__ import annotations
|
| 22 |
|
| 23 |
+
import importlib
|
| 24 |
import io
|
| 25 |
import json
|
| 26 |
import os
|
| 27 |
+
import subprocess
|
| 28 |
import sys
|
| 29 |
+
from collections.abc import Callable
|
| 30 |
|
| 31 |
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 32 |
if ROOT not in sys.path:
|
| 33 |
sys.path.insert(0, ROOT)
|
| 34 |
|
| 35 |
|
| 36 |
+
def _skip_optional_pip() -> bool:
|
| 37 |
+
return os.environ.get("FFASR_REMOTE_SKIP_OPTIONAL_PIP", "").strip().lower() in (
|
| 38 |
+
"1",
|
| 39 |
+
"true",
|
| 40 |
+
"yes",
|
| 41 |
+
"on",
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def _needs_nemo_stack(model_id: str) -> bool:
|
| 46 |
+
m = model_id.lower()
|
| 47 |
+
return "nvidia/parakeet" in m or "parakeet-tdt" in m
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
def _needs_qwen_asr_stack(model_id: str) -> bool:
|
| 51 |
+
m = model_id.lower()
|
| 52 |
+
return m.startswith("qwen/") or "qwen3-asr" in m or "qwen3_asr" in m
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
def _pip_install(packages: list[str], log: Callable[[str], None]) -> None:
|
| 56 |
+
cmd = [sys.executable, "-m", "pip", "install", "--no-cache-dir", *packages]
|
| 57 |
+
log(f"run_hf_remote_job: running {' '.join(cmd)}")
|
| 58 |
+
proc = subprocess.run(cmd, capture_output=True, text=True, timeout=3600)
|
| 59 |
+
if proc.returncode != 0:
|
| 60 |
+
out = (proc.stdout or "") + (proc.stderr or "")
|
| 61 |
+
raise RuntimeError(
|
| 62 |
+
f"pip install failed (exit {proc.returncode}): {out[-4000:]}"
|
| 63 |
+
)
|
| 64 |
+
if proc.stdout:
|
| 65 |
+
log(proc.stdout.strip()[-2000:])
|
| 66 |
+
if proc.stderr and proc.stderr.strip():
|
| 67 |
+
log(proc.stderr.strip()[-2000:])
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def _try_import(module: str) -> bool:
|
| 71 |
+
try:
|
| 72 |
+
importlib.import_module(module)
|
| 73 |
+
return True
|
| 74 |
+
except Exception:
|
| 75 |
+
return False
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
def maybe_install_optional_eval_deps(
|
| 79 |
+
model_id: str, family_id: str, log: Callable[[str], None]
|
| 80 |
+
) -> None:
|
| 81 |
+
"""
|
| 82 |
+
Install known optional stacks only when the model/family likely needs them
|
| 83 |
+
and imports fail. Allowlisted packages only.
|
| 84 |
+
"""
|
| 85 |
+
if _skip_optional_pip():
|
| 86 |
+
log("run_hf_remote_job: FFASR_REMOTE_SKIP_OPTIONAL_PIP set — skipping optional pip installs")
|
| 87 |
+
return
|
| 88 |
+
|
| 89 |
+
fid = (family_id or "auto").strip().lower()
|
| 90 |
+
|
| 91 |
+
want_nemo = _needs_nemo_stack(model_id) or fid == "nemo_asr"
|
| 92 |
+
want_qwen = _needs_qwen_asr_stack(model_id) or fid in ("qwen_asr", "qwen3_asr")
|
| 93 |
+
|
| 94 |
+
if want_nemo:
|
| 95 |
+
if _try_import("nemo.collections.asr"):
|
| 96 |
+
log("run_hf_remote_job: NeMo ASR import OK")
|
| 97 |
+
else:
|
| 98 |
+
log("run_hf_remote_job: NeMo not importable — installing nemo_toolkit[asr]")
|
| 99 |
+
_pip_install(["nemo_toolkit[asr]"], log)
|
| 100 |
+
if not _try_import("nemo.collections.asr"):
|
| 101 |
+
raise RuntimeError("NeMo install finished but nemo.collections.asr still not importable")
|
| 102 |
+
|
| 103 |
+
if want_qwen:
|
| 104 |
+
if _try_import("qwen_asr"):
|
| 105 |
+
log("run_hf_remote_job: qwen_asr import OK")
|
| 106 |
+
else:
|
| 107 |
+
log("run_hf_remote_job: qwen_asr not importable — installing qwen-asr")
|
| 108 |
+
_pip_install(["qwen-asr"], log)
|
| 109 |
+
if not _try_import("qwen_asr"):
|
| 110 |
+
raise RuntimeError("qwen-asr install finished but qwen_asr still not importable")
|
| 111 |
+
|
| 112 |
+
|
| 113 |
def main() -> int:
|
| 114 |
from evaluation.remote_artifact import ARTIFACT_SCHEMA_VERSION, build_artifact
|
| 115 |
from evaluation.runtime import apply_cpu_thread_settings_once
|
|
|
|
| 141 |
|
| 142 |
try:
|
| 143 |
_log(f"run_hf_remote_job: model_id={model_id!r} family_id={family_id!r}")
|
| 144 |
+
maybe_install_optional_eval_deps(model_id, family_id, _log)
|
| 145 |
result = run_evaluation(model_id, family_id=family_id, progress_cb=None)
|
| 146 |
artifact = build_artifact(
|
| 147 |
model_id=model_id,
|