| """FastAPI application factory and core infrastructure.""" |
|
|
| import asyncio |
| import warnings |
| from contextlib import asynccontextmanager |
| from typing import AsyncGenerator |
|
|
| from fastapi import FastAPI |
| from pydantic import Field |
| from pydantic_settings import BaseSettings |
|
|
| from app.core.logging import logger |
| from app.core.dependencies import set_inference_service |
| from app.services.inference import ResNetInferenceService |
| from app.api.routes import prediction |
|
|
|
|
| class Settings(BaseSettings): |
| """Application settings. Override via environment variables or .env file.""" |
|
|
| app_name: str = Field(default="ML Inference Service") |
| app_version: str = Field(default="0.1.0") |
| debug: bool = Field(default=False) |
| host: str = Field(default="0.0.0.0") |
| port: int = Field(default=8000) |
|
|
| class Config: |
| env_file = ".env" |
|
|
|
|
| settings = Settings() |
|
|
|
|
| @asynccontextmanager |
| async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]: |
| """Application lifecycle: startup/shutdown.""" |
| logger.info("Starting ML Inference Service...") |
|
|
| try: |
| with warnings.catch_warnings(): |
| warnings.filterwarnings("ignore", category=FutureWarning) |
|
|
| |
| service = ResNetInferenceService(model_name="microsoft/resnet-18") |
| await asyncio.to_thread(service.load_model) |
| set_inference_service(service) |
|
|
| logger.info("Startup completed successfully") |
|
|
| except Exception as e: |
| logger.error(f"Startup failed: {e}") |
| raise |
|
|
| yield |
|
|
| logger.info("Shutting down...") |
|
|
|
|
| def create_app() -> FastAPI: |
| """Create and configure FastAPI application.""" |
| app = FastAPI( |
| title=settings.app_name, |
| description="ML inference service for image classification", |
| version=settings.app_version, |
| debug=settings.debug, |
| lifespan=lifespan |
| ) |
|
|
| app.include_router(prediction.router) |
|
|
| return app |
|
|