91 lines
2.3 KiB
Python
91 lines
2.3 KiB
Python
"""Transport-neutral vector-store contract and canonical vector models."""
|
|
|
|
from dataclasses import dataclass
|
|
from typing import Protocol, runtime_checkable
|
|
|
|
from tht.vectorstore.records import VectorRecord
|
|
from tht.vectorstore.store import VectorHit
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class VectorCapabilities:
|
|
search: bool = True
|
|
existing_hashes: bool = False
|
|
upsert: bool = False
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class VectorHealth:
|
|
ok: bool
|
|
detail: str | None = None
|
|
read_configured: bool = False
|
|
read_reachable: bool | None = None
|
|
read_detail: str | None = None
|
|
write_configured: bool = False
|
|
write_reachable: bool | None = None
|
|
write_detail: str | None = None
|
|
expected_dimension: int | None = None
|
|
observed_dimensions: tuple[int, ...] = ()
|
|
dimension_compatible: bool | None = None
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class VectorWriteRecord:
|
|
"""A canonical record plus transport-neutral, precomputed vector data."""
|
|
|
|
record: VectorRecord
|
|
embedding: list[float]
|
|
content_hash: str
|
|
|
|
|
|
class VectorStoreError(Exception):
|
|
"""Base error exposed by vector adapters."""
|
|
|
|
|
|
class VectorWriteUnavailable(VectorStoreError):
|
|
"""Raised when a deployment has no vector writer credential."""
|
|
|
|
|
|
class VectorReadUnavailable(VectorStoreError):
|
|
"""Raised when a deployment has no vector reader credential."""
|
|
|
|
|
|
def require_positive_limit(limit: int) -> None:
|
|
"""Reject coercible values: vector limits are exact positive integers."""
|
|
if type(limit) is not int or limit <= 0:
|
|
raise ValueError("Vector search limit must be a positive integer")
|
|
|
|
|
|
@runtime_checkable
|
|
class VectorStore(Protocol):
|
|
@property
|
|
def capabilities(self) -> VectorCapabilities: ...
|
|
|
|
def health(self) -> VectorHealth: ...
|
|
|
|
def search(
|
|
self,
|
|
collections: list[str],
|
|
embedding: list[float],
|
|
*,
|
|
limit: int,
|
|
kinds: list[str] | None = None,
|
|
) -> list[VectorHit]: ...
|
|
|
|
def existing_hashes(self, collection: str, kinds: list[str]) -> dict[str, str]: ...
|
|
|
|
def upsert(self, collection: str, records: list[VectorWriteRecord]) -> int: ...
|
|
|
|
|
|
__all__ = [
|
|
"VectorCapabilities",
|
|
"VectorHealth",
|
|
"VectorHit",
|
|
"VectorRecord",
|
|
"VectorReadUnavailable",
|
|
"VectorStore",
|
|
"VectorStoreError",
|
|
"VectorWriteRecord",
|
|
"VectorWriteUnavailable",
|
|
]
|