Spaces:
Paused
Paused
| #!/usr/bin/env python3 | |
| """ | |
| Legal Dashboard FastAPI Main Application (Simplified) | |
| ==================================================== | |
| Simplified FastAPI application for testing API structure. | |
| """ | |
| import os | |
| import logging | |
| from pathlib import Path | |
| from contextlib import asynccontextmanager | |
| from fastapi import FastAPI, HTTPException | |
| from fastapi.staticfiles import StaticFiles | |
| from fastapi.responses import HTMLResponse, FileResponse | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.middleware.gzip import GZipMiddleware | |
| # Configure logging | |
| logging.basicConfig( | |
| level=logging.INFO, | |
| format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' | |
| ) | |
| logger = logging.getLogger(__name__) | |
| async def lifespan(app: FastAPI): | |
| """Application lifespan manager""" | |
| try: | |
| logger.info("🚀 Starting Legal Dashboard (Simplified)...") | |
| # Create required directories (Windows compatible) | |
| uploads_dir = Path.cwd() / "uploads" | |
| data_dir = Path.cwd() / "data" | |
| os.makedirs(uploads_dir, exist_ok=True) | |
| os.makedirs(data_dir, exist_ok=True) | |
| logger.info("🎉 Services initialized successfully!") | |
| yield # Application runs here | |
| except Exception as e: | |
| logger.error(f"❌ Initialization failed: {e}") | |
| raise | |
| finally: | |
| logger.info("🔄 Shutting down Legal Dashboard...") | |
| # Create FastAPI application | |
| app = FastAPI( | |
| title="Legal Dashboard API", | |
| description="AI-powered Persian legal document processing system", | |
| version="1.0.0", | |
| docs_url="/api/docs", | |
| redoc_url="/api/redoc", | |
| lifespan=lifespan | |
| ) | |
| # Add middlewares | |
| app.add_middleware(GZipMiddleware, minimum_size=1000) | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], # Configure properly in production | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # Serve static files (Frontend) | |
| frontend_dir = Path(__file__).parent.parent / "frontend" | |
| if frontend_dir.exists(): | |
| app.mount("/static", StaticFiles(directory=str(frontend_dir)), name="static") | |
| logger.info(f"📁 Static files mounted from: {frontend_dir}") | |
| else: | |
| logger.warning("⚠️ Frontend directory not found") | |
| # Root route - serve main dashboard | |
| async def read_root(): | |
| """Serve main dashboard page""" | |
| try: | |
| html_file = frontend_dir / "index.html" | |
| if html_file.exists(): | |
| return FileResponse(html_file, media_type="text/html") | |
| else: | |
| return HTMLResponse(""" | |
| <html> | |
| <head><title>Legal Dashboard</title></head> | |
| <body> | |
| <h1>🏛️ Legal Dashboard API</h1> | |
| <p>Backend is running! Frontend files not found.</p> | |
| <p><a href="/api/docs">📖 API Documentation</a></p> | |
| </body> | |
| </html> | |
| """) | |
| except Exception as e: | |
| logger.error(f"Error serving root: {e}") | |
| raise HTTPException(status_code=500, detail="Error serving homepage") | |
| # Health check endpoint | |
| async def health_check(): | |
| """System health check""" | |
| return { | |
| "status": "healthy", | |
| "services": { | |
| "database": "healthy", | |
| "ocr": "healthy", | |
| "ai": "healthy" | |
| }, | |
| "version": "1.0.0" | |
| } | |
| # Dashboard endpoints | |
| async def dashboard_summary(): | |
| """Dashboard summary data""" | |
| return { | |
| "total_documents": 6, | |
| "processed_documents": 4, | |
| "error_documents": 1, | |
| "average_quality": 8.1, | |
| "recent_activity": [ | |
| {"date": "2024-12-01", "count": 2}, | |
| {"date": "2024-12-02", "count": 3}, | |
| {"date": "2024-12-03", "count": 1} | |
| ] | |
| } | |
| async def charts_data(): | |
| """Charts data for dashboard""" | |
| return { | |
| "category_distribution": { | |
| "قراردادها": 1, | |
| "دادخواستها": 1, | |
| "احکام قضایی": 1, | |
| "آرای دیوان": 1, | |
| "سایر": 2 | |
| }, | |
| "processing_trends": [ | |
| {"date": "2024-12-01", "processed": 2, "uploaded": 3}, | |
| {"date": "2024-12-02", "processed": 3, "uploaded": 4}, | |
| {"date": "2024-12-03", "processed": 1, "uploaded": 2} | |
| ] | |
| } | |
| async def ai_suggestions(): | |
| """AI suggestions for dashboard""" | |
| return { | |
| "suggestions": [ | |
| { | |
| "title": "بهبود کیفیت OCR", | |
| "description": "پیشنهاد میشود از تصاویر با کیفیت بالاتر استفاده کنید", | |
| "score": 0.85 | |
| }, | |
| { | |
| "title": "دستهبندی خودکار", | |
| "description": "سیستم میتواند اسناد را به صورت خودکار دستهبندی کند", | |
| "score": 0.92 | |
| } | |
| ] | |
| } | |
| async def ai_feedback(): | |
| """AI feedback endpoint""" | |
| return {"status": "success", "message": "Feedback received"} | |
| async def performance_metrics(): | |
| """Performance metrics""" | |
| return { | |
| "ocr_accuracy": 0.92, | |
| "processing_speed": 15.3, | |
| "error_rate": 0.08 | |
| } | |
| async def dashboard_trends(): | |
| """Dashboard trends""" | |
| return { | |
| "document_growth": 15.2, | |
| "quality_improvement": 2.1, | |
| "processing_efficiency": 8.3 | |
| } | |
| # Documents endpoints | |
| async def get_documents(): | |
| """Get all documents""" | |
| return { | |
| "documents": [ | |
| {"id": 1, "title": "قرارداد اجاره", | |
| "status": "processed", "quality": 8.5}, | |
| {"id": 2, "title": "دادخواست حقوقی", | |
| "status": "processed", "quality": 7.8}, | |
| {"id": 3, "title": "حکم قضایی", "status": "error", "quality": 0.0} | |
| ] | |
| } | |
| async def search_documents(): | |
| """Search documents""" | |
| return {"results": [], "total": 0} | |
| async def get_categories(): | |
| """Get document categories""" | |
| return { | |
| "categories": ["قراردادها", "دادخواستها", "احکام قضایی", "آرای دیوان", "سایر"] | |
| } | |
| async def get_sources(): | |
| """Get document sources""" | |
| return { | |
| "sources": ["آپلود دستی", "اسکن خودکار", "ایمیل", "وبسایت"] | |
| } | |
| # OCR endpoints | |
| async def process_ocr(): | |
| """Process OCR""" | |
| return {"status": "success", "text": "متن استخراج شده"} | |
| async def process_and_save_ocr(): | |
| """Process OCR and save""" | |
| return {"status": "success", "document_id": 1} | |
| async def batch_process_ocr(): | |
| """Batch process OCR""" | |
| return {"status": "success", "processed": 5} | |
| async def ocr_quality_metrics(): | |
| """OCR quality metrics""" | |
| return { | |
| "average_accuracy": 0.92, | |
| "confidence_threshold": 0.8, | |
| "error_rate": 0.08 | |
| } | |
| async def ocr_models(): | |
| """Available OCR models""" | |
| return { | |
| "models": ["persian_ocr_v1", "persian_ocr_v2", "multilingual_ocr"] | |
| } | |
| async def ocr_status(): | |
| """OCR service status""" | |
| return {"status": "healthy", "active_models": 2} | |
| # Analytics endpoints | |
| async def analytics_overview(): | |
| """Analytics overview""" | |
| return { | |
| "total_documents": 6, | |
| "processing_rate": 85.7, | |
| "average_quality": 8.1 | |
| } | |
| async def analytics_trends(): | |
| """Analytics trends""" | |
| return { | |
| "daily_processing": [2, 3, 1, 4, 2, 3, 1], | |
| "quality_trend": [7.5, 8.1, 8.3, 8.0, 8.2, 8.1, 8.4] | |
| } | |
| async def analytics_similarity(): | |
| """Document similarity analysis""" | |
| return { | |
| "similarity_matrix": [], | |
| "clusters": [] | |
| } | |
| async def analytics_performance(): | |
| """Performance analytics""" | |
| return { | |
| "processing_time": 15.3, | |
| "accuracy_rate": 92.0, | |
| "throughput": 4.2 | |
| } | |
| async def analytics_entities(): | |
| """Entity extraction analytics""" | |
| return { | |
| "entities_found": 45, | |
| "entity_types": ["نام", "تاریخ", "مبلغ", "آدرس"] | |
| } | |
| async def analytics_quality(): | |
| """Quality analysis""" | |
| return { | |
| "quality_distribution": { | |
| "excellent": 2, | |
| "good": 3, | |
| "poor": 1 | |
| } | |
| } | |
| # Scraping endpoints | |
| async def start_scraping(): | |
| """Start web scraping""" | |
| return {"status": "started", "job_id": "scrape_001"} | |
| async def scraping_status(): | |
| """Scraping status""" | |
| return {"status": "idle", "last_run": "2024-12-01"} | |
| async def scraping_items(): | |
| """Scraped items""" | |
| return { | |
| "items": [ | |
| {"url": "https://example.com/1", "title": "مطلب اول"}, | |
| {"url": "https://example.com/2", "title": "مطلب دوم"} | |
| ] | |
| } | |
| async def scraping_statistics(): | |
| """Scraping statistics""" | |
| return { | |
| "total_scraped": 150, | |
| "success_rate": 95.2, | |
| "average_speed": 2.3 | |
| } | |
| async def scraping_rating_summary(): | |
| """Scraping rating summary""" | |
| return { | |
| "average_rating": 4.2, | |
| "total_ratings": 25, | |
| "rating_distribution": {"5": 10, "4": 8, "3": 4, "2": 2, "1": 1} | |
| } | |
| # Error handlers | |
| async def not_found_handler(request, exc): | |
| """Custom 404 handler""" | |
| return HTMLResponse(""" | |
| <html> | |
| <head><title>404 - صفحه یافت نشد</title></head> | |
| <body style="font-family: 'Tahoma', sans-serif; text-align: center; padding: 50px;"> | |
| <h1>🔍 صفحه یافت نشد</h1> | |
| <p>صفحه مورد نظر شما وجود ندارد.</p> | |
| <a href="/">🏠 بازگشت به صفحه اصلی</a> | |
| </body> | |
| </html> | |
| """, status_code=404) | |
| async def internal_error_handler(request, exc): | |
| """Custom 500 handler""" | |
| logger.error(f"Internal server error: {exc}") | |
| return HTMLResponse(""" | |
| <html> | |
| <head><title>500 - خطای سرور</title></head> | |
| <body style="font-family: 'Tahoma', sans-serif; text-align: center; padding: 50px;"> | |
| <h1>⚠️ خطای سرور</h1> | |
| <p>متأسفانه خطایی در سرور رخ داده است.</p> | |
| <a href="/">🏠 بازگشت به صفحه اصلی</a> | |
| </body> | |
| </html> | |
| """, status_code=500) | |
| if __name__ == "__main__": | |
| import uvicorn | |
| uvicorn.run(app, host="0.0.0.0", port=8000) | |