Spaces:
Running
Running
| """ | |
| RetailTalk — FastAPI Backend Entry Point | |
| This is the main file that starts the API server. | |
| Run with: uvicorn main:app --reload | |
| """ | |
| from fastapi import FastAPI | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from contextlib import asynccontextmanager | |
| from config import APP_NAME, DEBUG | |
| from database import close_db_pool | |
| from routes import auth, products, search, transactions, admin, insights, contacts, cart, delivery, manager, restock, wishlist | |
| async def lifespan(app: FastAPI): | |
| """Startup and shutdown events.""" | |
| # --- Startup --- | |
| print(f"[START] Starting {APP_NAME} backend...") | |
| # Load ML models | |
| from models.bert_service import bert_service | |
| from models.classifier import classifier_service | |
| from models.ranker import ranker_service | |
| from models.intent_service import intent_service | |
| from models.slot_service import slot_service | |
| from models.query_rewriter import query_rewriter | |
| print("[ML] Loading BERT model...") | |
| bert_service.load() | |
| print("[ML] Loading classifier model...") | |
| classifier_service.load() | |
| print("[ML] Loading ranker model (optional)...") | |
| ranker_service.load() | |
| print("[ML] Loading intent classifier (optional)...") | |
| intent_service.load() | |
| print("[ML] Loading slot extractor (optional)...") | |
| slot_service.load() | |
| # Initialize query rewriter with loaded services | |
| query_rewriter.init(intent_service, slot_service) | |
| print("[ML] Query rewriter initialized") | |
| print(f"[OK] {APP_NAME} backend ready!") | |
| yield | |
| # --- Shutdown --- | |
| print("[STOP] Shutting down...") | |
| close_db_pool() | |
| # Create FastAPI app | |
| app = FastAPI( | |
| title=f"{APP_NAME} API", | |
| description=( | |
| "An NLP for querying e-commerce product. " | |
| "Uses BERT embeddings + CrossEncoder ranking + QueryProductClassifier to " | |
| "find, rank, and classify product search results " | |
| "as Exact / Substitute / Complement / Irrelevant." | |
| ), | |
| version="1.0.0", | |
| lifespan=lifespan, | |
| ) | |
| # CORS — allow frontend to call the API | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # Register route groups | |
| app.include_router(auth.router) | |
| app.include_router(products.router) | |
| app.include_router(search.router) | |
| app.include_router(transactions.router) | |
| app.include_router(admin.router) | |
| app.include_router(insights.router) | |
| app.include_router(contacts.router) | |
| app.include_router(cart.router) | |
| app.include_router(delivery.router) | |
| app.include_router(manager.router) | |
| app.include_router(restock.router) | |
| app.include_router(wishlist.router) | |
| async def root(): | |
| """Health check endpoint.""" | |
| import os | |
| from models.bert_service import bert_service | |
| from models.classifier import classifier_service | |
| from models.ranker import ranker_service | |
| from models.intent_service import intent_service | |
| from models.slot_service import slot_service | |
| return { | |
| "app": APP_NAME, | |
| "status": "running", | |
| "ml_status": { | |
| "bert": "loaded" if bert_service._loaded else "not loaded", | |
| "classifier": "loaded" if classifier_service._loaded else "not loaded", | |
| "ranker": "loaded" if ranker_service._loaded else "not loaded", | |
| "intent": "loaded" if intent_service._loaded else "not loaded", | |
| "slot": "loaded" if slot_service._loaded else "not loaded", | |
| }, | |
| "env_check": { | |
| "SUPABASE_URL": "set" if os.environ.get("SUPABASE_URL") else "MISSING", | |
| "SUPABASE_KEY": "set" if os.environ.get("SUPABASE_KEY") else "MISSING", | |
| "DATABASE_URL": "set" if os.environ.get("DATABASE_URL") else "MISSING", | |
| "JWT_SECRET": "set" if os.environ.get("JWT_SECRET") else "MISSING", | |
| }, | |
| } | |