Initial SQL-only 1C adapter baseline
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import datetime as dt
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
|
||||
from check_inference_endpoint import check_endpoint
|
||||
from common import read_json
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
DEFAULT_REPORT = ROOT / "reports" / "gpu-readiness.json"
|
||||
GPU_PROFILES = ROOT / "config" / "gpu_profiles.json"
|
||||
PROFILE_MODEL_EXPECTATIONS = {
|
||||
"vLLM": "qwen3-4b-instruct",
|
||||
"llama.cpp": "devstral-1c-q4",
|
||||
}
|
||||
|
||||
|
||||
def run_command(command: list[str], timeout: int) -> dict:
|
||||
try:
|
||||
result = subprocess.run(
|
||||
command,
|
||||
cwd=ROOT,
|
||||
text=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
timeout=timeout,
|
||||
check=False,
|
||||
)
|
||||
except subprocess.TimeoutExpired as exc:
|
||||
return {
|
||||
"command": command,
|
||||
"status": "failed",
|
||||
"returncode": None,
|
||||
"stdout": exc.stdout or "",
|
||||
"stderr": f"Timed out after {timeout}s",
|
||||
}
|
||||
return {
|
||||
"command": command,
|
||||
"status": "ok" if result.returncode == 0 else "failed",
|
||||
"returncode": result.returncode,
|
||||
"stdout": result.stdout.strip(),
|
||||
"stderr": result.stderr.strip(),
|
||||
}
|
||||
|
||||
|
||||
def check_http_url(url: str, timeout: int, *, expected_model: str | None = None) -> dict:
|
||||
if url.rstrip("/").endswith("/v1/models"):
|
||||
base_url = url.rstrip("/")[: -len("/v1/models")]
|
||||
return check_endpoint(base_url, expected_model, timeout)
|
||||
|
||||
started_at = time.perf_counter()
|
||||
result = {
|
||||
"url": url,
|
||||
"status": "failed",
|
||||
"latency_ms": None,
|
||||
"http_status": None,
|
||||
"error": None,
|
||||
}
|
||||
try:
|
||||
request = urllib.request.Request(url, method="GET")
|
||||
with urllib.request.urlopen(request, timeout=timeout) as response:
|
||||
result["http_status"] = response.status
|
||||
except (TimeoutError, OSError, urllib.error.URLError) as exc:
|
||||
result["error"] = str(exc)
|
||||
return result
|
||||
|
||||
result["latency_ms"] = round((time.perf_counter() - started_at) * 1000)
|
||||
result["status"] = "ok" if 200 <= int(result["http_status"] or 0) < 500 else "failed"
|
||||
return result
|
||||
|
||||
|
||||
def profile_checks(profile_id: str, timeout: int) -> dict[str, dict]:
|
||||
profiles = read_json(GPU_PROFILES)
|
||||
profile = profiles.get(profile_id)
|
||||
if not isinstance(profile, dict):
|
||||
available = ", ".join(sorted(str(name) for name in profiles))
|
||||
raise ValueError(f"Unknown GPU profile `{profile_id}`. Available: {available}")
|
||||
|
||||
checks: dict[str, dict] = {}
|
||||
for index, item in enumerate(profile.get("wait") or [], start=1):
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
name = str(item.get("name") or f"wait_{index}")
|
||||
url = str(item.get("url") or "")
|
||||
if not url:
|
||||
continue
|
||||
key = f"profile_{profile_id}_{index}_{name.lower().replace('.', '').replace(' ', '_')}"
|
||||
checks[key] = check_http_url(url, timeout, expected_model=PROFILE_MODEL_EXPECTATIONS.get(name))
|
||||
return checks
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description="Check GPU host and inference endpoint readiness.")
|
||||
parser.add_argument("--profile", default="text", help="GPU profile from config/gpu_profiles.json to check.")
|
||||
parser.add_argument("--all-endpoints", action="store_true", help="Legacy mode: require vLLM and llama.cpp endpoints at the same time.")
|
||||
parser.add_argument("--vllm-url", default="http://docker-gpu.cin.su:8000")
|
||||
parser.add_argument("--vllm-model", default="qwen3-4b-instruct")
|
||||
parser.add_argument("--llama-url", default="http://docker-gpu.cin.su:8080")
|
||||
parser.add_argument("--llama-model", default="devstral-1c-q4")
|
||||
parser.add_argument("--ssh-target", default="docker-gpu.cin.su")
|
||||
parser.add_argument("--timeout", type=int, default=10)
|
||||
parser.add_argument("--report", type=Path, default=DEFAULT_REPORT)
|
||||
parser.add_argument("--print", action="store_true")
|
||||
args = parser.parse_args()
|
||||
|
||||
checks: dict[str, dict] = {
|
||||
"ssh_preflight": run_command(
|
||||
[
|
||||
"powershell",
|
||||
"-NoProfile",
|
||||
"-ExecutionPolicy",
|
||||
"Bypass",
|
||||
"-File",
|
||||
"scripts/check_gpu_host.ps1",
|
||||
"-SshTarget",
|
||||
args.ssh_target,
|
||||
"-ConnectTimeoutSeconds",
|
||||
str(args.timeout),
|
||||
],
|
||||
timeout=max(args.timeout * 6, 30),
|
||||
)
|
||||
}
|
||||
if args.all_endpoints:
|
||||
checks["vllm_endpoint"] = check_endpoint(args.vllm_url, args.vllm_model, args.timeout)
|
||||
checks["llama_endpoint"] = check_endpoint(args.llama_url, args.llama_model, args.timeout)
|
||||
else:
|
||||
checks.update(profile_checks(args.profile, args.timeout))
|
||||
|
||||
failed = [name for name, check in checks.items() if check.get("status") != "ok"]
|
||||
report = {
|
||||
"created_at": dt.datetime.now(dt.UTC).isoformat(),
|
||||
"profile": args.profile,
|
||||
"all_endpoints": args.all_endpoints,
|
||||
"status": "failed" if failed else "ok",
|
||||
"failed_checks": failed,
|
||||
"checks": checks,
|
||||
}
|
||||
|
||||
args.report.parent.mkdir(parents=True, exist_ok=True)
|
||||
args.report.write_text(json.dumps(report, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
|
||||
if args.print:
|
||||
print(json.dumps(report, ensure_ascii=False, indent=2))
|
||||
else:
|
||||
print(f"GPU readiness status: {report['status']}")
|
||||
print(f"Wrote report to {args.report}")
|
||||
return 0 if not failed else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user