deepshield / schemas /common.py
ar07xd's picture
Sync from GitHub via hub-sync
1b18758 verified
from __future__ import annotations
from typing import List, Optional
from pydantic import BaseModel, ConfigDict, Field
ANALYSIS_CACHE_VERSION = "2026-05-07-archive-7d-news-fallback"
class Verdict(BaseModel):
model_config = ConfigDict(protected_namespaces=())
label: str
severity: str
authenticity_score: int = Field(ge=0, le=100)
model_confidence: float = Field(ge=0.0, le=1.0)
model_label: str
class ArtifactIndicator(BaseModel):
type: str
severity: str # low | medium | high
description: str
confidence: float = Field(ge=0.0, le=1.0)
class TrustedSource(BaseModel):
source_name: str
title: str
url: str
description: Optional[str] = None
published_at: Optional[str] = None
relevance_score: float = Field(ge=0.0, le=1.0)
class ContradictingEvidence(BaseModel):
source_name: str
title: str
url: str
type: str = "fact_check"
class TruthOverride(BaseModel):
applied: bool = False
source_url: str = ""
source_name: str = ""
similarity: float = 0.0
fake_prob_before: float = 0.0
fake_prob_after: float = 0.0
class ExifSummary(BaseModel):
make: Optional[str] = None
model: Optional[str] = None
datetime_original: Optional[str] = None
gps_info: Optional[str] = None
software: Optional[str] = None
lens_model: Optional[str] = None
icc_profile: Optional[bool] = False
maker_note: Optional[bool] = False
trust_adjustment: int = 0 # negative = more real, positive = more fake
trust_reason: str = ""
class SignalObservation(BaseModel):
"""One forensic signal with a plain-English observation. Used in image analysis."""
name: str
observation: str
verdict: str = "" # "authentic" | "suspicious" | "inconclusive"
class LLMExplainabilitySummary(BaseModel):
model_config = ConfigDict(protected_namespaces=())
paragraph: str = ""
bullets: List[str] = []
# Per-signal breakdown for image analysis (empty for non-image media)
signals: List[SignalObservation] = []
model_used: str = ""
cached: bool = False
class VLMComponentScore(BaseModel):
score: int = Field(ge=0, le=100, default=75)
notes: str = ""
class VLMBreakdown(BaseModel):
model_config = ConfigDict(protected_namespaces=())
facial_symmetry: VLMComponentScore = VLMComponentScore()
skin_texture: VLMComponentScore = VLMComponentScore()
lighting_consistency: VLMComponentScore = VLMComponentScore()
background_coherence: VLMComponentScore = VLMComponentScore()
anatomy_hands_eyes: VLMComponentScore = VLMComponentScore()
context_objects: VLMComponentScore = VLMComponentScore()
model_used: str = ""
cached: bool = False
class ProcessingSummary(BaseModel):
model_config = ConfigDict(protected_namespaces=())
stages_completed: List[str]
total_duration_ms: int
model_used: str
models_used: List[str] = [] # all models that contributed (ensemble)
analysis_version: str = ANALYSIS_CACHE_VERSION
calibrator_applied: bool = False
# Phase A/B: unified evidence fusion details and disagreement clamping
evidence_fusion: Optional[dict] = None
disagreement_reason: Optional[str] = None
gating_applied: Optional[str] = None