ziadalaa7/Fake_Image_Detection
0
1"""
2FastAPI routes and endpoints.
3Defines the API contract and request/response handling.
4This is the "View" layer responsible for HTTP handling.
5"""
6
7from fastapi import APIRouter, HTTPException, status
8from fastapi.responses import JSONResponse
9import time
10from models.schemas import PredictionResponse, ErrorResponse, HealthCheckResponse, ImageURLRequest
11from services.model_service import get_model_service
12from core.config import CLASS_LABELS
13
14# Create router for v1 API
15router = APIRouter(prefix="/api/v1", tags=["Predictions"])
16
17
18@router.get(
19 "/health",
20 response_model=HealthCheckResponse,
21 summary="Health Check",
22 description="Check if the service is running and model is loaded"
23)
24async def health_check() -> HealthCheckResponse:
25 """
26 Health check endpoint to verify service status.
27
28 Returns:
29 HealthCheckResponse: Service health status and model state.
30 """
31 try:
32 model_service = get_model_service()
33 return HealthCheckResponse(
34 status="healthy",
35 model_loaded=model_service.model is not None,
36 version="1.0.0"
37 )
38 except Exception as e:
39 raise HTTPException(
40 status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
41 detail=f"Service unavailable: {str(e)}"
42 )
43
44
45@router.post(
46 "/predict",
47 response_model=PredictionResponse,
48 summary="Predict Image Classification from URL",
49 description="Send an image URL to detect whether it's real or AI-generated",
50 responses={
51 200: {
52 "description": "Successful prediction",
53 "model": PredictionResponse
54 },
55 400: {
56 "description": "Invalid request or URL",
57 "model": ErrorResponse
58 },
59 500: {
60 "description": "Server error during processing",
61 "model": ErrorResponse
62 }
63 }
64)
65async def predict_image(request: ImageURLRequest) -> PredictionResponse:
66 """
67 Analyze an image from URL and get a prediction of whether it's real or AI-generated.
68
69 Args:
70 request (ImageURLRequest): Request containing the image URL from S3.
71
72 Returns:
73 PredictionResponse: Prediction with verdict ("real" or "fake") and confidence score (0-100).
74
75 Raises:
76 HTTPException: If URL is invalid or prediction fails.
77
78 Example:
79 ```bash
80 curl -X POST "http://localhost:8000/api/v1/predict" \
81 -H "Content-Type: application/json" \
82 -d '{"image_url": "https://my-bucket.s3.amazonaws.com/image.jpg"}'
83 ```
84 """
85
86 try:
87 # Validate URL format
88 if not request.image_url or not request.image_url.startswith(('http://', 'https://')):
89 raise HTTPException(
90 status_code=status.HTTP_400_BAD_REQUEST,
91 detail="Invalid URL. Must start with http:// or https://"
92 )
93
94 # Get model service and perform prediction
95 model_service = get_model_service()
96 prediction_result = model_service.predict(request.image_url)
97
98 # Return formatted response
99 return PredictionResponse(
100 verdict=prediction_result["verdict"],
101 confidenceScore=prediction_result["confidenceScore"]
102 )
103
104 except HTTPException:
105 raise
106 except ValueError as e:
107 raise HTTPException(
108 status_code=status.HTTP_400_BAD_REQUEST,
109 detail=str(e)
110 )
111 except Exception as e:
112 raise HTTPException(
113 status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
114 detail=f"Prediction failed: {str(e)}"
115 )
116
117
118@router.get(
119 "/info",
120 summary="Model Information",
121 description="Get information about the loaded model"
122)
123async def model_info():
124 """
125 Get metadata about the currently loaded model.
126
127 Returns:
128 dict: Model information including name, version, and class labels.
129 """
130 try:
131 return {
132 "model_name": "EfficientNet-Fine-Tuned",
133 "version": "1.0.0",
134 "class_labels": CLASS_LABELS,
135 "supported_formats": list(ALLOWED_EXTENSIONS),
136 "max_file_size_mb": MAX_IMAGE_SIZE_MB,
137 "input_shape": (224, 224, 3)
138 }
139 except Exception as e:
140 raise HTTPException(
141 status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
142 detail=f"Failed to retrieve model info: {str(e)}"
143 )
144 