Files
searchi/tools/embeddinggemma2/linux_smoke.py
T

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()