Spaces:
Running
Running
github-actions[bot]
Deploy from GitHub 1af737237f5d10dfa9cf12849d98f47c3b30ce37 (filtered: code + Dockerfile + README + NOTICES only)
a2f55b2 Download src/deepfake_scanner/api/schemas.py from Veridicate/scanner: direct link, hf CLI and curl.
- Browser
- Download file 3.5 kB
-
https://huggingface.co/spaces/Veridicate/scanner/resolve/main/src/deepfake_scanner/api/schemas.py
- Command line
-
hf download hf://spaces/Veridicate/scanner/src/deepfake_scanner/api/schemas.py
-
curl -L -o schemas.py https://huggingface.co/spaces/Veridicate/scanner/resolve/main/src/deepfake_scanner/api/schemas.py
3.5 kB
| """ | |
| API schemas (v1). | |
| These are the public contract for the /v1/scan/image endpoint. Treat any change | |
| to a field name, type, or required-ness as a breaking change. | |
| Forward-compatibility notes | |
| --------------------------- | |
| • `probabilities` is a fixed 4-class vector. Stage 1 only meaningfully populates | |
| `authentic` and `ai_generated`; `deepfake` and `edited` start at 0.0 until | |
| the corresponding detectors come online in Stage 2. Clients should treat 0.0 | |
| as "not assessed" for an unsigned-classifier slot — but the field is always | |
| present so the schema itself never changes. | |
| • `signals` is a list, currently with a single entry for the CLIP detector. | |
| More detectors (frequency, face-swap) append to this list in later stages. | |
| • `provenance` is always present. When C2PA is disabled or unavailable, | |
| `c2pa_present` is False and `c2pa_valid` is None. | |
| """ | |
| from __future__ import annotations | |
| from typing import Literal | |
| from pydantic import BaseModel, Field | |
| # The 4-class taxonomy. New classes must NOT be added without bumping API to v2. | |
| Verdict = Literal["authentic", "ai_generated", "deepfake", "edited", "uncertain"] | |
| class Probabilities(BaseModel): | |
| """Probability mass over the 4 mutually-exclusive classes. | |
| Sums to 1.0 (allowing for floating-point rounding within ±1e-3). | |
| """ | |
| authentic: float = Field(ge=0.0, le=1.0) | |
| ai_generated: float = Field(ge=0.0, le=1.0) | |
| deepfake: float = Field(ge=0.0, le=1.0) | |
| edited: float = Field(ge=0.0, le=1.0) | |
| class DetectorSignal(BaseModel): | |
| """Per-detector contribution, surfaced for transparency / debugging. | |
| `score` is the detector's own internal "fakeness" estimate in [0, 1]; | |
| its meaning depends on the detector. Aggregation into `probabilities` | |
| happens in the ensemble layer. | |
| """ | |
| name: str | |
| score: float = Field(ge=0.0, le=1.0) | |
| notes: str | None = None | |
| class Provenance(BaseModel): | |
| """C2PA / Content Credentials check. | |
| A trustworthy C2PA manifest from a known camera or generator can short- | |
| circuit the model — those signals are currently advisory only. | |
| """ | |
| c2pa_present: bool | |
| c2pa_valid: bool | None = None # None → not checked / unverifiable | |
| issuer: str | None = None # e.g. "Sony", "OpenAI", "Adobe" | |
| claim_generator: str | None = None # raw claim_generator string from the manifest | |
| # True when a manifest anywhere in the chain declares an AI digital source | |
| # type (IPTC trainedAlgorithmicMedia). This is what can override the model. | |
| ai_declared: bool = False | |
| class ScanResponse(BaseModel): | |
| """The /v1/scan/image response. This is the public contract.""" | |
| verdict: Verdict | |
| confidence: float = Field(ge=0.0, le=1.0) | |
| probabilities: Probabilities | |
| signals: list[DetectorSignal] | |
| provenance: Provenance | |
| # "model" — the verdict is the classifier's own output | |
| # "provenance" — a validated C2PA chain declared the image AI-generated and | |
| # overrode the classifier. Read this before treating | |
| # `probabilities` as the explanation for `verdict`: when the | |
| # source is provenance the probabilities still show what the | |
| # model thought, which may disagree. | |
| verdict_source: str = "model" | |
| model_version: str | |
| service_version: str | |
| scan_id: str | |
| latency_ms: float | |
| class ErrorResponse(BaseModel): | |
| """Uniform error shape for non-2xx responses.""" | |
| error: str | |
| detail: str | None = None | |