Update src/main.py
Browse files- src/main.py +54 -10
src/main.py
CHANGED
|
@@ -73,6 +73,10 @@ app.include_router(prompt_injection.router, prefix="/api", tags=["prompt_injecti
|
|
| 73 |
# Routes - Mitigation Reports
|
| 74 |
app.include_router(mitigation.router, prefix="/api", tags=["mitigation"])
|
| 75 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
from .services.voice_history_manager import voice_history_manager
|
| 77 |
|
| 78 |
@app.get("/api/voice/history", tags=["Voice"])
|
|
@@ -84,9 +88,16 @@ async def get_voice_history():
|
|
| 84 |
logger.error(f"Error fetching voice history: {e}")
|
| 85 |
raise HTTPException(status_code=500, detail="Failed to fetch voice history")
|
| 86 |
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
|
| 91 |
|
| 92 |
# Routes - Deepfake Detection
|
|
@@ -127,7 +138,10 @@ async def detect_audio_deepfake(file: UploadFile = File(...)):
|
|
| 127 |
|
| 128 |
# Detect deepfake
|
| 129 |
logger.info(f"Analyzing audio file: {file.filename}")
|
| 130 |
-
|
|
|
|
|
|
|
|
|
|
| 131 |
|
| 132 |
return DeepfakeResponse(
|
| 133 |
is_deepfake=result.get("is_deepfake"),
|
|
@@ -191,7 +205,10 @@ async def detect_video_deepfake(file: UploadFile = File(...)):
|
|
| 191 |
|
| 192 |
# Detect deepfake
|
| 193 |
logger.info(f"Analyzing video file: {file.filename}")
|
| 194 |
-
|
|
|
|
|
|
|
|
|
|
| 195 |
|
| 196 |
return DeepfakeResponse(
|
| 197 |
is_deepfake=result.get("is_deepfake"),
|
|
@@ -254,7 +271,10 @@ async def detect_image_deepfake(file: UploadFile = File(...)):
|
|
| 254 |
|
| 255 |
# Detect deepfake
|
| 256 |
logger.info(f"Analyzing image file: {file.filename}")
|
| 257 |
-
|
|
|
|
|
|
|
|
|
|
| 258 |
|
| 259 |
return DeepfakeResponse(
|
| 260 |
is_deepfake=result.get("is_deepfake"),
|
|
@@ -306,12 +326,19 @@ async def detect_deepfake(file: UploadFile = File(...)):
|
|
| 306 |
file_ext = Path(file.filename).suffix.lower()
|
| 307 |
logger.info(f"Detecting type for: {file.filename} ({file_ext})")
|
| 308 |
|
|
|
|
| 309 |
if file_ext in [".mp3", ".wav", ".ogg", ".m4a", ".flac"]:
|
| 310 |
-
result =
|
|
|
|
|
|
|
| 311 |
elif file_ext in [".mp4", ".avi", ".mkv", ".mov", ".webm"]:
|
| 312 |
-
result =
|
|
|
|
|
|
|
| 313 |
elif file_ext in [".jpg", ".jpeg", ".png", ".webp", ".avif"]:
|
| 314 |
-
result =
|
|
|
|
|
|
|
| 315 |
else:
|
| 316 |
return DeepfakeResponse(
|
| 317 |
is_deepfake=None,
|
|
@@ -319,16 +346,33 @@ async def detect_deepfake(file: UploadFile = File(...)):
|
|
| 319 |
error=f"Unsupported file format: {file_ext}",
|
| 320 |
)
|
| 321 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 322 |
|
| 323 |
return DeepfakeResponse(
|
| 324 |
is_deepfake=result.get("is_deepfake"),
|
| 325 |
confidence=result.get("confidence", 0.0),
|
| 326 |
message=result.get("message"),
|
| 327 |
error=result.get("error"),
|
|
|
|
|
|
|
| 328 |
details={
|
| 329 |
k: v
|
| 330 |
for k, v in result.items()
|
| 331 |
-
if k not in ["is_deepfake", "confidence", "message", "error"]
|
| 332 |
},
|
| 333 |
)
|
| 334 |
|
|
|
|
| 73 |
# Routes - Mitigation Reports
|
| 74 |
app.include_router(mitigation.router, prefix="/api", tags=["mitigation"])
|
| 75 |
|
| 76 |
+
# Routes - Authentication
|
| 77 |
+
from .api import auth
|
| 78 |
+
app.include_router(auth.router, prefix="/auth", tags=["auth"])
|
| 79 |
+
|
| 80 |
from .services.voice_history_manager import voice_history_manager
|
| 81 |
|
| 82 |
@app.get("/api/voice/history", tags=["Voice"])
|
|
|
|
| 88 |
logger.error(f"Error fetching voice history: {e}")
|
| 89 |
raise HTTPException(status_code=500, detail="Failed to fetch voice history")
|
| 90 |
|
| 91 |
+
|
| 92 |
+
@app.get("/api/events", tags=["Real-time"])
|
| 93 |
+
async def stream_events():
|
| 94 |
+
"""
|
| 95 |
+
Server-Sent Events (SSE) endpoint to stream real-time threat alerts.
|
| 96 |
+
"""
|
| 97 |
+
return StreamingResponse(
|
| 98 |
+
event_hub.subscribe(),
|
| 99 |
+
media_type="text/event-stream"
|
| 100 |
+
)
|
| 101 |
|
| 102 |
|
| 103 |
# Routes - Deepfake Detection
|
|
|
|
| 138 |
|
| 139 |
# Detect deepfake
|
| 140 |
logger.info(f"Analyzing audio file: {file.filename}")
|
| 141 |
+
loop = asyncio.get_event_loop()
|
| 142 |
+
result = await loop.run_in_executor(
|
| 143 |
+
None, detector.detect_audio_deepfake, temp_file
|
| 144 |
+
)
|
| 145 |
|
| 146 |
return DeepfakeResponse(
|
| 147 |
is_deepfake=result.get("is_deepfake"),
|
|
|
|
| 205 |
|
| 206 |
# Detect deepfake
|
| 207 |
logger.info(f"Analyzing video file: {file.filename}")
|
| 208 |
+
loop = asyncio.get_event_loop()
|
| 209 |
+
result = await loop.run_in_executor(
|
| 210 |
+
None, detector.detect_video_deepfake, temp_file
|
| 211 |
+
)
|
| 212 |
|
| 213 |
return DeepfakeResponse(
|
| 214 |
is_deepfake=result.get("is_deepfake"),
|
|
|
|
| 271 |
|
| 272 |
# Detect deepfake
|
| 273 |
logger.info(f"Analyzing image file: {file.filename}")
|
| 274 |
+
loop = asyncio.get_event_loop()
|
| 275 |
+
result = await loop.run_in_executor(
|
| 276 |
+
None, detector.detect_image_deepfake, temp_file
|
| 277 |
+
)
|
| 278 |
|
| 279 |
return DeepfakeResponse(
|
| 280 |
is_deepfake=result.get("is_deepfake"),
|
|
|
|
| 326 |
file_ext = Path(file.filename).suffix.lower()
|
| 327 |
logger.info(f"Detecting type for: {file.filename} ({file_ext})")
|
| 328 |
|
| 329 |
+
loop = asyncio.get_event_loop()
|
| 330 |
if file_ext in [".mp3", ".wav", ".ogg", ".m4a", ".flac"]:
|
| 331 |
+
result = await loop.run_in_executor(
|
| 332 |
+
None, detector.detect_audio_deepfake, temp_file
|
| 333 |
+
)
|
| 334 |
elif file_ext in [".mp4", ".avi", ".mkv", ".mov", ".webm"]:
|
| 335 |
+
result = await loop.run_in_executor(
|
| 336 |
+
None, detector.detect_video_deepfake, temp_file
|
| 337 |
+
)
|
| 338 |
elif file_ext in [".jpg", ".jpeg", ".png", ".webp", ".avif"]:
|
| 339 |
+
result = await loop.run_in_executor(
|
| 340 |
+
None, detector.detect_image_deepfake, temp_file
|
| 341 |
+
)
|
| 342 |
else:
|
| 343 |
return DeepfakeResponse(
|
| 344 |
is_deepfake=None,
|
|
|
|
| 346 |
error=f"Unsupported file format: {file_ext}",
|
| 347 |
)
|
| 348 |
|
| 349 |
+
# Determine media type for reasoning engine
|
| 350 |
+
audio_exts = [".mp3", ".wav", ".ogg", ".m4a", ".flac"]
|
| 351 |
+
video_exts = [".mp4", ".avi", ".mkv", ".mov", ".webm"]
|
| 352 |
+
image_exts = [".jpg", ".jpeg", ".png", ".webp", ".avif"]
|
| 353 |
+
if file_ext in audio_exts:
|
| 354 |
+
media_type = "audio"
|
| 355 |
+
elif file_ext in video_exts:
|
| 356 |
+
media_type = "video"
|
| 357 |
+
elif file_ext in image_exts:
|
| 358 |
+
media_type = "image"
|
| 359 |
+
else:
|
| 360 |
+
media_type = "unknown"
|
| 361 |
+
|
| 362 |
+
# Run LLM reasoning on top of ML detection
|
| 363 |
+
result = await analyze_with_reasoning(result, media_type)
|
| 364 |
|
| 365 |
return DeepfakeResponse(
|
| 366 |
is_deepfake=result.get("is_deepfake"),
|
| 367 |
confidence=result.get("confidence", 0.0),
|
| 368 |
message=result.get("message"),
|
| 369 |
error=result.get("error"),
|
| 370 |
+
reasoning=result.get("reasoning"),
|
| 371 |
+
key_factors=result.get("key_factors"),
|
| 372 |
details={
|
| 373 |
k: v
|
| 374 |
for k, v in result.items()
|
| 375 |
+
if k not in ["is_deepfake", "confidence", "message", "error", "reasoning", "key_factors"]
|
| 376 |
},
|
| 377 |
)
|
| 378 |
|