Upload 12 files
Browse files- .dockerignore +43 -0
- .env.example +43 -0
- .gitattributes +2 -35
- .gitignore +234 -0
- Dockerfile1 +64 -0
- README.md +488 -10
- README_HF.md +9 -0
- docker-compose.yml +82 -0
- dockerfile.huggingface +64 -0
- pyproject.toml +42 -0
- render.yaml +37 -0
- uv.lock +0 -0
.dockerignore
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Backend .dockerignore
|
| 2 |
+
# Exclude files that are not needed in the Docker image
|
| 3 |
+
|
| 4 |
+
# Python bytecode
|
| 5 |
+
__pycache__/
|
| 6 |
+
*.pyc
|
| 7 |
+
*.pyo
|
| 8 |
+
*.pyd
|
| 9 |
+
.Python
|
| 10 |
+
|
| 11 |
+
# Virtual environments
|
| 12 |
+
.venv/
|
| 13 |
+
venv/
|
| 14 |
+
env/
|
| 15 |
+
|
| 16 |
+
# Development data / notebooks
|
| 17 |
+
Data/
|
| 18 |
+
Notebook/
|
| 19 |
+
|
| 20 |
+
# Git
|
| 21 |
+
.git/
|
| 22 |
+
.gitignore
|
| 23 |
+
|
| 24 |
+
# Docker files (not needed inside the container)
|
| 25 |
+
Dockerfile
|
| 26 |
+
docker-compose.yml
|
| 27 |
+
frontend/
|
| 28 |
+
|
| 29 |
+
# Logs (mounted as a volume)
|
| 30 |
+
logs/
|
| 31 |
+
|
| 32 |
+
# OS noise
|
| 33 |
+
.DS_Store
|
| 34 |
+
Thumbs.db
|
| 35 |
+
|
| 36 |
+
# IDE
|
| 37 |
+
.vscode/
|
| 38 |
+
.idea/
|
| 39 |
+
|
| 40 |
+
# Environment files (injected at runtime)
|
| 41 |
+
.env
|
| 42 |
+
.env.*
|
| 43 |
+
!.env.example
|
.env.example
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ── MongoDB ──────────────────────────────────────────────────
|
| 2 |
+
# Used by docker-compose to create the root user
|
| 3 |
+
MONGO_ROOT_USER=admin
|
| 4 |
+
MONGO_ROOT_PASSWORD=changeme_use_a_strong_password
|
| 5 |
+
DATABASE_NAME=fake_news_detector
|
| 6 |
+
# Full connection string (auto-built in docker-compose; set manually for standalone)
|
| 7 |
+
MONGODB_URL=mongodb+srv://ravishripad6:ravishripad6%402580@cluster0.kcyd6s1.mongodb.net/?appName=Cluster0
|
| 8 |
+
|
| 9 |
+
# ── JWT Auth ─────────────────────────────────────────────────
|
| 10 |
+
# Generate with: python -c "import secrets; print(secrets.token_hex(32))"
|
| 11 |
+
SECRET_KEY=6e7b97830f56d162d75deb39fb8c1f5d9bdaebedb8ee23042616cd09a6204d38
|
| 12 |
+
ALGORITHM=HS256
|
| 13 |
+
ACCESS_TOKEN_EXPIRE_MINUTES=1440
|
| 14 |
+
|
| 15 |
+
# ── AI Verification API Key (Gemini) ─────────────────────────
|
| 16 |
+
# Get free key at: https://aistudio.google.com/app/apikey
|
| 17 |
+
AI_API_KEY=AIzaSyCPAqy6YoO8ISFe-u0RcJ72eAjYUcGoN4o
|
| 18 |
+
|
| 19 |
+
# ── Mistral OCR API Key (for image text extraction) ──────────
|
| 20 |
+
# Get free key at: https://console.mistral.ai/
|
| 21 |
+
MISTRAL_API_KEY=wvJaTtuJDULRTnBGtSd3MxsQOuNN3e8Nstral
|
| 22 |
+
|
| 23 |
+
# ── NewsAPI (optional – for news validation) ─────────────────
|
| 24 |
+
# Get free key at: https://newsapi.org/register
|
| 25 |
+
NEWS_API_KEY=6281340be6194ac4abc800a4d1ddfdba
|
| 26 |
+
|
| 27 |
+
# ── SerpAPI (optional – for Google search verification) ───────
|
| 28 |
+
# Get free key at: https://serpapi.com/users/sign_up
|
| 29 |
+
SERP_API_KEY=6ac3b5f8a85d47a02a6f106d25e203be2091572f336f73f0bfd8556e9e3f0a7d
|
| 30 |
+
|
| 31 |
+
# ── API Configuration ─────────────────────────────────────────
|
| 32 |
+
API_HOST=0.0.0.0
|
| 33 |
+
API_PORT=8000
|
| 34 |
+
|
| 35 |
+
# ── Model Configuration ───────────────────────────────────────
|
| 36 |
+
MODEL_PATH=./enhanced_bert_liar_model
|
| 37 |
+
WELFAKE_MODEL_PATH=./enhanced_bert_welfake_model
|
| 38 |
+
MAX_LENGTH=512
|
| 39 |
+
|
| 40 |
+
# ── Enable/Disable AI Cross-Check ────────────────────────────
|
| 41 |
+
ENABLE_AI_CHECK=true
|
| 42 |
+
|
| 43 |
+
VITE_API_URL=https://YOUR_HF_USER-your-space.hf.space/api
|
.gitattributes
CHANGED
|
@@ -1,35 +1,2 @@
|
|
| 1 |
-
*.
|
| 2 |
-
|
| 3 |
-
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
-
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
-
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
-
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
-
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
-
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
-
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
-
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
-
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
-
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
-
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
-
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
-
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
-
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
-
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
-
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
-
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
-
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
-
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
-
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
-
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
-
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
-
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
-
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
-
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
-
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
-
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
-
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
-
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
| 1 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
Data/WELFake_Dataset.csv filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.gitignore
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# =================================
|
| 2 |
+
# TruthLens - AI Fake News Detector
|
| 3 |
+
# =================================
|
| 4 |
+
|
| 5 |
+
# =================================
|
| 6 |
+
# Python
|
| 7 |
+
# =================================
|
| 8 |
+
|
| 9 |
+
# Byte-compiled / optimized / DLL files
|
| 10 |
+
__pycache__/
|
| 11 |
+
*.py[cod]
|
| 12 |
+
*$py.class
|
| 13 |
+
|
| 14 |
+
# C extensions
|
| 15 |
+
*.so
|
| 16 |
+
|
| 17 |
+
# Distribution / packaging
|
| 18 |
+
.Python
|
| 19 |
+
build/
|
| 20 |
+
develop-eggs/
|
| 21 |
+
dist/
|
| 22 |
+
downloads/
|
| 23 |
+
eggs/
|
| 24 |
+
.eggs/
|
| 25 |
+
lib/
|
| 26 |
+
lib64/
|
| 27 |
+
parts/
|
| 28 |
+
sdist/
|
| 29 |
+
var/
|
| 30 |
+
wheels/
|
| 31 |
+
share/python-wheels/
|
| 32 |
+
*.egg-info/
|
| 33 |
+
.installed.cfg
|
| 34 |
+
*.egg
|
| 35 |
+
MANIFEST
|
| 36 |
+
|
| 37 |
+
# PyInstaller
|
| 38 |
+
*.manifest
|
| 39 |
+
*.spec
|
| 40 |
+
|
| 41 |
+
# Installer logs
|
| 42 |
+
pip-log.txt
|
| 43 |
+
pip-delete-this-directory.txt
|
| 44 |
+
|
| 45 |
+
# Unit test / coverage reports
|
| 46 |
+
htmlcov/
|
| 47 |
+
.tox/
|
| 48 |
+
.nox/
|
| 49 |
+
.coverage
|
| 50 |
+
.coverage.*
|
| 51 |
+
.cache
|
| 52 |
+
nosetests.xml
|
| 53 |
+
coverage.xml
|
| 54 |
+
*.cover
|
| 55 |
+
*.py,cover
|
| 56 |
+
.hypothesis/
|
| 57 |
+
.pytest_cache/
|
| 58 |
+
pytest_cache/
|
| 59 |
+
|
| 60 |
+
# Translations
|
| 61 |
+
*.mo
|
| 62 |
+
*.pot
|
| 63 |
+
|
| 64 |
+
# Virtual environments
|
| 65 |
+
.venv/
|
| 66 |
+
venv/
|
| 67 |
+
ENV/
|
| 68 |
+
env/
|
| 69 |
+
.env.local
|
| 70 |
+
|
| 71 |
+
# UV package manager
|
| 72 |
+
.uv/
|
| 73 |
+
uv.lock
|
| 74 |
+
|
| 75 |
+
# Jupyter Notebook checkpoints
|
| 76 |
+
.ipynb_checkpoints/
|
| 77 |
+
|
| 78 |
+
# pyenv
|
| 79 |
+
.python-version
|
| 80 |
+
|
| 81 |
+
# mypy
|
| 82 |
+
.mypy_cache/
|
| 83 |
+
.dmypy.json
|
| 84 |
+
dmypy.json
|
| 85 |
+
|
| 86 |
+
# Pyre type checker
|
| 87 |
+
.pyre/
|
| 88 |
+
|
| 89 |
+
# =================================
|
| 90 |
+
# Environment Variables
|
| 91 |
+
# =================================
|
| 92 |
+
.env
|
| 93 |
+
.env.local
|
| 94 |
+
.env.development.local
|
| 95 |
+
.env.test.local
|
| 96 |
+
.env.production.local
|
| 97 |
+
*.local
|
| 98 |
+
|
| 99 |
+
# =================================
|
| 100 |
+
# Node.js / Frontend
|
| 101 |
+
# =================================
|
| 102 |
+
|
| 103 |
+
# Dependencies
|
| 104 |
+
frontend/node_modules/
|
| 105 |
+
node_modules/
|
| 106 |
+
|
| 107 |
+
# Build output
|
| 108 |
+
frontend/dist/
|
| 109 |
+
frontend/build/
|
| 110 |
+
dist/
|
| 111 |
+
|
| 112 |
+
# Debug logs
|
| 113 |
+
npm-debug.log*
|
| 114 |
+
yarn-debug.log*
|
| 115 |
+
yarn-error.log*
|
| 116 |
+
pnpm-debug.log*
|
| 117 |
+
lerna-debug.log*
|
| 118 |
+
|
| 119 |
+
# Vite
|
| 120 |
+
*.local
|
| 121 |
+
.vite/
|
| 122 |
+
|
| 123 |
+
# =================================
|
| 124 |
+
# IDEs and Editors
|
| 125 |
+
# =================================
|
| 126 |
+
|
| 127 |
+
# VS Code
|
| 128 |
+
.vscode/*
|
| 129 |
+
!.vscode/settings.json
|
| 130 |
+
!.vscode/tasks.json
|
| 131 |
+
!.vscode/launch.json
|
| 132 |
+
!.vscode/extensions.json
|
| 133 |
+
|
| 134 |
+
# JetBrains (PyCharm, WebStorm, etc.)
|
| 135 |
+
.idea/
|
| 136 |
+
*.iml
|
| 137 |
+
*.iws
|
| 138 |
+
*.ipr
|
| 139 |
+
|
| 140 |
+
# Sublime Text
|
| 141 |
+
*.sublime-project
|
| 142 |
+
*.sublime-workspace
|
| 143 |
+
|
| 144 |
+
# Vim
|
| 145 |
+
*.swp
|
| 146 |
+
*.swo
|
| 147 |
+
*~
|
| 148 |
+
|
| 149 |
+
# Emacs
|
| 150 |
+
*~
|
| 151 |
+
\#*\#
|
| 152 |
+
/.emacs.desktop
|
| 153 |
+
/.emacs.desktop.lock
|
| 154 |
+
*.elc
|
| 155 |
+
|
| 156 |
+
# =================================
|
| 157 |
+
# Operating System
|
| 158 |
+
# =================================
|
| 159 |
+
|
| 160 |
+
# macOS
|
| 161 |
+
.DS_Store
|
| 162 |
+
.AppleDouble
|
| 163 |
+
.LSOverride
|
| 164 |
+
._*
|
| 165 |
+
.Spotlight-V100
|
| 166 |
+
.Trashes
|
| 167 |
+
|
| 168 |
+
# Windows
|
| 169 |
+
Thumbs.db
|
| 170 |
+
ehthumbs.db
|
| 171 |
+
Desktop.ini
|
| 172 |
+
$RECYCLE.BIN/
|
| 173 |
+
*.lnk
|
| 174 |
+
|
| 175 |
+
# Linux
|
| 176 |
+
*~
|
| 177 |
+
|
| 178 |
+
# =================================
|
| 179 |
+
# ML/AI Model Files (Optional)
|
| 180 |
+
# =================================
|
| 181 |
+
# Uncomment these if you don't want to track large model files
|
| 182 |
+
# enhanced_bert_liar_model/model.pth
|
| 183 |
+
|
| 184 |
+
# *.pt
|
| 185 |
+
# *.bin
|
| 186 |
+
# *.onnx
|
| 187 |
+
# *.h5
|
| 188 |
+
|
| 189 |
+
# =================================
|
| 190 |
+
# Logs and Databases
|
| 191 |
+
# =================================
|
| 192 |
+
*.log
|
| 193 |
+
logs/*.log
|
| 194 |
+
logs/*.log.*
|
| 195 |
+
*.sql
|
| 196 |
+
*.sqlite
|
| 197 |
+
*.db
|
| 198 |
+
|
| 199 |
+
# =================================
|
| 200 |
+
# Temporary Files
|
| 201 |
+
# =================================
|
| 202 |
+
tmp/
|
| 203 |
+
temp/
|
| 204 |
+
*.tmp
|
| 205 |
+
*.temp
|
| 206 |
+
*.bak
|
| 207 |
+
|
| 208 |
+
# =================================
|
| 209 |
+
# Secrets and Credentials
|
| 210 |
+
# =================================
|
| 211 |
+
*.pem
|
| 212 |
+
*.key
|
| 213 |
+
*.crt
|
| 214 |
+
secrets/
|
| 215 |
+
credentials/
|
| 216 |
+
|
| 217 |
+
# =================================
|
| 218 |
+
# Docker (if used later)
|
| 219 |
+
# =================================
|
| 220 |
+
docker-compose.override.yml
|
| 221 |
+
.docker/
|
| 222 |
+
|
| 223 |
+
# =================================
|
| 224 |
+
# Misc
|
| 225 |
+
# =================================
|
| 226 |
+
*.orig
|
| 227 |
+
*.rej
|
| 228 |
+
.history/
|
| 229 |
+
|
| 230 |
+
# =================================
|
| 231 |
+
# HF Spaces deployment repo
|
| 232 |
+
# (separate git repo — not a submodule)
|
| 233 |
+
# =================================
|
| 234 |
+
truthlens-backend/
|
Dockerfile1
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ──────────────────────────────────────────────
|
| 2 |
+
# Backend Dockerfile — FastAPI + BERT (PyTorch)
|
| 3 |
+
# ──────────────────────────────────────────────
|
| 4 |
+
FROM python:3.11-slim
|
| 5 |
+
|
| 6 |
+
# System dependencies needed by PyTorch / transformers / Pillow
|
| 7 |
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
| 8 |
+
build-essential \
|
| 9 |
+
libgl1 \
|
| 10 |
+
libglib2.0-0 \
|
| 11 |
+
curl \
|
| 12 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 13 |
+
|
| 14 |
+
# Set working directory
|
| 15 |
+
WORKDIR /app
|
| 16 |
+
|
| 17 |
+
# Copy dependency spec and install Python packages FIRST (layer cache)
|
| 18 |
+
COPY pyproject.toml ./
|
| 19 |
+
RUN pip install --upgrade pip \
|
| 20 |
+
&& pip install --no-cache-dir \
|
| 21 |
+
fastapi \
|
| 22 |
+
"uvicorn[standard]" \
|
| 23 |
+
torch \
|
| 24 |
+
transformers \
|
| 25 |
+
pillow \
|
| 26 |
+
requests \
|
| 27 |
+
pydantic \
|
| 28 |
+
"python-multipart" \
|
| 29 |
+
"google-genai" \
|
| 30 |
+
python-dotenv \
|
| 31 |
+
newsapi-python \
|
| 32 |
+
beautifulsoup4 \
|
| 33 |
+
serpapi \
|
| 34 |
+
motor \
|
| 35 |
+
pymongo \
|
| 36 |
+
"python-jose[cryptography]" \
|
| 37 |
+
"passlib[bcrypt]" \
|
| 38 |
+
email-validator \
|
| 39 |
+
mistralai \
|
| 40 |
+
slowapi \
|
| 41 |
+
pytesseract
|
| 42 |
+
|
| 43 |
+
# Copy application source code
|
| 44 |
+
COPY app/ ./app/
|
| 45 |
+
|
| 46 |
+
# Copy pre-trained BERT model directories
|
| 47 |
+
COPY enhanced_bert_liar_model/ ./enhanced_bert_liar_model/
|
| 48 |
+
COPY enhanced_bert_welfake_model/ ./enhanced_bert_welfake_model/
|
| 49 |
+
|
| 50 |
+
# Copy the server entry-point
|
| 51 |
+
COPY run_api.py ./
|
| 52 |
+
|
| 53 |
+
# Create logs directory
|
| 54 |
+
RUN mkdir -p logs
|
| 55 |
+
|
| 56 |
+
# Expose the FastAPI port
|
| 57 |
+
EXPOSE 8000
|
| 58 |
+
|
| 59 |
+
# Health check
|
| 60 |
+
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
| 61 |
+
CMD curl -f http://localhost:8000/health || exit 1
|
| 62 |
+
|
| 63 |
+
# Run with uvicorn
|
| 64 |
+
CMD ["python", "-m", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
README.md
CHANGED
|
@@ -1,10 +1,488 @@
|
|
| 1 |
-
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
--
|
| 9 |
-
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🛡️ TruthLens — BERT-Based Fake News Detector
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+

|
| 6 |
+

|
| 7 |
+

|
| 8 |
+

|
| 9 |
+

|
| 10 |
+

|
| 11 |
+

|
| 12 |
+

|
| 13 |
+
|
| 14 |
+
---
|
| 15 |
+
|
| 16 |
+
A full-stack web application that detects fake news using a **large language model (LLM)** as the primary classifier, backed by a fine-tuned BERT transformer model, real-time Google News RSS validation, image OCR analysis, API rate limiting, and a fully animated React interface with MongoDB-backed user authentication.
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
## 🌐 Live Demo
|
| 20 |
+
|
| 21 |
+
| | Link |
|
| 22 |
+
|---|---|
|
| 23 |
+
| **🖥️ Frontend (React App)** | **[https://truth-lens-bert-based-fake-news-and.vercel.app](https://truth-lens-bert-based-fake-news-and.vercel.app)** |
|
| 24 |
+
| **⚙️ Backend API** | [https://suryakf-truthlens-backend.hf.space](https://suryakf-truthlens-backend.hf.space) |
|
| 25 |
+
| **📖 Swagger / API Docs** | [https://suryakf-truthlens-backend.hf.space/docs](https://suryakf-truthlens-backend.hf.space/docs) |
|
| 26 |
+
|
| 27 |
+
> The backend runs on **Hugging Face Spaces** (CPU Basic — 2 vCPU, 16 GB RAM).
|
| 28 |
+
> The frontend is deployed on **Vercel** with global CDN.
|
| 29 |
+
> The database is **MongoDB Atlas** (M0 free cluster).
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
## ✨ Features
|
| 34 |
+
|
| 35 |
+
### Core Detection Pipeline
|
| 36 |
+
- **Fine-tuned BERT (Primary)** — PyTorch BERT model (~95% accuracy)
|
| 37 |
+
- **Three-label output** — `REAL` / `FAKE` / `UNVERIFIED`. The LLM outputs UNVERIFIED when evidence is inconclusive, avoiding over-flagging real recent news as fake.
|
| 38 |
+
- **Confidence Scoring** — Per-prediction probability distribution visualised as a live pie chart.
|
| 39 |
+
- **Batch Analysis** — Submit up to 10 news texts in one request.
|
| 40 |
+
|
| 41 |
+
### News Source Validation
|
| 42 |
+
- **Google News RSS** — Free real-time headline search (no API key required). Retrieves title, source, publish date, and article description.
|
| 43 |
+
- **NewsAPI Integration** — Extended article lookup with source attribution.
|
| 44 |
+
- **SerpAPI Integration** — Fallback search-engine news verification.
|
| 45 |
+
- **Live context injection** — All retrieved articles (headline + summary + URL + publish date) are passed directly into the LLM's prompt so it cross-references the claim against real-world evidence.
|
| 46 |
+
|
| 47 |
+
### Image & OCR
|
| 48 |
+
- **Screenshot Upload** — Paste or upload a screenshot of a news headline/article.
|
| 49 |
+
- **Mistral OCR** — Extracts title, body text, source, and date from the image.
|
| 50 |
+
- **Same pipeline as text** — After OCR, the extracted headline goes through the same LLM-primary flow (news search → LLM with context → BERT fallback).
|
| 51 |
+
|
| 52 |
+
### Rate Limiting
|
| 53 |
+
API rate limits enforced via **slowapi** (per client IP):
|
| 54 |
+
|
| 55 |
+
| Endpoint | Limit |
|
| 56 |
+
|---|---|
|
| 57 |
+
| `POST /api/predict` | 30 / minute |
|
| 58 |
+
| `POST /api/batch-predict` | 5 / minute |
|
| 59 |
+
| `POST /api/image-predict` | 10 / minute |
|
| 60 |
+
| `POST /api/extract-image-text` | 10 / minute |
|
| 61 |
+
| `POST /api/auth/login` | 5 / minute |
|
| 62 |
+
| `POST /api/auth/register` | 3 / minute |
|
| 63 |
+
|
| 64 |
+
### Authentication & History
|
| 65 |
+
- **JWT Authentication** — 24-hour access tokens, bcrypt-hashed passwords.
|
| 66 |
+
- **Prediction History** — Every analysis stored with timestamp and label in MongoDB.
|
| 67 |
+
- **User Dashboard** — Live stats, streak counter, accuracy breakdown.
|
| 68 |
+
|
| 69 |
+
### Developer Experience
|
| 70 |
+
- **Rotating Log Files** — All API activity written to `logs/app.log` (10 MB cap, 5 backups).
|
| 71 |
+
- **Swagger / ReDoc** — Auto-generated interactive API docs at `/docs` and `/redoc`.
|
| 72 |
+
- **Environment-Driven Config** — All secrets via `.env`.
|
| 73 |
+
|
| 74 |
+
---
|
| 75 |
+
|
| 76 |
+
## 🏗️ Architecture
|
| 77 |
+
|
| 78 |
+
```
|
| 79 |
+
┌─────────────────────────────────────────────────────────────────┐
|
| 80 |
+
│ FRONTEND (React + Vite) │
|
| 81 |
+
│ Home │ Login │ Register │ Dashboard │
|
| 82 |
+
│ GSAP ScrollTrigger · Framer Motion · TailwindCSS · Recharts │
|
| 83 |
+
└────────────────────────────┬────────────────────────────────────┘
|
| 84 |
+
│ HTTPS / JWT
|
| 85 |
+
┌────────────────────────────▼────────────────────────────────────┐
|
| 86 |
+
│ BACKEND (FastAPI) │
|
| 87 |
+
│ Rate Limiting (slowapi) → Logging Middleware → logs/app.log │
|
| 88 |
+
│ /api/predict /api/batch-predict /api/image-predict │
|
| 89 |
+
└──────┬──────────────────────────────────────┬───────────────────┘
|
| 90 |
+
│ │
|
| 91 |
+
▼ STEP 1 ▼ STEP 1 (image)
|
| 92 |
+
┌─────────────────┐ ┌─────────────────────┐
|
| 93 |
+
│ News Validator │ │ Mistral OCR │
|
| 94 |
+
│ Google News RSS │ │ Extracts title + │
|
| 95 |
+
│ NewsAPI │ │ text from image │
|
| 96 |
+
│ SerpAPI │ └──────────┬──────────┘
|
| 97 |
+
└────────┬────────┘ │
|
| 98 |
+
│ articles (title+desc+date+url) │ extracted headline
|
| 99 |
+
▼ STEP 2 (PRIMARY) ▼ STEP 2 (PRIMARY)
|
| 100 |
+
┌─────────────────────────────────────────────────────────────────┐
|
| 101 |
+
│ LLM Fact-Checker │
|
| 102 |
+
│ Primary model → Fallback 1 → Fallback 2 │
|
| 103 |
+
│ Output: REAL / FAKE / UNVERIFIED + confidence + reasoning │
|
| 104 |
+
└───────────────────────────────┬─────────────────────────────────┘
|
| 105 |
+
│ (only if ALL Gemini models fail)
|
| 106 |
+
▼ STEP 3 (FALLBACK)
|
| 107 |
+
┌────────────────────────┐
|
| 108 |
+
│ Fine-tuned BERT │
|
| 109 |
+
│ PyTorch + HF ~95% acc │
|
| 110 |
+
└────────────────────────┘
|
| 111 |
+
│
|
| 112 |
+
┌───────────────────────────────▼─────────────────────────────────┐
|
| 113 |
+
│ MongoDB Atlas (Motor async) │
|
| 114 |
+
│ users collection · predictions collection │
|
| 115 |
+
└─────────────────────────────────────────────────────────────────┘
|
| 116 |
+
```
|
| 117 |
+
|
| 118 |
+
### Hybrid Model Architecture (Mermaid)
|
| 119 |
+
|
| 120 |
+
```mermaid
|
| 121 |
+
flowchart TD
|
| 122 |
+
A[Input Text] --> B[Tokenizer<br/>bert-base-uncased]
|
| 123 |
+
B --> C[input_ids, attention_mask]
|
| 124 |
+
|
| 125 |
+
C --> D[BERT Encoder<br/>Hidden Size: 768]
|
| 126 |
+
D --> E[Dropout]
|
| 127 |
+
E --> F[BiLSTM<br/>2 layers, hidden=256, bidirectional]
|
| 128 |
+
F --> G[LayerNorm<br/>Output dim: 512]
|
| 129 |
+
G --> H[Multi-Head Self-Attention<br/>8 heads]
|
| 130 |
+
|
| 131 |
+
H --> I[Global Max Pooling<br/>across sequence]
|
| 132 |
+
I --> J[MLP Classifier]
|
| 133 |
+
|
| 134 |
+
J --> J1[Linear 512->256 + ReLU + Dropout]
|
| 135 |
+
J1 --> J2[Linear 256->128 + ReLU + Dropout]
|
| 136 |
+
J2 --> J3[Linear 128->2]
|
| 137 |
+
|
| 138 |
+
J3 --> K[Logits: Real vs Fake]
|
| 139 |
+
K --> L[Softmax / Argmax Prediction]
|
| 140 |
+
|
| 141 |
+
subgraph Training
|
| 142 |
+
M[CrossEntropyLoss<br/>class weights + label smoothing]
|
| 143 |
+
N[AdamW + LR Scheduler<br/>Warmup + Weight Decay]
|
| 144 |
+
O[Early Stopping<br/>monitor val F1]
|
| 145 |
+
end
|
| 146 |
+
|
| 147 |
+
J3 --> M
|
| 148 |
+
M --> N
|
| 149 |
+
N --> O
|
| 150 |
+
```
|
| 151 |
+
|
| 152 |
+
---
|
| 153 |
+
|
| 154 |
+
## 📁 Project Structure
|
| 155 |
+
|
| 156 |
+
```
|
| 157 |
+
FinalYearProject/
|
| 158 |
+
├── app/
|
| 159 |
+
│ ├── main.py # FastAPI app, CORS, rate limiter, logging middleware
|
| 160 |
+
│ ├── auth.py # JWT token logic, bcrypt helpers
|
| 161 |
+
│ ├── database.py # Motor async MongoDB client
|
| 162 |
+
│ ├── limiter.py # Shared slowapi Limiter instance
|
| 163 |
+
│ ├── api/
|
| 164 |
+
│ │ ├── routes.py # Prediction endpoints (/api/predict, /api/batch-predict, /api/image-predict)
|
| 165 |
+
│ │ └── auth_routes.py # Auth endpoints (/api/auth/*)
|
| 166 |
+
│ ├── models/
|
| 167 |
+
│ │ └── bert_model.py # BERT inference wrapper (fallback only)
|
| 168 |
+
│ ├── schemas/
|
| 169 |
+
│ │ ├── prediction.py # Pydantic request/response models
|
| 170 |
+
│ │ └── auth.py # User & token schemas
|
| 171 |
+
│ └── utils/
|
| 172 |
+
│ ├── ai_verification.py # LLM fact-checker (primary classifier)
|
| 173 |
+
│ ├── news_validator.py # Multi-source news validation + RSS parser
|
| 174 |
+
│ ├── image_ocr.py # Mistral OCR — image upload + text extraction
|
| 175 |
+
│ └── logger.py # RotatingFileHandler logger factory
|
| 176 |
+
├── enhanced_bert_liar_model/ # BERT fine-tuned on LIAR dataset (fallback)
|
| 177 |
+
├── enhanced_bert_welfake_model/ # BERT fine-tuned on WELFake dataset (fallback)
|
| 178 |
+
├── frontend/
|
| 179 |
+
│ └── src/
|
| 180 |
+
│ ├── App.jsx
|
| 181 |
+
│ ├── api/index.js
|
| 182 |
+
│ ├── context/AuthContext.jsx
|
| 183 |
+
│ ├── motion/ # GSAP + Framer Motion helpers
|
| 184 |
+
│ └── pages/ # Home, Dashboard, Login, Register
|
| 185 |
+
├── logs/ # Auto-created — rotating app.log
|
| 186 |
+
├── Data/WELFake_Dataset.csv
|
| 187 |
+
├── Notebook/
|
| 188 |
+
│ ├── bert_finetune_notebook.ipynb
|
| 189 |
+
│ └── wel-fakebert-finetune-notebook.ipynb
|
| 190 |
+
├── run_api.py
|
| 191 |
+
├── pyproject.toml
|
| 192 |
+
└── README.md
|
| 193 |
+
```
|
| 194 |
+
|
| 195 |
+
---
|
| 196 |
+
|
| 197 |
+
## 🚀 Production Deployment
|
| 198 |
+
|
| 199 |
+
```
|
| 200 |
+
Browser
|
| 201 |
+
└──▶ Vercel (React/Vite frontend)
|
| 202 |
+
└── VITE_API_URL ──▶ Hugging Face Spaces (FastAPI + BERT + LLM)
|
| 203 |
+
└── MONGODB_URL ──▶ MongoDB Atlas
|
| 204 |
+
```
|
| 205 |
+
|
| 206 |
+
| Layer | Platform | Plan |
|
| 207 |
+
|-------|----------|------|
|
| 208 |
+
| Frontend | [Vercel](https://vercel.com) | Free |
|
| 209 |
+
| Backend | [Hugging Face Spaces](https://huggingface.co/spaces) | CPU Basic (Free) |
|
| 210 |
+
| Database | [MongoDB Atlas](https://cloud.mongodb.com) | M0 Free |
|
| 211 |
+
|
| 212 |
+
### Deploy your own copy
|
| 213 |
+
|
| 214 |
+
**Backend (HF Spaces)**
|
| 215 |
+
1. Fork this repo and create a new Space (SDK: **Docker**)
|
| 216 |
+
2. Copy `app/`, `enhanced_bert_*/`, `run_api.py`, `Dockerfile.huggingface` (rename to `Dockerfile`)
|
| 217 |
+
3. Add secrets in Space Settings:
|
| 218 |
+
|
| 219 |
+
| Secret | Description |
|
| 220 |
+
|--------|-------------|
|
| 221 |
+
| `MONGODB_URL` | MongoDB Atlas connection string |
|
| 222 |
+
| `SECRET_KEY` | JWT signing secret |
|
| 223 |
+
| `AI_API_KEY` | LLM API key for the primary fact-checker |
|
| 224 |
+
| `MISTRAL_API_KEY` | Mistral API key (for image OCR) |
|
| 225 |
+
| `ALLOWED_ORIGINS` | Comma-separated frontend URLs |
|
| 226 |
+
|
| 227 |
+
**Frontend (Vercel)**
|
| 228 |
+
1. Import your GitHub repo → set **Root Directory** to `frontend`
|
| 229 |
+
2. Add env var: `VITE_API_URL=https://YOUR_HF_USER-your-space.hf.space/api`
|
| 230 |
+
|
| 231 |
+
---
|
| 232 |
+
|
| 233 |
+
## 💻 Local Development
|
| 234 |
+
|
| 235 |
+
### Prerequisites
|
| 236 |
+
- Python 3.11+, Node.js 18+
|
| 237 |
+
- [UV](https://github.com/astral-sh/uv) package manager
|
| 238 |
+
- MongoDB Atlas account
|
| 239 |
+
- LLM API key (for the primary fact-checker)
|
| 240 |
+
- Mistral API key (free at [mistral.ai](https://mistral.ai)) — for image OCR
|
| 241 |
+
|
| 242 |
+
### 1. Install Backend
|
| 243 |
+
|
| 244 |
+
```bash
|
| 245 |
+
git clone <your-repo-url>
|
| 246 |
+
cd FinalYearProject
|
| 247 |
+
pip install uv
|
| 248 |
+
uv sync
|
| 249 |
+
```
|
| 250 |
+
|
| 251 |
+
### 2. Configure Environment
|
| 252 |
+
|
| 253 |
+
Create `.env` in the project root:
|
| 254 |
+
|
| 255 |
+
```env
|
| 256 |
+
# MongoDB Atlas
|
| 257 |
+
MONGODB_URL=mongodb+srv://username:password@cluster.mongodb.net/?retryWrites=true&w=majority
|
| 258 |
+
DATABASE_NAME=fake_news_detector
|
| 259 |
+
|
| 260 |
+
# JWT
|
| 261 |
+
SECRET_KEY=your-super-secret-jwt-key-change-in-production
|
| 262 |
+
ACCESS_TOKEN_EXPIRE_MINUTES=1440
|
| 263 |
+
|
| 264 |
+
# LLM API key (primary fact-checker)
|
| 265 |
+
AI_API_KEY=your_api_key_here
|
| 266 |
+
|
| 267 |
+
# Mistral AI (image OCR)
|
| 268 |
+
MISTRAL_API_KEY=your_mistral_api_key_here
|
| 269 |
+
|
| 270 |
+
# News Validation (optional — Google News RSS is free)
|
| 271 |
+
NEWSAPI_KEY=your_newsapi_key
|
| 272 |
+
SERPAPI_KEY=your_serpapi_key
|
| 273 |
+
|
| 274 |
+
# CORS
|
| 275 |
+
ALLOWED_ORIGINS=http://localhost:5173,http://localhost:3000
|
| 276 |
+
```
|
| 277 |
+
|
| 278 |
+
### 3. Start the Backend
|
| 279 |
+
|
| 280 |
+
```bash
|
| 281 |
+
python run_api.py
|
| 282 |
+
```
|
| 283 |
+
|
| 284 |
+
- API: **http://localhost:8000**
|
| 285 |
+
- Swagger: **http://localhost:8000/docs**
|
| 286 |
+
|
| 287 |
+
### 4. Start the Frontend
|
| 288 |
+
|
| 289 |
+
```bash
|
| 290 |
+
cd frontend
|
| 291 |
+
npm install
|
| 292 |
+
npm run dev
|
| 293 |
+
```
|
| 294 |
+
|
| 295 |
+
Frontend: **http://localhost:5173**
|
| 296 |
+
|
| 297 |
+
---
|
| 298 |
+
|
| 299 |
+
## 🔐 API Reference
|
| 300 |
+
|
| 301 |
+
### Authentication
|
| 302 |
+
|
| 303 |
+
| Method | Endpoint | Rate Limit | Description |
|
| 304 |
+
|--------|----------|------------|-------------|
|
| 305 |
+
| `POST` | `/api/auth/register` | 3/min | Create a new user account |
|
| 306 |
+
| `POST` | `/api/auth/login` | 5/min | Login and receive a JWT token |
|
| 307 |
+
| `GET` | `/api/auth/me` | — | Get current authenticated user |
|
| 308 |
+
| `GET` | `/api/auth/history` | — | Retrieve prediction history |
|
| 309 |
+
| `GET` | `/api/auth/stats` | — | Get total/real/fake counts |
|
| 310 |
+
| `POST` | `/api/auth/logout` | — | Logout |
|
| 311 |
+
|
| 312 |
+
### Predictions (JWT required)
|
| 313 |
+
|
| 314 |
+
| Method | Endpoint | Rate Limit | Description |
|
| 315 |
+
|--------|----------|------------|-------------|
|
| 316 |
+
| `POST` | `/api/predict` | 30/min | Analyse a single news headline |
|
| 317 |
+
| `POST` | `/api/batch-predict` | 5/min | Analyse up to 10 texts in one call |
|
| 318 |
+
| `POST` | `/api/image-predict` | 10/min | OCR + analyse a news screenshot |
|
| 319 |
+
| `POST` | `/api/extract-image-text` | 10/min | OCR only (no prediction) |
|
| 320 |
+
|
| 321 |
+
### Example — Single Prediction
|
| 322 |
+
|
| 323 |
+
**Request:**
|
| 324 |
+
```bash
|
| 325 |
+
curl -X POST http://localhost:8000/api/predict \
|
| 326 |
+
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
|
| 327 |
+
-H "Content-Type: application/json" \
|
| 328 |
+
-d '{"title": "Scientists discover new planet in solar system"}'
|
| 329 |
+
```
|
| 330 |
+
|
| 331 |
+
**Response:**
|
| 332 |
+
```json
|
| 333 |
+
{
|
| 334 |
+
"text": "Scientists discover new planet in solar system",
|
| 335 |
+
"prediction": "unverified",
|
| 336 |
+
"confidence": 0.62,
|
| 337 |
+
"probabilities": { "real": 0.62, "fake": 0.38 },
|
| 338 |
+
"is_fake": false,
|
| 339 |
+
"prediction_source": "llm_primary",
|
| 340 |
+
"context_articles_used": 2,
|
| 341 |
+
"news_insight": "ℹ️ Limited related news coverage found."
|
| 342 |
+
}
|
| 343 |
+
```
|
| 344 |
+
|
| 345 |
+
---
|
| 346 |
+
|
| 347 |
+
## 🔧 Technology Stack
|
| 348 |
+
|
| 349 |
+
### Backend
|
| 350 |
+
| Library | Purpose |
|
| 351 |
+
|---------|---------|
|
| 352 |
+
| FastAPI | Async REST API framework |
|
| 353 |
+
| Uvicorn | ASGI server |
|
| 354 |
+
| **google-genai** | **LLM SDK — primary fact-checker** |
|
| 355 |
+
| **mistralai** | **Mistral OCR — image text extraction** |
|
| 356 |
+
| **slowapi** | **Per-IP API rate limiting** |
|
| 357 |
+
| PyTorch | BERT model inference (fallback) |
|
| 358 |
+
| Transformers (HuggingFace) | Tokeniser + BERT model architecture |
|
| 359 |
+
| Motor | Async MongoDB driver |
|
| 360 |
+
| python-jose | JWT token generation & validation |
|
| 361 |
+
| passlib[bcrypt] | Password hashing |
|
| 362 |
+
| requests + beautifulsoup4 | News RSS scraping |
|
| 363 |
+
| newsapi-python | NewsAPI client |
|
| 364 |
+
| serpapi | SerpAPI client |
|
| 365 |
+
|
| 366 |
+
### Frontend
|
| 367 |
+
| Library | Purpose |
|
| 368 |
+
|---------|---------|
|
| 369 |
+
| React 18 | UI component library |
|
| 370 |
+
| Vite | Build tool & dev server |
|
| 371 |
+
| TailwindCSS 3 | Utility-first styling |
|
| 372 |
+
| GSAP + ScrollTrigger | Scroll-driven animations |
|
| 373 |
+
| Framer Motion | Page transition system |
|
| 374 |
+
| Recharts | Pie chart visualisation |
|
| 375 |
+
| Axios | HTTP client with interceptors |
|
| 376 |
+
|
| 377 |
+
---
|
| 378 |
+
|
| 379 |
+
## 🤖 Classification Details
|
| 380 |
+
|
| 381 |
+
### LLM Fact-Checker (Primary)
|
| 382 |
+
| Property | Value |
|
| 383 |
+
|----------|-------|
|
| 384 |
+
| Input | User claim + live news articles (headline, summary, date, URL) |
|
| 385 |
+
| Output labels | `REAL` / `FAKE` / `UNVERIFIED` |
|
| 386 |
+
| Fallback chain | Multiple model tiers tried automatically on quota errors |
|
| 387 |
+
| Context | Receives live Google News articles before deciding |
|
| 388 |
+
|
| 389 |
+
**UNVERIFIED** is returned when the LLM cannot confirm or deny the claim from available evidence (e.g. very recent events not yet widely reported). It maps to `is_fake: false` with capped confidence (≤ 68%).
|
| 390 |
+
|
| 391 |
+
**FAKE** is only returned when retrieved articles **directly contradict** the specific factual assertion — not merely because the claim is surprising or uses dramatic language.
|
| 392 |
+
|
| 393 |
+
### BERT (Fallback)
|
| 394 |
+
| Property | Value |
|
| 395 |
+
|----------|-------|
|
| 396 |
+
| Architecture | BERT (bert-base-uncased) |
|
| 397 |
+
| Training | LIAR dataset (binarised) |
|
| 398 |
+
| Max token length | 512 |
|
| 399 |
+
| Accuracy | ~95% |
|
| 400 |
+
| When used | Only when all Gemini models fail |
|
| 401 |
+
|
| 402 |
+
---
|
| 403 |
+
|
| 404 |
+
## 🔒 Security
|
| 405 |
+
|
| 406 |
+
- JWT tokens with configurable expiry (default 24 hours)
|
| 407 |
+
- Bcrypt password hashing
|
| 408 |
+
- Per-IP rate limiting on all public endpoints
|
| 409 |
+
- CORS middleware (configurable via `ALLOWED_ORIGINS`)
|
| 410 |
+
- Pydantic input validation on all endpoints
|
| 411 |
+
- Environment-variable-driven secrets
|
| 412 |
+
|
| 413 |
+
---
|
| 414 |
+
|
| 415 |
+
## 🔧 Environment Variables Reference
|
| 416 |
+
|
| 417 |
+
| Variable | Required | Description |
|
| 418 |
+
|----------|----------|-------------|
|
| 419 |
+
| `MONGODB_URL` | ✅ | MongoDB Atlas connection string |
|
| 420 |
+
| `DATABASE_NAME` | ✅ | Target database name |
|
| 421 |
+
| `SECRET_KEY` | ✅ | Secret used to sign JWT tokens |
|
| 422 |
+
| `AI_API_KEY` | ✅ | LLM API key (primary fact-checker) |
|
| 423 |
+
| `MISTRAL_API_KEY` | ✅ | Mistral API key (image OCR) |
|
| 424 |
+
| `ACCESS_TOKEN_EXPIRE_MINUTES` | ❌ | Token TTL (default: 1440) |
|
| 425 |
+
| `NEWSAPI_KEY` | ❌ | NewsAPI key |
|
| 426 |
+
| `SERPAPI_KEY` | ❌ | SerpAPI key |
|
| 427 |
+
| `ALLOWED_ORIGINS` | ❌ | Comma-separated CORS origins |
|
| 428 |
+
| `ENABLE_AI_CHECK` | ❌ | Set `false` to force BERT-only mode |
|
| 429 |
+
|
| 430 |
+
---
|
| 431 |
+
|
| 432 |
+
## 📂 Datasets
|
| 433 |
+
|
| 434 |
+
### LIAR Dataset
|
| 435 |
+
| Property | Detail |
|
| 436 |
+
|----------|--------|
|
| 437 |
+
| **Source** | [W. Wang, 2017](https://aclanthology.org/P17-2067/) — UCSB |
|
| 438 |
+
| **Size** | ~12,800 labelled statements |
|
| 439 |
+
| **Labels** | 6-class → binarised to fake / real |
|
| 440 |
+
| **Domain** | Political statements (PolitiFact) |
|
| 441 |
+
| **License** | Public domain |
|
| 442 |
+
|
| 443 |
+
### WELFake Dataset
|
| 444 |
+
| Property | Detail |
|
| 445 |
+
|----------|--------|
|
| 446 |
+
| **Source** | [Verma et al., 2021](https://doi.org/10.1109/TVCG.2021.3071339) |
|
| 447 |
+
| **Size** | 72,134 articles (35,028 fake · 37,106 real) |
|
| 448 |
+
| **Domain** | Mixed: Kaggle, Reuters, BuzzFeed |
|
| 449 |
+
| **License** | CC BY 4.0 |
|
| 450 |
+
|
| 451 |
+
---
|
| 452 |
+
|
| 453 |
+
## 🧪 Training Notebooks
|
| 454 |
+
|
| 455 |
+
| Notebook | Description |
|
| 456 |
+
|----------|-------------|
|
| 457 |
+
| `Notebook/bert_finetune_notebook.ipynb` | BERT fine-tuning on LIAR dataset |
|
| 458 |
+
| `Notebook/wel-fakebert-finetune-notebook.ipynb` | BERT fine-tuning on WELFake dataset |
|
| 459 |
+
|
| 460 |
+
---
|
| 461 |
+
|
| 462 |
+
## 🤝 Contributing
|
| 463 |
+
|
| 464 |
+
1. Fork the repository
|
| 465 |
+
2. Create a feature branch: `git checkout -b feature/my-feature`
|
| 466 |
+
3. Commit: `git commit -m "feat: add my feature"`
|
| 467 |
+
4. Push: `git push origin feature/my-feature`
|
| 468 |
+
5. Open a Pull Request
|
| 469 |
+
|
| 470 |
+
---
|
| 471 |
+
|
| 472 |
+
## 📄 License
|
| 473 |
+
|
| 474 |
+
MIT License
|
| 475 |
+
|
| 476 |
+
---
|
| 477 |
+
|
| 478 |
+
## 🙏 Acknowledgements
|
| 479 |
+
|
| 480 |
+
- [LIAR Dataset](https://www.cs.ucsb.edu/~william/data/liar_dataset.zip) — W. Wang, 2017
|
| 481 |
+
- [WELFake Dataset](https://zenodo.org/record/4561253) — Verma et al., 2021
|
| 482 |
+
- [Hugging Face Transformers](https://huggingface.co/) — BERT tokeniser and model utilities
|
| 483 |
+
- Primary LLM fact-checker — contextual claim verification against live news
|
| 484 |
+
- [Mistral AI](https://mistral.ai/) — Image OCR
|
| 485 |
+
|
| 486 |
+
---
|
| 487 |
+
|
| 488 |
+
<p align="center">🛡️ Built to fight misinformation — TruthLens</p>
|
README_HF.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: TruthLens Backend API
|
| 3 |
+
emoji: 🔍
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: red
|
| 6 |
+
sdk: docker
|
| 7 |
+
pinned: false
|
| 8 |
+
app_port: 7860
|
| 9 |
+
---
|
docker-compose.yml
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ================================================================
|
| 2 |
+
# docker-compose.yml – TruthLens / Fake-News Detector
|
| 3 |
+
# Open-source stack: FastAPI backend + React/Nginx frontend + MongoDB
|
| 4 |
+
# ================================================================
|
| 5 |
+
#
|
| 6 |
+
# Quick start:
|
| 7 |
+
# 1. cp .env.example .env (fill in your API keys)
|
| 8 |
+
# 2. docker compose up --build
|
| 9 |
+
# 3. Open http://localhost in your browser
|
| 10 |
+
# ================================================================
|
| 11 |
+
|
| 12 |
+
services:
|
| 13 |
+
|
| 14 |
+
# ── MongoDB ──────────────────────────────────────────────────
|
| 15 |
+
mongodb:
|
| 16 |
+
image: mongo:7.0
|
| 17 |
+
container_name: fakenews_mongodb
|
| 18 |
+
restart: unless-stopped
|
| 19 |
+
environment:
|
| 20 |
+
MONGO_INITDB_ROOT_USERNAME: ${MONGO_ROOT_USER:-admin}
|
| 21 |
+
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_ROOT_PASSWORD:-changeme}
|
| 22 |
+
MONGO_INITDB_DATABASE: ${DATABASE_NAME:-fake_news_detector}
|
| 23 |
+
volumes:
|
| 24 |
+
- mongo_data:/data/db
|
| 25 |
+
ports:
|
| 26 |
+
- "27017:27017" # expose only for local development; remove in production
|
| 27 |
+
healthcheck:
|
| 28 |
+
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
|
| 29 |
+
interval: 10s
|
| 30 |
+
timeout: 5s
|
| 31 |
+
retries: 5
|
| 32 |
+
start_period: 20s
|
| 33 |
+
|
| 34 |
+
# ── FastAPI backend ───────────────────────────────────────────
|
| 35 |
+
backend:
|
| 36 |
+
build:
|
| 37 |
+
context: .
|
| 38 |
+
dockerfile: Dockerfile
|
| 39 |
+
container_name: fakenews_backend
|
| 40 |
+
restart: unless-stopped
|
| 41 |
+
env_file: .env
|
| 42 |
+
environment:
|
| 43 |
+
# Overrides anything in .env for the MongoDB URL (uses the container hostname)
|
| 44 |
+
MONGODB_URL: mongodb://${MONGO_ROOT_USER:-admin}:${MONGO_ROOT_PASSWORD:-changeme}@mongodb:27017/${DATABASE_NAME:-fake_news_detector}?authSource=admin
|
| 45 |
+
DATABASE_NAME: ${DATABASE_NAME:-fake_news_detector}
|
| 46 |
+
# Allow requests from Nginx (same-origin in production, localhost during dev)
|
| 47 |
+
ALLOWED_ORIGINS: "http://localhost,http://localhost:80,http://127.0.0.1,http://localhost:3000,http://localhost:5173"
|
| 48 |
+
volumes:
|
| 49 |
+
- ./logs:/app/logs # persist logs on the host
|
| 50 |
+
ports:
|
| 51 |
+
- "8000:8000" # expose for direct API access / debugging
|
| 52 |
+
depends_on:
|
| 53 |
+
mongodb:
|
| 54 |
+
condition: service_healthy
|
| 55 |
+
healthcheck:
|
| 56 |
+
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
| 57 |
+
interval: 30s
|
| 58 |
+
timeout: 10s
|
| 59 |
+
retries: 5
|
| 60 |
+
start_period: 90s # BERT model loading takes ~60 s
|
| 61 |
+
|
| 62 |
+
# ── React frontend (Nginx) ────────────────────────────────────
|
| 63 |
+
frontend:
|
| 64 |
+
build:
|
| 65 |
+
context: ./frontend
|
| 66 |
+
dockerfile: Dockerfile
|
| 67 |
+
args:
|
| 68 |
+
# All /api calls go to the same origin so the browser hits Nginx,
|
| 69 |
+
# which proxies to the backend container.
|
| 70 |
+
VITE_API_URL: /api
|
| 71 |
+
container_name: fakenews_frontend
|
| 72 |
+
restart: unless-stopped
|
| 73 |
+
ports:
|
| 74 |
+
- "80:80" # main entry point for users
|
| 75 |
+
depends_on:
|
| 76 |
+
backend:
|
| 77 |
+
condition: service_healthy
|
| 78 |
+
|
| 79 |
+
# ── Named volumes ─────────────────────────────────────────────
|
| 80 |
+
volumes:
|
| 81 |
+
mongo_data:
|
| 82 |
+
driver: local
|
dockerfile.huggingface
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ──────────────────────────────────────────────
|
| 2 |
+
# Backend Dockerfile — FastAPI + BERT (PyTorch)
|
| 3 |
+
# ──────────────────────────────────────────────
|
| 4 |
+
FROM python:3.11-slim
|
| 5 |
+
|
| 6 |
+
# System dependencies needed by PyTorch / transformers / Pillow
|
| 7 |
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
| 8 |
+
build-essential \
|
| 9 |
+
libgl1 \
|
| 10 |
+
libglib2.0-0 \
|
| 11 |
+
curl \
|
| 12 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 13 |
+
|
| 14 |
+
# Set working directory
|
| 15 |
+
WORKDIR /app
|
| 16 |
+
|
| 17 |
+
# Copy dependency spec and install Python packages FIRST (layer cache)
|
| 18 |
+
COPY pyproject.toml ./
|
| 19 |
+
RUN pip install --upgrade pip \
|
| 20 |
+
&& pip install --no-cache-dir \
|
| 21 |
+
fastapi \
|
| 22 |
+
"uvicorn[standard]" \
|
| 23 |
+
torch \
|
| 24 |
+
transformers \
|
| 25 |
+
pillow \
|
| 26 |
+
requests \
|
| 27 |
+
pydantic \
|
| 28 |
+
"python-multipart" \
|
| 29 |
+
"google-genai" \
|
| 30 |
+
python-dotenv \
|
| 31 |
+
newsapi-python \
|
| 32 |
+
beautifulsoup4 \
|
| 33 |
+
serpapi \
|
| 34 |
+
motor \
|
| 35 |
+
pymongo \
|
| 36 |
+
"python-jose[cryptography]" \
|
| 37 |
+
"passlib[bcrypt]" \
|
| 38 |
+
email-validator \
|
| 39 |
+
mistralai \
|
| 40 |
+
slowapi \
|
| 41 |
+
pytesseract
|
| 42 |
+
|
| 43 |
+
# Copy application source code
|
| 44 |
+
COPY app/ ./app/
|
| 45 |
+
|
| 46 |
+
# Copy pre-trained BERT model directories
|
| 47 |
+
COPY enhanced_bert_liar_model/ ./enhanced_bert_liar_model/
|
| 48 |
+
COPY enhanced_bert_welfake_model/ ./enhanced_bert_welfake_model/
|
| 49 |
+
|
| 50 |
+
# Copy the server entry-point
|
| 51 |
+
COPY run_api.py ./
|
| 52 |
+
|
| 53 |
+
# Create logs directory
|
| 54 |
+
RUN mkdir -p logs
|
| 55 |
+
|
| 56 |
+
# Expose the FastAPI port
|
| 57 |
+
EXPOSE 8000
|
| 58 |
+
|
| 59 |
+
# Health check
|
| 60 |
+
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
| 61 |
+
CMD curl -f http://localhost:8000/health || exit 1
|
| 62 |
+
|
| 63 |
+
# Run with uvicorn
|
| 64 |
+
CMD ["python", "-m", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
pyproject.toml
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[project]
|
| 2 |
+
name = "fake-news-detector"
|
| 3 |
+
version = "1.0.0"
|
| 4 |
+
description = "Fake news detection using fine-tuned BERT model"
|
| 5 |
+
requires-python = ">=3.9"
|
| 6 |
+
dependencies = [
|
| 7 |
+
"fastapi>=0.104.1",
|
| 8 |
+
"uvicorn[standard]>=0.24.0",
|
| 9 |
+
"torch>=2.0.0",
|
| 10 |
+
"transformers>=4.35.0",
|
| 11 |
+
"streamlit>=1.28.0",
|
| 12 |
+
"plotly>=5.18.0",
|
| 13 |
+
"requests>=2.31.0",
|
| 14 |
+
"pydantic>=2.5.0",
|
| 15 |
+
"python-multipart>=0.0.6",
|
| 16 |
+
"google-genai>=1.0.0",
|
| 17 |
+
"python-dotenv>=1.0.0",
|
| 18 |
+
"newsapi-python>=0.2.7",
|
| 19 |
+
"beautifulsoup4>=4.12.0",
|
| 20 |
+
"serpapi>=0.1.5",
|
| 21 |
+
"motor>=3.3.0",
|
| 22 |
+
"pymongo>=4.6.0",
|
| 23 |
+
"python-jose[cryptography]>=3.3.0",
|
| 24 |
+
"passlib[bcrypt]>=1.7.4",
|
| 25 |
+
"email-validator>=2.3.0",
|
| 26 |
+
"mistralai>=1.10.0",
|
| 27 |
+
"slowapi>=0.1.9",
|
| 28 |
+
]
|
| 29 |
+
|
| 30 |
+
[build-system]
|
| 31 |
+
requires = ["hatchling"]
|
| 32 |
+
build-backend = "hatchling.build"
|
| 33 |
+
|
| 34 |
+
[tool.hatch.build.targets.wheel]
|
| 35 |
+
packages = ["app"]
|
| 36 |
+
|
| 37 |
+
[tool.uv]
|
| 38 |
+
[dependency-groups]
|
| 39 |
+
dev = [
|
| 40 |
+
"pytest >=7.4.3",
|
| 41 |
+
"httpx >=0.25.1",
|
| 42 |
+
]
|
render.yaml
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# render.yaml – Render.com deployment config
|
| 2 |
+
# This file tells Render how to build and run the FastAPI backend.
|
| 3 |
+
# Docs: https://render.com/docs/blueprint-spec
|
| 4 |
+
|
| 5 |
+
services:
|
| 6 |
+
- type: web
|
| 7 |
+
name: fakenews-backend
|
| 8 |
+
runtime: docker
|
| 9 |
+
dockerfilePath: ./Dockerfile
|
| 10 |
+
# Render's free plan; upgrade to "starter" ($7/mo) if BERT needs more RAM
|
| 11 |
+
plan: free
|
| 12 |
+
healthCheckPath: /health
|
| 13 |
+
envVars:
|
| 14 |
+
# Set these in the Render dashboard after first deploy
|
| 15 |
+
- key: MONGODB_URL
|
| 16 |
+
sync: false # marks it as a secret – set manually in dashboard
|
| 17 |
+
- key: DATABASE_NAME
|
| 18 |
+
value: fake_news_detector
|
| 19 |
+
- key: SECRET_KEY
|
| 20 |
+
generateValue: true # Render auto-generates a secure random value
|
| 21 |
+
- key: ALGORITHM
|
| 22 |
+
value: HS256
|
| 23 |
+
- key: ACCESS_TOKEN_EXPIRE_MINUTES
|
| 24 |
+
value: "30"
|
| 25 |
+
- key: AI_API_KEY
|
| 26 |
+
sync: false
|
| 27 |
+
- key: MISTRAL_API_KEY
|
| 28 |
+
sync: false
|
| 29 |
+
- key: NEWS_API_KEY
|
| 30 |
+
sync: false
|
| 31 |
+
- key: SERP_API_KEY
|
| 32 |
+
sync: false
|
| 33 |
+
- key: ENABLE_AI_CHECK
|
| 34 |
+
value: "true"
|
| 35 |
+
# Set this AFTER you know your Vercel frontend URL, e.g. https://your-app.vercel.app
|
| 36 |
+
- key: ALLOWED_ORIGINS
|
| 37 |
+
sync: false
|
uv.lock
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|