Spaces:
Running
Running
| import tempfile | |
| import os | |
| from fastapi import APIRouter, UploadFile, File, Depends, HTTPException, status | |
| from core.security import verify_api_key | |
| from ml_services.audio_ai import audio_service | |
| from ml_services.nlp_graph_ai import nlp_graph_service | |
| from models.schemas import IncidentReport | |
| from datetime import datetime | |
| import uuid | |
| from core.db import db_handler | |
| router = APIRouter(prefix="/api/v1/scam", tags=["Scam Detection"]) | |
| async def analyze_scam_audio( | |
| file: UploadFile = File(...), | |
| api_key: str = Depends(verify_api_key) | |
| ): | |
| if not file.filename.endswith(('.wav', '.mp3', '.ogg', '.flac')): | |
| raise HTTPException(status_code=400, detail="Unsupported audio format.") | |
| temp_file_path = "" | |
| try: | |
| # Save upload to a temporary file asynchronously | |
| fd, temp_file_path = tempfile.mkstemp(suffix=f".{file.filename.split('.')[-1]}") | |
| os.close(fd) # Close the synchronous fd immediately | |
| import aiofiles | |
| async with aiofiles.open(temp_file_path, 'wb') as f: | |
| while chunk := await file.read(1024 * 1024): # 1MB chunks | |
| await f.write(chunk) | |
| # 1. Process Audio (STT + Deepfake check) | |
| transcription, fake_prob = await audio_service.process_audio(temp_file_path) | |
| # 2. Translate to English (assuming Hindi or other regional language as source for robust pipeline, | |
| # but Whisper might output English directly if translated, or source language. | |
| # Let's assume whisper gives text, and we pass to translator if we want to ensure English, | |
| # but for now we'll pass to intent directly to save overhead unless explicitly requested). | |
| # We'll use the LLM to classify intent directly as mistral handles multilingual. | |
| intent_and_risk = await nlp_graph_service.classify_intent(transcription) | |
| # 3. Extract Entities | |
| entities = await nlp_graph_service.extract_entities(transcription) | |
| # 4. Agentic AI Fusion (Threat Dossier) | |
| from ml_services.agentic_fusion import agent | |
| dossier = await agent.generate_threat_dossier(transcription, entities) | |
| # 5. DPDP Act Compliance (PII Redaction) | |
| redacted_transcription = nlp_graph_service.redact_pii(transcription, entities) | |
| # 6. Construct Report | |
| report = IncidentReport( | |
| incident_id=str(uuid.uuid4()), | |
| type="audio", | |
| timestamp=datetime.utcnow(), | |
| extracted_entities=entities, | |
| risk_score=fake_prob if fake_prob > 0.5 else (0.8 if intent_and_risk.get("risk") == "High" else 0.2), | |
| threat_dossier=dossier, | |
| explainability_report=intent_and_risk.get("explainability_report"), | |
| details={ | |
| "transcription": redacted_transcription, | |
| "intent": intent_and_risk.get("intent", ""), | |
| "scam_stage": intent_and_risk.get("scam_stage", ""), | |
| "deepfake_probability": fake_prob | |
| } | |
| ) | |
| # 7. Generate Immutable Evidence Hash | |
| db_payload = report.model_dump() | |
| sig = await db_handler.generate_evidence_hash(db_payload, file_path=temp_file_path) | |
| report.digital_signature = sig | |
| db_payload["digital_signature"] = sig | |
| # 7. Save to MongoDB atomically | |
| if db_handler.db is not None: | |
| await db_handler.db["incidents"].insert_one(db_payload) | |
| return report | |
| except Exception as e: | |
| raise HTTPException(status_code=500, detail=f"Internal Server Error: {str(e)}") | |
| finally: | |
| # Cleanup temp file | |
| if temp_file_path and os.path.exists(temp_file_path): | |
| os.remove(temp_file_path) | |
| from models.schemas import VideoAnalysisResponse | |
| from ml_services.vision_ai import vision_service | |
| async def analyze_scam_video( | |
| file: UploadFile = File(...), | |
| api_key: str = Depends(verify_api_key) | |
| ): | |
| if not file.filename.lower().endswith(('.png', '.jpg', '.jpeg', '.webp')): | |
| raise HTTPException(status_code=400, detail="Unsupported image format.") | |
| temp_file_path = "" | |
| try: | |
| fd, temp_file_path = tempfile.mkstemp(suffix=f".{file.filename.split('.')[-1]}") | |
| os.close(fd) | |
| import aiofiles | |
| async with aiofiles.open(temp_file_path, 'wb') as f: | |
| while chunk := await file.read(1024 * 1024): | |
| await f.write(chunk) | |
| result = await vision_service.analyze_video_call(temp_file_path) | |
| return VideoAnalysisResponse(**result) | |
| except Exception as e: | |
| raise HTTPException(status_code=500, detail=str(e)) | |
| finally: | |
| if temp_file_path and os.path.exists(temp_file_path): | |
| os.remove(temp_file_path) | |