Gradii commited on
Commit
7c5da40
·
1 Parent(s): 6c9d916
backend/app/api/routes.py CHANGED
@@ -1,5 +1,5 @@
1
  import logging
2
- from fastapi import APIRouter, HTTPException
3
 
4
  from app.models.schemas import (
5
  AnalysisRequest,
@@ -8,8 +8,6 @@ from app.models.schemas import (
8
  HealthResponse,
9
  TextAnalysisRequest,
10
  ImageAnalysisRequest,
11
- VideoAnalysisRequest,
12
- FileAnalysisRequest,
13
  )
14
  from app.services.download import download_file
15
  from app.services.text_analyzer import analyze_text
@@ -21,21 +19,6 @@ logger = logging.getLogger(__name__)
21
 
22
  router = APIRouter()
23
 
24
- AVAILABLE_MODELS = {
25
- "text": ["yaya36095/xlm-roberta-text-detector"],
26
- "image": ["capcheck/ai-image-detection"],
27
- "video": [],
28
- "file": [],
29
- }
30
-
31
- MAX_CONTENT_SIZES = {
32
- "text": 5000,
33
- "image": 100 * 1024 * 1024,
34
- "video": 100 * 1024 * 1024,
35
- "file": 100 * 1024 * 1024,
36
- }
37
-
38
-
39
  @router.get(
40
  "/",
41
  response_model=HealthResponse,
@@ -46,186 +29,78 @@ async def health_check() -> HealthResponse:
46
  settings = get_settings()
47
  logger.info("Health check endpoint accessed")
48
 
49
- supported_types = ["text", "image", "video", "file"]
50
-
51
  return HealthResponse(
52
  status="ok",
53
  service="Deepfake Detection Service",
54
  version=settings.APP_VERSION,
55
- available_models=AVAILABLE_MODELS,
56
- supported_types=supported_types,
57
  )
58
 
59
-
60
  @router.post(
61
  "/analyze",
62
  response_model=AnalysisResponse,
63
  responses={
64
  400: {"model": ErrorResponse, "description": "Bad request"},
65
  408: {"model": ErrorResponse, "description": "Request timeout"},
 
66
  500: {"model": ErrorResponse, "description": "Internal server error"},
67
  },
68
  tags=["Analysis"],
69
  summary="Analyze content for deepfake detection",
70
  )
71
  async def analyze(request: AnalysisRequest) -> AnalysisResponse:
72
- settings = get_settings()
73
-
74
  if isinstance(request, TextAnalysisRequest):
75
  content_type = "text"
76
-
77
- if len(request.text) > MAX_CONTENT_SIZES["text"]:
78
- raise HTTPException(
79
- status_code=400,
80
- detail=f"Text content exceeds maximum length of {MAX_CONTENT_SIZES['text']} characters"
81
- )
82
-
83
- if len(request.text) < 50:
84
- raise HTTPException(
85
- status_code=400,
86
- detail="Text content must be at least 50 characters"
87
- )
88
-
89
- if not AVAILABLE_MODELS["text"]:
90
- raise HTTPException(
91
- status_code=400,
92
- detail="No model available for text analysis"
93
- )
94
-
95
- model = AVAILABLE_MODELS["text"][0]
96
- logger.info(f"Received text analysis request, length: {len(request.text)} chars, model: {model}")
97
-
98
- try:
99
- analysis_result = await analyze_text(request.text)
100
- except ValueError as e:
101
- raise HTTPException(status_code=400, detail=str(e))
102
- except Exception as e:
103
- logger.error(f"Text analysis error: {str(e)}", exc_info=True)
104
- raise HTTPException(status_code=500, detail="Failed to analyze text")
105
-
106
- logger.info(f"Text analysis completed. Result: {analysis_result}")
107
-
108
- return AnalysisResponse(
109
- is_deepfake=analysis_result["is_deepfake"],
110
- confidence=analysis_result["confidence"],
111
- analysis_time=analysis_result["analysis_time"],
112
- model_used=model,
113
- content_type="text",
114
- )
115
-
116
  elif isinstance(request, ImageAnalysisRequest):
117
  content_type = "image"
118
-
119
- if not AVAILABLE_MODELS["image"]:
120
- raise HTTPException(
121
- status_code=400,
122
- detail="No model available for image analysis"
123
- )
124
-
125
- model = AVAILABLE_MODELS["image"][0]
126
- logger.info(f"Received image analysis request for URL: {request.image_url}, model: {model}")
127
-
128
- try:
129
- image_bytes = await download_file(str(request.image_url))
130
- if not image_bytes:
131
- raise HTTPException(status_code=500, detail="Failed to download image")
132
-
133
- if len(image_bytes) > MAX_CONTENT_SIZES["image"]:
134
- raise HTTPException(
135
- status_code=400,
136
- detail=f"Image size exceeds maximum of {MAX_CONTENT_SIZES['image']} bytes"
137
- )
138
-
139
- except DeepfakeDetectionError as e:
140
- raise HTTPException(status_code=e.status_code, detail=e.message)
141
-
142
- analysis_result = await analyze_image(image_bytes)
143
-
144
- logger.info(f"Image analysis completed. Result: {analysis_result}")
145
-
146
- return AnalysisResponse(
147
- is_deepfake=analysis_result["is_deepfake"],
148
- confidence=analysis_result["confidence"],
149
- analysis_time=analysis_result["analysis_time"],
150
- model_used=model,
151
- content_type="image",
152
- )
153
-
154
- elif isinstance(request, VideoAnalysisRequest):
155
- content_type = "video"
156
-
157
- if not AVAILABLE_MODELS["video"]:
158
- raise HTTPException(
159
- status_code=400,
160
- detail="No model available for video analysis"
161
- )
162
-
163
- model = AVAILABLE_MODELS["video"][0]
164
- logger.info(f"Received video analysis request for URL: {request.video_url}, model: {model}")
165
-
166
- try:
167
- video_bytes = await download_file(str(request.video_url))
168
- if not video_bytes:
169
- raise HTTPException(status_code=500, detail="Failed to download video")
170
-
171
- if len(video_bytes) > MAX_CONTENT_SIZES["video"]:
172
- raise HTTPException(
173
- status_code=400,
174
- detail=f"Video size exceeds maximum of {MAX_CONTENT_SIZES['video']} bytes"
175
- )
176
-
177
- except DeepfakeDetectionError as e:
178
- raise HTTPException(status_code=e.status_code, detail=e.message)
179
-
180
- analysis_result = await analyze_image(video_bytes)
181
-
182
- logger.info(f"Video analysis completed. Result: {analysis_result}")
183
-
184
- return AnalysisResponse(
185
- is_deepfake=analysis_result["is_deepfake"],
186
- confidence=analysis_result["confidence"],
187
- analysis_time=analysis_result["analysis_time"],
188
- model_used=model,
189
- content_type="video",
190
  )
 
 
 
 
 
191
 
192
- elif isinstance(request, FileAnalysisRequest):
193
- content_type = "file"
194
-
195
- if not AVAILABLE_MODELS["file"]:
196
- raise HTTPException(
197
- status_code=400,
198
- detail="No model available for file analysis"
199
- )
200
-
201
- model = AVAILABLE_MODELS["file"][0]
202
- logger.info(f"Received file analysis request for URL: {request.file_url}, model: {model}")
203
-
204
- try:
205
- file_bytes = await download_file(str(request.file_url))
206
- if not file_bytes:
207
- raise HTTPException(status_code=500, detail="Failed to download file")
208
 
209
- if len(file_bytes) > MAX_CONTENT_SIZES["file"]:
210
- raise HTTPException(
211
- status_code=400,
212
- detail=f"File size exceeds maximum of {MAX_CONTENT_SIZES['file']} bytes"
213
- )
 
 
 
214
 
215
- except DeepfakeDetectionError as e:
216
- raise HTTPException(status_code=e.status_code, detail=e.message)
217
-
218
- analysis_result = await analyze_image(file_bytes)
219
-
220
- logger.info(f"File analysis completed. Result: {analysis_result}")
221
-
222
- return AnalysisResponse(
223
- is_deepfake=analysis_result["is_deepfake"],
224
- confidence=analysis_result["confidence"],
225
- analysis_time=analysis_result["analysis_time"],
226
- model_used=model,
227
- content_type="file",
228
- )
229
 
230
- else:
231
- raise HTTPException(status_code=400, detail="Unsupported content type")
 
 
 
 
 
 
1
  import logging
2
+ from fastapi import APIRouter, HTTPException, status
3
 
4
  from app.models.schemas import (
5
  AnalysisRequest,
 
8
  HealthResponse,
9
  TextAnalysisRequest,
10
  ImageAnalysisRequest,
 
 
11
  )
12
  from app.services.download import download_file
13
  from app.services.text_analyzer import analyze_text
 
19
 
20
  router = APIRouter()
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  @router.get(
23
  "/",
24
  response_model=HealthResponse,
 
29
  settings = get_settings()
30
  logger.info("Health check endpoint accessed")
31
 
 
 
32
  return HealthResponse(
33
  status="ok",
34
  service="Deepfake Detection Service",
35
  version=settings.APP_VERSION,
36
+ available_models=settings.AVAILABLE_MODELS,
37
+ supported_types=list(settings.AVAILABLE_MODELS.keys()),
38
  )
39
 
 
40
  @router.post(
41
  "/analyze",
42
  response_model=AnalysisResponse,
43
  responses={
44
  400: {"model": ErrorResponse, "description": "Bad request"},
45
  408: {"model": ErrorResponse, "description": "Request timeout"},
46
+ 415: {"model": ErrorResponse, "description": "Unsupported media type"},
47
  500: {"model": ErrorResponse, "description": "Internal server error"},
48
  },
49
  tags=["Analysis"],
50
  summary="Analyze content for deepfake detection",
51
  )
52
  async def analyze(request: AnalysisRequest) -> AnalysisResponse:
 
 
53
  if isinstance(request, TextAnalysisRequest):
54
  content_type = "text"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  elif isinstance(request, ImageAnalysisRequest):
56
  content_type = "image"
57
+ else:
58
+ raise HTTPException(
59
+ status_code=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE,
60
+ detail="Unsupported file/content type. Only text and image are currently supported."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  )
62
+
63
+ settings = get_settings()
64
+ models = settings.AVAILABLE_MODELS.get(content_type)
65
+ if not models:
66
+ raise HTTPException(status_code=400, detail=f"No model available for {content_type} analysis")
67
 
68
+ model = models[0]
69
+ logger.info(f"Received {content_type} analysis request, model: {model}")
70
+
71
+ try:
72
+ if content_type == "text":
73
+ if len(request.text) > settings.MAX_CONTENT_SIZES["text"]:
74
+ raise ValueError(f"Text content exceeds maximum length of {settings.MAX_CONTENT_SIZES['text']} characters")
75
+ if len(request.text) < 50:
76
+ raise ValueError("Text content must be at least 50 characters")
 
 
 
 
 
 
 
77
 
78
+ analysis_result = await analyze_text(request.text)
79
+
80
+ elif content_type == "image":
81
+ image_bytes = await download_file(str(request.image_url))
82
+ if not image_bytes:
83
+ raise ValueError("Failed to download image")
84
+ if len(image_bytes) > settings.MAX_CONTENT_SIZES["image"]:
85
+ raise ValueError(f"Image size exceeds maximum of {settings.MAX_CONTENT_SIZES['image']} bytes")
86
 
87
+ analysis_result = await analyze_image(image_bytes)
88
+
89
+ # 4. Globalna obsługa błędów
90
+ except ValueError as e:
91
+ raise HTTPException(status_code=400, detail=str(e))
92
+ except DeepfakeDetectionError as e:
93
+ raise HTTPException(status_code=e.status_code, detail=e.message)
94
+ except Exception as e:
95
+ logger.error(f"{content_type.capitalize()} analysis error: {str(e)}", exc_info=True)
96
+ raise HTTPException(status_code=500, detail=f"Failed to analyze {content_type}")
97
+
98
+ logger.info(f"{content_type.capitalize()} analysis completed. Result: {analysis_result}")
 
 
99
 
100
+ return AnalysisResponse(
101
+ is_deepfake=analysis_result["is_deepfake"],
102
+ confidence=analysis_result["confidence"],
103
+ analysis_time=analysis_result["analysis_time"],
104
+ model_used=model,
105
+ content_type=content_type,
106
+ )
backend/app/core/config.py CHANGED
@@ -31,6 +31,16 @@ class Settings:
31
  # Logging
32
  LOG_LEVEL: str = os.getenv("LOG_LEVEL", "INFO")
33
  LOG_FILE: Optional[str] = os.getenv("LOG_FILE", None)
 
 
 
 
 
 
 
 
 
 
34
 
35
 
36
  @lru_cache()
 
31
  # Logging
32
  LOG_LEVEL: str = os.getenv("LOG_LEVEL", "INFO")
33
  LOG_FILE: Optional[str] = os.getenv("LOG_FILE", None)
34
+
35
+ AVAILABLE_MODELS = {
36
+ "text": ["yaya36095/xlm-roberta-text-detector"],
37
+ "image": ["capcheck/ai-image-detection"],
38
+ }
39
+
40
+ MAX_CONTENT_SIZES = {
41
+ "text": 5000,
42
+ "image": 100 * 1024 * 1024,
43
+ }
44
 
45
 
46
  @lru_cache()