63 lines
2.4 KiB
Python
63 lines
2.4 KiB
Python
"""F-05: refuse to become ready on a corpus/model manifest mismatch.
|
|
|
|
Two different embedding models can produce vectors of the same
|
|
dimensionality; Qdrant returns plausible-looking but meaningless nearest
|
|
neighbours with no error at query time — a stale or wrong collection is
|
|
otherwise invisible until a clinician notices the answers are subtly off.
|
|
The ingestion loader already writes a sidecar manifest recording what a
|
|
collection was built from (`ingestion/ingestion/load/manifest.py`); this is
|
|
the query-time half — compare it against the configured query embedder
|
|
*before* serving anything, not after a bad answer is reported.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
MANIFEST_POINT_ID = "00000000-0000-5000-8000-000000000001"
|
|
|
|
|
|
class ManifestMismatch(RuntimeError):
|
|
"""The configured query embedder does not match what the collection was
|
|
built from. Raised at startup so the service refuses to become ready
|
|
rather than search with mismatched vectors."""
|
|
|
|
|
|
def manifest_collection(name: str) -> str:
|
|
return f"{name}__manifest"
|
|
|
|
|
|
def check_manifest(
|
|
payload: dict | None,
|
|
collection: str,
|
|
expected_model_id: str,
|
|
expected_dimensions: int,
|
|
) -> None:
|
|
"""Raises `ManifestMismatch` unless `payload` (the manifest sidecar
|
|
point's payload, or `None` if the sidecar/point is missing entirely)
|
|
matches the configured query embedder.
|
|
|
|
A collection with no manifest at all is refused for the same reason a
|
|
mismatched one is: nothing can be said about what it was built from, and
|
|
"probably fine" is not a load-bearing claim for a medical formulary.
|
|
"""
|
|
if payload is None:
|
|
raise ManifestMismatch(
|
|
f"{collection!r} has no corpus manifest "
|
|
f"({manifest_collection(collection)!r}) — refusing to query an "
|
|
"unattested corpus."
|
|
)
|
|
mismatches = []
|
|
if payload.get("model_id") != expected_model_id:
|
|
mismatches.append(
|
|
f"model_id: corpus={payload.get('model_id')!r} "
|
|
f"query_embedder={expected_model_id!r}"
|
|
)
|
|
if payload.get("dimensions") != expected_dimensions:
|
|
mismatches.append(
|
|
f"dimensions: corpus={payload.get('dimensions')!r} "
|
|
f"query_embedder={expected_dimensions!r}"
|
|
)
|
|
if mismatches:
|
|
raise ManifestMismatch(
|
|
f"{collection!r}'s corpus manifest does not match the configured "
|
|
"query embedder — " + "; ".join(mismatches)
|
|
)
|