face-intel / api /container.py
Marwan
Restructure + add reverse face search (PimEyes-style)
f5eeb1c
Raw
History Blame Contribute Delete
9.47 kB
"""
DI container — constructs every dependency ONCE at app startup and
wires services together. This is the composition root.
No globals: the container is created in `create_app()` and stored on
`app.state.container`. Route handlers retrieve it via the `get_container`
FastAPI dependency.
"""
from __future__ import annotations
from dataclasses import dataclass
from config.settings import Settings, DATA_DIR, GALLERY_DIR, UPLOADS_DIR, JOBS_DIR
from confidence.engine import ConfidenceEngine
from confidence.conflicts import ConflictDetector
from metrics.collector import MetricsCollector
from orchestrator.health import HealthMonitor
from orchestrator.runner import Orchestrator
from pipeline import (
InputValidator,
ImagePreprocessor,
ImageHasher,
FeatureExtractor,
)
from providers.registry import ProviderRegistry
from services.analysis_service import AnalysisService
from services.cache_service import CacheService
from services.detection_service import DetectionService
from services.export_service import ExportService
from services.face_index_service import FaceIndexService
from services.face_intelligence_service import FaceIntelligenceService
from services.forensic_metadata_service import ForensicMetadataService
from services.health_service import HealthService
from services.job_service import JobService
from services.location_intelligence_service import LocationIntelligenceService
from services.object_intelligence_service import ObjectIntelligenceService
from services.osint_service import OSINTService
from services.correlation_engine_service import CorrelationEngineService
from services.provider_service import ProviderService
from services.recognition_service import RecognitionService
from services.search_service import SearchService
from storage.artifacts import ArtifactStore
from storage.cache import Cache
from storage.database import Database
from storage.face_index import FaceIndex
from storage.reference_store import ReferenceStore
@dataclass
class ServiceContainer:
"""Holds every wired service + infrastructure object."""
settings: Settings
registry: ProviderRegistry
cache: Cache
database: Database
artifacts: ArtifactStore
reference_store: ReferenceStore
metrics: MetricsCollector
health_monitor: HealthMonitor
orchestrator: Orchestrator
confidence_engine: ConfidenceEngine
conflict_detector: ConflictDetector
validator: InputValidator
preprocessor: ImagePreprocessor
hasher: ImageHasher
feature_extractor: FeatureExtractor
detection_service: DetectionService
recognition_service: RecognitionService
search_service: SearchService
analysis_service: AnalysisService
job_service: JobService
osint_service: OSINTService
face_intelligence_service: FaceIntelligenceService
forensic_metadata_service: ForensicMetadataService
object_intelligence_service: ObjectIntelligenceService
location_intelligence_service: LocationIntelligenceService
correlation_engine_service: CorrelationEngineService
provider_service: ProviderService
cache_service: CacheService
health_service: HealthService
export_service: ExportService
face_index: FaceIndex
face_index_service: FaceIndexService
def build_container(settings: Settings | None = None) -> ServiceContainer:
"""Construct the entire dependency graph. Called once at startup."""
settings = settings or Settings()
# Infrastructure
registry = ProviderRegistry(settings)
registry.discover()
cache = Cache(
ttl_seconds=settings.cache_ttl_seconds,
max_entries=settings.cache_max_entries,
)
database = Database(path=settings.db_path)
artifacts = ArtifactStore(root=UPLOADS_DIR)
reference_store = ReferenceStore(root=GALLERY_DIR)
metrics = MetricsCollector(
failure_threshold=settings.circuit_breaker_failure_threshold,
recovery_seconds=settings.circuit_breaker_recovery_seconds,
)
health_monitor = HealthMonitor(metrics=metrics.health)
orchestrator = Orchestrator(
registry=registry,
cache=cache,
metrics=metrics,
health=health_monitor,
settings=settings,
)
confidence_engine = ConfidenceEngine()
conflict_detector = ConflictDetector()
# Pipeline
validator = InputValidator(max_bytes=settings.max_image_bytes)
preprocessor = ImagePreprocessor(max_dim=1024)
hasher = ImageHasher()
# Use the first available detection provider as the default feature extractor
from models.providers import ProviderCapability
detectors = registry.list_by_capability(ProviderCapability.DETECTION)
default_detector = detectors[0] if detectors else None
feature_extractor = FeatureExtractor(detector=default_detector)
# Services
detection_service = DetectionService(
registry=registry, orchestrator=orchestrator, cache=cache, metrics=metrics,
validator=validator, preprocessor=preprocessor, hasher=hasher,
feature_extractor=feature_extractor,
confidence_engine=confidence_engine, conflict_detector=conflict_detector,
)
recognition_service = RecognitionService(
orchestrator=orchestrator, metrics=metrics,
validator=validator, preprocessor=preprocessor, hasher=hasher,
feature_extractor=feature_extractor, reference_store=reference_store,
confidence_engine=confidence_engine, conflict_detector=conflict_detector,
)
search_service = SearchService(
orchestrator=orchestrator, metrics=metrics,
validator=validator, preprocessor=preprocessor, hasher=hasher,
feature_extractor=feature_extractor,
confidence_engine=confidence_engine, conflict_detector=conflict_detector,
)
analysis_service = AnalysisService(
orchestrator=orchestrator, metrics=metrics,
validator=validator, preprocessor=preprocessor, hasher=hasher,
feature_extractor=feature_extractor,
confidence_engine=confidence_engine, conflict_detector=conflict_detector,
)
job_service = JobService(
detection=detection_service,
recognition=recognition_service,
search=search_service,
analysis=analysis_service,
database=database,
metrics=metrics,
job_timeout_seconds=settings.job_timeout_seconds,
)
osint_service = OSINTService(
orchestrator=orchestrator,
metrics=metrics,
validator=validator,
preprocessor=preprocessor,
hasher=hasher,
feature_extractor=feature_extractor,
)
face_intelligence_service = FaceIntelligenceService(
validator=validator,
preprocessor=preprocessor,
hasher=hasher,
feature_extractor=feature_extractor,
)
forensic_metadata_service = ForensicMetadataService(
validator=validator,
preprocessor=preprocessor,
hasher=hasher,
)
object_intelligence_service = ObjectIntelligenceService(
orchestrator=orchestrator,
validator=validator,
preprocessor=preprocessor,
hasher=hasher,
feature_extractor=feature_extractor,
)
location_intelligence_service = LocationIntelligenceService(
validator=validator,
preprocessor=preprocessor,
hasher=hasher,
)
correlation_engine_service = CorrelationEngineService(
validator=validator,
preprocessor=preprocessor,
hasher=hasher,
)
provider_service = ProviderService(registry=registry)
cache_service = CacheService(cache=cache)
health_service = HealthService(
registry=registry, health_monitor=health_monitor, metrics=metrics,
version=settings.app_version,
)
export_service = ExportService(database=database)
# Reverse face search index (sqlite-vec backed)
face_index = FaceIndex(path=settings.face_index_path)
face_index_service = FaceIndexService(
settings=settings,
validator=validator,
preprocessor=preprocessor,
hasher=hasher,
feature_extractor=feature_extractor,
face_index=face_index,
)
return ServiceContainer(
settings=settings,
registry=registry,
cache=cache,
database=database,
artifacts=artifacts,
reference_store=reference_store,
metrics=metrics,
health_monitor=health_monitor,
orchestrator=orchestrator,
confidence_engine=confidence_engine,
conflict_detector=conflict_detector,
validator=validator,
preprocessor=preprocessor,
hasher=hasher,
feature_extractor=feature_extractor,
detection_service=detection_service,
recognition_service=recognition_service,
search_service=search_service,
analysis_service=analysis_service,
job_service=job_service,
osint_service=osint_service,
face_intelligence_service=face_intelligence_service,
forensic_metadata_service=forensic_metadata_service,
object_intelligence_service=object_intelligence_service,
location_intelligence_service=location_intelligence_service,
correlation_engine_service=correlation_engine_service,
provider_service=provider_service,
cache_service=cache_service,
health_service=health_service,
export_service=export_service,
face_index=face_index,
face_index_service=face_index_service,
)