feat(runtime): implement single-article consolidation runtime and modularize codebase

This commit is contained in:
2026-08-24 00:14:07 -03:00
parent e1e0be1353
commit 23de7d8fe7
176 changed files with 266754 additions and 10179 deletions
+78
View File
@@ -0,0 +1,78 @@
"""ECP classification adapter consuming src.classifier.InherenceClassifier."""
from __future__ import annotations
import json
from pathlib import Path
from typing import Any, Dict, Optional
import jsonschema
from referencing import Registry, Resource
from src.runtime.core.config import create_schema_registry, load_schema
from src.tools.classifier import InherenceClassifier
from src.tools.models import ECPSnapshot
CANONICAL_ECP_SCHEMA_PATH = (
Path(__file__).resolve().parent.parent.parent
/ "tools"
/ "adapters"
/ "ecp"
/ "schemas"
/ "ecp-profile.schema.json"
)
def load_ecp_schema_registry() -> Registry:
registry = create_schema_registry()
if CANONICAL_ECP_SCHEMA_PATH.exists():
schema_data = json.loads(CANONICAL_ECP_SCHEMA_PATH.read_text(encoding="utf-8"))
schema_id = schema_data.get(
"$id", "https://schemas.aftech.internal/ecp/v1/ecp-profile.schema.json"
)
resource = Resource.from_contents(schema_data)
registry = registry.with_resource(schema_id, resource)
return registry
def validate_ecp_snapshot(ecp_data: Dict[str, Any]) -> None:
schema = load_schema("ecp-snapshot.schema.json")
registry = load_ecp_schema_registry()
validator = jsonschema.Draft202012Validator(schema, registry=registry)
errors = list(validator.iter_errors(ecp_data))
if errors:
msg = "; ".join([f"{e.json_path}: {e.message}" for e in errors])
raise ValueError(f"ECP Snapshot schema validation failed: {msg}")
class ECPClassificationAdapter:
def __init__(self, classifier: Optional[InherenceClassifier] = None):
self.classifier = classifier or InherenceClassifier()
def classify(self, ecp_dict: Dict[str, Any], content_md: str) -> Dict[str, Any]:
"""Classifies content_md against ecp_dict using InherenceClassifier."""
# 1. Validate ECP schema
validate_ecp_snapshot(ecp_dict)
# 2. Build model object
ecp_snapshot = ECPSnapshot.from_dict(ecp_dict)
# 3. Invoke classifier
result = self.classifier.classify(ecp=ecp_snapshot, content_md=content_md)
# 4. Extract fields & validate evidences grounding
decision_val = (
result.decision.value if hasattr(result.decision, "value") else str(result.decision)
)
is_inherent = bool(result.is_inherent)
confidence = float(getattr(result, "confidence", 1.0))
rationale = str(getattr(result, "rationale", ""))
evidences = [str(e) for e in (getattr(result, "evidence", []) or [])]
return {
"category": decision_val,
"is_inherent": is_inherent,
"confidence": confidence,
"rationale": rationale,
"evidences": evidences,
}