""" FILE: app/main.py DESCRIPTION: Bootstrap der FastAPI Anwendung für WP-25 (Agentic RAG). Orchestriert Lifespan-Events, globale Fehlerbehandlung und Routing. VERSION: 1.0.0 (WP-25 Release) STATUS: Active DEPENDENCIES: app.config, app.routers.*, app.services.llm_service """ from __future__ import annotations import logging import os from contextlib import asynccontextmanager from fastapi import FastAPI, Request from fastapi.responses import JSONResponse from .config import get_settings from .services.llm_service import LLMService # Import der Router from .routers.query import router as query_router from .routers.graph import router as graph_router from .routers.tools import router as tools_router from .routers.feedback import router as feedback_router from .routers.chat import router as chat_router from .routers.ingest import router as ingest_router try: from .routers.admin import router as admin_router except Exception: admin_router = None from .core.logging_setup import setup_logging # Initialisierung noch VOR create_app() setup_logging() logger = logging.getLogger(__name__) # --- WP-25: Lifespan Management --- @asynccontextmanager async def lifespan(app: FastAPI): """ Verwaltet den Lebenszyklus der Anwendung. Führt Startup-Prüfungen durch und bereinigt Ressourcen beim Shutdown. """ settings = get_settings() logger.info("🚀 mindnet API: Starting up (WP-25 Agentic RAG Mode)...") # 1. Startup: Integritäts-Check der WP-25 Konfiguration # Wir prüfen, ob die für die DecisionEngine kritischen Dateien vorhanden sind. decision_cfg = os.getenv("MINDNET_DECISION_CONFIG", "config/decision_engine.yaml") prompts_cfg = settings.PROMPTS_PATH if not os.path.exists(decision_cfg): logger.error(f"❌ CRITICAL: Decision Engine config missing at {decision_cfg}") if not os.path.exists(prompts_cfg): logger.error(f"❌ CRITICAL: Prompts config missing at {prompts_cfg}") yield # 2. Shutdown: Ressourcen bereinigen logger.info("🛑 mindnet API: Shutting down...") llm = LLMService() await llm.close() logger.info("✨ Cleanup complete. Goodbye.") # --- App Factory --- def create_app() -> FastAPI: """Initialisiert die FastAPI App mit WP-25 Erweiterungen.""" app = FastAPI( title="mindnet API", version="1.0.0", # WP-25 Milestone lifespan=lifespan, description="Digital Twin Knowledge Engine mit Agentic Multi-Stream RAG." ) s = get_settings() # --- Globale Fehlerbehandlung (WP-25 Resilienz) --- @app.exception_handler(Exception) async def global_exception_handler(request: Request, exc: Exception): """Fängt unerwartete Fehler in der Multi-Stream Kette ab.""" logger.error(f"❌ Unhandled Engine Error: {exc}", exc_info=True) return JSONResponse( status_code=500, content={ "detail": "Ein interner Fehler ist aufgetreten. Die DecisionEngine konnte die Anfrage nicht finalisieren.", "error_type": type(exc).__name__ } ) # Healthcheck @app.get("/healthz") def healthz(): return { "status": "ok", "version": "1.0.0", "qdrant": s.QDRANT_URL, "prefix": s.COLLECTION_PREFIX, "agentic_mode": True } # Inkludieren der Router (100% Kompatibilität erhalten) app.include_router(query_router, prefix="/query", tags=["query"]) app.include_router(graph_router, prefix="/graph", tags=["graph"]) app.include_router(tools_router, prefix="/tools", tags=["tools"]) app.include_router(feedback_router, prefix="/feedback", tags=["feedback"]) app.include_router(chat_router, prefix="/chat", tags=["chat"]) # Nutzt nun WP-25 DecisionEngine app.include_router(ingest_router, prefix="/ingest", tags=["ingest"]) if admin_router: app.include_router(admin_router, prefix="/admin", tags=["admin"]) return app # Instanziierung der App app = create_app()