107 lines
5.7 KiB
Python
107 lines
5.7 KiB
Python
"""Exercise a real Linux distribution worker on CPU, outside its build directory.
|
|
|
|
This checks genuine Google inference and origin-relative runtime packaging.
|
|
It does not certify GPU operation, older processors or a Linux desktop.
|
|
"""
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
import math
|
|
import os
|
|
from pathlib import Path
|
|
import shutil
|
|
import subprocess
|
|
import tempfile
|
|
import time
|
|
|
|
|
|
def sha256(path):
|
|
with path.open("rb") as stream:
|
|
return hashlib.file_digest(stream, "sha256").hexdigest()
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--worker", type=Path, required=True)
|
|
parser.add_argument("--models", type=Path, required=True)
|
|
parser.add_argument("--output", type=Path, required=True)
|
|
parser.add_argument("--baseline", action="store_true")
|
|
args = parser.parse_args()
|
|
if os.name != "posix" or not Path("/proc/self/exe").exists():
|
|
parser.error("Run this check natively on Linux")
|
|
# Reuse exactly the staging verifier: hashes and bounded inventory names
|
|
# must agree with what enters a distribution.
|
|
from stage_runtime import verify_runtime
|
|
dependencies = verify_runtime(args.worker.resolve(), True)
|
|
manifest = json.loads(Path(__file__).with_name("model-manifest.json").read_text())
|
|
model = args.models.resolve() / manifest["files"][0]["path"]
|
|
if model.stat().st_size != manifest["files"][0]["bytes"] or sha256(model) != manifest["files"][0]["sha256"]:
|
|
raise RuntimeError("Google model checksum mismatch")
|
|
with tempfile.TemporaryDirectory(prefix="searchi-linux-smoke-") as temporary:
|
|
target = Path(temporary)
|
|
copied = []
|
|
for source in [args.worker.resolve(), *dependencies]:
|
|
# Only exact approved CPU module names are omitted. Core libraries
|
|
# and GPU support remain present in the baseline extraction.
|
|
if args.baseline and source.name.startswith("libggml-cpu-") and source.name != "libggml-cpu-x64.so":
|
|
continue
|
|
destination = target / source.name
|
|
shutil.copy2(source, destination)
|
|
if sha256(destination) != sha256(source):
|
|
raise RuntimeError("Extracted runtime checksum mismatch")
|
|
copied.append(source.name)
|
|
worker = target / args.worker.name
|
|
dynamic = subprocess.check_output(["readelf", "-d", str(worker)], text=True)
|
|
if "libvulkan" in dynamic or "libggml-vulkan" in dynamic:
|
|
raise RuntimeError("Worker requires Vulkan at process startup; CPU fallback cannot work without the loader")
|
|
if "$ORIGIN" not in dynamic:
|
|
raise RuntimeError("Worker lacks origin-relative runtime lookup")
|
|
environment = dict(os.environ, SEARCHI_FORCE_CPU="1", GGML_DISABLE_VULKAN="1")
|
|
environment.pop("LD_LIBRARY_PATH", None)
|
|
environment.pop("GGML_BACKEND_PATH", None)
|
|
started = time.perf_counter()
|
|
process = subprocess.Popen([str(worker), "--model", str(model), "--threads", "1", "--device", "cpu"],
|
|
cwd=target, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
|
text=True, encoding="utf-8", env=environment)
|
|
try:
|
|
stdout, stderr = process.communicate(json.dumps({"op": "code_query", "text": "retry failed requests with exponential backoff"}) + "\n", timeout=180)
|
|
except BaseException:
|
|
process.kill()
|
|
process.wait(timeout=10)
|
|
raise
|
|
elapsed_ms = (time.perf_counter() - started) * 1000
|
|
if process.returncode:
|
|
raise RuntimeError(f"Worker failed ({process.returncode}): {stderr[-4096:]}")
|
|
lines = [json.loads(line) for line in stdout.splitlines()]
|
|
if len(lines) != 2:
|
|
raise RuntimeError("Unexpected worker protocol output")
|
|
hello, result = lines
|
|
if not hello.get("ready") or hello.get("device") != "cpu" or not result.get("ok") or result.get("device") != "cpu":
|
|
raise RuntimeError("Expected genuine ready CPU inference")
|
|
if hello.get("vulkan_module_loaded"):
|
|
raise RuntimeError("CPU check loaded a Vulkan provider")
|
|
vectors = result.get("vectors")
|
|
vector = vectors[0] if isinstance(vectors, list) and len(vectors) == 1 else None
|
|
if not isinstance(vector, list) or len(vector) != 768 or not all(isinstance(value, (int, float)) and math.isfinite(value) for value in vector):
|
|
raise RuntimeError("Invalid Google embedding vector")
|
|
norm = math.sqrt(sum(value * value for value in vector))
|
|
if abs(norm - 1) > 0.001:
|
|
raise RuntimeError("Google vector is not normalized")
|
|
module = hello.get("cpu_backend_module", "")
|
|
if args.baseline and module != "libggml-cpu-x64.so":
|
|
raise RuntimeError(f"Baseline extraction selected unexpected CPU module: {module}")
|
|
evidence = {"platform": "linux", "cpu_only": True, "baseline_only_extraction": args.baseline,
|
|
"worker_sha256": sha256(args.worker), "model_sha256": sha256(model),
|
|
"files": sorted(copied), "hello": hello, "dimensions": len(vector), "norm": norm,
|
|
"startup_query_exit_ms": elapsed_ms,
|
|
"timing_scope": "single diagnostic smoke sample; not a performance benchmark",
|
|
"worker_dynamic_section": dynamic,
|
|
"limitations": ["GPU untested", "older physical CPUs untested", "desktop and installer untested", "system-loader absence not physically exercised"]}
|
|
args.output.parent.mkdir(parents=True, exist_ok=True)
|
|
args.output.write_text(json.dumps(evidence, indent=2) + "\n", encoding="utf-8")
|
|
print(json.dumps({"ready": True, "cpu_module": module, "dimensions": 768, "baseline": args.baseline}))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|