from __future__ import annotations import logging from typing import Any from src.config import load_settings from src.search_service import SearchService logger = logging.getLogger(__name__) class AppRuntime: """Owns expensive application services that should be reused across callbacks.""" def __init__(self) -> None: self._search_service: SearchService | None = None self._preloaded_embedder: Any | None = None self._preload_error: str | None = None @property def preload_error(self) -> str | None: return self._preload_error def preload_clip_model(self) -> None: if self._preloaded_embedder is not None: return try: from src.clip_embedder import ClipEmbedder settings = load_settings() logger.info("Preloading CLIP model before Gradio launches") self._preloaded_embedder = ClipEmbedder(settings.clip_model_name) self._preload_error = None logger.info("CLIP model preload complete") except Exception as exc: self._preload_error = str(exc) logger.exception("CLIP model preload failed") def get_search_service(self) -> SearchService: if self._search_service is None: self._search_service = SearchService(embedder=self._preloaded_embedder) return self._search_service def reset_search_service(self) -> None: self._search_service = None