workers: let every isolated-venv worker point at a remote service

Each `ensure_service()` already returns a base URL, so a worker can be
pointed at a service running elsewhere — another host, a container, a
rented RunPod pod — without anything downstream noticing. Only the TTS
backends had that escape hatch (parler/melo, checked at the caller);
now the check lives in the workers themselves, per-model via
`service_url` in the config plus a CODERAI_*_SERVICE_URL env var:

  vllm, ds4, kt, h3, pyannote, melotts, canary, crisperwhisper, parler

Each verifies the remote's health check before returning it, so a stale
or wrong URL fails loudly instead of surfacing as a confusing timeout
later. vLLM additionally checks that the remote actually serves the
requested model — the OCR path asks for surya-2 by name, and a generic
remote vLLM would otherwise be proxied silently.

colibri/k3 are left out: they speak a stdin/stdout mux protocol, not
HTTP, so there is no URL to redirect.
Co-Authored-By: 's avatarClaude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0182DhR1eFNPQyGmDrpHbedY
parent b456c041
...@@ -124,6 +124,19 @@ def ensure_service(model_name: str, config: dict = None, ...@@ -124,6 +124,19 @@ def ensure_service(model_name: str, config: dict = None,
First call may build the venv and download the model, so the timeout is First call may build the venv and download the model, so the timeout is
generous. Raises RuntimeError if the service never comes up.""" generous. Raises RuntimeError if the service never comes up."""
config = config or {} config = config or {}
# An explicit `service_url` points at a NeMo worker running somewhere else — another
# host, a container, a rented pod — so nothing is built, spawned or downloaded
# here and coderai just proxies to it. This function already returns a URL, so
# its callers cannot tell the difference.
_remote = ((config.get("service_url") or "") or os.environ.get("CODERAI_CANARY_SERVICE_URL") or "").strip()
if _remote:
_remote = str(_remote).rstrip("/")
if not _health_ok(_remote):
raise RuntimeError(
f"configured service_url {_remote} is not answering its health check")
print(f"[canary] using the configured remote service at {_remote}", flush=True)
return _remote
with _lock: with _lock:
svc = _services.get(model_name) svc = _services.get(model_name)
if svc and svc["proc"].poll() is None and _health_ok(svc["url"]): if svc and svc["proc"].poll() is None and _health_ok(svc["url"]):
......
...@@ -111,6 +111,19 @@ def _health_ok(url: str) -> bool: ...@@ -111,6 +111,19 @@ def _health_ok(url: str) -> bool:
def ensure_service(model_name: str, config: dict = None, def ensure_service(model_name: str, config: dict = None,
ready_timeout: float = 1800.0) -> str: ready_timeout: float = 1800.0) -> str:
config = config or {} config = config or {}
# An explicit `service_url` points at a CrisperWhisper worker running somewhere else — another
# host, a container, a rented pod — so nothing is built, spawned or downloaded
# here and coderai just proxies to it. This function already returns a URL, so
# its callers cannot tell the difference.
_remote = ((config.get("service_url") or "") or os.environ.get("CODERAI_CRISPERWHISPER_SERVICE_URL") or "").strip()
if _remote:
_remote = str(_remote).rstrip("/")
if not _health_ok(_remote):
raise RuntimeError(
f"configured service_url {_remote} is not answering its health check")
print(f"[crisperwhisper] using the configured remote service at {_remote}", flush=True)
return _remote
with _lock: with _lock:
svc = _services.get(model_name) svc = _services.get(model_name)
if svc and svc["proc"].poll() is None and _health_ok(svc["url"]): if svc and svc["proc"].poll() is None and _health_ok(svc["url"]):
......
...@@ -352,6 +352,19 @@ def ensure_service(cfg, model_file: Optional[str] = None, ...@@ -352,6 +352,19 @@ def ensure_service(cfg, model_file: Optional[str] = None,
downloading ``cfg.model_variant``. ``ctx`` overrides the ds4 global context downloading ``cfg.model_variant``. ``ctx`` overrides the ds4 global context
(so the per-model n_ctx configuration wins). Returns the base URL. (so the per-model n_ctx configuration wins). Returns the base URL.
""" """
# An explicit `service_url` points at a ds4-server running somewhere else — another
# host, a container, a rented pod — so nothing is built, spawned or downloaded
# here and coderai just proxies to it. This function already returns a URL, so
# its callers cannot tell the difference.
_remote = (str(getattr(cfg, "service_url", "") or "") or os.environ.get("CODERAI_DS4_SERVICE_URL") or "").strip()
if _remote:
_remote = str(_remote).rstrip("/")
if not _health_ok(_remote):
raise RuntimeError(
f"configured service_url {_remote} is not answering its health check")
print(f"[ds4] using the configured remote service at {_remote}", flush=True)
return _remote
resolved, svc_key = resolve_service_key(cfg, model_file) resolved, svc_key = resolve_service_key(cfg, model_file)
with _lock: with _lock:
svc = _services.get(svc_key) svc = _services.get(svc_key)
......
...@@ -272,6 +272,21 @@ def ensure_service(model_path: str, config: dict = None, ...@@ -272,6 +272,21 @@ def ensure_service(model_path: str, config: dict = None,
ready_timeout: float = 1800.0) -> str: ready_timeout: float = 1800.0) -> str:
"""Start (or reuse) the H3 service for one checkpoint; return its base URL.""" """Start (or reuse) the H3 service for one checkpoint; return its base URL."""
config = config or {} config = config or {}
# An explicit `service_url` points at a service running somewhere else —
# another host, a container, a rented RunPod pod — so nothing is spawned or
# downloaded here and coderai just proxies to it. Same contract the TTS
# backends have used for parler/melo, and the hook that makes a per-engine
# remote pod possible without changing anything downstream: this function
# already returns a URL, so its callers cannot tell the difference.
_remote = (config.get("service_url") or os.environ.get("CODERAI_H3_SERVICE_URL") or "").strip()
if _remote:
_remote = str(_remote).rstrip("/")
if not _health_ok(_remote):
raise RuntimeError(
f"configured service_url {_remote} is not answering its health check")
print(f"[h3] using the configured remote service at {_remote}", flush=True)
return _remote
with _lock: with _lock:
svc = _services.get(model_path) svc = _services.get(model_path)
if svc and svc["proc"].poll() is None and _health_ok(svc["url"]): if svc and svc["proc"].poll() is None and _health_ok(svc["url"]):
......
...@@ -124,6 +124,19 @@ def _launch_cmd(cfg, host: str, port: int, model_path: str) -> list: ...@@ -124,6 +124,19 @@ def _launch_cmd(cfg, host: str, port: int, model_path: str) -> list:
def ensure_service(cfg, model_path: Optional[str] = None, def ensure_service(cfg, model_path: Optional[str] = None,
ready_timeout: float = 3600.0) -> str: ready_timeout: float = 3600.0) -> str:
"""Launch (or reuse) the SGLang server for a ktransformers model; return its base URL.""" """Launch (or reuse) the SGLang server for a ktransformers model; return its base URL."""
# An explicit `service_url` points at a SGLang server running somewhere else — another
# host, a container, a rented pod — so nothing is built, spawned or downloaded
# here and coderai just proxies to it. This function already returns a URL, so
# its callers cannot tell the difference.
_remote = (str(getattr(cfg, "service_url", "") or "") or os.environ.get("CODERAI_KT_SERVICE_URL") or "").strip()
if _remote:
_remote = str(_remote).rstrip("/")
if not _health_ok(_remote):
raise RuntimeError(
f"configured service_url {_remote} is not answering its health check")
print(f"[kt] using the configured remote service at {_remote}", flush=True)
return _remote
resolved, svc_key = resolve_service_key(cfg, model_path) resolved, svc_key = resolve_service_key(cfg, model_path)
with _lock: with _lock:
svc = _services.get(svc_key) svc = _services.get(svc_key)
......
...@@ -123,11 +123,28 @@ def _health_ok(url: str) -> bool: ...@@ -123,11 +123,28 @@ def _health_ok(url: str) -> bool:
return False return False
def ensure_service(model_name: str, ready_timeout: float = 1800.0) -> str: def ensure_service(model_name: str, ready_timeout: float = 1800.0,
config: dict = None) -> str:
"""Start (or reuse) the worker for ``model_name`` and return its base URL. """Start (or reuse) the worker for ``model_name`` and return its base URL.
First call bootstraps the venv and downloads the model, so the timeout is First call bootstraps the venv and downloads the model, so the timeout is
generous. Raises RuntimeError if the service never comes up.""" generous. Raises RuntimeError if the service never comes up."""
# An explicit `service_url` points at a service running somewhere else —
# another host, a container, a rented RunPod pod — so nothing is spawned or
# downloaded here and coderai just proxies to it. Same contract the TTS
# backends have used for parler/melo, and the hook that makes a per-engine
# remote pod possible without changing anything downstream: this function
# already returns a URL, so its callers cannot tell the difference.
_remote = ((config or {}).get("service_url")
or os.environ.get("CODERAI_MELOTTS_SERVICE_URL") or "").strip()
if _remote:
_remote = _remote.rstrip("/")
if not _health_ok(_remote):
raise RuntimeError(
f"configured service_url {_remote} is not answering its health check")
print(f"[melotts] using the configured remote service at {_remote}", flush=True)
return _remote
with _lock: with _lock:
svc = _services.get(model_name) svc = _services.get(model_name)
if svc and svc["proc"].poll() is None and _health_ok(svc["url"]): if svc and svc["proc"].poll() is None and _health_ok(svc["url"]):
......
...@@ -124,6 +124,19 @@ def ensure_service(model_name: str, ready_timeout: float = 1800.0) -> str: ...@@ -124,6 +124,19 @@ def ensure_service(model_name: str, ready_timeout: float = 1800.0) -> str:
First call bootstraps the venv and downloads the model, so the timeout is First call bootstraps the venv and downloads the model, so the timeout is
generous. Raises RuntimeError if the service never comes up.""" generous. Raises RuntimeError if the service never comes up."""
# An explicit service URL points at a parler worker running somewhere else —
# another host, a container, a rented pod — so nothing is built, spawned or
# downloaded here. The per-model `service_url` is handled one level up in
# tts_backends; this env var covers direct callers too.
_remote = (os.environ.get("CODERAI_PARLER_SERVICE_URL") or "").strip()
if _remote:
_remote = _remote.rstrip("/")
if not _health_ok(_remote):
raise RuntimeError(
f"configured service_url {_remote} is not answering its health check")
print(f"[parler] using the configured remote service at {_remote}", flush=True)
return _remote
with _lock: with _lock:
svc = _services.get(model_name) svc = _services.get(model_name)
if svc and svc["proc"].poll() is None and _health_ok(svc["url"]): if svc and svc["proc"].poll() is None and _health_ok(svc["url"]):
......
...@@ -151,6 +151,21 @@ def ensure_service(model_name: str = None, config: dict = None, ...@@ -151,6 +151,21 @@ def ensure_service(model_name: str = None, config: dict = None,
ready_timeout: float = 1800.0) -> str: ready_timeout: float = 1800.0) -> str:
"""Start (or reuse) the pyannote worker and return its base URL.""" """Start (or reuse) the pyannote worker and return its base URL."""
config = config or {} config = config or {}
# An explicit `service_url` points at a service running somewhere else —
# another host, a container, a rented RunPod pod — so nothing is spawned or
# downloaded here and coderai just proxies to it. Same contract the TTS
# backends have used for parler/melo, and the hook that makes a per-engine
# remote pod possible without changing anything downstream: this function
# already returns a URL, so its callers cannot tell the difference.
_remote = (config.get("service_url") or os.environ.get("CODERAI_PYANNOTE_SERVICE_URL") or "").strip()
if _remote:
_remote = str(_remote).rstrip("/")
if not _health_ok(_remote):
raise RuntimeError(
f"configured service_url {_remote} is not answering its health check")
print(f"[pyannote] using the configured remote service at {_remote}", flush=True)
return _remote
model_name = model_name or config.get("model_path") or _default_model() model_name = model_name or config.get("model_path") or _default_model()
with _lock: with _lock:
svc = _services.get(model_name) svc = _services.get(model_name)
......
...@@ -144,6 +144,18 @@ def _launch_cmd(py, cfg, host: str, port: int, model_path: str, ...@@ -144,6 +144,18 @@ def _launch_cmd(py, cfg, host: str, port: int, model_path: str,
return cmd return cmd
def _remote_serves(url: str, name: str) -> bool:
"""True when a remote vLLM's /v1/models lists ``name`` (or a suffix match)."""
import requests
try:
r = requests.get(url + "/v1/models", timeout=5)
ids = [str(m.get("id", "")) for m in (r.json().get("data") or [])]
except Exception:
return False
tail = name.rstrip("/").split("/")[-1]
return any(i == name or i.rstrip("/").split("/")[-1] == tail for i in ids)
def ensure_service(cfg, model_path: Optional[str] = None, def ensure_service(cfg, model_path: Optional[str] = None,
served_name: Optional[str] = None, served_name: Optional[str] = None,
ready_timeout: float = 3600.0) -> str: ready_timeout: float = 3600.0) -> str:
...@@ -151,6 +163,27 @@ def ensure_service(cfg, model_path: Optional[str] = None, ...@@ -151,6 +163,27 @@ def ensure_service(cfg, model_path: Optional[str] = None,
``model_path``/``served_name`` override the config (used by the OCR subsystem to serve ``model_path``/``served_name`` override the config (used by the OCR subsystem to serve
surya-2 on its own vLLM instance alongside any LLM instance).""" surya-2 on its own vLLM instance alongside any LLM instance)."""
# An explicit `service_url` points at a vLLM running somewhere else — another
# host, a container, a rented RunPod pod (where vLLM's own image is the ready-
# made option) — so nothing is spawned or downloaded here. This function
# already returns a URL, so its callers cannot tell the difference.
_remote = (str(getattr(cfg, "service_url", "") or "")
or os.environ.get("CODERAI_VLLM_SERVICE_URL") or "").strip()
if _remote:
_remote = _remote.rstrip("/")
if not _health_ok(_remote):
raise RuntimeError(
f"configured service_url {_remote} is not answering its health check")
# A remote vLLM serves whatever it was started with. When the caller asks
# for a specific model (the OCR path does, for surya-2), make sure that
# model is actually there rather than silently proxying to the wrong one.
_want = (served_name or model_path or "").strip()
if _want and not _remote_serves(_remote, _want):
raise RuntimeError(
f"configured service_url {_remote} does not serve {_want}")
print(f"[vllm] using the configured remote service at {_remote}", flush=True)
return _remote
resolved, svc_key = resolve_service_key(cfg, model_path) resolved, svc_key = resolve_service_key(cfg, model_path)
if served_name: if served_name:
svc_key = f"{svc_key}|{served_name}" svc_key = f"{svc_key}|{served_name}"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment