YassmineNouisser commited on
Commit
179d606
·
0 Parent(s):

Verify — multimodal disinformation detection platform (6 modules + chatbot)

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .dockerignore +44 -0
  2. .env.example +59 -0
  3. .gitattributes +7 -0
  4. .gitignore +73 -0
  5. AI_Investigate_Report_COMPLETE.pdf +3 -0
  6. DEPLOYMENT.md +238 -0
  7. Dockerfile +97 -0
  8. MODELS.md +105 -0
  9. README.md +177 -0
  10. Verify_Description_Commerciale.html +358 -0
  11. Verify_Description_Commerciale.pdf +3 -0
  12. archive.html +199 -0
  13. article.html +161 -0
  14. assets/css/styles.css +0 -0
  15. assets/img/ads-marketing.jpg +3 -0
  16. assets/img/ads.jpg +3 -0
  17. assets/img/ads.png +3 -0
  18. assets/img/ai-generative.jpg +3 -0
  19. assets/img/cover1.png +3 -0
  20. assets/img/cover2.png +3 -0
  21. assets/img/cover4.png +3 -0
  22. assets/img/cover5.png +3 -0
  23. assets/img/cover6.png +3 -0
  24. assets/img/deepfake-hero.jpg +3 -0
  25. assets/img/examples/m-ai1.png +3 -0
  26. assets/img/examples/m-ai2.png +3 -0
  27. assets/img/examples/m-ai3.png +3 -0
  28. assets/img/examples/m-doc1.jpg +3 -0
  29. assets/img/examples/m-doc2.jpg +3 -0
  30. assets/img/examples/m-edit1.jpg +3 -0
  31. assets/img/examples/m-manip2.jpg +3 -0
  32. assets/img/examples/m-manip4.jpg +3 -0
  33. assets/img/examples/m-manip6.jpg +3 -0
  34. assets/img/examples/m-news1.jpg +3 -0
  35. assets/img/examples/m-news2.jpg +3 -0
  36. assets/img/examples/m-orig1.jpg +3 -0
  37. assets/img/examples/m-real1.jpg +3 -0
  38. assets/img/examples/m-real2.jpg +3 -0
  39. assets/img/examples/m-real3.jpg +3 -0
  40. assets/img/examples/m-real4.jpg +3 -0
  41. assets/img/factchecks/fc-elamra.png +3 -0
  42. assets/img/factchecks/fc-gabes.jpg +3 -0
  43. assets/img/factchecks/fc-ghannouchi.jpg +3 -0
  44. assets/img/factchecks/fc-guardian.png +3 -0
  45. assets/img/factchecks/fc-henneberg.png +3 -0
  46. assets/img/factchecks/fc-kerkennah.jpg +3 -0
  47. assets/img/factchecks/fc-migrant.jpg +3 -0
  48. assets/img/factchecks/fc-nasrallah.png +3 -0
  49. assets/img/factchecks/fc-yutong.png +3 -0
  50. 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 &amp; 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 &amp; 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 &gt; 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

  • SHA256: 0eb61c55cacee2b1984c186caa36e549a00681a5788bc5e511887e75322bfff8
  • Pointer size: 131 Bytes
  • Size of remote file: 222 kB
assets/img/ads.jpg ADDED

Git LFS Details

  • SHA256: 0eb61c55cacee2b1984c186caa36e549a00681a5788bc5e511887e75322bfff8
  • Pointer size: 131 Bytes
  • Size of remote file: 222 kB
assets/img/ads.png ADDED

Git LFS Details

  • SHA256: ae4f12b68321e50b2282da10a67817e0e17f38482047eeec5ee8be7ef625d363
  • Pointer size: 131 Bytes
  • Size of remote file: 435 kB
assets/img/ai-generative.jpg ADDED

Git LFS Details

  • SHA256: bf04403bdff29468f0818ead5414aa2a71a9c4d9768f081fd77782a75fe4174e
  • Pointer size: 130 Bytes
  • Size of remote file: 48.2 kB
assets/img/cover1.png ADDED

Git LFS Details

  • SHA256: 50f8f6e78f6b8dbed86c71d78b29c91ef66836eb590c1a1b7341b0804db27394
  • Pointer size: 131 Bytes
  • Size of remote file: 218 kB
assets/img/cover2.png ADDED

