import logging from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles from fastapi.responses import FileResponse from pydantic import BaseModel import os from hadith_mcp import search_hadith # Configure logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # Pre-download the model during server boot so the first request doesn't timeout try: logger.info("Pre-downloading HF model during boot...") from sentence_transformers import SentenceTransformer SentenceTransformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2') logger.info("Model ready!") except Exception as e: logger.warning(f"Could not pre-download model: {e}") app = FastAPI(title="Hadith Search API") # Allow CORS for HuggingFace Spaces app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) class SearchRequest(BaseModel): query: str top_k: int = 5 @app.post("/api/search") async def search_hadith_endpoint(req: SearchRequest): """API Endpoint to perform hybrid search on Hadiths.""" if not req.query or not req.query.strip(): raise HTTPException(status_code=400, detail="Query cannot be empty") try: # search_hadith is an async function returning a dict result = await search_hadith(req.query.strip(), top_k=req.top_k) if result.get("error"): raise HTTPException(status_code=500, detail=result["error"]) return {"results": result.get("hadiths", [])} except Exception as e: logger.error(f"Search API Error: {e}") raise HTTPException(status_code=500, detail=str(e)) # Base directory base_dir = os.path.dirname(__file__) # Mount assets folder assets_dir = os.path.join(base_dir, "assets") if os.path.isdir(assets_dir): app.mount("/assets", StaticFiles(directory=assets_dir), name="assets") # Serve index.html at root @app.get("/{full_path:path}") async def serve_frontend(full_path: str): if full_path.startswith("api/"): raise HTTPException(status_code=404, detail="API route not found") path_to_file = os.path.join(base_dir, full_path) if os.path.isfile(path_to_file): return FileResponse(path_to_file) return FileResponse(os.path.join(base_dir, "index.html")) # HF Spaces automatically runs uvicorn app:app if Gradio is selected if __name__ == "__main__": import uvicorn uvicorn.run("app:app", host="0.0.0.0", port=7860, reload=False)