SentinelAI / app /main.py
sajith-0701's picture
initial deployment for HF Spaces
71c1ad2
# app/main.py
# FastAPI application factory β€” entry point for the Hubble AI Engine
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from app.config import get_settings
from app.observability.logging import setup_logging, get_logger
from app.observability.langsmith import setup_langsmith
from app.models.model_registry import model_registry
from app.services.redis_service import redis_service
from app.services.mongo_service import mongo_service
from app.services.gemini_service import gemini_service
from app.pipeline.workflow import get_workflow
from app.api.router import api_router
from app.db.connection import connect_db, close_db
@asynccontextmanager
async def lifespan(app: FastAPI):
"""
Application lifespan manager.
Startup:
1. Configure logging
2. Setup LangSmith tracing
3. Connect MongoDB & Redis
4. Initialize Gemini service
5. Load all ML models
6. Compile LangGraph workflow
Shutdown:
1. Disconnect MongoDB & Redis
"""
logger = get_logger(__name__)
settings = get_settings()
# ── Startup ──
logger.info("=" * 60)
logger.info("[STARTUP] HUBBLE AI ENGINE β€” Starting up...")
logger.info("=" * 60)
# 1. LangSmith
langsmith_ok = setup_langsmith()
logger.info("langsmith", enabled=langsmith_ok)
# 2. MongoDB (legacy motor service + Beanie ODM)
logger.info("connecting_mongodb")
await mongo_service.connect()
await connect_db() # initializes Beanie document models
# 3. Redis
logger.info("connecting_redis")
await redis_service.connect()
# 4. Gemini
logger.info("initializing_gemini")
gemini_service.initialize()
# 5. ML Models
logger.info("loading_models")
model_status = await model_registry.load_all()
logger.info("models_loaded", status=model_status)
# 6. LangGraph Workflow
logger.info("compiling_workflow")
get_workflow()
logger.info("=" * 60)
logger.info("[READY] HUBBLE AI ENGINE β€” Ready!")
logger.info(f" Environment: {settings.env}")
logger.info(f" Port: {settings.port}")
logger.info(f" Docs: http://localhost:{settings.port}/docs")
logger.info("=" * 60)
yield # ── Application runs here ──
# ── Shutdown ──
logger.info("[SHUTDOWN] HUBBLE β€” Shutting down...")
await redis_service.disconnect()
await mongo_service.disconnect()
await close_db()
logger.info("Shutdown complete")
def create_app() -> FastAPI:
"""Create and configure the FastAPI application."""
settings = get_settings()
# Configure logging first
setup_logging()
app = FastAPI(
title="Hubble AI Engine β€” Cyberbullying Detection API",
description=(
"Production-grade content moderation pipeline with layered AI analysis. "
"Supports text, image, and video inputs with risk-based routing."
),
version="4.0.0",
docs_url="/docs",
redoc_url="/redoc",
lifespan=lifespan,
)
# CORS β€” use origins from config
app.add_middleware(
CORSMiddleware,
allow_origins=settings.cors_origins_list if settings.is_production else ["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Mount routes
app.include_router(api_router)
@app.get("/", include_in_schema=False)
async def root():
return JSONResponse({
"name": "Hubble Unified API",
"version": "5.0.0",
"docs": "/docs",
"health": "/health",
"endpoints": {
"auth": "POST /api/v1/auth/{register|login|refresh|logout}",
"users": "GET /api/v1/users/me",
"scan_text": "POST /api/v1/scan/text",
"scan_image": "POST /api/v1/scan/image",
"scan_history": "GET /api/v1/scan/history",
"alerts": "GET /api/v1/alerts",
"analyze_text": "POST /api/v1/analyze/text (raw, no auth)",
"analyze_image": "POST /api/v1/analyze/image (raw, no auth)",
},
})
return app
# Create the app instance
app = create_app()
if __name__ == "__main__":
import uvicorn
settings = get_settings()
uvicorn.run(
"app.main:app",
host=settings.host,
port=settings.port,
reload=not settings.is_production,
)