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) | |