# """ # FastAPI Main Application Entry Point # Banking RAG Chatbot API with JWT Authentication # This file: # 1. Creates the FastAPI app # 2. Configures CORS middleware # 3. Connects to MongoDB on startup/shutdown # 4. Includes API routers (auth + chat) # 5. Provides health check endpoints # """ # from fastapi import FastAPI, Request # from fastapi.middleware.cors import CORSMiddleware # from fastapi.responses import JSONResponse # from contextlib import asynccontextmanager # from app.config import settings # from app.db.mongodb import connect_to_mongo, close_mongo_connection # # ============================================================================ # # LIFESPAN MANAGER (Startup & Shutdown) # # ============================================================================ # @asynccontextmanager # async def lifespan(app: FastAPI): # """ # Manage application lifespan events. # Startup: # - Connect to MongoDB Atlas # - ML models load lazily on first use # Shutdown: # - Close MongoDB connection # - Cleanup resources # """ # # ======================================================================== # # STARTUP # # ======================================================================== # print("\n" + "=" * 80) # print("šŸš€ STARTING BANKING RAG CHATBOT API") # print("=" * 80) # print(f"Environment: {settings.ENVIRONMENT}") # print(f"Debug Mode: {settings.DEBUG}") # print("=" * 80) # # Connect to MongoDB # await connect_to_mongo() # print("\nšŸ’” ML Models Info:") # print(" Policy Network: Loads on first chat request (lazy loading)") # print(" Retriever Model: Loads on first retrieval (lazy loading)") # print(" LLM: Groq (ChatGroq) with HuggingFace fallback") # print("\nšŸ¤– LLM Configuration:") # print(f" Chat Model: {settings.GROQ_CHAT_MODEL} (Llama 3 8B)") # print(f" Eval Model: {settings.GROQ_EVAL_MODEL} (Llama 3 70B)") # print(f" Groq API Keys: {len(settings.get_groq_api_keys())} configured") # print(f" HuggingFace Tokens: {len(settings.get_hf_tokens())} configured") # print(f" Fallback: Groq → HuggingFace") # print("\nāœ… Backend startup complete!") # print("=" * 80) # print(f"šŸ“– API Docs: https://eeshanyaj-questrag-backend.hf.space/docs") # print(f"šŸ„ Health Check: https://eeshanyaj-questrag-backend.hf.space/health") # print(f"🧠 Backend Link: https://eeshanyaj-questrag-backend.hf.space/") # # print(f"šŸ”‘ Login: POST http://localhost:8000/api/v1/auth/login") # print("=" * 80 + "\n") # yield # Application runs here # # ======================================================================== # # SHUTDOWN # # ======================================================================== # print("\n" + "=" * 80) # print("šŸ›‘ SHUTTING DOWN API") # print("=" * 80) # # Close MongoDB connection # await close_mongo_connection() # print("āœ… Shutdown complete") # print("=" * 80 + "\n") # # ============================================================================ # # CREATE FASTAPI APPLICATION # # ============================================================================ # app = FastAPI( # title="Banking RAG Chatbot API", # description=""" # šŸ¤– AI-powered Banking Assistant with: # **Features:** # - šŸ” JWT Authentication (Sign up, Login, Protected routes) # - šŸ’¬ RAG (Retrieval-Augmented Generation) # - 🧠 RL-based Policy Network (BERT) # - šŸ” Custom E5 Retriever # - ⚔ Groq LLM with HuggingFace Fallback (Llama 3 models) # **Capabilities:** # - Intelligent document retrieval # - Context-aware responses # - Conversation history # - Real-time chat # - User authentication & authorization # - Multi-provider LLM with automatic fallback # """, # version="1.0.0", # docs_url="/docs", # redoc_url="/redoc", # lifespan=lifespan # ) # # ============================================================================ # # CORS MIDDLEWARE # # ============================================================================ # allowed_origins = settings.get_allowed_origins() # print("\n🌐 CORS Configuration:") # print(f" Allowed Origins: {allowed_origins}") # app.add_middleware( # CORSMiddleware, # allow_origins=allowed_origins, # allow_credentials=True, # allow_methods=["*"], # allow_headers=["*"], # ) # # ============================================================================ # # INCLUDE API ROUTERS # # ============================================================================ # from app.api.v1 import chat, auth # # Auth router (public endpoints - register, login) # app.include_router( # auth.router, # prefix="/api/v1/auth", # tags=["šŸ” Authentication"] # ) # # Chat router (protected endpoints - requires JWT token) # app.include_router( # chat.router, # prefix="/api/v1/chat", # tags=["šŸ’¬ Chat"] # ) # # ============================================================================ # # ROOT ENDPOINTS # # ============================================================================ # @app.get("/", tags=["šŸ“ Root"]) # async def root(): # """ # Root endpoint - API information and available endpoints # """ # return { # "message": "Banking RAG Chatbot API with Authentication", # "version": "1.0.0", # "status": "online", # "authentication": "JWT Bearer Token Required for chat endpoints", # "llm_provider": "Groq (ChatGroq) with HuggingFace fallback", # "models": { # "chat": settings.GROQ_CHAT_MODEL, # "evaluation": settings.GROQ_EVAL_MODEL # }, # "documentation": { # "swagger_ui": "/docs", # "redoc": "/redoc" # }, # "endpoints": { # "auth": { # "register": "POST /api/v1/auth/register", # "login": "POST /api/v1/auth/login", # "me": "GET /api/v1/auth/me (requires token)", # "logout": "POST /api/v1/auth/logout (requires token)" # }, # "chat": { # "send_message": "POST /api/v1/chat/ (requires token)", # "get_history": "GET /api/v1/chat/history/{conversation_id} (requires token)", # "list_conversations": "GET /api/v1/chat/conversations (requires token)", # "delete_conversation": "DELETE /api/v1/chat/conversation/{conversation_id} (requires token)" # }, # "health": "GET /health" # } # } # @app.get("/health", tags=["šŸ„ Health"]) # async def health_check(): # """ # Comprehensive health check endpoint # Checks status of: # - API service # - MongoDB connection # - ML models (lazy loaded) # - Authentication system # - LLM providers (Groq & HuggingFace) # Returns: # dict: Health status of all components # """ # from app.db.mongodb import get_database # # Check MongoDB # mongodb_status = "connected" if get_database() is not None else "disconnected" # # Check ML models (don't load them, just check readiness) # ml_models_status = { # "policy_network": "ready (lazy load)", # "retriever": "ready (lazy load)", # "llm": "ready (API-based)" # } # # Check LLM providers # llm_providers = { # "groq": { # "enabled": settings.is_groq_enabled(), # "api_keys_configured": len(settings.get_groq_api_keys()), # "chat_model": settings.GROQ_CHAT_MODEL, # "eval_model": settings.GROQ_EVAL_MODEL # }, # "huggingface": { # "enabled": settings.is_hf_enabled(), # "tokens_configured": len(settings.get_hf_tokens()), # "chat_model": settings.HF_CHAT_MODEL, # "eval_model": settings.HF_EVAL_MODEL # } # } # # Check authentication # auth_status = { # "jwt_enabled": bool(settings.SECRET_KEY and settings.SECRET_KEY != "your-secret-key-change-in-production"), # "algorithm": settings.ALGORITHM, # "token_expiry_minutes": settings.ACCESS_TOKEN_EXPIRE_MINUTES # } # # Overall health # is_healthy = ( # mongodb_status == "connected" and # auth_status["jwt_enabled"] and # (llm_providers["groq"]["enabled"] or llm_providers["huggingface"]["enabled"]) # ) # return { # "status": "healthy" if is_healthy else "degraded", # "api": "online", # "mongodb": mongodb_status, # "authentication": auth_status, # "llm_providers": llm_providers, # "ml_models": ml_models_status, # "environment": settings.ENVIRONMENT, # "debug_mode": settings.DEBUG # } # # ============================================================================ # # GLOBAL EXCEPTION HANDLER # # ============================================================================ # @app.exception_handler(Exception) # async def global_exception_handler(request: Request, exc: Exception): # """ # Global exception handler for unhandled errors # """ # print(f"\nāŒ Unhandled Exception:") # print(f" Path: {request.url.path}") # print(f" Error: {str(exc)}") # if settings.DEBUG: # import traceback # traceback.print_exc() # return JSONResponse( # status_code=500, # content={ # "error": "Internal Server Error", # "detail": str(exc) if settings.DEBUG else "An unexpected error occurred", # "path": str(request.url.path) # } # ) # # ============================================================================ # # MAIN ENTRY POINT (for direct execution) # # ============================================================================ # if __name__ == "__main__": # import uvicorn # print("\nšŸš€ Starting server directly...") # print(" Note: For production, use: uvicorn app.main:app --host 0.0.0.0 --port 8000") # uvicorn.run( # "app.main:app", # host="0.0.0.0", # port=8000, # reload=settings.DEBUG # Auto-reload only in debug mode # )