feat: add desktop document search and verified native CPU embeddings
Core CI / core (ubuntu-latest) (push) Failing after 1m22s
Core CI / core (macos-latest) (push) Canceled after 0s
Core CI / core (windows-latest) (push) Canceled after 0s
Core CI / desktop (ubuntu-latest) (push) Successful in 3m46s
Core CI / desktop (macos-latest) (push) Canceled after 0s
Core CI / desktop (windows-latest) (push) Canceled after 0s

This commit is contained in:
karl committed 2026-10-12 16:07:53 +02:00
1 parent f77112db97
commit a9b6592330
46 files changed
+10794 -77

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
.venv/
model/
__pycache__/
+53
View File
@@ -0,0 +1,53 @@
"""Explicit provisioning only; inference never imports this downloader."""
import argparse
import hashlib
import json
import os
from pathlib import Path
import urllib.request
HERE = Path(__file__).resolve().parent
def digest(path):
with path.open("rb") as source:
return hashlib.file_digest(source, "sha256").hexdigest()
def verified(path, spec):
return path.is_file() and path.stat().st_size == spec["bytes"] and digest(path) == spec["sha256"]
def main():
parser = argparse.ArgumentParser(description="Explicitly download ~136 MB of pinned, verified model artifacts")
parser.add_argument("--model-dir", type=Path, default=HERE / "model")
args = parser.parse_args()
manifest = json.loads((HERE / "model-manifest.json").read_text())
for spec in manifest["files"]:
target = args.model_dir / spec["path"]
if verified(target, spec):
print(f"Verified existing {spec['path']}")
continue
target.parent.mkdir(parents=True, exist_ok=True)
temporary = target.with_suffix(target.suffix + ".part")
url = f"https://huggingface.co/{manifest['model_id']}/resolve/{manifest['revision']}/{spec['path']}"
print(f"Downloading {spec['path']} ({spec['bytes']} bytes)", flush=True)
try:
request = urllib.request.Request(url, headers={"User-Agent": "Searchi-semantic-proof/0.1"})
with urllib.request.urlopen(request, timeout=60) as response, temporary.open("wb") as output:
total = 0
while chunk := response.read(1024 * 1024):
total += len(chunk)
if total > spec["bytes"]:
raise ValueError("Download exceeds manifest size")
output.write(chunk)
if not verified(temporary, spec):
raise ValueError(f"Size or SHA256 mismatch for {spec['path']}")
os.replace(temporary, target)
print(f"Verified SHA256 {spec['sha256']}")
finally:
temporary.unlink(missing_ok=True)
if __name__ == "__main__":
main()
+20
View File
@@ -0,0 +1,20 @@
{
"documents": [
{"id": "supplier-contract", "text": "The supplier agreement may be ended by giving sixty days written notice. Early cancellation incurs no additional fee."},
{"id": "backup-policy", "text": "Backups are encrypted and stored each night. Recovery copies are retained for thirty days."},
{"id": "travel-expenses", "text": "Business train tickets and hotel stays can be reimbursed. Submit receipts with the monthly expense report."},
{"id": "meeting-notes", "text": "The design team decided to move the launch to November because accessibility testing needs another week."},
{"id": "apartment-lease", "text": "Die Wohnung kostet monatlich 950 Euro. Die Kaution beträgt drei Monatsmieten und wird nach dem Auszug zurückgezahlt."},
{"id": "garden-guide", "text": "Tomaten brauchen viel Sonnenlicht und regelmäßiges Gießen. Die Pflanzen sollten vor Frost geschützt werden."},
{"id": "password-reset", "text": "To recover your account, request a password reset link. The link expires after fifteen minutes."},
{"id": "invoice", "text": "Invoice 1042 lists five software licenses at forty euros each. Payment is due on the first of December."}
],
"queries": [
{"text": "How do we stop working with the vendor?", "expected": "supplier-contract", "language": "en"},
{"text": "Wie können wir die Zusammenarbeit mit dem Lieferanten beenden?", "expected": "supplier-contract", "language": "de-crosslingual"},
{"text": "Wo finde ich die Regeln zur Erstattung meiner Dienstreise?", "expected": "travel-expenses", "language": "de-crosslingual"},
{"text": "Why was the product release postponed?", "expected": "meeting-notes", "language": "en"},
{"text": "How much money must I leave as a security deposit for the flat?", "expected": "apartment-lease", "language": "en-crosslingual"},
{"text": "Wie pflege ich die Gemüsepflanzen im Garten?", "expected": "garden-guide", "language": "de"}
]
}
+14
View File
@@ -0,0 +1,14 @@
{
"model_id": "Xenova/paraphrase-multilingual-MiniLM-L12-v2",
"revision": "2c4055b12046f11709e9df2c122e59ffbdc2f900",
"base_model": "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2",
"base_license": "Apache-2.0",
"dimensions": 384,
"max_tokens": 128,
"pooling": "attention-mask-mean",
"normalization": "l2",
"files": [
{"path": "onnx/model_quantized.onnx", "bytes": 118308126, "sha256": "66fc00f5f29afcaff34092e1bdd20008ca3918265a82fb9695a551e510cc4ebc"},
{"path": "tokenizer.json", "bytes": 17082913, "sha256": "b60b6b43406a48bf3638526314f3d232d97058bc93472ff2de930d43686fa441"}
]
}
+135
View File
@@ -0,0 +1,135 @@
"""Real, local ONNX text embeddings with an enforced CPU-only session."""
import argparse
import hashlib
import json
import os
from pathlib import Path
import platform
import statistics
import sys
import time
# Fail rather than silently contacting a model service or downloading an asset.
os.environ["HF_HUB_OFFLINE"] = "1"
os.environ["TRANSFORMERS_OFFLINE"] = "1"
os.environ["TOKENIZERS_PARALLELISM"] = "false"
def reject_network(event, args):
if event in {"socket.connect", "socket.getaddrinfo", "socket.bind"}:
raise RuntimeError("Semantic proof inference is offline; network access is forbidden")
sys.addaudithook(reject_network)
import numpy as np
import onnxruntime as ort
from tokenizers import Tokenizer
HERE = Path(__file__).resolve().parent
class CpuEmbedder:
"""Bounded reference contract for a future Rust ONNX adapter."""
def __init__(self, model_dir, threads=1):
if not 1 <= threads <= 8:
raise ValueError("threads must be between 1 and 8")
self.manifest = json.loads((HERE / "model-manifest.json").read_text())
for spec in self.manifest["files"]:
path = model_dir / spec["path"]
if not path.is_file():
raise ValueError(f"Missing local artifact {path}; explicitly run download.py first")
with path.open("rb") as source:
checksum = hashlib.file_digest(source, "sha256").hexdigest()
if path.stat().st_size != spec["bytes"] or checksum != spec["sha256"]:
raise ValueError(f"Artifact size/SHA256 mismatch: {path}")
options = ort.SessionOptions()
options.intra_op_num_threads = threads
options.inter_op_num_threads = 1
options.execution_mode = ort.ExecutionMode.ORT_SEQUENTIAL
self.session = ort.InferenceSession(
str(model_dir / "onnx/model_quantized.onnx"),
sess_options=options,
providers=["CPUExecutionProvider"],
)
if self.session.get_providers() != ["CPUExecutionProvider"]:
raise RuntimeError("Only CPUExecutionProvider is allowed")
self.tokenizer = Tokenizer.from_file(str(model_dir / "tokenizer.json"))
self.tokenizer.enable_truncation(max_length=self.manifest["max_tokens"])
self.tokenizer.enable_padding(pad_id=1, pad_token="<pad>")
def encode(self, texts):
if not texts or len(texts) > 8:
raise ValueError("Batch size must be between 1 and 8")
if any(not text.strip() or len(text.encode("utf-8")) > 65536 for text in texts):
raise ValueError("Text must be nonempty and at most 64 KiB UTF-8")
encoded = self.tokenizer.encode_batch(texts)
available = {
"input_ids": np.asarray([item.ids for item in encoded], dtype=np.int64),
"attention_mask": np.asarray([item.attention_mask for item in encoded], dtype=np.int64),
"token_type_ids": np.asarray([item.type_ids for item in encoded], dtype=np.int64),
}
inputs = {item.name: available[item.name] for item in self.session.get_inputs()}
hidden = self.session.run(None, inputs)[0]
mask = available["attention_mask"][..., None].astype(np.float32)
pooled = (hidden * mask).sum(axis=1) / np.maximum(mask.sum(axis=1), 1e-9)
vectors = pooled / np.maximum(np.linalg.norm(pooled, axis=1, keepdims=True), 1e-9)
if vectors.shape != (len(texts), self.manifest["dimensions"]) or not np.isfinite(vectors).all():
raise RuntimeError("Invalid model embedding shape or nonfinite values")
return vectors.astype(np.float32)
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--model-dir", type=Path, default=HERE / "model")
parser.add_argument("--fixture", type=Path, default=HERE / "fixture.json")
parser.add_argument("--output", type=Path)
parser.add_argument("--threads", type=int, default=1, choices=range(1, 9))
parser.add_argument("--repeats", type=int, default=10, choices=range(1, 101))
args = parser.parse_args()
fixture = json.loads(args.fixture.read_text(encoding="utf-8"))
started = time.perf_counter()
embedder = CpuEmbedder(args.model_dir, args.threads)
load_ms = (time.perf_counter() - started) * 1000
started = time.perf_counter()
vectors = embedder.encode([item["text"] for item in fixture["documents"]])
corpus_ms = (time.perf_counter() - started) * 1000
rankings = []
timings = []
for query in fixture["queries"]:
vector = embedder.encode([query["text"]])[0] # Warm this input shape.
for _ in range(args.repeats):
started = time.perf_counter()
vector = embedder.encode([query["text"]])[0]
scores = vectors @ vector
order = np.argsort(-scores)
timings.append((time.perf_counter() - started) * 1000)
ranked = [{"id": fixture["documents"][int(i)]["id"], "cosine": float(scores[i])} for i in order]
expected_rank = next(i + 1 for i, result in enumerate(ranked) if result["id"] == query["expected"])
rankings.append({**query, "expected_rank": expected_rank, "top3": ranked[:3]})
report = {
"platform": platform.platform(), "python": platform.python_version(),
"machine": platform.machine(), "logical_cpus": os.cpu_count(),
"onnxruntime": ort.__version__, "numpy": np.__version__,
"providers": embedder.session.get_providers(), "threads": args.threads,
"model": embedder.manifest, "documents": len(fixture["documents"]),
"queries": len(rankings), "timed_query_runs": len(timings),
"artifact_verify_and_load_ms": load_ms, "corpus_embedding_ms": corpus_ms,
"query_p50_ms": statistics.median(timings),
"query_p95_ms": float(np.percentile(timings, 95)),
"top1_accuracy": sum(item["expected_rank"] == 1 for item in rankings) / len(rankings),
"recall_at_3": sum(item["expected_rank"] <= 3 for item in rankings) / len(rankings),
"network": "Python socket audit guard active during import, model load, and inference",
"rankings": rankings,
}
serialized = json.dumps(report, ensure_ascii=False, indent=2)
if args.output:
args.output.write_text(serialized + "\n", encoding="utf-8")
print(serialized)
if report["top1_accuracy"] < 1:
raise SystemExit("Fixture top-1 quality gate failed")
if __name__ == "__main__":
main()
@@ -0,0 +1,21 @@
anyio==4.15.1
click==8.5.0
colorama==0.4.6
filelock==4.1.1
flatbuffers==25.12.19
fsspec==2026.9.0
h11==0.16.0
hf-xet==1.7.0
httpcore2==2.13.1
httpx2==2.13.1
huggingface_hub==2.2.0
idna==3.20
numpy==2.5.4
onnxruntime==1.31.0
packaging==26.3
protobuf==7.36.2
PyYAML==6.0.3
tokenizers==0.23.3
tqdm==4.70.1
truststore==0.10.4
typing_extensions==4.16.0
+4
View File
@@ -0,0 +1,4 @@
# CPU wheel only. Never replace with onnxruntime-gpu.
onnxruntime==1.31.0
tokenizers==0.23.3
numpy==2.5.4
@@ -0,0 +1,166 @@
{
"platform": "Windows-11-10.0.26300-SP0",
"python": "3.14.8",
"machine": "AMD64",
"logical_cpus": 4,
"onnxruntime": "1.31.0",
"numpy": "2.5.4",
"providers": [
"CPUExecutionProvider"
],
"threads": 1,
"model": {
"model_id": "Xenova/paraphrase-multilingual-MiniLM-L12-v2",
"revision": "2c4055b12046f11709e9df2c122e59ffbdc2f900",
"base_model": "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2",
"base_license": "Apache-2.0",
"dimensions": 384,
"max_tokens": 128,
"pooling": "attention-mask-mean",
"normalization": "l2",
"files": [
{
"path": "onnx/model_quantized.onnx",
"bytes": 118308126,
"sha256": "66fc00f5f29afcaff34092e1bdd20008ca3918265a82fb9695a551e510cc4ebc"
},
{
"path": "tokenizer.json",
"bytes": 17082913,
"sha256": "b60b6b43406a48bf3638526314f3d232d97058bc93472ff2de930d43686fa441"
}
]
},
"documents": 8,
"queries": 6,
"timed_query_runs": 60,
"artifact_verify_and_load_ms": 3399.298300006194,
"corpus_embedding_ms": 145.497699995758,
"query_p50_ms": 3.0544000037480146,
"query_p95_ms": 11.88376000645803,
"top1_accuracy": 0.8333333333333334,
"recall_at_3": 1.0,
"network": "Python socket audit guard active during import, model load, and inference",
"rankings": [
{
"text": "How do we stop working with the vendor?",
"expected": "supplier-contract",
"language": "en",
"expected_rank": 1,
"top3": [
{
"id": "supplier-contract",
"cosine": 0.389570415019989
},
{
"id": "invoice",
"cosine": 0.16107530891895294
},
{
"id": "travel-expenses",
"cosine": 0.06973522156476974
}
]
},
{
"text": "Wie können wir die Zusammenarbeit mit dem Lieferanten beenden?",
"expected": "supplier-contract",
"language": "de-crosslingual",
"expected_rank": 1,
"top3": [
{
"id": "supplier-contract",
"cosine": 0.5199419260025024
},
{
"id": "invoice",
"cosine": 0.21696728467941284
},
{
"id": "meeting-notes",
"cosine": 0.14755962789058685
}
]
},
{
"text": "Wo finde ich die Regeln zur Erstattung meiner Dienstreise?",
"expected": "travel-expenses",
"language": "de-crosslingual",
"expected_rank": 1,
"top3": [
{
"id": "travel-expenses",
"cosine": 0.5095880627632141
},
{
"id": "apartment-lease",
"cosine": 0.3584939241409302
},
{
"id": "invoice",
"cosine": 0.2985326647758484
}
]
},
{
"text": "Why was the product release postponed?",
"expected": "meeting-notes",
"language": "en",
"expected_rank": 2,
"top3": [
{
"id": "supplier-contract",
"cosine": 0.3999302387237549
},
{
"id": "meeting-notes",
"cosine": 0.3511156439781189
},
{
"id": "backup-policy",
"cosine": 0.19898240268230438
}
]
},
{
"text": "How much money must I leave as a security deposit for the flat?",
"expected": "apartment-lease",
"language": "en-crosslingual",
"expected_rank": 1,
"top3": [
{
"id": "apartment-lease",
"cosine": 0.5188605785369873
},
{
"id": "travel-expenses",
"cosine": 0.2738097310066223
},
{
"id": "backup-policy",
"cosine": 0.2614522874355316
}
]
},
{
"text": "Wie pflege ich die Gemüsepflanzen im Garten?",
"expected": "garden-guide",
"language": "de",
"expected_rank": 1,
"top3": [
{
"id": "garden-guide",
"cosine": 0.5030614733695984
},
{
"id": "apartment-lease",
"cosine": 0.03017299994826317
},
{
"id": "meeting-notes",
"cosine": 0.030125245451927185
}
]
}
]
}