Spaces:
Sleeping
Sleeping
| from fastapi import FastAPI, UploadFile, File | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.responses import JSONResponse | |
| # Import both services | |
| try: | |
| from split import ( | |
| app as ingestion_app, | |
| ingest_pdf, | |
| get_stats as get_ingestion_stats | |
| ) | |
| print("β Loaded ingestion service (split.py)") | |
| except Exception as e: | |
| print(f"β οΈ Warning: Could not load ingestion service: {e}") | |
| ingestion_app = None | |
| try: | |
| from query_service import ( | |
| app as query_app, | |
| query_rag, | |
| query_with_details, | |
| get_stats as get_query_stats | |
| ) | |
| print("β Loaded query service (query_service.py)") | |
| except Exception as e: | |
| print(f"β οΈ Warning: Could not load query service: {e}") | |
| query_app = None | |
| # Create main application | |
| app = FastAPI( | |
| title="π Multimodal RAG - Combined Service", | |
| description="Unified service for PDF ingestion and multimodal querying", | |
| version="1.0.0", | |
| docs_url="/docs", | |
| redoc_url="/redoc" | |
| ) | |
| # Add CORS middleware | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # ==================== HOME & HEALTH ENDPOINTS ==================== | |
| async def home(): | |
| """Main endpoint with service information""" | |
| return { | |
| "message": "β Multimodal RAG Service is running", | |
| "status": "healthy", | |
| "services": { | |
| "ingestion": "available" if ingestion_app else "unavailable", | |
| "query": "available" if query_app else "unavailable" | |
| }, | |
| "endpoints": { | |
| "ingestion": { | |
| "ingest_pdf": "POST /ingest", | |
| "ingestion_stats": "GET /ingest/stats" | |
| }, | |
| "query": { | |
| "query": "POST /query?question=YOUR_QUESTION&k=5", | |
| "query_detailed": "POST /query/details?question=YOUR_QUESTION&k=5", | |
| "query_stats": "GET /query/stats" | |
| }, | |
| "documentation": { | |
| "swagger": "/docs", | |
| "redoc": "/redoc" | |
| } | |
| }, | |
| "features": [ | |
| "PDF text extraction", | |
| "Table extraction", | |
| "Image extraction", | |
| "Multimodal summarization", | |
| "Vector similarity search", | |
| "Context-aware answering" | |
| ] | |
| } | |
| async def health_check(): | |
| """Health check endpoint""" | |
| return { | |
| "status": "healthy", | |
| "services": { | |
| "ingestion": ingestion_app is not None, | |
| "query": query_app is not None | |
| } | |
| } | |
| # ==================== INGESTION ENDPOINTS ==================== | |
| async def ingest_document(file: UploadFile = File(...)): | |
| """ | |
| Upload and ingest a PDF document | |
| This endpoint processes PDFs and extracts: | |
| - Text content | |
| - Tables | |
| - Images | |
| All content is summarized and stored in the vectorstore. | |
| """ | |
| if ingestion_app is None: | |
| return JSONResponse( | |
| status_code=503, | |
| content={"error": "Ingestion service not available"} | |
| ) | |
| return await ingest_pdf(file) | |
| async def ingestion_stats(): | |
| """Get ingestion service statistics""" | |
| if ingestion_app is None: | |
| return JSONResponse( | |
| status_code=503, | |
| content={"error": "Ingestion service not available"} | |
| ) | |
| return get_ingestion_stats() | |
| # ==================== QUERY ENDPOINTS ==================== | |
| async def query_documents(question: str, k: int = 5): | |
| """ | |
| Query the RAG system | |
| Args: | |
| question: The question to ask | |
| k: Number of documents to retrieve (default: 5) | |
| Returns: | |
| Answer based on retrieved documents | |
| """ | |
| if query_app is None: | |
| return JSONResponse( | |
| status_code=503, | |
| content={"error": "Query service not available"} | |
| ) | |
| return await query_rag(question, k) | |
| async def query_documents_detailed(question: str, k: int = 5): | |
| """ | |
| Query with detailed document information | |
| Args: | |
| question: The question to ask | |
| k: Number of documents to retrieve (default: 5) | |
| Returns: | |
| Answer with detailed information about retrieved documents | |
| """ | |
| if query_app is None: | |
| return JSONResponse( | |
| status_code=503, | |
| content={"error": "Query service not available"} | |
| ) | |
| return await query_with_details(question, k) | |
| async def query_stats(): | |
| """Get query service statistics""" | |
| if query_app is None: | |
| return JSONResponse( | |
| status_code=503, | |
| content={"error": "Query service not available"} | |
| ) | |
| return get_query_stats() | |
| # ==================== COMBINED STATS ENDPOINT ==================== | |
| async def combined_stats(): | |
| """Get combined statistics from both services""" | |
| stats = { | |
| "service": "combined", | |
| "status": "healthy" | |
| } | |
| try: | |
| if query_app: | |
| query_stats_data = get_query_stats() | |
| stats["vectorstore"] = query_stats_data | |
| except Exception as e: | |
| stats["vectorstore_error"] = str(e) | |
| return stats | |
| async def startup_event(): | |
| """Run on application startup""" | |
| print("\n" + "="*50) | |
| print("π Multimodal RAG Service Starting...") | |
| print("="*50) | |
| if ingestion_app: | |
| print("β Ingestion service: READY") | |
| else: | |
| print("β οΈ Ingestion service: NOT LOADED") | |
| if query_app: | |
| print("β Query service: READY") | |
| else: | |
| print("β οΈ Query service: NOT LOADED") | |
| print("="*50) | |
| print("π‘ Service available at: http://0.0.0.0:7860") | |
| print("π API Documentation: http://0.0.0.0:7860/docs") | |
| print("="*50 + "\n") | |
| if __name__ == "__main__": | |
| import uvicorn | |
| uvicorn.run(app, host="0.0.0.0", port=7860) |