from dotenv import load_dotenv load_dotenv() import logging logging.basicConfig( level=logging.INFO, format="%(asctime)s [%(levelname)s] %(name)s — %(message)s", datefmt="%H:%M:%S", ) from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from contextlib import asynccontextmanager from routers import yolo, clip, flow, pinecone from services.yolo_service import YoloService from services.clip_service import ClipService from services.vision_service import VisionService from services.pinecone_service import PineconeService # Global service instances yolo_service = YoloService() clip_service = ClipService() vision_service = VisionService() pinecone_service = PineconeService() @asynccontextmanager async def lifespan(app: FastAPI): # Load models on startup print("Loading models...") await yolo_service.load_model() await clip_service.load_model() print("✅ All models ready") yield print("Shutting down...") app = FastAPI( title="Fashion AI – ML Service", description="CLIP + YOLO inference service for fashion detection and vector generation", version="1.0.0", lifespan=lifespan, ) app.add_middleware( CORSMiddleware, allow_origins=["*"], # tighten to your Vercel domain in production if needed allow_credentials=False, allow_methods=["*"], allow_headers=["*"], ) # Pass services to routers app.state.yolo_service = yolo_service app.state.clip_service = clip_service app.state.vision_service = vision_service app.state.pinecone_service = pinecone_service app.include_router(yolo.router, prefix="/yolo", tags=["YOLO – Fashion Detection"]) app.include_router(clip.router, prefix="/clip", tags=["CLIP – Vector Generation"]) app.include_router(flow.router, prefix="/flow", tags=["Flow – End-to-End"]) app.include_router(pinecone.router, prefix="/pinecone", tags=["Pinecone"]) @app.get("/health") def health(): return { "status": "ok" }