"""Shared data models for the detection pipeline.""" from __future__ import annotations from enum import Enum from typing import Any from pydantic import BaseModel, Field class Verdict(str, Enum): REAL = "REAL" AI_GENERATED = "AI_GENERATED" MANIPULATED_DEEPFAKE = "MANIPULATED_DEEPFAKE" # face-swap / reenactment (V1 model) UNCERTAIN = "UNCERTAIN" class DetectionResult(BaseModel): """Output of a single detector.""" detector: str # e.g. "hive", "claude_vision" p_fake: float # P(not real) — combines AI_GENERATED + MANIPULATED_DEEPFAKE verdict: Verdict confidence: float # how confident the detector is (0–1) evidence: list[str] = Field(default_factory=list) # human-readable signals raw: dict[str, Any] = Field(default_factory=dict) # full API response error: str | None = None # set if the detector failed # Feature reuse fields generator: str | None = None # detected generator name (e.g., "Stable Diffusion") from Sightengine # V1 model extended fields (None for API-based detectors) p_ai_generated: float | None = None # P(AI_GENERATED) from 3-class model p_manipulated_deepfake: float | None = None # P(MANIPULATED_DEEPFAKE) from 3-class model face_detected: bool | None = None # whether a face was found in the image class EnsembleResult(BaseModel): """Final fused result across all detectors.""" verdict: Verdict p_fake: float # ensemble P(fake) confidence: float primary_evidence: str supporting_evidence: list[str] = Field(default_factory=list) uncertainty_factors: list[str] = Field(default_factory=list) detector_results: list[DetectionResult] = Field(default_factory=list) fusion_details: dict[str, Any] = Field(default_factory=dict) processing_time_ms: float = 0.0 model_version: str = "latest" # which hybrid model version was used diffusion_suspicion: float = 0.0 # 0–1 score from local_forensics diffusion scorer generator: str | None = None # detected generator name (e.g., "Stable Diffusion"), if any detector identified it