hitenvk22/FinStream-API
0
1from contextlib import asynccontextmanager2import logging3import os4 5from fastapi import FastAPI6from fastapi.middleware.cors import CORSMiddleware7from fastapi.responses import JSONResponse8from starlette.requests import Request9from fastapi.exceptions import RequestValidationError10 11from app.api.routes import router as api_router12from app.services.model_service import SentimentModelManager13 14 15logging.basicConfig(16 level=logging.INFO,17 format="%(asctime)s | %(levelname)s | %(name)s | %(message)s",18)19logger = logging.getLogger("finstream")20 21MODEL_NAME = os.getenv("MODEL_NAME", "hitenvk22/FinStream-Sentiment")22 23 24@asynccontextmanager25async def lifespan(app: FastAPI):26 mm = SentimentModelManager(model_name=MODEL_NAME)27 app.state.model_manager = mm28 await mm.load_async()29 logger.info("Device: %s | Ready: %s", mm.device, mm.is_ready)30 yield31 32 33app = FastAPI(34 title="FinStream Sentiment API",35 version="1.0.0",36 description="GPU-accelerated FinStream sentiment inference on Hugging Face Spaces",37 lifespan=lifespan,38)39 40 41@app.get("/")42async def root():43 mm = getattr(app.state, "model_manager", None)44 return {45 "service": "FinStream Sentiment API",46 "version": "1.0.0",47 "mode": "transformers",48 "status": "running",49 "model": MODEL_NAME,50 "device": mm.device if mm else "unknown",51 "endpoints": {52 "predict": "/predict",53 "analyze_csv": "/analyze-csv",54 "health": "/health",55 },56 }57 58 59app.add_middleware(60 CORSMiddleware,61 allow_origins=["*"],62 allow_credentials=False,63 allow_methods=["*"],64 allow_headers=["*"],65)66 67app.include_router(api_router)68 69 70@app.exception_handler(RequestValidationError)71async def validation_exception_handler(request: Request, exc: RequestValidationError):72 logger.warning("Validation error on %s: %s", request.url.path, exc.errors())73 return JSONResponse(74 status_code=422,75 content={"detail": "Invalid request payload", "errors": exc.errors()},76 )77 78 79@app.exception_handler(Exception)80async def unhandled_exception_handler(request: Request, exc: Exception):81 logger.exception("Unhandled error on %s", request.url.path)82 return JSONResponse(83 status_code=500,84 content={"detail": "Internal server error"},85 )86 