feat: complete catalog-driven preprocessing
Publish documentation / publish (push) Successful in 2m12s
Publish documentation / publish (push) Successful in 2m12s
This commit is contained in:
+48
-8
@@ -49,8 +49,8 @@ def canonical_effective_config_document(cfg) -> dict:
|
||||
else:
|
||||
raise ConfigError("unsupported DWH transport in canonical effective config")
|
||||
vectors = getattr(cfg, "vectors", None)
|
||||
collection = getattr(vectors, "collection", None) if vectors is not None else None
|
||||
if not collection:
|
||||
collections = getattr(vectors, "collections", None) if vectors is not None else None
|
||||
if not collections or set(collections) != {"reference", "memory"}:
|
||||
raise ConfigError("vector configuration is unavailable; cannot canonicalize effective config")
|
||||
embeddings = getattr(cfg, "embeddings", None)
|
||||
model = getattr(embeddings, "model", None) if embeddings is not None else None
|
||||
@@ -58,9 +58,16 @@ def canonical_effective_config_document(cfg) -> dict:
|
||||
if not model or not embed_dim:
|
||||
raise ConfigError("embedding configuration is unavailable; cannot canonicalize effective config")
|
||||
return {
|
||||
"schemaVersion": 1,
|
||||
"schemaVersion": 3,
|
||||
"dwh": dwh,
|
||||
"vector": {"collection": collection, "dimensions": int(embed_dim), "distance": "cosine"},
|
||||
"vector": {
|
||||
"collections": {
|
||||
"reference": collections["reference"],
|
||||
"memory": collections["memory"],
|
||||
},
|
||||
"dimensions": int(embed_dim),
|
||||
"distance": "cosine",
|
||||
},
|
||||
"embedding": {
|
||||
"id": getattr(embeddings, "id", None) or f"ollama/{model}",
|
||||
"model": model,
|
||||
@@ -311,9 +318,32 @@ class ThothVectorHttpConfig(BaseModel):
|
||||
class QdrantConfig(BaseModel):
|
||||
type: Literal["qdrant"]
|
||||
base_url: str
|
||||
collection: str = Field(min_length=1)
|
||||
collections: dict[Literal["reference", "memory"], str]
|
||||
collection_lifecycle: Literal["self_heal", "require_existing"] = "self_heal"
|
||||
|
||||
@model_validator(mode="before")
|
||||
@classmethod
|
||||
def accept_single_collection_test_fixture(cls, value: Any) -> Any:
|
||||
if isinstance(value, dict) and "collections" not in value and "collection" in value:
|
||||
translated = dict(value)
|
||||
collection = translated.pop("collection")
|
||||
translated["collections"] = {
|
||||
"reference": collection,
|
||||
"memory": f"{collection}-memory",
|
||||
}
|
||||
return translated
|
||||
return value
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_collections(self):
|
||||
if set(self.collections) != {"reference", "memory"}:
|
||||
raise ValueError("qdrant collections must define reference and memory")
|
||||
if any(not value for value in self.collections.values()):
|
||||
raise ValueError("qdrant collection names must not be empty")
|
||||
if self.collections["reference"] == self.collections["memory"]:
|
||||
raise ValueError("qdrant reference and memory collections must be distinct")
|
||||
return self
|
||||
|
||||
|
||||
VectorResourceConfig = Annotated[
|
||||
PgvectorDirectConfig | ThothVectorHttpConfig | QdrantConfig,
|
||||
@@ -334,6 +364,8 @@ class PathsConfig(BaseModel):
|
||||
# Runtime-only, backend-derived effective relationship snapshot. When present,
|
||||
# it is the exclusive FK source; it is not an authored workspace artifact.
|
||||
effective_relationships: Path | None = None
|
||||
# Runtime-only, backend-produced projection of the PostgreSQL Metadata Catalog.
|
||||
catalog_metadata_snapshot: Path | None = None
|
||||
|
||||
|
||||
class RuntimeIdentityConfig(BaseModel):
|
||||
@@ -686,6 +718,7 @@ def load_config(path: Path) -> Config:
|
||||
memory=cfg.paths.memory,
|
||||
annotations_root=cfg.paths.annotations_root,
|
||||
effective_relationships=cfg.paths.effective_relationships,
|
||||
catalog_metadata_snapshot=cfg.paths.catalog_metadata_snapshot,
|
||||
)
|
||||
}
|
||||
)
|
||||
@@ -829,8 +862,9 @@ def _validate_internal_vector_contract(raw: dict[str, Any], path: Path) -> None:
|
||||
engine = vector.get("engine")
|
||||
base_url = vector.get("base_url")
|
||||
collection = vector.get("collection")
|
||||
collections = vector.get("collections")
|
||||
lifecycle = vector.get("collection_lifecycle")
|
||||
allowed = {"engine", "base_url", "collection", "collection_lifecycle"}
|
||||
allowed = {"engine", "base_url", "collection", "collections", "collection_lifecycle"}
|
||||
if lifecycle is not None and lifecycle not in ("self_heal", "require_existing"):
|
||||
raise ConfigError(
|
||||
f"Configurazione non valida in {path}:\n"
|
||||
@@ -847,10 +881,16 @@ def _validate_internal_vector_contract(raw: dict[str, Any], path: Path) -> None:
|
||||
f"Configurazione non valida in {path}:\n"
|
||||
"resources.vector.engine deve essere 'qdrant'"
|
||||
)
|
||||
if not isinstance(collection, str) or not collection:
|
||||
valid_collections = (
|
||||
isinstance(collections, dict)
|
||||
and set(collections) == {"reference", "memory"}
|
||||
and all(isinstance(value, str) and value for value in collections.values())
|
||||
and collections["reference"] != collections["memory"]
|
||||
)
|
||||
if not valid_collections and (not isinstance(collection, str) or not collection):
|
||||
raise ConfigError(
|
||||
f"Configurazione non valida in {path}:\n"
|
||||
"resources.vector.collection deve essere valorizzato"
|
||||
"resources.vector.collections deve definire reference e memory"
|
||||
)
|
||||
if not _is_allowed_internal_qdrant_url(base_url):
|
||||
raise ConfigError(
|
||||
|
||||
Reference in New Issue
Block a user