Git LFS Details

  • SHA256: e2478e0a8a3c9b54be733a8784d1f3a09cb064cb053781c3c5955575f6221c62
  • Pointer size: 131 Bytes
  • Size of remote file: 253 kB
assets/img/cover4.png ADDED

Git LFS Details

  • SHA256: ae42f175bcedcab0f21c7686b49401e492e9adc03de4099105a0d707f5168bd8
  • Pointer size: 131 Bytes
  • Size of remote file: 295 kB
assets/img/cover5.png ADDED

Git LFS Details

  • SHA256: 7db27e7dc69406079180959b1845abf0dd0eb2c5de286c324af7b940d02f3c12
  • Pointer size: 131 Bytes
  • Size of remote file: 233 kB
assets/img/cover6.png ADDED

Git LFS Details

  • SHA256: 0182b4565c633184040618d54c9b62fe2de2829b448d30838b448c6ebced0281
  • Pointer size: 131 Bytes
  • Size of remote file: 208 kB
assets/img/deepfake-hero.jpg ADDED

Git LFS Details

  • SHA256: 43bb30002f7fbd33e4905b4e0485bcac1ab28d8e6f1f7419c05e8d2981eb456b
  • Pointer size: 131 Bytes
  • Size of remote file: 140 kB
assets/img/examples/m-ai1.png ADDED

Git LFS Details

  • SHA256: b42748bd5fc92c3f015b12b0a5db9f225f224a8862b57ca15a29f27461801ce9
  • Pointer size: 131 Bytes
  • Size of remote file: 208 kB
assets/img/examples/m-ai2.png ADDED

Git LFS Details

  • SHA256: 7fc6df17ae40883694836507876d71bf4c30e2238c8d67b2a34d63f38a17bc86
  • Pointer size: 131 Bytes
  • Size of remote file: 207 kB
assets/img/examples/m-ai3.png ADDED

Git LFS Details

  • SHA256: ff103c8baade0d99d49a5b8105a0b330f84b6d503fcdbe1c36b3f07b9c8d2303
  • Pointer size: 131 Bytes
  • Size of remote file: 239 kB
assets/img/examples/m-doc1.jpg ADDED

Git LFS Details

  • SHA256: 93f1eb088271b6680019d77a79d2e4e390790ba69ef064b1dd2ec2ec2f99e26d
  • Pointer size: 131 Bytes
  • Size of remote file: 109 kB
assets/img/examples/m-doc2.jpg ADDED

Git LFS Details

  • SHA256: cec18356541223cddd0f66827be270f6aaf139f12407b43456fd4603fa714273
  • Pointer size: 130 Bytes
  • Size of remote file: 96.2 kB
assets/img/examples/m-edit1.jpg ADDED

Git LFS Details

  • SHA256: f0384525312d672d5b219183f299195343e7e86c0def989f5dfd865791bdafd5
  • Pointer size: 131 Bytes
  • Size of remote file: 279 kB
assets/img/examples/m-manip2.jpg ADDED

Git LFS Details

  • SHA256: 60142e62ce10892414663d97990957b9936fa0e9d8e58046a2e877a6412c7086
  • Pointer size: 131 Bytes
  • Size of remote file: 143 kB
assets/img/examples/m-manip4.jpg ADDED

Git LFS Details

  • SHA256: 6623aee383a7a11a5ebd9e58add19bf5ca6959b160120a193ed8805d949cc451
  • Pointer size: 131 Bytes
  • Size of remote file: 205 kB
assets/img/examples/m-manip6.jpg ADDED

Git LFS Details

  • SHA256: 5b0c4d8801f1c149194a17f95cfa3e137dc2d584d2b5eca6de5910aa3a9766c7
  • Pointer size: 131 Bytes
  • Size of remote file: 145 kB
assets/img/examples/m-news1.jpg ADDED

Git LFS Details

  • SHA256: 6c78b4641368340e6adb5fce03a4c5a09ba32124497d607daacd4889990864e7
  • Pointer size: 130 Bytes
  • Size of remote file: 82.9 kB
assets/img/examples/m-news2.jpg ADDED

Git LFS Details

  • SHA256: d5978e1a35a2f8b81c1e6f9699c776744ae07b922348d864be124d80308a6098
  • Pointer size: 131 Bytes
  • Size of remote file: 113 kB
