github-actions[bot]
Deploy from GitHub 39b3777315c11d9c8bcd39ad7bf034f2a88a7379 (filtered: code + Dockerfile + README + NOTICES only)
2e175db
Raw
History Blame Contribute Delete
1.72 kB
"""
Detector interface.
Every detector is a plug-in that takes a PIL image and returns a
DetectorResult. The ensemble layer aggregates results from all enabled
detectors into a single Probabilities vector.
Adding a new detector = subclassing Detector + registering it in ensemble.py.
The /v1 API response shape never changes.
"""
from __future__ import annotations
from abc import ABC, abstractmethod
from dataclasses import dataclass
from PIL import Image
@dataclass
class DetectorResult:
"""Output of a single detector run.
Attributes
----------
name :
Stable identifier for this detector (used in API `signals`).
score :
The detector's own "fakeness" estimate in [0, 1].
1.0 means "definitely synthetic"; 0.0 means "definitely authentic".
contributions :
Optional per-class hints in [0, 1]. Keys must be a subset of the
4-class taxonomy: "authentic", "ai_generated", "deepfake", "edited".
Detectors that only know "real vs. fake" leave this empty and let
the ensemble splat their score across the relevant classes.
notes :
Free-form human-readable note (surfaced in API for debugging).
"""
name: str
score: float
contributions: dict[str, float]
notes: str | None = None
class Detector(ABC):
"""Base class for all forensic detectors.
Detectors must be safe to instantiate once at process start and reused
across requests — load model weights in __init__, not in run().
"""
name: str = "abstract"
@abstractmethod
def run(self, image: Image.Image) -> DetectorResult:
"""Score a single PIL image. Must not mutate the image."""
raise NotImplementedError