""" Civic Issue Urgency Classifier - Production API Server ====================================================== iOS 26 Liquid Design UI + Advanced AI Classification """ import os from fastapi import FastAPI, HTTPException, Request from fastapi.responses import HTMLResponse, JSONResponse, FileResponse from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel from typing import Optional from pathlib import Path import uvicorn import random import json from datetime import datetime # Get base directory BASE_DIR = Path(__file__).parent.parent STATIC_DIR = BASE_DIR / "static" TEMPLATES_DIR = BASE_DIR / "templates" # Get port from environment variable (for HF Spaces: 7860, local dev: 8001) PORT = int(os.getenv("PORT", 8001)) app = FastAPI( title="Civic Issue Urgency Classifier - Production API", description="AI-powered multimodal system for government civic issue prioritization with iOS 26 design", version="1.0.0" ) # Add CORS middleware app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Create directories if they don't exist STATIC_DIR.mkdir(parents=True, exist_ok=True) TEMPLATES_DIR.mkdir(parents=True, exist_ok=True) # Mount static files (only if directory exists and has content) if STATIC_DIR.exists(): try: app.mount("/static", StaticFiles(directory=str(STATIC_DIR)), name="static") except Exception as e: print(f"Warning: Could not mount static files: {e}") else: print(f"Warning: Static directory not found at {STATIC_DIR}") # Setup templates templates = Jinja2Templates(directory=str(TEMPLATES_DIR)) # Simple demo data and logic class CivicIssueRequest(BaseModel): text_description: str location_address: Optional[str] = "Unknown Location" category: Optional[str] = "General" def analyze_civic_issue_demo(text: str, location: str = "Unknown") -> dict: """Simple demo analysis logic""" text_lower = text.lower() # Simple urgency detection high_keywords = ['emergency', 'urgent', 'critical', 'danger', 'fire', 'hospital', 'crack', 'as soon as possible'] medium_keywords = ['problem', 'issue', 'broken', 'repair', 'fix'] low_keywords = ['minor', 'small', 'cosmetic', 'maintenance'] high_score = sum(1 for word in high_keywords if word in text_lower) medium_score = sum(1 for word in medium_keywords if word in text_lower) low_score = sum(1 for word in low_keywords if word in text_lower) # Determine urgency if high_score >= 2 or any(word in text_lower for word in ['hospital', 'emergency', 'fire']): urgency_level = "HIGH" urgency_score = min(10.0, 7.0 + high_score) department = "Emergency Services" response_time = "Immediate (within 1 hour)" elif medium_score >= 1 or high_score >= 1: urgency_level = "MEDIUM" urgency_score = 4.0 + medium_score + high_score department = "Public Works" response_time = "Next business day (within 24 hours)" else: urgency_level = "LOW" urgency_score = 2.0 + low_score department = "Maintenance Department" response_time = "Within 1 week" confidence = min(0.95, 0.6 + (high_score + medium_score) * 0.1) return { "urgency_level": urgency_level, "urgency_score": round(urgency_score, 1), "confidence": round(confidence, 3), "recommended_department": department, "estimated_response_time": response_time, "reasoning": f"Text analysis detected {high_score} high-priority keywords, {medium_score} medium-priority keywords. Location context: {location}", "text_contribution": 0.7, "image_contribution": 0.3, "location_context": "Hospital" if "hospital" in text_lower else "General", "safety_context": "Emergency" if any(word in text_lower for word in ['fire', 'danger', 'emergency']) else "Standard" } @app.get("/", response_class=HTMLResponse) async def root(request: Request): """Modern iOS 26 liquid design home page""" return templates.TemplateResponse("index.html", {"request": request}) @app.get("/old-demo", response_class=HTMLResponse) async def old_demo(): """Old demo page (kept for reference)""" return """
Government-ready multimodal AI system for civic issue prioritization
Test your civic issue classification:
Visit /docs for interactive Swagger documentation
Description: {text}
Location: {location}
📊 Urgency Score: {result['urgency_score']}/10
🎯 Confidence: {result['confidence']:.1%}
🏢 Recommended Department: {result['recommended_department']}
⏰ Estimated Response Time: {result['estimated_response_time']}
{result['reasoning']}
📝 Text Analysis: {result['text_contribution']:.0%}
🖼️ Image Analysis: {result['image_contribution']:.0%}
📍 Location Context: {result['location_context']}
⚠️ Safety Context: {result['safety_context']}