assets/img/examples/m-orig1.jpg ADDED

Git LFS Details

  • SHA256: 136bf28068cac05457ad53023f171fa9ba4ca3d2938a9ed46d6da9a11f5cdeed
  • Pointer size: 131 Bytes
  • Size of remote file: 338 kB
assets/img/examples/m-real1.jpg ADDED

Git LFS Details

  • SHA256: 54452d6b79eecb5fb3a28d5f353837e2cdd780474e770d61a5be1879cfd9703d
  • Pointer size: 130 Bytes
  • Size of remote file: 94.3 kB
assets/img/examples/m-real2.jpg ADDED

Git LFS Details

  • SHA256: bdfbcf54d8136aae9f0ff820a123ef3ade137dbeb7eb874fb76b389cde7510de
  • Pointer size: 131 Bytes
  • Size of remote file: 174 kB
assets/img/examples/m-real3.jpg ADDED

Git LFS Details

  • SHA256: 2a2898789241373a600f5835ec973b481dfa5fda1fe0ea7c3ee2a9caf02f3af6
  • Pointer size: 131 Bytes
  • Size of remote file: 178 kB
assets/img/examples/m-real4.jpg ADDED

Git LFS Details

  • SHA256: c721dfc1ad904f33054337aec40c00f6f9ad2a4c117b27c72c4507ca9eb63981
  • Pointer size: 131 Bytes
  • Size of remote file: 140 kB
assets/img/factchecks/fc-elamra.png ADDED

Git LFS Details

  • SHA256: a10e6d929c9783477565665fd19106012804e7e93b21d3410a8529406707201f
  • Pointer size: 131 Bytes
  • Size of remote file: 152 kB
assets/img/factchecks/fc-gabes.jpg ADDED

Git LFS Details

  • SHA256: 0f2c92c5fecda58b7ef98ce8a5bd46aac1346c06b95f1763cf4067bcafec6a4c
  • Pointer size: 131 Bytes
  • Size of remote file: 200 kB
assets/img/factchecks/fc-ghannouchi.jpg ADDED

Git LFS Details

  • SHA256: b75ce63447ff1bb958277c7a2618caae3d40ddeb5911320a31a511a5bb235d71
  • Pointer size: 131 Bytes
  • Size of remote file: 131 kB
assets/img/factchecks/fc-guardian.png ADDED

Git LFS Details

  • SHA256: ae8c7b4af86eaeb9bf409f6a8b36cf9666f9973a9bf5ffd1bd734462520e89c8
  • Pointer size: 131 Bytes
  • Size of remote file: 127 kB
assets/img/factchecks/fc-henneberg.png ADDED

Git LFS Details

  • SHA256: cb94222ebb0a14a4cb85a0542478035cda8a5ef09553c6e9f355d50120ffe227
  • Pointer size: 130 Bytes
  • Size of remote file: 91.2 kB
assets/img/factchecks/fc-kerkennah.jpg ADDED

Git LFS Details

  • SHA256: 1d84779d4246361b7617fc6a294db5fe17360e49d5846d34af9a177ca476ea6c
  • Pointer size: 131 Bytes
  • Size of remote file: 157 kB
assets/img/factchecks/fc-migrant.jpg ADDED

Git LFS Details

  • SHA256: d21355f3bb1cbf589c068c66e32adefaba5528518b9ecb1cc8dfdcbc700f7ecb
  • Pointer size: 131 Bytes
  • Size of remote file: 205 kB
assets/img/factchecks/fc-nasrallah.png ADDED

Git LFS Details

  • SHA256: db15e2d1444f5655c466bc856e2474f2ad94a71544f6c8f8d9da04b16308fabf
  • Pointer size: 131 Bytes
  • Size of remote file: 180 kB
assets/img/factchecks/fc-yutong.png ADDED

Git LFS Details

  • SHA256: fae036aa08a0be3d4a98e526834fcaa5e6253fa4aaf56e5d2e0c0c6995c0d7fd
  • Pointer size: 131 Bytes
  • Size of remote file: 136 kB
assets/img/factchecks/fc-zammel.png ADDED

Git LFS Details

  • SHA256: 61eb4222e76403075f4c60fb3bdff21f9a216a5180b55bfb073d68f3ba18e9fe
  • Pointer size: 130 Bytes
  • Size of remote file: 82.9 kB