Spaces:
Running
Running
File size: 5,139 Bytes
2e175db | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | """
Central configuration for DeepFakeScanner.
All runtime knobs are read from environment variables with sensible defaults
so the service can run unchanged from local dev → HF Spaces → Cloud Run.
Read this once at import; do NOT scatter os.getenv() calls throughout the code.
"""
from __future__ import annotations
import os
from dataclasses import dataclass
def _env_bool(name: str, default: bool) -> bool:
raw = os.getenv(name)
if raw is None:
return default
return raw.strip().lower() in {"1", "true", "yes", "on"}
def _env_int(name: str, default: int) -> int:
raw = os.getenv(name)
if raw is None:
return default
try:
return int(raw)
except ValueError:
return default
@dataclass(frozen=True)
class Settings:
# ------------------------------------------------------------------ API
api_title: str = "DeepFakeScanner"
api_version: str = "0.2.0"
max_upload_bytes: int = _env_int("MAX_UPLOAD_BYTES", 10 * 1024 * 1024) # 10 MB
# --------------------------------------------------------- Image policy
# Privacy-by-default: visitor uploads are NEVER persisted.
# Logged-in paid users will be able to opt in later via a separate flag.
store_uploads: bool = _env_bool("STORE_UPLOADS", False)
# ---------------------------------------------------------- Detectors
# Stage 1: only the CLIP-based classifier is wired up.
# Stage 2 will flip these on as the detectors are trained / verified.
enable_clip_detector: bool = _env_bool("ENABLE_CLIP_DETECTOR", True)
enable_frequency_detector: bool = _env_bool("ENABLE_FREQUENCY_DETECTOR", False)
enable_face_swap_detector: bool = _env_bool("ENABLE_FACE_SWAP_DETECTOR", False)
# The CLIP backbone we use for feature extraction.
# OpenAI CLIP ViT-B/32 weights are MIT-licensed (commercially safe).
clip_model_name: str = os.getenv("CLIP_MODEL_NAME", "openai/clip-vit-base-patch32")
# Path to the trained classifier-head checkpoint. ClipClassifier auto-
# loads this in __init__ if the file exists. The same env var works
# locally (dev machine) and inside the inference Docker image.
# Stage 3A: head_v3a.pt (multi-generator: Flux+SDXL+SD3.5+AuraFlow).
head_checkpoint_path: str = os.getenv(
"HEAD_CHECKPOINT_PATH", "data/checkpoints/head_v3a.pt"
)
# Fallback for production: if the local checkpoint file isn't present,
# ClipClassifier downloads the weights from this HF Hub model repo at
# startup. The repo is PRIVATE — the container authenticates with the
# HF_TOKEN secret set in the HF Space settings (huggingface_hub reads
# HF_TOKEN from the environment automatically). Setting this to an
# empty string disables the fallback (used in tests).
# Stage 3A: head_v3a.pt. The Stage 2 head_v1.pt remains in the same
# private repo for rollback — set HEAD_CHECKPOINT_HF_FILENAME=head_v1.pt
# (and MODEL_VERSION=v0.3.0-stage2) to revert without a redeploy.
head_checkpoint_hf_repo: str = os.getenv(
"HEAD_CHECKPOINT_HF_REPO", "Veridicate/scanner-head-v1"
)
head_checkpoint_hf_filename: str = os.getenv(
"HEAD_CHECKPOINT_HF_FILENAME", "head_v3a.pt"
)
# ---------------------------------------------------------- Provenance
enable_c2pa_check: bool = _env_bool("ENABLE_C2PA_CHECK", True)
# ------------------------------------------------------------ Storage
# Postgres URL for scan records (None → in-memory fallback for local dev).
database_url: str | None = os.getenv("DATABASE_URL")
# S3-compatible blob storage (e.g. Cloudflare R2). Only used when
# store_uploads is True AND a paid user opts in.
blob_endpoint: str | None = os.getenv("BLOB_ENDPOINT")
blob_bucket: str | None = os.getenv("BLOB_BUCKET")
# ---------------------------------------------------- Model identifier
# Surfaced in API responses so clients can pin behaviour to a version.
# v0.4.0-stage3a = CLIP head trained on a multi-generator dataset
# (50k Flux + 20k SDXL + 20k SD 3.5 + 10k AuraFlow + matched authentic).
# In-distribution test accuracy 98.43%; +5.55 pp vs the Stage 2 head on
# the SDXL hold-out (a generator never seen in training). See
# docs/stage3a-implementation.md.
# Previous: v0.3.0-stage2 (Flux-only, head_v1.pt) — still available in the
# HF Hub repo for rollback (see head_checkpoint_hf_filename above).
model_version: str = os.getenv("MODEL_VERSION", "v0.4.0-stage3a")
# --------------------------------------------------------------- CORS
# Browser preflight allowlist for the static-HTML frontend. The default
# covers the production domain, any Cloudflare Pages preview, and
# localhost (any port) for local dev. Override via env var if a new
# origin needs access.
cors_allow_origin_regex: str = os.getenv(
"CORS_ALLOW_ORIGIN_REGEX",
r"^(https://(www\.)?veridicate\.com|https://[a-z0-9-]+\.pages\.dev|https://[a-z0-9-]+\.dulipcf\.workers\.dev|http://localhost(:\d+)?|http://127\.0\.0\.1(:\d+)?)$",
)
settings = Settings()
|