Spaces:
Running
Running
| [1mdiff --git a/app.py b/app.py[m | |
| [1mindex 58d2706..20c00eb 100644[m | |
| [1m--- a/app.py[m | |
| [1m+++ b/app.py[m | |
| [36m@@ -1,52 +1,173 @@[m | |
| import os[m | |
| import sys[m | |
| [32m+[m[32mfrom pathlib import Path[m | |
| [32m+[m[32mfrom fastapi import FastAPI, HTTPException[m | |
| [32m+[m[32mfrom fastapi.staticfiles import StaticFiles[m | |
| [32m+[m[32mfrom fastapi.responses import FileResponse, JSONResponse[m | |
| [32m+[m[32mfrom fastapi.middleware.cors import CORSMiddleware[m | |
| [m | |
| [31m-# Set environment variables for Hugging Face[m | |
| [31m-os.environ["TRANSFORMERS_CACHE"] = "/tmp/model_cache"[m | |
| [31m-os.environ["HF_HOME"] = "/tmp/model_cache"[m | |
| [31m-os.environ["SENTENCE_TRANSFORMERS_HOME"] = "/tmp/model_cache"[m | |
| [31m-os.environ["PYTHONUNBUFFERED"] = "1"[m | |
| [31m-[m | |
| [31m-# Print startup diagnostic info[m | |
| [32m+[m[32mprint("=" * 60)[m | |
| print("=== STARTUP: Beginning application initialization ===")[m | |
| [31m-print(f"=== STARTUP: PORT environment variable: {os.environ.get('PORT')} ===")[m | |
| [32m+[m[32mprint("=" * 60)[m | |
| [m | |
| [31m-# First import just the app from main[m | |
| [31m-from main import app[m | |
| [32m+[m[32m# Add current directory to Python path so imports work[m | |
| [32m+[m[32mcurrent_path = os.path.dirname(__file__)[m | |
| [32m+[m[32mif current_path not in sys.path:[m | |
| [32m+[m[32m sys.path.insert(0, current_path)[m | |
| [m | |
| [31m-# THEN import other components[m | |
| [31m-from main import conversation_memory[m | |
| [31m-from data_integration.alu_api_connector import ALUDataConnector[m | |
| [31m-from analytics.conversation_analytics import ConversationAnalytics[m | |
| [32m+[m[32m# Ensure required directories exist[m | |
| [32m+[m[32mos.makedirs("build/static", exist_ok=True)[m | |
| [32m+[m[32mos.makedirs("build/assets", exist_ok=True)[m | |
| [m | |
| [31m-@app.get("/api/alu-events")[m | |
| [31m-async def get_alu_events(campus: str = "all", days: int = 7):[m | |
| [31m- """Get upcoming events at ALU"""[m | |
| [32m+[m[32m# Load comprehensive knowledge base on startup[m | |
| [32m+[m[32mdef load_comprehensive_knowledge_base():[m | |
| [32m+[m[32m """Load the comprehensive ALU knowledge base into vector store"""[m | |
| try:[m | |
| [31m- alu_connector = ALUDataConnector()[m | |
| [31m- events = alu_connector.get_upcoming_events(campus, days)[m | |
| [31m- return {"events": events}[m | |
| [32m+[m[32m print("\nπ Loading comprehensive ALU knowledge base...")[m | |
| [32m+[m[32m from retrieval_engine import RetrievalEngine[m | |
| [32m+[m[41m [m | |
| [32m+[m[32m # Check for knowledge base files[m | |
| [32m+[m[32m kb_paths = [[m | |
| [32m+[m[32m Path("data/alu_knowledge"),[m | |
| [32m+[m[32m Path("backend/data/alu_knowledge"),[m | |
| [32m+[m[32m Path("/data/alu_knowledge")[m | |
| [32m+[m[32m ][m | |
| [32m+[m[41m [m | |
| [32m+[m[32m kb_dir = None[m | |
| [32m+[m[32m for path in kb_paths:[m | |
| [32m+[m[32m if path.exists():[m | |
| [32m+[m[32m kb_dir = path[m | |
| [32m+[m[32m break[m | |
| [32m+[m[41m [m | |
| [32m+[m[32m if not kb_dir:[m | |
| [32m+[m[32m print("β οΈ Knowledge base directory not found. Using default ALU Brain.")[m | |
| [32m+[m[32m return False[m | |
| [32m+[m[41m [m | |
| [32m+[m[32m # Find knowledge base file[m | |
| [32m+[m[32m kb_files = [[m | |
| [32m+[m[32m "alu_ultimate_knowledge_base.txt",[m | |
| [32m+[m[32m "alu_knowledge_base.txt"[m | |
| [32m+[m[32m ][m | |
| [32m+[m[41m [m | |
| [32m+[m[32m kb_file = None[m | |
| [32m+[m[32m for filename in kb_files:[m | |
| [32m+[m[32m file_path = kb_dir / filename[m | |
| [32m+[m[32m if file_path.exists():[m | |
| [32m+[m[32m kb_file = file_path[m | |
| [32m+[m[32m break[m | |
| [32m+[m[41m [m | |
| [32m+[m[32m if not kb_file:[m | |
| [32m+[m[32m print("β οΈ Knowledge base file not found. Using default ALU Brain.")[m | |
| [32m+[m[32m return False[m | |
| [32m+[m[41m [m | |
| [32m+[m[32m print(f"π Found knowledge base: {kb_file.name}")[m | |
| [32m+[m[41m [m | |
| [32m+[m[32m # Load and process[m | |
| [32m+[m[32m with open(kb_file, 'r', encoding='utf-8') as f:[m | |
| [32m+[m[32m kb_text = f.read()[m | |
| [32m+[m[41m [m | |
| [32m+[m[32m print(f"β Loaded {len(kb_text):,} characters")[m | |
| [32m+[m[41m [m | |
| [32m+[m[32m # Initialize retrieval engine[m | |
| [32m+[m[32m retrieval_engine = RetrievalEngine()[m | |
| [32m+[m[41m [m | |
| [32m+[m[32m # Chunk text[m | |
| [32m+[m[32m chunks = retrieval_engine._chunk_text(kb_text, chunk_size=800, chunk_overlap=100)[m | |
| [32m+[m[32m print(f"β Created {len(chunks)} chunks")[m | |
| [32m+[m[41m [m | |
| [32m+[m[32m # Add to vector store[m | |
| [32m+[m[32m print("π₯ Adding to vector store...")[m | |
| [32m+[m[32m for i, chunk in enumerate(chunks):[m | |
| [32m+[m[32m chunk_id = f"alu_comprehensive_kb_{i}"[m | |
| [32m+[m[32m metadata = {[m | |
| [32m+[m[32m "source": "ALU Comprehensive Knowledge Base 2024",[m | |
| [32m+[m[32m "chunk_id": i,[m | |
| [32m+[m[32m "type": "comprehensive_kb"[m | |
| [32m+[m[32m }[m | |
| [32m+[m[41m [m | |
| [32m+[m[32m try:[m | |
| [32m+[m[32m retrieval_engine.collection.add([m | |
| [32m+[m[32m ids=[chunk_id],[m | |
| [32m+[m[32m documents=[chunk],[m | |
| [32m+[m[32m metadatas=[metadata][m | |
| [32m+[m[32m )[m | |
| [32m+[m[32m except Exception as e:[m | |
| [32m+[m[32m if i == 0: # Only print error for first chunk[m | |
| [32m+[m[32m print(f"β οΈ Note: {e}")[m | |
| [32m+[m[41m [m | |
| [32m+[m[32m print(f"β Comprehensive knowledge base loaded! ({len(chunks)} chunks)")[m | |
| [32m+[m[32m return True[m | |
| [32m+[m[41m [m | |
| except Exception as e:[m | |
| [31m- print(f"Error fetching ALU events: {e}")[m | |
| [31m- return {"events": [], "error": "Could not fetch events"}[m | |
| [32m+[m[32m print(f"β οΈ Error loading comprehensive KB: {e}")[m | |
| [32m+[m[32m return False[m | |
| [32m+[m | |
| [32m+[m[32m# Load knowledge base (commented out to prevent startup timeout)[m | |
| [32m+[m[32m# Uncomment this line once the Space is stable:[m | |
| [32m+[m[32m# load_comprehensive_knowledge_base()[m | |
| [32m+[m[32mprint("β οΈ Comprehensive KB loading disabled to prevent timeout")[m | |
| [32m+[m[32mprint("π‘ The chatbot will use the existing ALU Brain knowledge base")[m | |
| [m | |
| [31m-@app.get("/api/analytics/dashboard")[m | |
| [31m-async def get_analytics_dashboard():[m | |
| [31m- """Get analytics dashboard data"""[m | |
| [32m+[m[32m# Import your backend app (using minimal version to avoid model loading issues)[m | |
| [32m+[m[32mprint("\nπ¦ Importing minimal backend application...")[m | |
| [32m+[m[32mtry:[m | |
| [32m+[m[32m from minimal_app import app as backend_app[m | |
| [32m+[m[32m print("β Minimal backend application imported (no ML models required)")[m | |
| [32m+[m[32mexcept ImportError:[m | |
| [32m+[m[32m print("β οΈ Minimal backend not found, trying lightweight...")[m | |
| try:[m | |
| [31m- if not conversation_memory:[m | |
| [31m- return {"error": "Conversation memory not initialized"}[m | |
| [31m- [m | |
| [31m- analytics = ConversationAnalytics(conversation_memory)[m | |
| [31m- dashboard_data = analytics.generate_dashboard_data()[m | |
| [31m- return dashboard_data[m | |
| [31m- except Exception as e:[m | |
| [31m- print(f"Error generating analytics dashboard: {e}")[m | |
| [31m- return {"error": f"Could not generate analytics: {str(e)}"}[m | |
| [31m-[m | |
| [31m-# This is needed for Hugging Face Spaces[m | |
| [31m-if __name__ == "__main__":[m | |
| [31m- import uvicorn[m | |
| [31m- port = int(os.environ.get("PORT", 7860)) # Hugging Face uses port 7860[m | |
| [31m- print(f"Starting server on port {port}")[m | |
| [31m- uvicorn.run(app, host="0.0.0.0", port=port)[m | |
| \ No newline at end of file[m | |
| [32m+[m[32m from main_lightweight import app as backend_app[m | |
| [32m+[m[32m print("β Lightweight backend application imported")[m | |
| [32m+[m[32m except ImportError:[m | |
| [32m+[m[32m print("β οΈ Using main backend...")[m | |
| [32m+[m[32m from main import app as backend_app[m | |
| [32m+[m[32m print("β Main backend application imported")[m | |
| [32m+[m | |
| [32m+[m[32mapp = FastAPI()[m | |
| [32m+[m | |
| [32m+[m[32m# Configure CORS - copy settings from your backend[m | |
| [32m+[m[32mallowed_origins = os.getenv("CORS_ALLOWED_ORIGINS", "http://localhost:3000,http://localhost:3001").split(",")[m | |
| [32m+[m[32mapp.add_middleware([m | |
| [32m+[m[32m CORSMiddleware,[m | |
| [32m+[m[32m allow_origins=["*"], # Allow all origins when serving from same domain[m | |
| [32m+[m[32m allow_credentials=True,[m | |
| [32m+[m[32m allow_methods=["*"],[m | |
| [32m+[m[32m allow_headers=["*"],[m | |
| [32m+[m[32m)[m | |
| [32m+[m | |
| [32m+[m[32m# Serve static files from React build[m | |
| [32m+[m[32mapp.mount("/static", StaticFiles(directory="build/static"), name="static")[m | |
| [32m+[m[32mapp.mount("/assets", StaticFiles(directory="build/assets", check_dir=False), name="assets")[m | |
| [32m+[m | |
| [32m+[m[32m# Mount your backend API - all backend routes will be served under /api[m | |
| [32m+[m[32m# IMPORTANT: Mount this AFTER static files but BEFORE catch-all route[m | |
| [32m+[m[32mapp.mount("/api", backend_app)[m | |
| [32m+[m | |
| [32m+[m[32m# Root endpoint - return JSON instead of trying to serve files[m | |
| [32m+[m[32m@app.get("/")[m | |
| [32m+[m[32masync def root():[m | |
| [32m+[m[32m return {[m | |
| [32m+[m[32m "status": "running",[m | |
| [32m+[m[32m "message": "ALU Student Companion API",[m | |
| [32m+[m[32m "api_endpoints": {[m | |
| [32m+[m[32m "health": "/health",[m | |
| [32m+[m[32m "chat": "/api/chat",[m | |
| [32m+[m[32m "docs": "/docs"[m | |
| [32m+[m[32m }[m | |
| [32m+[m[32m }[m | |
| [32m+[m | |
| [32m+[m[32m# Health check endpoint[m | |
| [32m+[m[32m@app.get("/health")[m | |
| [32m+[m[32masync def health():[m | |
| [32m+[m[32m return {"status": "healthy", "api": True, "backend": True}[m | |
| [32m+[m | |
| [32m+[m[32m# Serve React app for specific paths only (not catch-all)[m | |
| [32m+[m[32m@app.get("/static/{full_path:path}")[m | |
| [32m+[m[32masync def serve_static(full_path: str):[m | |
| [32m+[m[32m file_path = f"build/static/{full_path}"[m | |
| [32m+[m[32m if os.path.exists(file_path):[m | |
| [32m+[m[32m return FileResponse(file_path)[m | |
| [32m+[m[32m return JSONResponse([m | |
| [32m+[m[32m content={"error": "File not found"},[m | |
| [32m+[m[32m status_code=404[m | |
| [32m+[m[32m )[m | |