KShoichi commited on
Commit
245cbca
·
verified ·
1 Parent(s): d4595fd

Upload app/main.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app/main.py +134 -0
app/main.py ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ import os
3
+ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
4
+
5
+ from fastapi import FastAPI, Request, HTTPException
6
+ from fastapi.middleware.cors import CORSMiddleware
7
+ from fastapi.middleware.gzip import GZipMiddleware
8
+ from fastapi.middleware.trustedhost import TrustedHostMiddleware
9
+ from fastapi.responses import JSONResponse
10
+ from fastapi.staticfiles import StaticFiles
11
+ from slowapi import Limiter, _rate_limit_exceeded_handler
12
+ from slowapi.errors import RateLimitExceeded
13
+ from slowapi.util import get_remote_address
14
+ from starlette import status
15
+ import time
16
+ import logging
17
+ from api import predict, train, status, dashboard, batch_predict, playground
18
+ from api.monitor import router as monitor
19
+ from core.config import settings
20
+
21
+ # Configure logging
22
+ logging.basicConfig(
23
+ level=logging.INFO,
24
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
25
+ handlers=[
26
+ logging.FileHandler('app.log'),
27
+ logging.StreamHandler()
28
+ ]
29
+ )
30
+ logger = logging.getLogger(__name__)
31
+
32
+ # Configure rate limiting
33
+ limiter = Limiter(key_func=get_remote_address)
34
+
35
+ # Custom rate limit error handler
36
+ async def custom_rate_limit_handler(request: Request, exc: RateLimitExceeded) -> JSONResponse:
37
+ response = JSONResponse(
38
+ status_code=status.HTTP_429_TOO_MANY_REQUESTS,
39
+ content={
40
+ "error": "Rate limit exceeded",
41
+ "message": "Too many requests. Please wait a moment before trying again.",
42
+ "detail": f"Rate limit: {exc.detail}",
43
+ "retry_after": "Please wait 5-10 seconds before your next request",
44
+ "tip": "For testing, try clicking more slowly or wait between requests"
45
+ }
46
+ )
47
+ return response
48
+
49
+ app = FastAPI(
50
+ title="Hallucination Detection System",
51
+ version="1.0.0",
52
+ description="Production-ready hallucination detection API with ML model"
53
+ )
54
+
55
+ # Set up rate limiting
56
+ app.state.limiter = limiter
57
+ app.add_exception_handler(RateLimitExceeded, custom_rate_limit_handler)
58
+
59
+ # Add security and performance middleware
60
+ app.add_middleware(GZipMiddleware, minimum_size=1000)
61
+ app.add_middleware(
62
+ TrustedHostMiddleware,
63
+ allowed_hosts=["localhost", "127.0.0.1", "*.localhost", "testserver"]
64
+ )
65
+
66
+ # Request timing and monitoring middleware
67
+ @app.middleware("http")
68
+ async def add_process_time_header(request: Request, call_next):
69
+ start_time = time.time()
70
+ try:
71
+ response = await call_next(request)
72
+ process_time = time.time() - start_time
73
+ response.headers["X-Process-Time"] = str(process_time)
74
+ logger.info(f"Request: {request.method} {request.url.path} - Time: {process_time:.3f}s - Status: {response.status_code}")
75
+ return response
76
+ except Exception as e:
77
+ process_time = time.time() - start_time
78
+ logger.error(f"Request failed: {request.method} {request.url.path} - Time: {process_time:.3f}s - Error: {str(e)}")
79
+ return JSONResponse(
80
+ status_code=500,
81
+ content={"detail": "Internal server error", "request_id": str(time.time())},
82
+ headers={"X-Process-Time": str(process_time)}
83
+ )
84
+
85
+ # Static files
86
+ frontend_path = os.path.join(os.path.dirname(__file__), "frontend")
87
+ app.mount("/frontend", StaticFiles(directory=frontend_path), name="frontend")
88
+
89
+ # CORS with restricted origins for security
90
+ app.add_middleware(
91
+ CORSMiddleware,
92
+ allow_origins=["http://localhost:8000", "http://127.0.0.1:8000", "http://localhost:3000"],
93
+ allow_credentials=True,
94
+ allow_methods=["GET", "POST", "PUT", "DELETE"],
95
+ allow_headers=["*"],
96
+ )
97
+
98
+ # Include routers
99
+ app.include_router(predict, prefix="/api", tags=["predictions"])
100
+ app.include_router(batch_predict, prefix="/api", tags=["batch_predictions"])
101
+ app.include_router(train, prefix="/api", tags=["training"])
102
+ app.include_router(status, prefix="/api", tags=["status"])
103
+ app.include_router(dashboard, prefix="/dashboard", tags=["dashboard"])
104
+ app.include_router(monitor, prefix="/api", tags=["monitoring"])
105
+ app.include_router(playground, prefix="", tags=["playground"])
106
+
107
+ # Competition API
108
+ try:
109
+ from api.competition import router as competition_router
110
+ app.include_router(competition_router, prefix="/api", tags=["competition"])
111
+ logger.info("Competition API loaded successfully")
112
+ except ImportError as e:
113
+ logger.warning(f"Competition API not available: {e}")
114
+
115
+ @app.get("/", tags=["health"])
116
+ async def root():
117
+ return {
118
+ "message": "Hallucination Detection System is running",
119
+ "version": "1.0.0",
120
+ "status": "healthy",
121
+ "timestamp": time.time()
122
+ }
123
+
124
+ @app.get("/health", tags=["health"])
125
+ async def health_check():
126
+ return {
127
+ "status": "healthy",
128
+ "timestamp": time.time(),
129
+ "service": "hallucination-detector"
130
+ }
131
+
132
+ if __name__ == "__main__":
133
+ import uvicorn
134
+ uvicorn.run(app, host="0.0.0.0", port=8000)