Update configuration and documentation for LLM support and local watchdog
- Added `ollama-models.yaml` to .gitignore and implemented logic to copy it in gpu-rent.ps1 and gpu-rent.sh. - Enhanced env.example to include new variables for LLM runtime options and local watchdog configuration. - Updated CLI commands to support LLM options during setup and execution, including new flags for Ollama and llama.cpp. - Improved documentation in cli.md and README.md to reflect changes in LLM integration and local watchdog functionality. - Adjusted architecture and decisions documentation to clarify the role of LLMs and local watchdog in the system.
This commit is contained in:
@@ -88,6 +88,46 @@ def swarm_busy(swarm_url: str, timeout: float = 8.0) -> tuple[bool, str]:
|
||||
return False, f"idle backend={bstat}"
|
||||
|
||||
|
||||
def llm_busy(timeout: float = 3.0) -> tuple[bool, str]:
|
||||
"""Ollama pull / loaded models or llama.cpp with a model count as busy."""
|
||||
if (DATA / ".gpu-rent-ollama-pulling").is_file():
|
||||
return True, "ollama pulling"
|
||||
ctx = ssl.create_default_context()
|
||||
# Ollama: any running model
|
||||
try:
|
||||
req = urllib.request.Request("http://127.0.0.1:11434/api/ps", method="GET")
|
||||
with urllib.request.urlopen(req, timeout=timeout, context=ctx) as resp:
|
||||
data = json.loads(resp.read().decode("utf-8"))
|
||||
models = data.get("models") or []
|
||||
if models:
|
||||
names = ",".join(str(m.get("name") or "?") for m in models[:3])
|
||||
return True, f"ollama running {names}"
|
||||
except (urllib.error.URLError, urllib.error.HTTPError, TimeoutError, json.JSONDecodeError, OSError):
|
||||
pass
|
||||
# llama.cpp OpenAI models endpoint — if server up and lists a model, treat lightly:
|
||||
# only busy if /health ok AND we recently had activity is hard; use loaded via props.
|
||||
try:
|
||||
req = urllib.request.Request("http://127.0.0.1:8080/health", method="GET")
|
||||
with urllib.request.urlopen(req, timeout=timeout, context=ctx) as resp:
|
||||
if getattr(resp, "status", 200) == 200:
|
||||
# Server alive with a model is OK for idle unless slots busy — skip kill only
|
||||
# when props show n_slots_in_use if available.
|
||||
try:
|
||||
req2 = urllib.request.Request("http://127.0.0.1:8080/props", method="GET")
|
||||
with urllib.request.urlopen(req2, timeout=timeout, context=ctx) as resp2:
|
||||
props = json.loads(resp2.read().decode("utf-8"))
|
||||
in_use = int(props.get("total_slots") or 0) - int(
|
||||
props.get("available_slots") or props.get("total_slots") or 0
|
||||
)
|
||||
if in_use > 0:
|
||||
return True, f"llamacpp slots_in_use={in_use}"
|
||||
except Exception:
|
||||
pass
|
||||
except (urllib.error.URLError, urllib.error.HTTPError, TimeoutError, OSError):
|
||||
pass
|
||||
return False, "llm idle"
|
||||
|
||||
|
||||
def keystone_token(creds: dict) -> tuple[str, str]:
|
||||
"""Return (token, compute_url)."""
|
||||
auth = {
|
||||
@@ -189,6 +229,12 @@ def main() -> int:
|
||||
log(f"busy: {detail}")
|
||||
return 0
|
||||
|
||||
llm_is_busy, llm_detail = llm_busy()
|
||||
if llm_is_busy:
|
||||
write_ts(IDLE_SINCE, None)
|
||||
log(f"busy: {llm_detail}")
|
||||
return 0
|
||||
|
||||
idle_minutes = float(creds.get("idle_minutes") or 30)
|
||||
since = read_ts(IDLE_SINCE)
|
||||
if since is None:
|
||||
|
||||
Reference in New Issue
Block a user