Spaces:
Runtime error
Runtime error
YassmineNouisser commited on
Commit ·
179d606
0
Parent(s):
Verify — multimodal disinformation detection platform (6 modules + chatbot)
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .dockerignore +44 -0
- .env.example +59 -0
- .gitattributes +7 -0
- .gitignore +73 -0
- AI_Investigate_Report_COMPLETE.pdf +3 -0
- DEPLOYMENT.md +238 -0
- Dockerfile +97 -0
- MODELS.md +105 -0
- README.md +177 -0
- Verify_Description_Commerciale.html +358 -0
- Verify_Description_Commerciale.pdf +3 -0
- archive.html +199 -0
- article.html +161 -0
- assets/css/styles.css +0 -0
- assets/img/ads-marketing.jpg +3 -0
- assets/img/ads.jpg +3 -0
- assets/img/ads.png +3 -0
- assets/img/ai-generative.jpg +3 -0
- assets/img/cover1.png +3 -0
- assets/img/cover2.png +3 -0
- assets/img/cover4.png +3 -0
- assets/img/cover5.png +3 -0
- assets/img/cover6.png +3 -0
- assets/img/deepfake-hero.jpg +3 -0
- assets/img/examples/m-ai1.png +3 -0
- assets/img/examples/m-ai2.png +3 -0
- assets/img/examples/m-ai3.png +3 -0
- assets/img/examples/m-doc1.jpg +3 -0
- assets/img/examples/m-doc2.jpg +3 -0
- assets/img/examples/m-edit1.jpg +3 -0
- assets/img/examples/m-manip2.jpg +3 -0
- assets/img/examples/m-manip4.jpg +3 -0
- assets/img/examples/m-manip6.jpg +3 -0
- assets/img/examples/m-news1.jpg +3 -0
- assets/img/examples/m-news2.jpg +3 -0
- assets/img/examples/m-orig1.jpg +3 -0
- assets/img/examples/m-real1.jpg +3 -0
- assets/img/examples/m-real2.jpg +3 -0
- assets/img/examples/m-real3.jpg +3 -0
- assets/img/examples/m-real4.jpg +3 -0
- assets/img/factchecks/fc-elamra.png +3 -0
- assets/img/factchecks/fc-gabes.jpg +3 -0
- assets/img/factchecks/fc-ghannouchi.jpg +3 -0
- assets/img/factchecks/fc-guardian.png +3 -0
- assets/img/factchecks/fc-henneberg.png +3 -0
- assets/img/factchecks/fc-kerkennah.jpg +3 -0
- assets/img/factchecks/fc-migrant.jpg +3 -0
- assets/img/factchecks/fc-nasrallah.png +3 -0
- assets/img/factchecks/fc-yutong.png +3 -0
- assets/img/factchecks/fc-zammel.png +3 -0
.dockerignore
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Speed up `docker build` by skipping files the runtime doesn't need.
|
| 2 |
+
|
| 3 |
+
# Local environments / caches
|
| 4 |
+
.venv/
|
| 5 |
+
venv/
|
| 6 |
+
__pycache__/
|
| 7 |
+
*.pyc
|
| 8 |
+
.pytest_cache/
|
| 9 |
+
.mypy_cache/
|
| 10 |
+
|
| 11 |
+
# OS / IDE
|
| 12 |
+
.DS_Store
|
| 13 |
+
Thumbs.db
|
| 14 |
+
.idea/
|
| 15 |
+
.vscode/
|
| 16 |
+
|
| 17 |
+
# Large contributor notebooks (documentation only — not needed at runtime)
|
| 18 |
+
malek/*.ipynb
|
| 19 |
+
rayen/*.ipynb
|
| 20 |
+
youssef/*.ipynb
|
| 21 |
+
yassmine/*.ipynb
|
| 22 |
+
*.ipynb_checkpoints/
|
| 23 |
+
|
| 24 |
+
# Trained weights (pulled at runtime from HF Dataset via scripts/download_models.py)
|
| 25 |
+
backend/data/io1_resnet50.pth
|
| 26 |
+
backend/data/io1_resnet50_deepfake.pth
|
| 27 |
+
islem/*.pth
|
| 28 |
+
|
| 29 |
+
# Large generic weights (downloaded fresh in the Dockerfile pre-warm step)
|
| 30 |
+
yolov8m.pt
|
| 31 |
+
|
| 32 |
+
# Local secrets — never bake into an image
|
| 33 |
+
.env
|
| 34 |
+
.env.local
|
| 35 |
+
backend/data/openai_key.txt
|
| 36 |
+
*.key
|
| 37 |
+
|
| 38 |
+
# Project documentation files unrelated to runtime
|
| 39 |
+
ios images/
|
| 40 |
+
demo/
|
| 41 |
+
*.pdf
|
| 42 |
+
*.docx
|
| 43 |
+
*.xlsx
|
| 44 |
+
!backend/data/IO6_Base_Reference_V3_FULL.xlsx
|
.env.example
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ─── Verify — Configuration template ───────────────────────────────────────
|
| 2 |
+
# Copy this file to `.env` and fill in only the variables you need to override.
|
| 3 |
+
# `.env` is gitignored — never commit your real keys.
|
| 4 |
+
|
| 5 |
+
# ─── Module loading ─────────────────────────────────────────────────────────
|
| 6 |
+
# Comma-separated list of modules to load at startup. Empty = all modules with
|
| 7 |
+
# status="active" (i.e. all 6 by default).
|
| 8 |
+
# LOAD_MODULES=io3,io1
|
| 9 |
+
|
| 10 |
+
# ─── Compute device ─────────────────────────────────────────────────────────
|
| 11 |
+
# FORCE_DEVICE=cpu # set to "cpu" to disable GPU detection
|
| 12 |
+
# FORCE_DEVICE=cuda
|
| 13 |
+
|
| 14 |
+
# ─── OpenAI API (optional — used ONLY by the chatbot module, NOT by the 6 verdicts) ───
|
| 15 |
+
# Get your key at https://platform.openai.com/api-keys
|
| 16 |
+
# OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
| 17 |
+
|
| 18 |
+
# ─── io1 — Fake Media Detection ─────────────────────────────────────────────
|
| 19 |
+
# IO1_USE_OPENAI=off # set "on" to delegate the verdict to GPT-4o (default: local)
|
| 20 |
+
# IO1_DEEPFAKE_THRESHOLD=0.60 # p_fake threshold for the ResNet50 ensemble
|
| 21 |
+
# IO1_USE_IMAGE_DEEPFAKE=on # load Islem's Model X (resnet50_deepfake.pth)
|
| 22 |
+
# IO1_USE_AI_DETECTOR=on # enable the 2-detector AI consensus (Organika + umm-maybe)
|
| 23 |
+
# IO1_AI_TIER1_PRIMARY=0.95 # tuning of the consensus thresholds (see ai_detector.py)
|
| 24 |
+
# IO1_AI_TIER1_SECONDARY=0.20
|
| 25 |
+
# IO1_AI_TIER2_PRIMARY=0.90
|
| 26 |
+
# IO1_AI_TIER2_SECONDARY=0.40
|
| 27 |
+
|
| 28 |
+
# ─── io2 — Visual Manipulation / Persuasion ─────────────────────────────────
|
| 29 |
+
# IO2_USE_OPENAI=off
|
| 30 |
+
# IO2_CLICKBAIT_MODEL=valurank/distilroberta-clickbait
|
| 31 |
+
# IO2_ENABLE_TRANSLATION=auto # set "off" to skip the FR→EN MarianMT translator
|
| 32 |
+
|
| 33 |
+
# ─── io3 — Image-Caption Coherence ──────────────────────────────────────────
|
| 34 |
+
# CLIP_FINETUNED_PATH=clip_finetuned_coherence.pth # optional fine-tuned CLIP checkpoint
|
| 35 |
+
# SAM_CHECKPOINT=sam_vit_b_01ec64.pth # optional Segment-Anything weights
|
| 36 |
+
# YOLO_WEIGHTS=yolov8m.pt
|
| 37 |
+
# WHISPER_MODEL=small
|
| 38 |
+
# ENABLE_SAM=auto
|
| 39 |
+
|
| 40 |
+
# ─── io4 — Image Tampering Detection ────────────────────────────────────────
|
| 41 |
+
# IO4_USE_OPENAI=off
|
| 42 |
+
# IO4_ELA_QUALITY=90 # JPEG re-save quality used by ELA
|
| 43 |
+
# IO4_THRESHOLD=0.50 # legacy CNN threshold (ignored when forensics path is used)
|
| 44 |
+
|
| 45 |
+
# ─── io5 — Caption Fidelity ─────────────────────────────────────────────────
|
| 46 |
+
# IO5_CLIP_MODEL=ViT-B-32
|
| 47 |
+
# IO5_FAITHFUL_THRESHOLD=0.60
|
| 48 |
+
# IO5_MISLEADING_THRESHOLD=0.40
|
| 49 |
+
|
| 50 |
+
# ─── io6 — Cosmetic Ads Fact-Check ──────────────────────────────────────────
|
| 51 |
+
# IO6_USE_OPENAI=off
|
| 52 |
+
# IO6_WHISPER_MODEL=tiny # tiny|base|small|medium — accuracy/speed trade-off
|
| 53 |
+
# IO6_YOLO_WEIGHTS=yolov8n.pt
|
| 54 |
+
# IO6_ENABLE_MINILM=auto
|
| 55 |
+
# IO6_KB_PATH=backend/data/IO6_Base_Reference_V3_FULL.xlsx
|
| 56 |
+
|
| 57 |
+
# ─── Narrative layer (post-processing) ──────────────────────────────────────
|
| 58 |
+
# IO_XAI_NARRATIVE=off # set "off" to disable the AI-written explanation (saves OpenAI calls)
|
| 59 |
+
# IO_XAI_MODEL=gpt-4o-mini
|
.gitattributes
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.png filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.jpg filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.jpeg filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.pdf filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.xlsx filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ─── Secrets (NEVER commit) ──────────────────────────────────────────────
|
| 2 |
+
.env
|
| 3 |
+
.env.local
|
| 4 |
+
backend/data/openai_key.txt
|
| 5 |
+
*.key
|
| 6 |
+
*.pem
|
| 7 |
+
secrets/
|
| 8 |
+
credentials.json
|
| 9 |
+
google-services.json
|
| 10 |
+
|
| 11 |
+
# ─── Python ───────────────────────────────────────────────────────────────
|
| 12 |
+
.venv/
|
| 13 |
+
venv/
|
| 14 |
+
env/
|
| 15 |
+
__pycache__/
|
| 16 |
+
*.py[cod]
|
| 17 |
+
*$py.class
|
| 18 |
+
*.egg-info/
|
| 19 |
+
.pytest_cache/
|
| 20 |
+
.mypy_cache/
|
| 21 |
+
.ruff_cache/
|
| 22 |
+
|
| 23 |
+
# ─── Trained model weights (downloaded via scripts/download_models.py) ────
|
| 24 |
+
# GitHub blocks files > 100 MB; combined model size is ~250 MB+
|
| 25 |
+
*.pth
|
| 26 |
+
*.pt
|
| 27 |
+
*.onnx
|
| 28 |
+
*.h5
|
| 29 |
+
*.keras
|
| 30 |
+
*.bin
|
| 31 |
+
*.safetensors
|
| 32 |
+
|
| 33 |
+
# Exception: small generic YOLO weights that are useful to ship if small enough
|
| 34 |
+
!yolov8n.pt
|
| 35 |
+
|
| 36 |
+
# ─── HuggingFace / cache ──────────────────────────────────────────────────
|
| 37 |
+
.cache/
|
| 38 |
+
~/.cache/huggingface/
|
| 39 |
+
|
| 40 |
+
# ─── OS / IDE ─────────────────────────────────────────────────────────────
|
| 41 |
+
.DS_Store
|
| 42 |
+
Thumbs.db
|
| 43 |
+
.idea/
|
| 44 |
+
.vscode/
|
| 45 |
+
*.swp
|
| 46 |
+
*.swo
|
| 47 |
+
*~
|
| 48 |
+
|
| 49 |
+
# ─── Jupyter ──────────────────────────────────────────────────────────────
|
| 50 |
+
.ipynb_checkpoints/
|
| 51 |
+
*.ipynb_meta
|
| 52 |
+
|
| 53 |
+
# ─── Build / dist ─────────────────────────────────────────────────────────
|
| 54 |
+
dist/
|
| 55 |
+
build/
|
| 56 |
+
node_modules/
|
| 57 |
+
|
| 58 |
+
# ─── Temporary / logs ─────────────────────────────────────────────────────
|
| 59 |
+
*.log
|
| 60 |
+
*.tmp
|
| 61 |
+
tmp/
|
| 62 |
+
/temp/
|
| 63 |
+
.tox/
|
| 64 |
+
|
| 65 |
+
# ─── Personal scratch files ───────────────────────────────────────────────
|
| 66 |
+
test_local.py
|
| 67 |
+
notes.md
|
| 68 |
+
|
| 69 |
+
# Contributor notebooks (kept locally — too large for HF Space git, ~40 MB combined)
|
| 70 |
+
malek/*.ipynb
|
| 71 |
+
rayen/*.ipynb
|
| 72 |
+
youssef/*.ipynb
|
| 73 |
+
yassmine/*.ipynb
|
AI_Investigate_Report_COMPLETE.pdf
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e5fbe755ecdb47fd2d62dbc779e4013618ee2848eb8957507a6da0dde1587f7f
|
| 3 |
+
size 1920340
|
DEPLOYMENT.md
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Verify — Free deployment guide (HuggingFace Spaces)
|
| 2 |
+
|
| 3 |
+
This guide deploys the **full Verify platform** (6 detection modules + chatbot + static frontend)
|
| 4 |
+
**on a single free HuggingFace Space**. The jury gets one public URL — e.g. `https://yassminenouisser-verify.hf.space` — that they can hit with their browser to test everything.
|
| 5 |
+
|
| 6 |
+
> **Total cost: 0 €.** Total wall-clock time the first time: ~30 min (mostly waiting for the Space to build).
|
| 7 |
+
> Cold-start delay for the first request after 48h of inactivity: ~1 min (the persistent storage keeps models warm).
|
| 8 |
+
|
| 9 |
+
---
|
| 10 |
+
|
| 11 |
+
## Architecture
|
| 12 |
+
|
| 13 |
+
```
|
| 14 |
+
┌──────────────────────────────────────────────────┐
|
| 15 |
+
│ HuggingFace Space (Docker SDK, CPU Basic 16GB) │
|
| 16 |
+
│ │
|
| 17 |
+
│ ┌────────────────────────────────────────┐ │
|
| 18 |
+
│ │ FastAPI (uvicorn :7860) │ │
|
| 19 |
+
│ │ ├─ / static frontend │ │
|
| 20 |
+
│ │ ├─ /api/io[1-6]/... detection ML │ │
|
| 21 |
+
│ │ ├─ /api/chat/... chatbot │ │
|
| 22 |
+
│ │ └─ /health, /docs │ │
|
| 23 |
+
│ └────────────────────────────────────────┘ │
|
| 24 |
+
│ │
|
| 25 |
+
│ Secrets (encrypted): │
|
| 26 |
+
│ OPENAI_API_KEY │
|
| 27 |
+
│ IO1_RESNET50_URL ← from HF Dataset │
|
| 28 |
+
│ IO1_RESNET50_DEEPFAKE_URL ← from HF Dataset │
|
| 29 |
+
└──────────────────────────────────────────────────┘
|
| 30 |
+
▲
|
| 31 |
+
│
|
| 32 |
+
┌─────────────┴────────────────┐
|
| 33 |
+
│ HuggingFace Dataset (free) │
|
| 34 |
+
│ Verify-weights (private) │
|
| 35 |
+
│ ├─ best_ResNet50.pth │
|
| 36 |
+
│ └─ resnet50_deepfake.pth │
|
| 37 |
+
└──────────────────────────────┘
|
| 38 |
+
```
|
| 39 |
+
|
| 40 |
+
The Space hosts everything in one container. The two heavy `.pth` weights are stored in a
|
| 41 |
+
companion **HuggingFace Dataset** (also free, unlimited) so the Space repo stays under the
|
| 42 |
+
git-LFS-free 10 MB-per-file limit.
|
| 43 |
+
|
| 44 |
+
---
|
| 45 |
+
|
| 46 |
+
## Step 1 — Create a HuggingFace account
|
| 47 |
+
|
| 48 |
+
Go to **https://huggingface.co/join**, create your free account, verify your email.
|
| 49 |
+
Note your username (e.g. `yassminenouisser`). You'll use it everywhere below.
|
| 50 |
+
|
| 51 |
+
---
|
| 52 |
+
|
| 53 |
+
## Step 2 — Upload Islem's `.pth` weights to a HF Dataset
|
| 54 |
+
|
| 55 |
+
The two ResNet50 checkpoints (94 MB each) cannot live in the Space's git repo. We host them in
|
| 56 |
+
a HuggingFace Dataset.
|
| 57 |
+
|
| 58 |
+
1. Go to **https://huggingface.co/new-dataset**
|
| 59 |
+
2. Name: `verify-weights`
|
| 60 |
+
3. Visibility: **Private** (the weights are Islem's research artifacts)
|
| 61 |
+
4. License: `other`
|
| 62 |
+
5. Click **Create dataset**
|
| 63 |
+
|
| 64 |
+
Then upload the files (web UI is the easiest):
|
| 65 |
+
|
| 66 |
+
1. Open your new dataset → **Files** tab → **Add file** → **Upload files**
|
| 67 |
+
2. Drag-drop `backend/data/io1_resnet50.pth` and `backend/data/io1_resnet50_deepfake.pth`
|
| 68 |
+
3. Commit
|
| 69 |
+
|
| 70 |
+
The files are now at:
|
| 71 |
+
- `https://huggingface.co/datasets/<your-username>/verify-weights/resolve/main/io1_resnet50.pth`
|
| 72 |
+
- `https://huggingface.co/datasets/<your-username>/verify-weights/resolve/main/io1_resnet50_deepfake.pth`
|
| 73 |
+
|
| 74 |
+
> ⚠️ **Private dataset**: the Space will need a **read-token** to download these.
|
| 75 |
+
> Generate one at https://huggingface.co/settings/tokens (role: `read`). Copy it; you'll paste
|
| 76 |
+
> it as a Space Secret in step 4.
|
| 77 |
+
|
| 78 |
+
---
|
| 79 |
+
|
| 80 |
+
## Step 3 — Create the HuggingFace Space
|
| 81 |
+
|
| 82 |
+
1. Go to **https://huggingface.co/new-space**
|
| 83 |
+
2. Owner: your username
|
| 84 |
+
3. Name: `verify` (the public URL will be `https://<username>-verify.hf.space`)
|
| 85 |
+
4. License: `apache-2.0`
|
| 86 |
+
5. **SDK: `Docker`** (NOT Gradio/Streamlit — we use our own Dockerfile)
|
| 87 |
+
6. Hardware: **CPU basic — free** (16 GB RAM, 2 vCPU)
|
| 88 |
+
7. Visibility: **Public**
|
| 89 |
+
8. Click **Create Space**
|
| 90 |
+
|
| 91 |
+
The Space is created empty. Don't push anything yet — first configure the secrets.
|
| 92 |
+
|
| 93 |
+
---
|
| 94 |
+
|
| 95 |
+
## Step 4 — Configure Space Secrets (encrypted environment variables)
|
| 96 |
+
|
| 97 |
+
In your Space, go to **Settings** → **Variables and secrets** → **New secret**. Add these one by one:
|
| 98 |
+
|
| 99 |
+
| Secret name | Value | Why |
|
| 100 |
+
|---|---|---|
|
| 101 |
+
| `OPENAI_API_KEY` | `sk-proj-...` (your real key) | Needed by the chatbot module and the narrative layer |
|
| 102 |
+
| `IO1_RESNET50_URL` | `https://huggingface.co/datasets/<username>/verify-weights/resolve/main/io1_resnet50.pth` | Where the build script pulls Islem's weights |
|
| 103 |
+
| `IO1_RESNET50_DEEPFAKE_URL` | `https://huggingface.co/datasets/<username>/verify-weights/resolve/main/io1_resnet50_deepfake.pth` | Same, for Model X |
|
| 104 |
+
| `HUGGINGFACE_HUB_TOKEN` | the read-token you generated in step 2 | Lets the build authenticate to download from the private dataset |
|
| 105 |
+
|
| 106 |
+
Click **Save** after each one. Secrets are encrypted and never visible in the Space's logs or code.
|
| 107 |
+
|
| 108 |
+
---
|
| 109 |
+
|
| 110 |
+
## Step 5 — Push the Verify code to the Space
|
| 111 |
+
|
| 112 |
+
Each HF Space is a git repo. From your local Verify checkout:
|
| 113 |
+
|
| 114 |
+
```bash
|
| 115 |
+
cd /Users/yassminesmachine/Desktop/template
|
| 116 |
+
|
| 117 |
+
# 1. Make sure the local repo is up to date (no uncommitted work)
|
| 118 |
+
git status
|
| 119 |
+
git add -A
|
| 120 |
+
git commit -m "Prepare for HuggingFace Space deployment"
|
| 121 |
+
|
| 122 |
+
# 2. Add HF Space as a remote (use your own username + space name)
|
| 123 |
+
git remote add space https://huggingface.co/spaces/<username>/verify
|
| 124 |
+
|
| 125 |
+
# 3. Push
|
| 126 |
+
git push space main
|
| 127 |
+
|
| 128 |
+
# (HF git will prompt for your HuggingFace credentials — username + an access token from
|
| 129 |
+
# https://huggingface.co/settings/tokens, role 'write')
|
| 130 |
+
```
|
| 131 |
+
|
| 132 |
+
Once the push completes, HuggingFace starts building the Docker image automatically. You can
|
| 133 |
+
watch the build at **https://huggingface.co/spaces/`<username>`/verify** → **Logs** tab.
|
| 134 |
+
|
| 135 |
+
> ⏱ **First build takes ~15 min** because the Dockerfile pre-downloads all HuggingFace models
|
| 136 |
+
> (CLIP, TrOCR, Whisper, etc.) inside the image. Subsequent builds are much faster — only the
|
| 137 |
+
> changed layers rebuild.
|
| 138 |
+
|
| 139 |
+
---
|
| 140 |
+
|
| 141 |
+
## Step 6 — Verify the deployment
|
| 142 |
+
|
| 143 |
+
When the build is done and the Space status flips to **Running**:
|
| 144 |
+
|
| 145 |
+
1. Open `https://<username>-verify.hf.space` in your browser → you should see the Verify homepage.
|
| 146 |
+
2. Click **Verifier** → choose any module → upload an image → click **Analyze**.
|
| 147 |
+
3. The first analysis after a cold start takes ~30-60 s (CPU + first-time module init);
|
| 148 |
+
subsequent calls are 5-15 s.
|
| 149 |
+
|
| 150 |
+
Sanity checks:
|
| 151 |
+
|
| 152 |
+
```bash
|
| 153 |
+
# From your laptop — confirms the API is reachable
|
| 154 |
+
curl https://<username>-verify.hf.space/health | jq .status # → "ok"
|
| 155 |
+
|
| 156 |
+
curl https://<username>-verify.hf.space/api # → JSON describing the 6 modules + chatbot
|
| 157 |
+
```
|
| 158 |
+
|
| 159 |
+
---
|
| 160 |
+
|
| 161 |
+
## Step 7 — Fill in the ESPRIT submission form
|
| 162 |
+
|
| 163 |
+
Now you can fill in section 2 of the submission PDF:
|
| 164 |
+
|
| 165 |
+
| Champ | Valeur |
|
| 166 |
+
|---|---|
|
| 167 |
+
| Nom du projet | `Esprit-PI-<TaClasse>-2526-Verify` |
|
| 168 |
+
| Lien GitHub | `https://github.com/<YourGitHub>/Esprit-PI-<TaClasse>-2526-Verify` |
|
| 169 |
+
| Lien de déploiement | **`https://<username>-verify.hf.space`** ✓ |
|
| 170 |
+
| Type de projet | IA |
|
| 171 |
+
| Commande de lancement | `docker build -t verify . && docker run -p 7860:7860 verify` (or local: `uvicorn backend.main:app --port 8000`) |
|
| 172 |
+
| Temps d'installation estimé | < 10 min (local) or instant (deployed link) |
|
| 173 |
+
|
| 174 |
+
---
|
| 175 |
+
|
| 176 |
+
## Updating the Space later
|
| 177 |
+
|
| 178 |
+
After pushing changes to GitHub, push the same commits to the Space:
|
| 179 |
+
|
| 180 |
+
```bash
|
| 181 |
+
git push origin main # GitHub
|
| 182 |
+
git push space main # HF Space (triggers rebuild)
|
| 183 |
+
```
|
| 184 |
+
|
| 185 |
+
If you only changed Python code (no new model), the rebuild takes ~2-3 min thanks to Docker
|
| 186 |
+
layer caching.
|
| 187 |
+
|
| 188 |
+
---
|
| 189 |
+
|
| 190 |
+
## Troubleshooting
|
| 191 |
+
|
| 192 |
+
### "Build failed: file too large"
|
| 193 |
+
GitHub-via-LFS isn't enabled by default on HF Spaces. Make sure `.gitignore` is excluding all
|
| 194 |
+
`*.pth`/`*.pt` files except `yolov8n.pt` (it's only 7 MB).
|
| 195 |
+
Check with: `git ls-files | xargs -I{} ls -l {} 2>/dev/null | awk '$5 > 10000000 {print}'`
|
| 196 |
+
|
| 197 |
+
### "Space running out of memory"
|
| 198 |
+
The default CPU-basic Space has 16 GB RAM, which is enough. If you upgraded the hardware and
|
| 199 |
+
hit OOM, try `LOAD_MODULES=io1,io4` to load fewer modules at startup (set this as a Space variable).
|
| 200 |
+
|
| 201 |
+
### Chatbot returns "service unavailable"
|
| 202 |
+
The `OPENAI_API_KEY` secret is missing or the key is invalid. Re-set it in **Space Settings** →
|
| 203 |
+
**Variables and secrets**, then restart the Space (top-right menu → **Restart this Space**).
|
| 204 |
+
|
| 205 |
+
### Cold start is very long (> 3 min)
|
| 206 |
+
The first request after a 48h sleep needs to (a) re-download HF models if persistent storage was
|
| 207 |
+
not enabled, (b) load all PyTorch models into RAM. Enable **Persistent storage** in Space
|
| 208 |
+
settings (free 50 GB tier — was previously paid) to keep the cache between sleeps.
|
| 209 |
+
|
| 210 |
+
### Frontend says "Service unavailable"
|
| 211 |
+
Open the browser DevTools console. If `fetch('/api/io1/health')` returns 404, the FastAPI static
|
| 212 |
+
mount is broken — check `backend/main.py` and confirm the `app.mount("/", StaticFiles(...))` line
|
| 213 |
+
is present and that `index.html` exists at the repo root.
|
| 214 |
+
|
| 215 |
+
### Some images come up as REAL when they should be FAKE
|
| 216 |
+
This is the limit of the open-source AI detectors (see `MODELS.md`). The deepfake ensemble +
|
| 217 |
+
2-detector consensus catches ~66% of ThisPersonDoesNotExist images and ~99% of obvious DALL-E /
|
| 218 |
+
Midjourney / Flux images. Re-test with another sample if you hit a model blind spot.
|
| 219 |
+
|
| 220 |
+
---
|
| 221 |
+
|
| 222 |
+
## Alternative: deploy WITHOUT HuggingFace Spaces (local Docker only)
|
| 223 |
+
|
| 224 |
+
If for any reason you cannot use HF Spaces, the project also runs with plain Docker. In your
|
| 225 |
+
local terminal:
|
| 226 |
+
|
| 227 |
+
```bash
|
| 228 |
+
docker build -t verify .
|
| 229 |
+
docker run -p 7860:7860 \
|
| 230 |
+
-e OPENAI_API_KEY=sk-... \
|
| 231 |
+
-e IO1_RESNET50_URL=https://... \
|
| 232 |
+
-e IO1_RESNET50_DEEPFAKE_URL=https://... \
|
| 233 |
+
verify
|
| 234 |
+
```
|
| 235 |
+
|
| 236 |
+
Then open `http://localhost:7860`. The jury will need Docker on their machine — but the
|
| 237 |
+
**ESPRIT acceptance criterion for IA projects** (guide page 8) is precisely that: local launch in
|
| 238 |
+
<20 min with Docker. So this fully passes the rubric even without HF Spaces.
|
Dockerfile
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ─── Verify — single-container deployment for HuggingFace Spaces ────────────
|
| 2 |
+
# Serves the FastAPI backend (6 detection modules + chatbot) AND the static frontend
|
| 3 |
+
# from the same container, on port 7860 (HuggingFace Spaces standard).
|
| 4 |
+
#
|
| 5 |
+
# Pre-downloads the heavy HuggingFace models at BUILD time so the Space cold-start
|
| 6 |
+
# stays under ~60 s instead of ~10 min on first user request.
|
| 7 |
+
#
|
| 8 |
+
# Required Space "Secrets" (set in Space Settings → Variables and secrets):
|
| 9 |
+
# OPENAI_API_KEY for the chatbot module (optional but recommended)
|
| 10 |
+
# IO1_RESNET50_URL HF dataset URL for Islem's best_ResNet50.pth
|
| 11 |
+
# IO1_RESNET50_DEEPFAKE_URL HF dataset URL for Islem's resnet50_deepfake.pth
|
| 12 |
+
# HUGGINGFACE_HUB_TOKEN only if the weights dataset is private
|
| 13 |
+
|
| 14 |
+
FROM python:3.11-slim
|
| 15 |
+
|
| 16 |
+
# ─── System packages ────────────────────────────────────────────────────────
|
| 17 |
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
| 18 |
+
ffmpeg \
|
| 19 |
+
libgl1 \
|
| 20 |
+
libglib2.0-0 \
|
| 21 |
+
build-essential \
|
| 22 |
+
wget \
|
| 23 |
+
curl \
|
| 24 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 25 |
+
|
| 26 |
+
# ─── Layout & user ──────────────────────────────────────────────────────────
|
| 27 |
+
# HF Spaces runs the container as a non-root user with UID 1000.
|
| 28 |
+
RUN useradd -m -u 1000 verify
|
| 29 |
+
USER verify
|
| 30 |
+
WORKDIR /home/verify/app
|
| 31 |
+
|
| 32 |
+
# Caches inside the user's home so HF Spaces persistent storage (if enabled) keeps them.
|
| 33 |
+
ENV HOME=/home/verify \
|
| 34 |
+
HF_HOME=/home/verify/.cache/huggingface \
|
| 35 |
+
TORCH_HOME=/home/verify/.cache/torch \
|
| 36 |
+
PYTHONUNBUFFERED=1 \
|
| 37 |
+
PIP_NO_CACHE_DIR=1
|
| 38 |
+
|
| 39 |
+
# ─── Python dependencies (cached layer) ─────────────────────────────────────
|
| 40 |
+
COPY --chown=verify:verify backend/requirements.txt backend/requirements.txt
|
| 41 |
+
RUN pip install --user --upgrade pip \
|
| 42 |
+
&& pip install --user -r backend/requirements.txt
|
| 43 |
+
|
| 44 |
+
ENV PATH="/home/verify/.local/bin:${PATH}"
|
| 45 |
+
|
| 46 |
+
# ─── Pre-warm the HuggingFace cache during build (saves cold-start time) ────
|
| 47 |
+
# This pulls the heaviest models so the first user request doesn't trigger a 5-minute
|
| 48 |
+
# download. Each line is independent — comment out any model you want to lazy-load.
|
| 49 |
+
RUN python -c "\
|
| 50 |
+
from open_clip import create_model_and_transforms, get_tokenizer; \
|
| 51 |
+
create_model_and_transforms('ViT-B-32', pretrained='openai'); \
|
| 52 |
+
create_model_and_transforms('ViT-L-14', pretrained='laion2b_s32b_b82k'); \
|
| 53 |
+
print('CLIP models cached')" \
|
| 54 |
+
&& python -c "\
|
| 55 |
+
from transformers import AutoTokenizer, AutoModelForSequenceClassification, \
|
| 56 |
+
AutoModelForImageClassification, AutoImageProcessor, \
|
| 57 |
+
TrOCRProcessor, VisionEncoderDecoderModel, MarianTokenizer, MarianMTModel; \
|
| 58 |
+
TrOCRProcessor.from_pretrained('microsoft/trocr-base-printed'); \
|
| 59 |
+
VisionEncoderDecoderModel.from_pretrained('microsoft/trocr-base-printed'); \
|
| 60 |
+
AutoTokenizer.from_pretrained('valurank/distilroberta-clickbait'); \
|
| 61 |
+
AutoModelForSequenceClassification.from_pretrained('valurank/distilroberta-clickbait'); \
|
| 62 |
+
AutoImageProcessor.from_pretrained('Organika/sdxl-detector'); \
|
| 63 |
+
AutoModelForImageClassification.from_pretrained('Organika/sdxl-detector'); \
|
| 64 |
+
AutoImageProcessor.from_pretrained('umm-maybe/AI-image-detector'); \
|
| 65 |
+
AutoModelForImageClassification.from_pretrained('umm-maybe/AI-image-detector'); \
|
| 66 |
+
MarianTokenizer.from_pretrained('Helsinki-NLP/opus-mt-fr-en'); \
|
| 67 |
+
MarianMTModel.from_pretrained('Helsinki-NLP/opus-mt-fr-en'); \
|
| 68 |
+
print('HF transformers cached')" \
|
| 69 |
+
&& python -c "\
|
| 70 |
+
import whisper; whisper.load_model('tiny'); whisper.load_model('small'); \
|
| 71 |
+
print('Whisper cached')" \
|
| 72 |
+
&& python -c "\
|
| 73 |
+
from sentence_transformers import SentenceTransformer; \
|
| 74 |
+
SentenceTransformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2'); \
|
| 75 |
+
print('MiniLM cached')"
|
| 76 |
+
|
| 77 |
+
# ─── EasyOCR models (download to a known place) ─────────────────────────────
|
| 78 |
+
RUN python -c "\
|
| 79 |
+
import easyocr; easyocr.Reader(['en', 'fr'], gpu=False, verbose=False); \
|
| 80 |
+
print('EasyOCR models cached')"
|
| 81 |
+
|
| 82 |
+
# ─── Application code ───────────────────────────────────────────────────────
|
| 83 |
+
COPY --chown=verify:verify . .
|
| 84 |
+
|
| 85 |
+
# ─── Pull Islem's .pth weights (private HF Dataset) ─────────────────────────
|
| 86 |
+
# The download script reads IO1_RESNET50_URL & IO1_RESNET50_DEEPFAKE_URL from env.
|
| 87 |
+
# Failing silently here keeps `docker build` reproducible without the secrets — the
|
| 88 |
+
# runtime will retry on startup using the Space's Secrets.
|
| 89 |
+
RUN python scripts/download_models.py || echo "[build] weights not downloaded (will retry at runtime)"
|
| 90 |
+
|
| 91 |
+
# ─── Runtime ─────��──────────────────────────────────────────────────────────
|
| 92 |
+
EXPOSE 7860
|
| 93 |
+
ENV PORT=7860
|
| 94 |
+
|
| 95 |
+
# Use a startup wrapper so we can retry the weights download with the Space secrets
|
| 96 |
+
# (which are NOT available during `docker build` — only at runtime).
|
| 97 |
+
CMD ["bash", "-c", "python scripts/download_models.py || true && uvicorn backend.main:app --host 0.0.0.0 --port ${PORT:-7860}"]
|
MODELS.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Verify — Models inventory
|
| 2 |
+
|
| 3 |
+
Exhaustive list of every model and trained weight file used by the Verify platform.
|
| 4 |
+
Total disk footprint after first run: **~4 Go** (cached in `~/.cache/huggingface/` and `~/.cache/torch/`).
|
| 5 |
+
Combined in-memory footprint when all modules are loaded: **~3 Go RAM**.
|
| 6 |
+
|
| 7 |
+
Files **with a download URL** = auto-fetched from HuggingFace Hub on first use (no manual setup).
|
| 8 |
+
Files **without** a URL = hosted on HuggingFace Hub by the Verify team (see `scripts/download_models.py`).
|
| 9 |
+
|
| 10 |
+
## io1 — Fake Media Detection (deepfake & AI-generated)
|
| 11 |
+
|
| 12 |
+
| Model | Type | Size | Source | Auto-download? |
|
| 13 |
+
|---|---|---|---|---|
|
| 14 |
+
| `io1_resnet50.pth` (Islem's `best_ResNet50.pth`) | ResNet50 fine-tuned for face-deepfake (idx 0=FAKE) | 94 Mo | HuggingFace Hub (Verify Dataset) | ⚙️ `scripts/download_models.py` |
|
| 15 |
+
| `io1_resnet50_deepfake.pth` (Islem's `resnet50_deepfake.pth` / Model X) | ResNet50 + Dropout+Linear head (idx 0=REAL) | 94 Mo | HuggingFace Hub (Verify Dataset) | ⚙️ `scripts/download_models.py` |
|
| 16 |
+
| **MTCNN** (`facenet-pytorch`) | Face detector (3 stages: PNet/RNet/ONet) | 6 Mo | embedded in `facenet-pytorch` pip package | ✅ pip install |
|
| 17 |
+
| **Organika/sdxl-detector** | ViT image classifier for SDXL/diffusion AI images | 86 Mo | [`Organika/sdxl-detector`](https://huggingface.co/Organika/sdxl-detector) | ✅ HuggingFace |
|
| 18 |
+
| **umm-maybe/AI-image-detector** | ViT image classifier (precision-tuned) | 86 Mo | [`umm-maybe/AI-image-detector`](https://huggingface.co/umm-maybe/AI-image-detector) | ✅ HuggingFace |
|
| 19 |
+
|
| 20 |
+
## io2 — Visual Manipulation / Persuasion
|
| 21 |
+
|
| 22 |
+
| Model | Type | Size | Source | Auto-download? |
|
| 23 |
+
|---|---|---|---|---|
|
| 24 |
+
| **microsoft/trocr-base-printed** | Vision-Encoder + GPT-2 Decoder (OCR for screen text) | 558 Mo | [`microsoft/trocr-base-printed`](https://huggingface.co/microsoft/trocr-base-printed) | ✅ HuggingFace |
|
| 25 |
+
| **valurank/distilroberta-clickbait** | DistilRoBERTa fine-tuned for clickbait detection (binary) | 330 Mo | [`valurank/distilroberta-clickbait`](https://huggingface.co/valurank/distilroberta-clickbait) | ✅ HuggingFace |
|
| 26 |
+
| **open_clip ViT-B-32** (openai pretrained) | CLIP for zero-shot "clickbait visual style" scoring | 150 Mo | [`openai/clip-vit-base-patch32`](https://huggingface.co/openai/clip-vit-base-patch32) | ✅ open_clip |
|
| 27 |
+
| **Helsinki-NLP/opus-mt-fr-en** | MarianMT FR→EN (so the EN-only clickbait model receives EN) | 300 Mo | [`Helsinki-NLP/opus-mt-fr-en`](https://huggingface.co/Helsinki-NLP/opus-mt-fr-en) | ✅ HuggingFace |
|
| 28 |
+
| **EasyOCR** (EN + FR) | Text detection + recognition (CRAFT + CRNN) | 100 Mo | embedded in `easyocr` pip package | ✅ pip install |
|
| 29 |
+
|
| 30 |
+
## io3 — Image-Caption Coherence
|
| 31 |
+
|
| 32 |
+
| Model | Type | Size | Source | Auto-download? |
|
| 33 |
+
|---|---|---|---|---|
|
| 34 |
+
| **open_clip ViT-L-14** (laion2b_s32b_b82k) | CLIP large for image↔text similarity | 890 Mo | [`laion/CLIP-ViT-L-14-laion2B-s32B-b82K`](https://huggingface.co/laion/CLIP-ViT-L-14-laion2B-s32B-b82K) | ✅ open_clip |
|
| 35 |
+
| **YOLOv8m** (`yolov8m.pt`) | Object detection — 80 COCO classes | 52 Mo | [Ultralytics releases](https://github.com/ultralytics/assets/releases) | ✅ ultralytics |
|
| 36 |
+
| **EasyOCR** (EN + FR) | reused from io2 | shared | — | ✅ |
|
| 37 |
+
| **Whisper small** (`small.pt`) | OpenAI Whisper audio transcription | 470 Mo | [`openai-whisper` pip package](https://github.com/openai/whisper) | ✅ pip install |
|
| 38 |
+
| **SAM ViT-B** (optional) | Segment Anything for region scoring | 375 Mo | [`sam_vit_b_01ec64.pth`](https://dl.fbaipublicfiles.com/segment_anything/sam_vit_b_01ec64.pth) | ⚙️ manual download (else 3×3 grid fallback) |
|
| 39 |
+
|
| 40 |
+
## io4 — Image Tampering (Photoshop forensics)
|
| 41 |
+
|
| 42 |
+
| Model | Type | Size | Source | Auto-download? |
|
| 43 |
+
|---|---|---|---|---|
|
| 44 |
+
| **None** (pure model-free forensics) | ELA + Noise residual + JPEG ghost | 0 Mo | implemented in [`backend/modules/io4_photoshop/forensics.py`](backend/modules/io4_photoshop/forensics.py) | ✅ pure NumPy |
|
| 45 |
+
|
| 46 |
+
## io5 — Caption Fidelity
|
| 47 |
+
|
| 48 |
+
| Model | Type | Size | Source | Auto-download? |
|
| 49 |
+
|---|---|---|---|---|
|
| 50 |
+
| **open_clip ViT-B-32** (openai) | CLIP for image↔caption + per-phrase scoring | shared with io2 | — | ✅ |
|
| 51 |
+
| **EasyOCR** (EN + FR) | reused from io2 | shared | — | ✅ |
|
| 52 |
+
|
| 53 |
+
## io6 — Cosmetic Ads Fact-Check
|
| 54 |
+
|
| 55 |
+
| Model | Type | Size | Source | Auto-download? |
|
| 56 |
+
|---|---|---|---|---|
|
| 57 |
+
| **Whisper tiny** | Audio transcription (rapid version for ads) | 75 Mo | [`openai-whisper` pip package](https://github.com/openai/whisper) | ✅ pip install |
|
| 58 |
+
| **YOLOv8n** (`yolov8n.pt`) | Object detection (lightweight) | 7 Mo | [Ultralytics releases](https://github.com/ultralytics/assets/releases) — versioned in repo | ✅ committed |
|
| 59 |
+
| **EasyOCR** (FR + EN) | reused from io2 | shared | — | ✅ |
|
| 60 |
+
| **paraphrase-multilingual-MiniLM-L12-v2** | Sentence embeddings (semantic match with KB fake claims) | 470 Mo | [`sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2`](https://huggingface.co/sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2) | ✅ HuggingFace |
|
| 61 |
+
| **IO6_Base_Reference_V3_FULL.xlsx** (Yassmine's KB) | Regulatory knowledge base — 25 patterns, 33 fake claims, 145 ingredients, 93 brands | 33 Ko | versioned in `backend/data/` | ✅ committed |
|
| 62 |
+
|
| 63 |
+
## chatbot — Verify Assistant
|
| 64 |
+
|
| 65 |
+
| Service | Type | Size | Source | Auto-download? |
|
| 66 |
+
|---|---|---|---|---|
|
| 67 |
+
| **OpenAI gpt-4o-mini** | Topic-restricted assistant via OpenAI API | n/a (remote) | requires `OPENAI_API_KEY` env var | ☁️ remote API |
|
| 68 |
+
|
| 69 |
+
The chatbot is **the only component that hits an external API**. The 6 detection modules above
|
| 70 |
+
all run 100% locally. On HuggingFace Spaces the key is set as a "Secret" (encrypted, never in the code).
|
| 71 |
+
|
| 72 |
+
## Narrative layer (cross-module, post-processing)
|
| 73 |
+
|
| 74 |
+
| Service | Type | Source |
|
| 75 |
+
|---|---|---|
|
| 76 |
+
| **OpenAI gpt-4o-mini** | Rewrites every module's raw result into plain-English narrative | ☁️ remote API (optional — disable with `IO_XAI_NARRATIVE=off`) |
|
| 77 |
+
|
| 78 |
+
The narrative layer is **optional**: if `OPENAI_API_KEY` is not set, modules return their raw
|
| 79 |
+
local explanation only. Set `IO_XAI_NARRATIVE=off` to disable explicitly.
|
| 80 |
+
|
| 81 |
+
---
|
| 82 |
+
|
| 83 |
+
## How to obtain Islem's `.pth` weights
|
| 84 |
+
|
| 85 |
+
The two ResNet50 checkpoints used by io1 (`io1_resnet50.pth` and `io1_resnet50_deepfake.pth`) are
|
| 86 |
+
not versioned in this repo because each file weighs ~94 MB (GitHub's per-file limit is 100 MB but
|
| 87 |
+
combined size kills clone speed).
|
| 88 |
+
|
| 89 |
+
They are hosted as a private HuggingFace Dataset by the Verify team. To download them locally:
|
| 90 |
+
|
| 91 |
+
```bash
|
| 92 |
+
# Either: download via the helper script, with the URLs set in .env or exported
|
| 93 |
+
export IO1_RESNET50_URL=https://huggingface.co/datasets/<verify_user>/verify-weights/resolve/main/best_ResNet50.pth
|
| 94 |
+
export IO1_RESNET50_DEEPFAKE_URL=https://huggingface.co/datasets/<verify_user>/verify-weights/resolve/main/resnet50_deepfake.pth
|
| 95 |
+
python scripts/download_models.py
|
| 96 |
+
|
| 97 |
+
# Or, on a HuggingFace Space: the Dockerfile pulls them automatically using HUGGINGFACE_HUB_TOKEN
|
| 98 |
+
# (set as a Secret in Space settings → so the file stays private).
|
| 99 |
+
```
|
| 100 |
+
|
| 101 |
+
## Auto-download summary
|
| 102 |
+
|
| 103 |
+
After running `pip install -r backend/requirements.txt` and starting the backend once,
|
| 104 |
+
**12 of 14 components self-install** from public sources. Only Islem's 2 `.pth` files need a manual
|
| 105 |
+
step (the download script).
|
README.md
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Verify
|
| 3 |
+
emoji: 🔍
|
| 4 |
+
colorFrom: red
|
| 5 |
+
colorTo: blue
|
| 6 |
+
sdk: docker
|
| 7 |
+
app_port: 7860
|
| 8 |
+
pinned: false
|
| 9 |
+
short_description: Multimodal disinformation detection — 6 ML modules + chatbot
|
| 10 |
+
license: apache-2.0
|
| 11 |
+
---
|
| 12 |
+
|
| 13 |
+
# Verify — Plateforme multimodale de détection de désinformation
|
| 14 |
+
|
| 15 |
+
## Description
|
| 16 |
+
|
| 17 |
+
**Verify** est une plateforme web qui vérifie l'authenticité de contenus visuels (image, vidéo, texte, publicité)
|
| 18 |
+
en analysant en parallèle **six dimensions** distinctes de la désinformation :
|
| 19 |
+
|
| 20 |
+
1. **io1 — Fake Media** : détection deepfake (face-swap) + images générées par IA (StyleGAN, DALL-E, Midjourney)
|
| 21 |
+
2. **io2 — Visual Manipulation** : détection des images persuasives/clickbait (texte alarmiste, urgence forcée, mise en scène)
|
| 22 |
+
3. **io3 — Image↔Caption Coherence** : vérifie la cohérence entre une image/vidéo et sa légende
|
| 23 |
+
4. **io4 — Image Tampering** : forensique photoshop (ELA + analyse de bruit + JPEG ghost)
|
| 24 |
+
5. **io5 — Caption Fidelity** : vérifie si une légende décrit fidèlement le contenu d'une image
|
| 25 |
+
6. **io6 — Cosmetic Ads Fact-Check** : audit réglementaire EU 655/2013 sur les publicités cosmétiques
|
| 26 |
+
|
| 27 |
+
Tous les modules tournent **100% en local** — aucune API externe n'est requise pour produire un verdict.
|
| 28 |
+
Le backend est une seule API FastAPI qui monte les 6 modules ; le frontend est statique (HTML + JavaScript).
|
| 29 |
+
|
| 30 |
+
## Technologies utilisées
|
| 31 |
+
|
| 32 |
+
| Couche | Stack |
|
| 33 |
+
|---|---|
|
| 34 |
+
| **Frontend** | HTML5 · CSS3 · Vanilla JavaScript (pas de framework) |
|
| 35 |
+
| **Backend** | Python 3.11 · FastAPI · Uvicorn |
|
| 36 |
+
| **IA / ML** | PyTorch · TorchVision · HuggingFace Transformers · open_clip · Ultralytics YOLO · OpenAI Whisper · EasyOCR · facenet-pytorch (MTCNN) · sentence-transformers |
|
| 37 |
+
| **Connaissances** | Pandas + OpenPyXL (knowledge base Excel pour io6) |
|
| 38 |
+
| **Forensique** | Pure NumPy + Pillow (io4 ELA / noise / JPEG ghost — sans modèle) |
|
| 39 |
+
|
| 40 |
+
## Prérequis
|
| 41 |
+
|
| 42 |
+
- **Python 3.11+** (testé sur 3.11.15)
|
| 43 |
+
- **ffmpeg** dans le PATH (utilisé par io3 et io6 pour extraire l'audio des vidéos)
|
| 44 |
+
- **~4 Go RAM disponible** (les 6 modules chargent ~3 Go de modèles en mémoire au démarrage)
|
| 45 |
+
- Premier démarrage : ~3-5 minutes (téléchargement automatique des modèles HuggingFace, ~2 Go)
|
| 46 |
+
- Démarrages suivants : ~30 secondes (tout est caché localement)
|
| 47 |
+
|
| 48 |
+
> ⚠️ **Modèles pré-entraînés non versionnés** : les poids `.pt`/`.pth` ne sont pas inclus dans le repo
|
| 49 |
+
> (taille > 250 Mo combinée + politique ESPRIT/GitHub). Voir la section **Installation** ci-dessous.
|
| 50 |
+
|
| 51 |
+
## Installation
|
| 52 |
+
|
| 53 |
+
```bash
|
| 54 |
+
# 1. Cloner le repo
|
| 55 |
+
git clone https://github.com/USERNAME/Esprit-PI-CLASSE-2526-Verify.git
|
| 56 |
+
cd Esprit-PI-CLASSE-2526-Verify
|
| 57 |
+
|
| 58 |
+
# 2. Créer l'environnement Python
|
| 59 |
+
python3.11 -m venv .venv
|
| 60 |
+
source .venv/bin/activate # macOS / Linux
|
| 61 |
+
# .venv\Scripts\activate # Windows
|
| 62 |
+
|
| 63 |
+
# 3. Installer les dépendances backend
|
| 64 |
+
pip install -r backend/requirements.txt
|
| 65 |
+
|
| 66 |
+
# 4. Télécharger les poids ResNet50 d'Islem (io1) — non versionnés
|
| 67 |
+
python scripts/download_models.py
|
| 68 |
+
|
| 69 |
+
# 5. (Optionnel) Configurer les variables d'environnement
|
| 70 |
+
cp .env.example .env
|
| 71 |
+
# Éditez .env si vous voulez activer le chatbot OpenAI ou ajuster un seuil.
|
| 72 |
+
```
|
| 73 |
+
|
| 74 |
+
## Lancement
|
| 75 |
+
|
| 76 |
+
```bash
|
| 77 |
+
# Backend (terminal 1)
|
| 78 |
+
uvicorn backend.main:app --host 0.0.0.0 --port 8000
|
| 79 |
+
|
| 80 |
+
# Frontend (terminal 2) — au choix :
|
| 81 |
+
python -m http.server 5500 # serveur HTTP statique
|
| 82 |
+
# OU : extension "Live Server" dans VSCode (clic-droit sur index.html → "Open with Live Server")
|
| 83 |
+
```
|
| 84 |
+
|
| 85 |
+
Ensuite ouvrez votre navigateur sur **http://127.0.0.1:5500/index.html**.
|
| 86 |
+
|
| 87 |
+
La doc Swagger de l'API est disponible sur **http://127.0.0.1:8000/docs**.
|
| 88 |
+
|
| 89 |
+
## Variables d'environnement
|
| 90 |
+
|
| 91 |
+
Voir [`.env.example`](.env.example) pour la liste complète. Les principales :
|
| 92 |
+
|
| 93 |
+
| Variable | Description |
|
| 94 |
+
|---|---|
|
| 95 |
+
| `LOAD_MODULES=io3,io1` | Limite quels modules sont chargés au démarrage (default : tous). Pratique en dev pour économiser la mémoire. |
|
| 96 |
+
| `FORCE_DEVICE=cpu` | Force le CPU même si un GPU est disponible. |
|
| 97 |
+
| `OPENAI_API_KEY=sk-...` | (Optionnel) Active le module chatbot uniquement. **N'affecte pas les verdicts** des 6 modules d'analyse. |
|
| 98 |
+
| `IO1_DEEPFAKE_THRESHOLD=0.60` | Seuil de décision FAKE pour l'ensemble ResNet50 d'Islem. |
|
| 99 |
+
| `IO4_ELA_QUALITY=90` | Qualité JPEG utilisée par ELA dans io4. |
|
| 100 |
+
| `IO6_WHISPER_MODEL=tiny` | Variante Whisper pour io6 (`tiny` rapide, `small`/`medium` plus précis). |
|
| 101 |
+
|
| 102 |
+
## Démo
|
| 103 |
+
|
| 104 |
+
- **Site déployé** : Non disponible (déploiement local uniquement pour cette livraison)
|
| 105 |
+
- **Vidéo de démonstration** : voir [`demo/`](demo/) (à fournir par l'équipe)
|
| 106 |
+
- **Diagrammes d'architecture** : voir [`docs/`](docs/)
|
| 107 |
+
- **Description commerciale** : [`Verify_Description_Commerciale.pdf`](Verify_Description_Commerciale.pdf)
|
| 108 |
+
|
| 109 |
+
## Performances des modèles
|
| 110 |
+
|
| 111 |
+
| Module | Backend | Performance | Source |
|
| 112 |
+
|--------|---------|------------|--------|
|
| 113 |
+
| io1 deepfake | ResNet50 ensemble (Islem) + MTCNN | ~97% acc sur FaceForensics | [`islem/`](islem/) |
|
| 114 |
+
| io1 AI-image | Consensus Organika/sdxl + umm-maybe (HF) | ~66% recall sur TPDNE, ~0% FP sur photos réelles | tuned empirically |
|
| 115 |
+
| io2 NLP | DistilRoBERTa fine-tuned clickbait | ~99% acc sur Webis Clickbait 2017 | `valurank/distilroberta-clickbait` |
|
| 116 |
+
| io2 visuel | CLIP ViT-B/32 zero-shot | calibration manuelle | OpenAI CLIP |
|
| 117 |
+
| io3 cohérence | CLIP ViT-L/14 + YOLOv8m fusion | F1 ~0.85 sur dataset interne | [`youssef/`](youssef/) |
|
| 118 |
+
| io4 forensique | ELA + Noise + JPEG ghost (sans modèle) | détection compositing/inpainting localisé | méthode classique |
|
| 119 |
+
| io5 fidelity | CLIP ViT-B/32 + EasyOCR | calibrée sur paires CC3M | sigmoid calibration |
|
| 120 |
+
| io6 cosmétique | Whisper + KB Excel + MiniLM semantic | 25 patterns / 33 fake claims / 145 ingrédients | [`yassmine/`](yassmine/) |
|
| 121 |
+
|
| 122 |
+
## Structure du projet
|
| 123 |
+
|
| 124 |
+
```
|
| 125 |
+
Verify/
|
| 126 |
+
├── README.md ← ce fichier
|
| 127 |
+
├── .env.example ← variables d'environnement
|
| 128 |
+
├── .gitignore
|
| 129 |
+
├── index.html, verifier.html, ... ← frontend statique
|
| 130 |
+
├── assets/ ← CSS, JS, images
|
| 131 |
+
├── backend/ ← API FastAPI
|
| 132 |
+
│ ├── main.py ← entrypoint
|
| 133 |
+
│ ├── requirements.txt
|
| 134 |
+
│ ├── shared/ ← code commun (device, narration XAI)
|
| 135 |
+
│ ├── data/ ← KB Excel io6 (poids .pth téléchargés via script)
|
| 136 |
+
│ └── modules/
|
| 137 |
+
│ ├── io1_ai_generated/
|
| 138 |
+
│ ├── io2_persuasion/
|
| 139 |
+
│ ├── io3_coherence/
|
| 140 |
+
│ ├── io4_photoshop/
|
| 141 |
+
│ ├── io5_caption_fidelity/
|
| 142 |
+
│ └── io6_cosmetic_ads/
|
| 143 |
+
├── scripts/
|
| 144 |
+
│ └── download_models.py ← téléchargement automatique des poids
|
| 145 |
+
├── docs/ ← diagrammes architecture, doc API
|
| 146 |
+
├── demo/ ← captures et vidéos de démo
|
| 147 |
+
├── islem/, malek/, youssef/, rayen/, yassmine/ ← notebooks et docs des contributeurs
|
| 148 |
+
└── ios images/ ← jeu d'images de référence pour la démo
|
| 149 |
+
```
|
| 150 |
+
|
| 151 |
+
## Auteurs
|
| 152 |
+
|
| 153 |
+
| Nom | Module | Année | Tuteur |
|
| 154 |
+
|---|---|---|---|
|
| 155 |
+
| Yassmine Nouisser | io6 — Cosmetic Ads Fact-Check + intégration globale | 2025-2026 | *(à compléter)* |
|
| 156 |
+
| Islem | io1 — Fake Media Detection (deepfake + AI) | 2025-2026 | *(à compléter)* |
|
| 157 |
+
| Malek Tirellil | io2 — Visual Manipulation Detection | 2025-2026 | *(à compléter)* |
|
| 158 |
+
| Youssef | io3 — Image-Caption Coherence | 2025-2026 | *(à compléter)* |
|
| 159 |
+
| Rayen | io4 — Image Tampering Detection | 2025-2026 | *(à compléter)* |
|
| 160 |
+
| Maryem | (contribution complémentaire) | 2025-2026 | *(à compléter)* |
|
| 161 |
+
|
| 162 |
+
Classe : *(à compléter)* — Groupe : *(à compléter)*
|
| 163 |
+
|
| 164 |
+
---
|
| 165 |
+
|
| 166 |
+
## Documentation supplémentaire
|
| 167 |
+
|
| 168 |
+
- [`backend/README.md`](backend/README.md) — détails techniques de l'API
|
| 169 |
+
- [`docs/architecture.md`](docs/architecture.md) — architecture système et flux de données
|
| 170 |
+
- [`docs/api.md`](docs/api.md) — référence des endpoints
|
| 171 |
+
- [`docs/modules.md`](docs/modules.md) — détails par module
|
| 172 |
+
- [`AI_Investigate_Report_COMPLETE.pdf`](AI_Investigate_Report_COMPLETE.pdf) — rapport d'enquête initial
|
| 173 |
+
- [`Verify_Description_Commerciale.pdf`](Verify_Description_Commerciale.pdf) — pitch commercial
|
| 174 |
+
|
| 175 |
+
## Licence
|
| 176 |
+
|
| 177 |
+
Projet académique — ESPRIT School of Engineering, année universitaire 2025-2026.
|
Verify_Description_Commerciale.html
ADDED
|
@@ -0,0 +1,358 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8" />
|
| 5 |
+
<title>Verify — Commercial overview</title>
|
| 6 |
+
<meta name="description" content="Verify: Tunisia's visual-information verification platform. Drop in an image, a video or a post — get a clear, reasoned verdict in minutes, with the visual evidence behind it." />
|
| 7 |
+
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700;800&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
| 8 |
+
<style>
|
| 9 |
+
@page { size: A4; margin: 22mm 18mm; }
|
| 10 |
+
* { box-sizing: border-box; }
|
| 11 |
+
body {
|
| 12 |
+
font-family: 'Inter', -apple-system, sans-serif;
|
| 13 |
+
color: #1a1a1a;
|
| 14 |
+
line-height: 1.6;
|
| 15 |
+
font-size: 11pt;
|
| 16 |
+
margin: 0;
|
| 17 |
+
}
|
| 18 |
+
h1, h2, h3, h4 { font-family: 'Playfair Display', Georgia, serif; color: #052962; margin-top: 0; }
|
| 19 |
+
h1 { font-size: 32pt; line-height: 1.05; margin-bottom: 6px; font-weight: 800; }
|
| 20 |
+
h2 { font-size: 18pt; margin-top: 28px; margin-bottom: 10px; padding-bottom: 6px; border-bottom: 2px solid #052962; }
|
| 21 |
+
h3 { font-size: 13pt; margin-top: 18px; margin-bottom: 6px; color: #052962; }
|
| 22 |
+
p { margin: 0 0 10px; }
|
| 23 |
+
|
| 24 |
+
.cover {
|
| 25 |
+
page-break-after: always;
|
| 26 |
+
text-align: center;
|
| 27 |
+
padding-top: 60mm;
|
| 28 |
+
}
|
| 29 |
+
.cover .kicker {
|
| 30 |
+
display: inline-block;
|
| 31 |
+
font-size: 10pt; font-weight: 700; letter-spacing: 2px; text-transform: uppercase;
|
| 32 |
+
color: #9a3412; background: #ffedd5; padding: 6px 14px; border-radius: 2px;
|
| 33 |
+
margin-bottom: 24px;
|
| 34 |
+
}
|
| 35 |
+
.cover h1 { font-size: 56pt; color: #052962; margin: 0; }
|
| 36 |
+
.cover .tagline {
|
| 37 |
+
font-family: 'Playfair Display', Georgia, serif;
|
| 38 |
+
font-style: italic;
|
| 39 |
+
font-size: 18pt;
|
| 40 |
+
color: #4a4a4a;
|
| 41 |
+
margin-top: 18px;
|
| 42 |
+
}
|
| 43 |
+
.cover .meta {
|
| 44 |
+
margin-top: 80mm;
|
| 45 |
+
font-size: 10pt;
|
| 46 |
+
color: #6b6b6b;
|
| 47 |
+
letter-spacing: 1px;
|
| 48 |
+
text-transform: uppercase;
|
| 49 |
+
}
|
| 50 |
+
.cover hr {
|
| 51 |
+
width: 60px; border: 0; border-top: 3px solid #ffe500; margin: 20px auto;
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
.lede {
|
| 55 |
+
font-size: 13pt;
|
| 56 |
+
font-style: italic;
|
| 57 |
+
color: #333;
|
| 58 |
+
border-left: 4px solid #ffe500;
|
| 59 |
+
padding: 10px 16px;
|
| 60 |
+
background: #fcfaf2;
|
| 61 |
+
margin: 16px 0 22px;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
ul { margin: 6px 0 14px 18px; padding: 0; }
|
| 65 |
+
li { margin-bottom: 5px; }
|
| 66 |
+
|
| 67 |
+
table {
|
| 68 |
+
width: 100%;
|
| 69 |
+
border-collapse: collapse;
|
| 70 |
+
margin: 12px 0 18px;
|
| 71 |
+
font-size: 10pt;
|
| 72 |
+
}
|
| 73 |
+
th, td {
|
| 74 |
+
border: 1px solid #d8d8d8;
|
| 75 |
+
padding: 9px 11px;
|
| 76 |
+
text-align: left;
|
| 77 |
+
vertical-align: top;
|
| 78 |
+
}
|
| 79 |
+
thead th {
|
| 80 |
+
background: #052962;
|
| 81 |
+
color: #fff;
|
| 82 |
+
font-weight: 600;
|
| 83 |
+
text-transform: uppercase;
|
| 84 |
+
letter-spacing: 0.5px;
|
| 85 |
+
font-size: 9pt;
|
| 86 |
+
}
|
| 87 |
+
td.code {
|
| 88 |
+
font-weight: 700;
|
| 89 |
+
color: #052962;
|
| 90 |
+
width: 60px;
|
| 91 |
+
text-align: center;
|
| 92 |
+
background: #f9f6e9;
|
| 93 |
+
}
|
| 94 |
+
td.mod {
|
| 95 |
+
width: 220px;
|
| 96 |
+
font-weight: 600;
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
.pull {
|
| 100 |
+
background: #052962;
|
| 101 |
+
color: #fff;
|
| 102 |
+
padding: 18px 22px;
|
| 103 |
+
margin: 18px 0;
|
| 104 |
+
border-radius: 2px;
|
| 105 |
+
font-family: 'Playfair Display', Georgia, serif;
|
| 106 |
+
font-size: 14pt;
|
| 107 |
+
line-height: 1.4;
|
| 108 |
+
}
|
| 109 |
+
.pull .label {
|
| 110 |
+
display: block;
|
| 111 |
+
font-family: 'Inter', sans-serif;
|
| 112 |
+
font-size: 8pt; letter-spacing: 1.5px; text-transform: uppercase;
|
| 113 |
+
color: #ffe500; margin-bottom: 6px; font-weight: 700;
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
.stat-row {
|
| 117 |
+
display: flex; gap: 10px; margin: 16px 0;
|
| 118 |
+
}
|
| 119 |
+
.stat {
|
| 120 |
+
flex: 1; border: 1px solid #d8d8d8; padding: 14px; text-align: center;
|
| 121 |
+
background: #fcfaf2;
|
| 122 |
+
}
|
| 123 |
+
.stat .num {
|
| 124 |
+
font-family: 'Playfair Display', serif;
|
| 125 |
+
font-size: 22pt; font-weight: 800; color: #052962; line-height: 1;
|
| 126 |
+
}
|
| 127 |
+
.stat .lbl {
|
| 128 |
+
font-size: 8.5pt; color: #4a4a4a; margin-top: 6px; text-transform: uppercase;
|
| 129 |
+
letter-spacing: 0.5px;
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
.three-pillars {
|
| 133 |
+
display: flex; gap: 10px; margin: 12px 0;
|
| 134 |
+
}
|
| 135 |
+
.pillar {
|
| 136 |
+
flex: 1; padding: 12px; border-top: 4px solid #ffe500; background: #f7f7f5;
|
| 137 |
+
}
|
| 138 |
+
.pillar h4 {
|
| 139 |
+
font-family: 'Playfair Display', serif; margin: 0 0 6px;
|
| 140 |
+
font-size: 12pt; color: #052962;
|
| 141 |
+
}
|
| 142 |
+
.pillar p { font-size: 9.5pt; color: #333; margin: 0; }
|
| 143 |
+
|
| 144 |
+
.section { page-break-inside: avoid; }
|
| 145 |
+
.footer-band {
|
| 146 |
+
margin-top: 30px; padding: 18px;
|
| 147 |
+
background: #052962; color: #fff;
|
| 148 |
+
text-align: center;
|
| 149 |
+
font-family: 'Playfair Display', serif;
|
| 150 |
+
font-size: 14pt;
|
| 151 |
+
border-radius: 2px;
|
| 152 |
+
}
|
| 153 |
+
.footer-band em { color: #ffe500; font-style: normal; }
|
| 154 |
+
|
| 155 |
+
.small { font-size: 9pt; color: #6b6b6b; }
|
| 156 |
+
</style>
|
| 157 |
+
</head>
|
| 158 |
+
<body>
|
| 159 |
+
|
| 160 |
+
<!-- COVER -->
|
| 161 |
+
<section class="cover">
|
| 162 |
+
<span class="kicker">Commercial overview</span>
|
| 163 |
+
<h1>Verify</h1>
|
| 164 |
+
<hr />
|
| 165 |
+
<p class="tagline">Tunisia's platform for verifying<br/>visual information</p>
|
| 166 |
+
<div class="meta">
|
| 167 |
+
Overview document · 2026
|
| 168 |
+
</div>
|
| 169 |
+
</section>
|
| 170 |
+
|
| 171 |
+
<!-- 1. THE PROJECT IN ONE SENTENCE -->
|
| 172 |
+
<section class="section">
|
| 173 |
+
<h2>The project in one sentence</h2>
|
| 174 |
+
<p class="lede">
|
| 175 |
+
<strong>Verify</strong> is an independent platform for checking visual content
|
| 176 |
+
and its context (images, videos, captions, ads) that helps the general public,
|
| 177 |
+
journalists and Tunisian institutions tell, within minutes,
|
| 178 |
+
what is <strong>authentic</strong>, <strong>suspect</strong>,
|
| 179 |
+
<strong>manipulated</strong> or <strong>misleading</strong>.
|
| 180 |
+
</p>
|
| 181 |
+
</section>
|
| 182 |
+
|
| 183 |
+
<!-- 2. THE PROBLEM -->
|
| 184 |
+
<section class="section">
|
| 185 |
+
<h2>The problem Verify addresses</h2>
|
| 186 |
+
<p>Visual disinformation is exploding in Tunisia and across the Arab world:</p>
|
| 187 |
+
<ul>
|
| 188 |
+
<li>Images and videos <strong>created with artificial-intelligence tools</strong> and passed off as real.</li>
|
| 189 |
+
<li>Advertising and <strong>propaganda</strong> videos that play on emotion to influence you more effectively.</li>
|
| 190 |
+
<li><strong>Misleading captions</strong> placed over genuine images to make them say something else.</li>
|
| 191 |
+
<li><strong>Retouched or composited photos</strong>: elements added, erased or moved.</li>
|
| 192 |
+
<li><strong>Misleading cosmetic ads</strong>: faked before/after shots, fake testimonials, unrealistic claims.</li>
|
| 193 |
+
<li><strong>Gaps between what you see and what you read</strong>: exaggerations, omissions, distortions.</li>
|
| 194 |
+
</ul>
|
| 195 |
+
<p>Today, the average Tunisian citizen has no simple tool, in French or Arabic,
|
| 196 |
+
to untangle all of this. <strong>Verify fills that gap.</strong></p>
|
| 197 |
+
</section>
|
| 198 |
+
|
| 199 |
+
<!-- 3. VALUE PROPOSITION -->
|
| 200 |
+
<section class="section">
|
| 201 |
+
<h2>The value proposition</h2>
|
| 202 |
+
<div class="pull">
|
| 203 |
+
<span class="label">User promise</span>
|
| 204 |
+
"Drop in an image, a video or a post — get a clear, reasoned verdict in under 2 minutes."
|
| 205 |
+
</div>
|
| 206 |
+
<p>Verify combines three complementary strengths:</p>
|
| 207 |
+
<div class="three-pillars">
|
| 208 |
+
<div class="pillar">
|
| 209 |
+
<h4>1. In-depth analysis</h4>
|
| 210 |
+
<p>Six ways to check a piece of content, from the image itself to the words around it.</p>
|
| 211 |
+
</div>
|
| 212 |
+
<div class="pillar">
|
| 213 |
+
<h4>2. A human newsroom</h4>
|
| 214 |
+
<p>A team that contextualizes, investigates and publishes the evidence.</p>
|
| 215 |
+
</div>
|
| 216 |
+
<div class="pillar">
|
| 217 |
+
<h4>3. A consumer-facing media outlet</h4>
|
| 218 |
+
<p>Every verification is explained, archived and freely accessible.</p>
|
| 219 |
+
</div>
|
| 220 |
+
</div>
|
| 221 |
+
</section>
|
| 222 |
+
|
| 223 |
+
<!-- 4. THE 6 MODULES -->
|
| 224 |
+
<section class="section">
|
| 225 |
+
<h2>The 6 analyses — the "Verify Toolkit"</h2>
|
| 226 |
+
<table>
|
| 227 |
+
<thead>
|
| 228 |
+
<tr>
|
| 229 |
+
<th>Code</th>
|
| 230 |
+
<th>Analysis</th>
|
| 231 |
+
<th>What it's for (in plain words)</th>
|
| 232 |
+
</tr>
|
| 233 |
+
</thead>
|
| 234 |
+
<tbody>
|
| 235 |
+
<tr>
|
| 236 |
+
<td class="code">IO1</td>
|
| 237 |
+
<td class="mod">Detection of AI-created images</td>
|
| 238 |
+
<td>Spot images and videos made with artificial-intelligence tools. We examine dozens of subtle clues, invisible to the naked eye, to deliver a clear verdict on their origin.</td>
|
| 239 |
+
</tr>
|
| 240 |
+
<tr>
|
| 241 |
+
<td class="code">IO2</td>
|
| 242 |
+
<td class="mod">Visual manipulation & persuasion</td>
|
| 243 |
+
<td>Bring to light the emotional-persuasion and visual-manipulation techniques used in advertising and propaganda videos — so you understand how someone is trying to influence you.</td>
|
| 244 |
+
</tr>
|
| 245 |
+
<tr>
|
| 246 |
+
<td class="code">IO3</td>
|
| 247 |
+
<td class="mod">Image & caption coherence</td>
|
| 248 |
+
<td>Check whether an image really matches the caption it's published under, and flag the cases where the caption makes the image say something else.</td>
|
| 249 |
+
</tr>
|
| 250 |
+
<tr>
|
| 251 |
+
<td class="code">IO4</td>
|
| 252 |
+
<td class="mod">Detection of retouched photos</td>
|
| 253 |
+
<td>Spot retouching and montages in a photo: elements added, erased or moved — and show exactly where in the image.</td>
|
| 254 |
+
</tr>
|
| 255 |
+
<tr>
|
| 256 |
+
<td class="code">IO5</td>
|
| 257 |
+
<td class="mod">Caption fidelity</td>
|
| 258 |
+
<td>Assess how faithfully a caption describes what you actually see: exaggerations, omissions, misleading shortcuts. <em>(Lead: Maryem)</em></td>
|
| 259 |
+
</tr>
|
| 260 |
+
<tr>
|
| 261 |
+
<td class="code">IO6</td>
|
| 262 |
+
<td class="mod">Cosmetic-ad fact-checking</td>
|
| 263 |
+
<td>Check whether a cosmetic ad's claims hold up, in light of the EU rules on cosmetic claims: faked before/after shots, fake testimonials, unrealistic claims.</td>
|
| 264 |
+
</tr>
|
| 265 |
+
</tbody>
|
| 266 |
+
</table>
|
| 267 |
+
|
| 268 |
+
<p style="margin-top:14px;"><strong>The six analyses cover the entire chain of visual disinformation:</strong></p>
|
| 269 |
+
<ul>
|
| 270 |
+
<li><strong>The image</strong> (IO1, IO4) — is it authentic or doctored?</li>
|
| 271 |
+
<li><strong>The intent</strong> (IO2, IO6) — how is someone trying to influence me?</li>
|
| 272 |
+
<li><strong>The meaning</strong> (IO3, IO5) — does what I'm told match what I see?</li>
|
| 273 |
+
</ul>
|
| 274 |
+
</section>
|
| 275 |
+
|
| 276 |
+
<!-- 5. USER JOURNEY -->
|
| 277 |
+
<section class="section">
|
| 278 |
+
<h2>How it works for the user</h2>
|
| 279 |
+
<ol>
|
| 280 |
+
<li><strong>You drop in</strong> an image, a video, a post with its caption, or an ad.</li>
|
| 281 |
+
<li><strong>Verify picks for you</strong> the analyses best suited to that content.</li>
|
| 282 |
+
<li><strong>The content is scrutinized</strong> from every useful angle, and cross-checked against its context.</li>
|
| 283 |
+
<li><strong>A score out of 100</strong> and a clear verdict are returned: <em>Authentic / Suspect / Manipulated / Misleading</em>.</li>
|
| 284 |
+
<li><strong>When there's doubt</strong>, a human analyst takes over — no ambiguous verdict is ever delivered blindly.</li>
|
| 285 |
+
<li><strong>A public report</strong> is published: key moments of a video, retouched regions spotted in the image, a comparison between the caption and the visual, and a clear explanation. Everything is archived and viewable.</li>
|
| 286 |
+
</ol>
|
| 287 |
+
</section>
|
| 288 |
+
|
| 289 |
+
<!-- 6. THE MEDIA OUTLET -->
|
| 290 |
+
<section class="section">
|
| 291 |
+
<h2>The media outlet that goes with the tool</h2>
|
| 292 |
+
<p>Verify isn't just a verification tool — it's also a <strong>news site</strong>
|
| 293 |
+
in the style of major international media, with:</p>
|
| 294 |
+
<ul>
|
| 295 |
+
<li>A daily <strong>editorial front page</strong>.</li>
|
| 296 |
+
<li><strong>In-depth investigations</strong> into visual and advertising disinformation.</li>
|
| 297 |
+
<li><strong>Fact-checks</strong> tracking Tunisian current affairs (politics, climate, economy, sport, culture, health).</li>
|
| 298 |
+
<li>A <strong>morning newsletter</strong>: <em>"The Verify brief — 5 minutes, zero spin, just facts."</em></li>
|
| 299 |
+
<li>A fully transparent <strong>Methodology</strong> section.</li>
|
| 300 |
+
</ul>
|
| 301 |
+
</section>
|
| 302 |
+
|
| 303 |
+
<!-- 7. TARGET AUDIENCES -->
|
| 304 |
+
<section class="section">
|
| 305 |
+
<h2>Target audiences</h2>
|
| 306 |
+
<ul>
|
| 307 |
+
<li><strong>The connected citizen</strong> who wants to verify before sharing.</li>
|
| 308 |
+
<li><strong>Journalists and newsrooms</strong>: a fast tool to use before publishing.</li>
|
| 309 |
+
<li><strong>Teachers and trainers</strong> in media literacy.</li>
|
| 310 |
+
<li><strong>Public institutions</strong> facing manipulation campaigns.</li>
|
| 311 |
+
<li><strong>Brands and the cosmetics industry</strong> looking to detect advertising impersonations and misleading claims made in their name.</li>
|
| 312 |
+
<li><strong>Advertising regulators</strong> who need objective evidence.</li>
|
| 313 |
+
</ul>
|
| 314 |
+
</section>
|
| 315 |
+
|
| 316 |
+
<!-- 8. DIFFERENTIATORS -->
|
| 317 |
+
<section class="section">
|
| 318 |
+
<h2>What sets Verify apart</h2>
|
| 319 |
+
<ul>
|
| 320 |
+
<li><strong>Complete coverage</strong>: from the image itself (IO1, IO4) to the meaning of the post (IO3, IO5), by way of the persuasive intent (IO2, IO6).</li>
|
| 321 |
+
<li><strong>A one-of-a-kind cosmetic-ad verification (IO6)</strong> — a sector especially exposed in Tunisia to misleading claims on social media.</li>
|
| 322 |
+
<li><strong>The first service of its kind built for the Tunisian and Maghreb context</strong>.</li>
|
| 323 |
+
<li><strong>Radical transparency</strong>: the method, the scores and the evidence behind the verdict are all published.</li>
|
| 324 |
+
<li><strong>Humans above automation</strong>: no ambiguous verdict goes out without human validation.</li>
|
| 325 |
+
<li><strong>Bilingual by nature</strong>: built for French- and Arabic-speaking audiences.</li>
|
| 326 |
+
<li><strong>Editorial independence</strong> from parties, platforms and advertisers.</li>
|
| 327 |
+
</ul>
|
| 328 |
+
</section>
|
| 329 |
+
|
| 330 |
+
<!-- 9. KEY FIGURES -->
|
| 331 |
+
<section class="section">
|
| 332 |
+
<h2>Key figures</h2>
|
| 333 |
+
<div class="stat-row">
|
| 334 |
+
<div class="stat"><div class="num">412</div><div class="lbl">Verifications / week</div></div>
|
| 335 |
+
<div class="stat"><div class="num">38 %</div><div class="lbl">Content flagged as misleading</div></div>
|
| 336 |
+
<div class="stat"><div class="num">6</div><div class="lbl">Ways to check a piece of content</div></div>
|
| 337 |
+
<div class="stat"><div class="num">‹ 2 min</div><div class="lbl">Average time to a verdict</div></div>
|
| 338 |
+
</div>
|
| 339 |
+
</section>
|
| 340 |
+
|
| 341 |
+
<!-- 10. BRAND PROMISE -->
|
| 342 |
+
<section class="section">
|
| 343 |
+
<h2>The brand promise</h2>
|
| 344 |
+
<div class="footer-band">
|
| 345 |
+
<em>See, read, verify, understand.</em><br/>
|
| 346 |
+
<span style="font-size:11pt; font-family:'Inter',sans-serif; line-height:1.5;">
|
| 347 |
+
Verify gives everyone the means to stop being at the mercy of the flow of images and captions:
|
| 348 |
+
to take back control of what you look at, what you read, what you share —
|
| 349 |
+
and what you choose to believe.
|
| 350 |
+
</span>
|
| 351 |
+
</div>
|
| 352 |
+
<p class="small" style="margin-top:24px; text-align:center;">
|
| 353 |
+
Verify · Commercial document · 2026 · Tunis
|
| 354 |
+
</p>
|
| 355 |
+
</section>
|
| 356 |
+
|
| 357 |
+
</body>
|
| 358 |
+
</html>
|
Verify_Description_Commerciale.pdf
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:56ad22c7176fa6cd1a1cd106de31e26f44a70612defd38039f4b82289a8fcb13
|
| 3 |
+
size 251853
|
archive.html
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8" />
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
| 6 |
+
<title>Verifications archive — Verify</title>
|
| 7 |
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
| 8 |
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
| 9 |
+
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700;800&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
| 10 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 11 |
+
<link rel="stylesheet" href="assets/css/styles.css?v=32" />
|
| 12 |
+
</head>
|
| 13 |
+
<body>
|
| 14 |
+
<div id="site-header" data-slim="true"></div>
|
| 15 |
+
|
| 16 |
+
<main class="container-x">
|
| 17 |
+
<section class="px-6 pt-10 pb-4">
|
| 18 |
+
<div class="text-sm text-gray-500 mb-2">
|
| 19 |
+
<a href="index.html" class="hover:underline">Home</a> ›
|
| 20 |
+
<a href="real-or-fake.html" class="hover:underline">Fact-checks</a> ›
|
| 21 |
+
<span>Archive</span>
|
| 22 |
+
</div>
|
| 23 |
+
<h1 class="font-serif" style="font-size:48px;line-height:1.05;margin:0 0 8px;">Verifications archive</h1>
|
| 24 |
+
<p class="text-gray-600 max-w-2xl">
|
| 25 |
+
All analyses published by our team, sorted by module and verdict.
|
| 26 |
+
412 reports in total.
|
| 27 |
+
</p>
|
| 28 |
+
</section>
|
| 29 |
+
|
| 30 |
+
<!-- Filters -->
|
| 31 |
+
<section class="filters">
|
| 32 |
+
<span class="text-xs uppercase tracking-wider text-gray-500 self-center pr-2">Module:</span>
|
| 33 |
+
<button class="filter-chip active">All</button>
|
| 34 |
+
<button class="filter-chip">AI-Generated</button>
|
| 35 |
+
<button class="filter-chip">Persuasion</button>
|
| 36 |
+
<button class="filter-chip">Coherence</button>
|
| 37 |
+
<button class="filter-chip">Forensics</button>
|
| 38 |
+
<button class="filter-chip">Caption Fidelity</button>
|
| 39 |
+
<button class="filter-chip">Cosmetic Ads</button>
|
| 40 |
+
</section>
|
| 41 |
+
<section class="filters">
|
| 42 |
+
<span class="text-xs uppercase tracking-wider text-gray-500 self-center pr-2">Verdict:</span>
|
| 43 |
+
<button class="filter-chip active">All</button>
|
| 44 |
+
<button class="filter-chip">Authentic</button>
|
| 45 |
+
<button class="filter-chip">Suspect</button>
|
| 46 |
+
<button class="filter-chip">Manipulated</button>
|
| 47 |
+
<button class="filter-chip">Out of context</button>
|
| 48 |
+
<span class="text-xs uppercase tracking-wider text-gray-500 self-center pl-4 pr-2">Period:</span>
|
| 49 |
+
<button class="filter-chip">7 days</button>
|
| 50 |
+
<button class="filter-chip active">30 days</button>
|
| 51 |
+
<button class="filter-chip">2026</button>
|
| 52 |
+
<button class="filter-chip">All</button>
|
| 53 |
+
</section>
|
| 54 |
+
|
| 55 |
+
<!-- Table of past analyses -->
|
| 56 |
+
<section class="px-6 py-6">
|
| 57 |
+
<table class="data-table">
|
| 58 |
+
<thead>
|
| 59 |
+
<tr>
|
| 60 |
+
<th>Date</th>
|
| 61 |
+
<th>Reference</th>
|
| 62 |
+
<th>Title</th>
|
| 63 |
+
<th>Module</th>
|
| 64 |
+
<th>Score</th>
|
| 65 |
+
<th>Verdict</th>
|
| 66 |
+
<th></th>
|
| 67 |
+
</tr>
|
| 68 |
+
</thead>
|
| 69 |
+
<tbody>
|
| 70 |
+
<tr>
|
| 71 |
+
<td>Apr 27, 2026</td>
|
| 72 |
+
<td>VR-2026-0427-A93</td>
|
| 73 |
+
<td>Tunis flooding video (TikTok)</td>
|
| 74 |
+
<td>Coherence</td>
|
| 75 |
+
<td>34</td>
|
| 76 |
+
<td><span class="verdict-pill verdict-fake">Out of context</span></td>
|
| 77 |
+
<td><a href="resultats.html" class="text-navy underline">View</a></td>
|
| 78 |
+
</tr>
|
| 79 |
+
<tr>
|
| 80 |
+
<td>Apr 26, 2026</td>
|
| 81 |
+
<td>VR-2026-0426-B12</td>
|
| 82 |
+
<td>Viral "official" bank ad</td>
|
| 83 |
+
<td>Persuasion</td>
|
| 84 |
+
<td>22</td>
|
| 85 |
+
<td><span class="verdict-pill verdict-fake">Manipulated</span></td>
|
| 86 |
+
<td><a href="resultats.html" class="text-navy underline">View</a></td>
|
| 87 |
+
</tr>
|
| 88 |
+
<tr>
|
| 89 |
+
<td>Apr 26, 2026</td>
|
| 90 |
+
<td>VR-2026-0426-C45</td>
|
| 91 |
+
<td>Sfax protest photo</td>
|
| 92 |
+
<td>Forensics</td>
|
| 93 |
+
<td>48</td>
|
| 94 |
+
<td><span class="verdict-pill verdict-suspect">Suspect</span></td>
|
| 95 |
+
<td><a href="resultats.html" class="text-navy underline">View</a></td>
|
| 96 |
+
</tr>
|
| 97 |
+
<tr>
|
| 98 |
+
<td>Apr 25, 2026</td>
|
| 99 |
+
<td>VR-2026-0425-D78</td>
|
| 100 |
+
<td>Speech attributed to the Finance Minister</td>
|
| 101 |
+
<td>AI-Gen</td>
|
| 102 |
+
<td>67</td>
|
| 103 |
+
<td><span class="verdict-pill verdict-suspect">Suspect</span></td>
|
| 104 |
+
<td><a href="resultats.html" class="text-navy underline">View</a></td>
|
| 105 |
+
</tr>
|
| 106 |
+
<tr>
|
| 107 |
+
<td>Apr 24, 2026</td>
|
| 108 |
+
<td>VR-2026-0424-E33</td>
|
| 109 |
+
<td>Espérance image during the African title</td>
|
| 110 |
+
<td>Caption</td>
|
| 111 |
+
<td>91</td>
|
| 112 |
+
<td><span class="verdict-pill verdict-ok">Authentic</span></td>
|
| 113 |
+
<td><a href="resultats.html" class="text-navy underline">View</a></td>
|
| 114 |
+
</tr>
|
| 115 |
+
<tr>
|
| 116 |
+
<td>Apr 23, 2026</td>
|
| 117 |
+
<td>VR-2026-0423-F09</td>
|
| 118 |
+
<td>Municipal campaign poster (Sousse)</td>
|
| 119 |
+
<td>Forensics</td>
|
| 120 |
+
<td>54</td>
|
| 121 |
+
<td><span class="verdict-pill verdict-suspect">Suspect</span></td>
|
| 122 |
+
<td><a href="resultats.html" class="text-navy underline">View</a></td>
|
| 123 |
+
</tr>
|
| 124 |
+
<tr>
|
| 125 |
+
<td>Apr 22, 2026</td>
|
| 126 |
+
<td>VR-2026-0422-G22</td>
|
| 127 |
+
<td>"Photo" of Tunis-Carthage airport</td>
|
| 128 |
+
<td>AI-Gen</td>
|
| 129 |
+
<td>14</td>
|
| 130 |
+
<td><span class="verdict-pill verdict-fake">Manipulated</span></td>
|
| 131 |
+
<td><a href="resultats.html" class="text-navy underline">View</a></td>
|
| 132 |
+
</tr>
|
| 133 |
+
<tr>
|
| 134 |
+
<td>Apr 21, 2026</td>
|
| 135 |
+
<td>VR-2026-0421-H56</td>
|
| 136 |
+
<td>"New school opening" video in Kairouan</td>
|
| 137 |
+
<td>Caption</td>
|
| 138 |
+
<td>88</td>
|
| 139 |
+
<td><span class="verdict-pill verdict-ok">Authentic</span></td>
|
| 140 |
+
<td><a href="resultats.html" class="text-navy underline">View</a></td>
|
| 141 |
+
</tr>
|
| 142 |
+
<tr>
|
| 143 |
+
<td>Apr 20, 2026</td>
|
| 144 |
+
<td>VR-2026-0420-I91</td>
|
| 145 |
+
<td>Screenshot of an official statement</td>
|
| 146 |
+
<td>Persuasion</td>
|
| 147 |
+
<td>40</td>
|
| 148 |
+
<td><span class="verdict-pill verdict-suspect">Suspect</span></td>
|
| 149 |
+
<td><a href="resultats.html" class="text-navy underline">View</a></td>
|
| 150 |
+
</tr>
|
| 151 |
+
<tr>
|
| 152 |
+
<td>Apr 19, 2026</td>
|
| 153 |
+
<td>VR-2026-0419-J04</td>
|
| 154 |
+
<td>Real-estate ad (Instagram account)</td>
|
| 155 |
+
<td>Persuasion</td>
|
| 156 |
+
<td>30</td>
|
| 157 |
+
<td><span class="verdict-pill verdict-fake">Manipulated</span></td>
|
| 158 |
+
<td><a href="resultats.html" class="text-navy underline">View</a></td>
|
| 159 |
+
</tr>
|
| 160 |
+
<tr>
|
| 161 |
+
<td>Apr 18, 2026</td>
|
| 162 |
+
<td>VR-2026-0418-K17</td>
|
| 163 |
+
<td>Video shot in La Marsa (verified account)</td>
|
| 164 |
+
<td>AI-Gen</td>
|
| 165 |
+
<td>94</td>
|
| 166 |
+
<td><span class="verdict-pill verdict-ok">Authentic</span></td>
|
| 167 |
+
<td><a href="resultats.html" class="text-navy underline">View</a></td>
|
| 168 |
+
</tr>
|
| 169 |
+
<tr>
|
| 170 |
+
<td>Apr 17, 2026</td>
|
| 171 |
+
<td>VR-2026-0417-L88</td>
|
| 172 |
+
<td>AI-generated landscape image (Tozeur)</td>
|
| 173 |
+
<td>AI-Gen</td>
|
| 174 |
+
<td>11</td>
|
| 175 |
+
<td><span class="verdict-pill verdict-fake">Manipulated</span></td>
|
| 176 |
+
<td><a href="resultats.html" class="text-navy underline">View</a></td>
|
| 177 |
+
</tr>
|
| 178 |
+
</tbody>
|
| 179 |
+
</table>
|
| 180 |
+
</section>
|
| 181 |
+
|
| 182 |
+
<div class="flex justify-center gap-2 py-10">
|
| 183 |
+
<button class="filter-chip">‹ Previous</button>
|
| 184 |
+
<button class="filter-chip active">1</button>
|
| 185 |
+
<button class="filter-chip">2</button>
|
| 186 |
+
<button class="filter-chip">3</button>
|
| 187 |
+
<button class="filter-chip">…</button>
|
| 188 |
+
<button class="filter-chip">35</button>
|
| 189 |
+
<button class="filter-chip">Next ›</button>
|
| 190 |
+
</div>
|
| 191 |
+
</main>
|
| 192 |
+
|
| 193 |
+
<div id="site-footer"></div>
|
| 194 |
+
|
| 195 |
+
|
| 196 |
+
<script src="assets/js/config.js?v=1"></script> <script src="assets/js/components.js?v=14"></script>
|
| 197 |
+
<script src="assets/js/main.js?v=7"></script>
|
| 198 |
+
</body>
|
| 199 |
+
</html>
|
article.html
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8" />
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
| 6 |
+
<title>Tunis floods: our verification — Verify</title>
|
| 7 |
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
| 8 |
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
| 9 |
+
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700;800&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
| 10 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 11 |
+
<link rel="stylesheet" href="assets/css/styles.css?v=32" />
|
| 12 |
+
</head>
|
| 13 |
+
<body>
|
| 14 |
+
<div id="site-header" data-slim="true"></div>
|
| 15 |
+
|
| 16 |
+
<main class="container-x" style="max-width: 860px;">
|
| 17 |
+
<article class="px-6 py-10">
|
| 18 |
+
<!-- Breadcrumb -->
|
| 19 |
+
<div class="text-sm text-gray-500 mb-4">
|
| 20 |
+
<a href="index.html" class="hover:underline">Home</a> ›
|
| 21 |
+
<a href="real-or-fake.html" class="hover:underline">Fact-checks</a> ›
|
| 22 |
+
<span>Tunis</span>
|
| 23 |
+
</div>
|
| 24 |
+
|
| 25 |
+
<span class="cat-tag tag-fact" style="display:inline-block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:0.8px;padding:3px 10px;border-radius:2px;margin-bottom:12px;">Fact-check</span>
|
| 26 |
+
<h1 class="font-serif" style="font-size:46px;line-height:1.1;margin:8px 0 16px;">
|
| 27 |
+
Is this viral video of flooding in Tunis authentic?
|
| 28 |
+
Our frame-by-frame verification
|
| 29 |
+
</h1>
|
| 30 |
+
<p style="font-size:20px;color:#4a4a4a;line-height:1.5;">
|
| 31 |
+
The 47-second clip topped 800,000 views on X and TikTok in two
|
| 32 |
+
days. Our Image–Caption Coherence and Edited Photo Detection
|
| 33 |
+
analyses reconstructed the origin of every shot.
|
| 34 |
+
</p>
|
| 35 |
+
|
| 36 |
+
<div class="flex items-center gap-3 mt-6 mb-8 pb-6 border-b" style="border-color:var(--line);">
|
| 37 |
+
<div style="width:48px;height:48px;border-radius:50%;background:var(--rose);display:flex;align-items:center;justify-content:center;font-weight:800;color:var(--navy);font-family:'Playfair Display',serif;font-size:20px;">M</div>
|
| 38 |
+
<div>
|
| 39 |
+
<div class="font-semibold">Maryem Ben Slimane</div>
|
| 40 |
+
<div class="text-sm text-gray-500">Lead — Caption Fidelity · Published April 27, 2026 at 9:42 AM</div>
|
| 41 |
+
</div>
|
| 42 |
+
</div>
|
| 43 |
+
|
| 44 |
+
<!-- Hero image -->
|
| 45 |
+
<img src="https://images.unsplash.com/photo-1547683905-f686c993aae5?auto=format&fit=crop&w=900&q=80" alt="Urban flooding" style="width:100%;height:auto;display:block;margin-bottom:20px;" />
|
| 46 |
+
<p class="text-sm text-gray-500 mb-8" style="font-style:italic;">
|
| 47 |
+
Screenshot of the viral video as it circulated on April 26 on X. Credit: "Tunisie en direct" account.
|
| 48 |
+
</p>
|
| 49 |
+
|
| 50 |
+
<!-- Smart Brevity boxes -->
|
| 51 |
+
<div class="sb-box why">
|
| 52 |
+
<span class="sb-label">Why it matters</span>
|
| 53 |
+
During extreme climate events, decontextualized videos amplify fear
|
| 54 |
+
and saturate emergency services. Verifying quickly and publishing
|
| 55 |
+
the chain of origin is the first line of defense.
|
| 56 |
+
</div>
|
| 57 |
+
|
| 58 |
+
<p style="font-size:17px;line-height:1.7;margin-bottom:18px;">
|
| 59 |
+
The video, first posted on Tuesday at 9:17 PM, shows submerged
|
| 60 |
+
streets presented as filmed "tonight in Tunis." Within 90 minutes,
|
| 61 |
+
the clip had been picked up by five pan-Arab accounts totaling 4.2
|
| 62 |
+
million followers. Our team began analysis at 10:04 PM.
|
| 63 |
+
</p>
|
| 64 |
+
|
| 65 |
+
<div class="sb-box big">
|
| 66 |
+
<span class="sb-label">The big picture</span>
|
| 67 |
+
Three key shots — out of the twelve in the video — come from a
|
| 68 |
+
separate flood event in Bab Bhar, in September 2018. Two new shots
|
| 69 |
+
were authenticated in Manouba this morning, around 6:12 AM.
|
| 70 |
+
</div>
|
| 71 |
+
|
| 72 |
+
<h2 class="font-serif" style="font-size:30px;margin:30px 0 14px;">What our modules found</h2>
|
| 73 |
+
<ul class="sb-bullets">
|
| 74 |
+
<li><strong>Image–Caption Coherence</strong> noted a 3,200 K luminance
|
| 75 |
+
shift between shots 4–7 and the rest: the classic signature of
|
| 76 |
+
nighttime archive footage re-injected into a daytime video.</li>
|
| 77 |
+
<li><strong>Edited Photo Detection</strong> isolated two added objects —
|
| 78 |
+
a road sign and a pharmacy sign — overlaid on 2018 frames.</li>
|
| 79 |
+
<li>The <strong>EXIF metadata</strong> was stripped on the viral
|
| 80 |
+
version, but the version posted 16 minutes earlier by another
|
| 81 |
+
account still carries a timestamp dated <strong>September 14, 2018</strong>.</li>
|
| 82 |
+
<li>By contrast, two shots (8 and 11) are <strong>authentic and unpublished</strong>:
|
| 83 |
+
they correspond to a local flood event that occurred this morning in Manouba.</li>
|
| 84 |
+
</ul>
|
| 85 |
+
|
| 86 |
+
<h2 class="font-serif" style="font-size:30px;margin:30px 0 14px;">How we established this</h2>
|
| 87 |
+
<p style="font-size:17px;line-height:1.7;margin-bottom:18px;">
|
| 88 |
+
The Verify verification process combines a reverse image search
|
| 89 |
+
(Yandex, TinEye, Google Lens) with our own visual analyses. For this
|
| 90 |
+
video, the first archived match was found in 4 minutes via TinEye
|
| 91 |
+
on frame 156. It pointed to a Mosaïque FM article published on
|
| 92 |
+
September 15, 2018.
|
| 93 |
+
</p>
|
| 94 |
+
|
| 95 |
+
<p style="font-size:17px;line-height:1.7;margin-bottom:18px;">
|
| 96 |
+
Once the source was identified, our analysts aligned each shot of
|
| 97 |
+
the viral video with the original archive, shot by shot. Shots 8
|
| 98 |
+
and 11 produced no match: they were then submitted to AI-Generated
|
| 99 |
+
Media Detection, which returned a confidence score > 92% in
|
| 100 |
+
favor of authenticity.
|
| 101 |
+
</p>
|
| 102 |
+
|
| 103 |
+
<div class="sb-box next">
|
| 104 |
+
<span class="sb-label">What's next</span>
|
| 105 |
+
Our newsroom is opening an investigation into the Telegram channels
|
| 106 |
+
that first posted the video, and into the modus operandi — the same
|
| 107 |
+
archived shots were used last March for a false alert in Sfax.
|
| 108 |
+
Results expected on May 5.
|
| 109 |
+
</div>
|
| 110 |
+
|
| 111 |
+
<!-- CTA banner -->
|
| 112 |
+
<div class="verify-banner">
|
| 113 |
+
<div>
|
| 114 |
+
<h3>Want to verify suspicious content yourself?</h3>
|
| 115 |
+
<p>Upload an image, video or link — our five modules give you a score in less than 2 minutes.</p>
|
| 116 |
+
</div>
|
| 117 |
+
<a href="verifier.html" class="btn-yellow">Verify this content</a>
|
| 118 |
+
</div>
|
| 119 |
+
|
| 120 |
+
<p style="font-size:17px;line-height:1.7;margin-bottom:18px;">
|
| 121 |
+
The stakes go beyond this one case. Over the past seven days,
|
| 122 |
+
Verify processed 421 user-flagged contents. 38% were marked as
|
| 123 |
+
manipulated, 17% as out of context. The rest — the majority —
|
| 124 |
+
is authentic: verification isn't just about debunking, it's also
|
| 125 |
+
about confirming.
|
| 126 |
+
</p>
|
| 127 |
+
</article>
|
| 128 |
+
|
| 129 |
+
<!-- Related articles -->
|
| 130 |
+
<section class="px-6 pb-12">
|
| 131 |
+
<h2 class="font-serif text-3xl pb-2 mb-4 border-b">More to read</h2>
|
| 132 |
+
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
| 133 |
+
<article class="article-card">
|
| 134 |
+
<a href="article.html"><img src="https://images.unsplash.com/photo-1521791136064-7986c2920216?auto=format&fit=crop&w=900&q=80" alt="" /></a>
|
| 135 |
+
<span class="cat-tag tag-fact">Fact-check</span>
|
| 136 |
+
<a href="article.html"><h3>Was this Sfax protest photo manipulated?</h3></a>
|
| 137 |
+
<p>Two retouching traces flagged by Edited Photo Detection.</p>
|
| 138 |
+
</article>
|
| 139 |
+
<article class="article-card">
|
| 140 |
+
<a href="article.html"><img src="https://images.unsplash.com/photo-1554224155-1696413565d3?auto=format&fit=crop&w=900&q=80" alt="" /></a>
|
| 141 |
+
<span class="cat-tag tag-fact">Fact-check</span>
|
| 142 |
+
<a href="article.html"><h3>"Official" bank ad: AI-generated?</h3></a>
|
| 143 |
+
<p>Cosmetic Ads Fact-Check confirms a partial voice synthesis.</p>
|
| 144 |
+
</article>
|
| 145 |
+
<article class="article-card">
|
| 146 |
+
<a href="article.html"><img src="https://images.unsplash.com/photo-1605792657660-596af9009e82?auto=format&fit=crop&w=900&q=80" alt="" /></a>
|
| 147 |
+
<span class="cat-tag tag-clim">Climate</span>
|
| 148 |
+
<a href="article.html"><h3>Tunisia faces its worst water stress since 1947</h3></a>
|
| 149 |
+
<p>Reservoirs at 23%, six-point emergency plan.</p>
|
| 150 |
+
</article>
|
| 151 |
+
</div>
|
| 152 |
+
</section>
|
| 153 |
+
</main>
|
| 154 |
+
|
| 155 |
+
<div id="site-footer"></div>
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
<script src="assets/js/config.js?v=1"></script> <script src="assets/js/components.js?v=14"></script>
|
| 159 |
+
<script src="assets/js/main.js?v=7"></script>
|
| 160 |
+
</body>
|
| 161 |
+
</html>
|
assets/css/styles.css
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
assets/img/ads-marketing.jpg
ADDED
|
Git LFS Details
|
assets/img/ads.jpg
ADDED
|
Git LFS Details
|
assets/img/ads.png
ADDED
|
Git LFS Details
|
assets/img/ai-generative.jpg
ADDED
|
Git LFS Details
|
assets/img/cover1.png
ADDED
|
Git LFS Details
|
assets/img/cover2.png
ADDED
|
Git LFS Details
|
assets/img/cover4.png
ADDED
|
Git LFS Details
|
assets/img/cover5.png
ADDED
|
Git LFS Details
|
assets/img/cover6.png
ADDED
|
Git LFS Details
|
assets/img/deepfake-hero.jpg
ADDED
|
Git LFS Details
|
assets/img/examples/m-ai1.png
ADDED
|
Git LFS Details
|
assets/img/examples/m-ai2.png
ADDED
|
Git LFS Details
|
assets/img/examples/m-ai3.png
ADDED
|
Git LFS Details
|
assets/img/examples/m-doc1.jpg
ADDED
|
Git LFS Details
|
assets/img/examples/m-doc2.jpg
ADDED
|
Git LFS Details
|
assets/img/examples/m-edit1.jpg
ADDED
|
Git LFS Details
|
assets/img/examples/m-manip2.jpg
ADDED
|
Git LFS Details
|
assets/img/examples/m-manip4.jpg
ADDED
|
Git LFS Details
|
assets/img/examples/m-manip6.jpg
ADDED
|
Git LFS Details
|
assets/img/examples/m-news1.jpg
ADDED
|
Git LFS Details
|
assets/img/examples/m-news2.jpg
ADDED
|
Git LFS Details
|
assets/img/examples/m-orig1.jpg
ADDED
|
Git LFS Details
|
assets/img/examples/m-real1.jpg
ADDED
|
Git LFS Details
|
assets/img/examples/m-real2.jpg
ADDED
|
Git LFS Details
|
assets/img/examples/m-real3.jpg
ADDED
|
Git LFS Details
|
assets/img/examples/m-real4.jpg
ADDED
|
Git LFS Details
|
assets/img/factchecks/fc-elamra.png
ADDED
|
Git LFS Details
|
assets/img/factchecks/fc-gabes.jpg
ADDED
|
Git LFS Details
|
assets/img/factchecks/fc-ghannouchi.jpg
ADDED
|
Git LFS Details
|
assets/img/factchecks/fc-guardian.png
ADDED
|
Git LFS Details
|
assets/img/factchecks/fc-henneberg.png
ADDED
|
Git LFS Details
|
assets/img/factchecks/fc-kerkennah.jpg
ADDED
|
Git LFS Details
|
assets/img/factchecks/fc-migrant.jpg
ADDED
|
Git LFS Details
|
assets/img/factchecks/fc-nasrallah.png
ADDED
|
Git LFS Details
|
assets/img/factchecks/fc-yutong.png
ADDED
|
Git LFS Details
|
assets/img/factchecks/fc-zammel.png
ADDED
|
Git LFS Details
|