""" FastAPI application factory with lifespan management. The lifespan context manager handles: - Startup: initialize Qdrant, embedding, LLM, reranker services - Shutdown: close connections gracefully Services are stored in app.state and injected into route handlers. This avoids global state and makes the app testable. """ from __future__ import annotations from contextlib import asynccontextmanager from typing import AsyncGenerator import structlog from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from ahcgr import __app_name__, __version__ from ahcgr.api.middleware import RequestLoggingMiddleware from ahcgr.api.routes import router from ahcgr.pipeline.p1b_entity import EntityIndex from ahcgr.services.embedding import EmbeddingService from ahcgr.services.llm import LLMService from ahcgr.services.qdrant_client import QdrantService from ahcgr.services.reranker import RerankerService from ahcgr.utils.logging import setup_logging logger = structlog.get_logger("ahcgr.api.server") @asynccontextmanager async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]: """ Application lifespan: initialize shared services, then close them cleanly. """ setup_logging() logger.info("startup_begin", app=__app_name__, version=__version__) qdrant = QdrantService() embedding = EmbeddingService() llm = LLMService() reranker = RerankerService() entity_index = EntityIndex() entity_index.build_from_qdrant(qdrant) app.state.qdrant = qdrant app.state.embedding = embedding app.state.llm = llm app.state.reranker = reranker app.state.entity_index = entity_index health = qdrant.health_check() logger.info("qdrant_health", **health) logger.info( "startup_complete", services=["qdrant", "embedding", "llm", "reranker", "entity_index"], entity_acts=entity_index.act_count, ) yield logger.info("shutdown_begin") qdrant.close() logger.info("shutdown_complete") def create_app() -> FastAPI: """ Build the FastAPI application. """ app = FastAPI( title=__app_name__, version=__version__, description=( "AHCGR - Adaptive Hierarchical Confidence-Guided Retrieval. " "A 7-phase Indian legal inference engine with hybrid search, " "RAPTOR tree traversal, and multi-gate quality evaluation." ), lifespan=lifespan, ) app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) app.add_middleware(RequestLoggingMiddleware) app.include_router(router, prefix="/api/v1") return app