Download scripts/smoke_native.py from adampippert/granite-decisions: direct link, hf CLI and curl.
- Browser
- Download file 6.16 kB
-
https://huggingface.co/adampippert/granite-decisions/resolve/main/scripts/smoke_native.py
- Command line
-
hf download hf://adampippert/granite-decisions/scripts/smoke_native.py
-
curl -L -o smoke_native.py https://huggingface.co/adampippert/granite-decisions/resolve/main/scripts/smoke_native.py
6.16 kB
| """Launch real llama.cpp subprocesses and check Granite interfaces on one host. | |
| This is an integration smoke test, not a decision-quality benchmark. | |
| Defaults to ROCm offload for Hyde; --gpu-layers 0 is an explicit CPU reference. | |
| """ | |
| import argparse | |
| import json | |
| import os | |
| import re | |
| import subprocess | |
| import time | |
| from pathlib import Path | |
| import numpy as np | |
| from granite_decisions import DecisionEngine | |
| from granite_decisions.contracts import dumps | |
| from granite_decisions.llamacpp import BackendError, BaselineBackend, LlamaRuntime, NativeClient, bind_runtime, gpu_offload_evidence | |
| from granite_decisions.training import fit_head | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("--server", required=True) | |
| parser.add_argument("--gguf", required=True) | |
| parser.add_argument("--gpu-layers", type=int, default=99) | |
| parser.add_argument("--out", required=True) | |
| parser.add_argument("--log-dir", help="New directory for retained server logs (default: OUT.logs)") | |
| args = parser.parse_args() | |
| if Path(args.out).exists(): | |
| raise SystemExit("Output already exists; choose a new report path.") | |
| log_directory = Path(args.log_dir or (args.out + ".logs")) | |
| log_directory.mkdir(parents=True, exist_ok=False) | |
| server, model = str(Path(args.server).resolve()), str(Path(args.gguf).resolve()) | |
| report = {"test": "real_granite_native_interface_smoke", "gpu_layers_requested": args.gpu_layers, "quality_benchmark": False} | |
| devices = subprocess.run([server, "--list-devices"], check=True, capture_output=True, text=True) | |
| report["devices"] = devices.stdout + devices.stderr | |
| if args.gpu_layers > 0 and not re.search(r"(?:ROCm|HIP)\d", report["devices"]): | |
| raise SystemExit("No ROCm device reported; refusing to call this a GPU test.") | |
| try: | |
| for mode, port in (("baseline", 19092), ("embedding", 19091)): | |
| log_path = log_directory / (mode + ".log") | |
| command = [server, "--model", model, "--host", "127.0.0.1", "--port", str(port), | |
| "--ctx-size", "4096", "--batch-size", "4096", "--ubatch-size", "4096", | |
| "--verbosity", "4", "--cors-origins", "localhost", | |
| "--parallel", "1", "--n-gpu-layers", str(args.gpu_layers), | |
| "--threads", "4", "--threads-batch", "4", "--no-context-shift", "--no-webui"] | |
| if mode == "embedding": | |
| command += ["--embedding", "--pooling", "last"] | |
| with log_path.open("w") as log: | |
| proc = subprocess.Popen(command, stdout=log, stderr=subprocess.STDOUT) | |
| try: | |
| client = NativeClient(f"http://127.0.0.1:{port}", timeout=120, api_key=os.environ.get("LLAMA_API_KEY")) | |
| deadline = time.monotonic() + 90 | |
| while True: | |
| if proc.poll() is not None: | |
| raise RuntimeError("llama-server exited: " + log_path.read_text()[-3000:]) | |
| try: | |
| if client.request("/health").get("status") == "ok": | |
| break | |
| except BackendError: | |
| pass | |
| if time.monotonic() > deadline: | |
| raise RuntimeError("server did not become ready") | |
| time.sleep(.25) | |
| evidence = gpu_offload_evidence(log_path.read_text()) if args.gpu_layers > 0 else {"basis": "explicit_cpu_reference"} | |
| manifest = bind_runtime(client, model, mode=mode) | |
| runtime = LlamaRuntime(client, manifest) | |
| if mode == "baseline": | |
| qs = { | |
| "route": {"type": "choice", "instructions": "What does the request ask to do?", "criteria": { | |
| "code": "Write or fix code.", "retrieve": "Find documentation.", "unknown": "Cannot determine the request."}}, | |
| "python_mentioned": {"type": "noul", "instructions": "Does the request explicitly mention Python?"}, | |
| "complexity": {"type": "score", "instructions": "How complex is the request?", "criteria": ["Simple task", "Several dependent steps", "Open-ended research"]}, | |
| } | |
| response = DecisionEngine(BaselineBackend(runtime)).evaluate({"request": "Write a Python function that adds two integers."}, qs) | |
| assert response["status"] == "abstained", "Uncalibrated scores must abstain by default" | |
| report[mode] = response | |
| else: | |
| data = [{"request": text} for text in ( | |
| "Write a Python function to add two integers.", | |
| "Fix the Python function with a syntax error.", | |
| "Find documentation for Python list methods.", | |
| "Find the official API reference for Python dictionaries.")] | |
| start = time.perf_counter() | |
| x = runtime.encode(data) | |
| assert x.shape == (4, 2560), x.shape | |
| assert np.isfinite(x).all() | |
| np.testing.assert_allclose(np.linalg.norm(x, axis=1), 1, atol=1e-3) | |
| w, b = fit_head(x, [0, 0, 1, 1], 2) | |
| z = x @ w + b | |
| assert np.isfinite(z).all() and z.shape == (4, 2) | |
| report[mode] = {"runtime": manifest, "feature_shape": list(x.shape), | |
| "l2_norms": np.linalg.norm(x, axis=1).tolist(), | |
| "training_smoke_logits": z.tolist(), "calibration": "not_fitted", | |
| "elapsed_ms_including_four_encodings_and_head_fit": (time.perf_counter() - start)*1000} | |
| report[mode]["offload_evidence"] = evidence | |
| print(mode + " interface passed", flush=True) | |
| finally: | |
| proc.terminate() | |
| try: | |
| proc.wait(timeout=10) | |
| except subprocess.TimeoutExpired: | |
| proc.kill() | |
| proc.wait() | |
| except BaseException as exc: | |
| report["status"] = "failed" | |
| report["error"] = str(exc) | |
| report["server_logs"] = str(log_directory) | |
| Path(args.out).write_text(dumps(report) + "\n") | |
| raise | |
| report["status"] = "passed" | |
| report["server_logs"] = str(log_directory) | |
| Path(args.out).write_text(dumps(report) + "\n") | |
| print(json.dumps({"status": "passed", "report": args.out})) | |