QuantIQ / backend /app /main.py
Karan6124's picture
feat: implement weekly MLOps retraining loop and specialized multi-model router
432f713
Raw
History Blame Contribute Delete
4.73 kB
import os
import uuid
from typing import Optional
from fastapi import FastAPI, Depends, Header
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy.ext.asyncio import AsyncSession
from strawberry.fastapi import GraphQLRouter
from huggingface_hub import hf_hub_download
from prometheus_fastapi_instrumentator import Instrumentator
from backend.app.config.settings import settings
from backend.app.database.session import get_db
from backend.app.database import crud
from backend.app.graphql.schema import schema
from backend.app.api.endpoints import router as api_router, decode_access_token
from backend.app.services.gemini import init_onnx_session
app= FastAPI(
title= settings.PROJECT_NAME,
description= "Real-time event-driven stock intelligence dashboard backend.",
version="1.0.0"
)
app.add_middleware(
CORSMiddleware,
allow_origins= ["http://localhost:5173", "http://127.0.0.1:5173", "*"],
allow_credentials= True,
allow_methods= ["*"],
allow_headers= ["*"],
)
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from fastapi import HTTPException, status, Response
from prometheus_client import generate_latest, CONTENT_TYPE_LATEST
import secrets
security = HTTPBasic()
def authenticate_metrics(credentials: HTTPBasicCredentials = Depends(security)):
correct_username = secrets.compare_digest(credentials.username, "admin")
correct_password = secrets.compare_digest(credentials.password, "admin")
if not (correct_username and correct_password):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Basic"},
)
return credentials.username
# Instrument FastAPI
Instrumentator().instrument(app)
@app.get("/metrics")
async def metrics(username: str = Depends(authenticate_metrics)):
return Response(content=generate_latest(), media_type=CONTENT_TYPE_LATEST)
@app.on_event("startup")
async def startup_event():
repo_id = os.getenv("HF_MODEL_REPO", "Karan6124/quantiq-model")
model_types = ["tech", "crypto", "index"]
print(f"Starting application: checking for ONNX models...")
for m_type in model_types:
filename = f"model_{m_type}.onnx"
try:
local_path = filename
if os.path.exists(local_path):
print(f"Using local model found at {local_path} for '{m_type}'")
init_onnx_session(local_path, m_type)
else:
print(f"Downloading model '{filename}' from Hugging Face Hub: {repo_id}...")
model_path = hf_hub_download(repo_id=repo_id, filename=filename)
init_onnx_session(model_path, m_type)
except Exception as e:
print(f"Could not load specialized model '{filename}' from HF Hub: {e}")
# Try to fall back to general model.onnx
fallback_filename = "model.onnx"
try:
if os.path.exists(fallback_filename):
print(f"Falling back to local {fallback_filename} for '{m_type}'")
init_onnx_session(fallback_filename, m_type)
else:
print(f"Downloading fallback model.onnx from HF Hub for '{m_type}'...")
model_path = hf_hub_download(repo_id=repo_id, filename=fallback_filename)
init_onnx_session(model_path, m_type)
except Exception as fb_err:
print(f"Error loading fallback model for '{m_type}': {fb_err}")
# Custom GraphQL Context Getter to inject AsyncSession and User from JWT
async def get_graphql_context(db: AsyncSession= Depends(get_db), authorization: Optional[str]= Header(None)):
context= {"db": db, "user": None}
if authorization and authorization.startswith("Bearer "):
token= authorization.split(" ")[1]
payload= decode_access_token(token)
if payload and "sub" in payload:
try:
user_id= uuid.UUID(payload["sub"])
user= await crud.get_user(db, user_id)
if user:
context["user"]= user
except ValueError:
pass
return context
# Create and mount Strawberry GraphQL Router
graphql_router= GraphQLRouter(
schema,
context_getter= get_graphql_context
)
app.include_router(api_router, prefix= settings.API_V1_STR)
app.include_router(graphql_router, prefix= "/graphql")
@app.get("/")
async def root():
return {
"status": "healthy",
"project": settings.PROJECT_NAME,
"graphql_endpoint": "/graphql",
"api_v1_endpoint": settings.API_V1_STR
}