Spaces:
Sleeping
Sleeping
File size: 6,408 Bytes
1c3fe08 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 | ---
title: Wasla Feedback Moderation API
emoji: π‘οΈ
colorFrom: blue
colorTo: indigo
sdk: docker
app_port: 7860
pinned: false
---
# Feedback Moderation API
AI-powered microservice that detects toxic / abusive language in user-submitted text.
Uses **local** Hugging Face transformer models β your data never leaves your infrastructure.
### Dual-Model Architecture
| Language | Model | Labels |
| -------- | ----- | ------ |
| English, French, Italian (and more) | `citizenlab/distilbert-base-multilingual-cased-toxicity` | `toxic` / `not_toxic` |
| Arabic | `Hate-speech-CNERG/dehatebert-mono-arabic` | `HATE` / `NON_HATE` |
Arabic text is **automatically detected** using the [lingua](https://github.com/pemistahl/lingua-py) language-detection library and routed to the dedicated Arabic hate-speech model for significantly higher accuracy (~87.8 %). All other languages use the multilingual model.
### LLM Verification Layer (optional)
When the local classifier's confidence falls in a configurable **grey zone** (default: 0.40 β 0.85), the text is forwarded to a free **Hugging Face Inference API** LLM (default: `mistralai/Mistral-7B-Instruct-v0.3`) for a second opinion. The LLM score is blended with the local score (40/60 weighting) to produce a refined verdict.
- β‘ **No extra latency** for clear-cut predictions (>95 % of requests)
- π **Free** β uses HF Inference Providers with a free token
- π **Graceful fallback** β if the LLM is unavailable, the local model result is used as-is
Set `HF_TOKEN` in `.env` to enable. Leave it empty to disable.
---
## Quick Start
### 1. Clone & create a virtual environment
```bash
git clone <your-repo-url> moderator-api
cd moderator-api
python -m venv venv
# Windows
.\venv\Scripts\Activate.ps1
# macOS / Linux
source venv/bin/activate
```
### 2. Install dependencies
```bash
pip install -r requirements.txt
```
### 3. Configure
Copy the example env file and set a strong API key:
```bash
cp .env.example .env
# then edit .env β MODERATOR_API_KEY=<your-secret>
```
### 4. Run
```bash
uvicorn main:app --reload
```
The server starts at **http://127.0.0.1:8000**.
Interactive docs are at **http://127.0.0.1:8000/docs**.
> **First launch** will download two models (~1 GB total).
> Subsequent starts load from the local cache.
---
## API Reference
### `GET /health`
Liveness probe. Returns `{"status": "ok", "model_loaded": true}`.
### `POST /api/v1/moderate`
Analyse a piece of text for toxicity.
**Headers**
| Header | Required | Description |
| ----------- | -------- | -------------------- |
| `X-API-Key` | β
| Your secret API key |
**Request body**
```json
{
"text": "This product is terrible and I hate everything about it!"
}
```
**Response**
```json
{
"has_bad_words": true,
"confidence": 0.9812,
"label": "toxic",
"detected_language": "en",
"llm_verified": false
}
```
---
## Calling from an External App
```python
import requests
API_URL = "http://your-server:8000/api/v1/moderate"
API_KEY = "your-secret-api-key"
response = requests.post(
API_URL,
json={"text": "I absolutely love this!"},
headers={"X-API-Key": API_KEY},
)
result = response.json()
if result["has_bad_words"]:
print("β οΈ Feedback rejected β toxic content detected.")
else:
print("β
Feedback is clean.")
```
---
## Docker
### Build
```bash
docker build -t moderator-api .
```
### Run
```bash
docker run -d \
-p 8000:8000 \
-e MODERATOR_API_KEY=your-secret-api-key \
--name moderator-api \
moderator-api
```
---
## Deploy to Hugging Face Spaces (Free)
### 1. Create a Space
Go to [huggingface.co/new-space](https://huggingface.co/new-space) and create a new Space:
- **Space name**: `moderator-api`
- **SDK**: Docker
- **Visibility**: Private (recommended)
### 2. Add secrets
In your Space β **Settings β Secrets**, add:
| Secret | Value |
| ------ | ----- |
| `MODERATOR_API_KEY` | A strong random string |
| `HF_TOKEN` | Your Hugging Face token |
| `LLM_VERIFY_LOW` | `0.0` (or `0.40` for grey-zone only) |
| `LLM_VERIFY_HIGH` | `1.0` (or `0.85` for grey-zone only) |
### 3. Push your code
```bash
git init
git remote add space https://huggingface.co/spaces/YOUR_USERNAME/moderator-api
git add .
git commit -m "Deploy moderator API"
git push space main
```
### 4. Access your API
Once built, your API is live at:
```
https://YOUR_USERNAME-moderator-api.hf.space/api/v1/moderate
```
Interactive docs at:
```
https://YOUR_USERNAME-moderator-api.hf.space/docs
```
> β οΈ First deploy takes ~5 minutes (model downloads ~1 GB).
> Subsequent deploys use cached layers and are much faster.
---
## Configuration (Environment Variables)
| Variable | Default | Description |
| --------------------- | ------------------------------ | ------------------------------------------ |
| `MODERATOR_API_KEY` | `change-me-before-production` | Secret key clients must send in headers |
| `MODEL_NAME` | `citizenlab/distilbert-base-multilingual-cased-toxicity` | Multilingual Hugging Face model (en/fr/it) |
| `ARABIC_MODEL_NAME` | `Hate-speech-CNERG/dehatebert-mono-arabic` | Dedicated Arabic hate-speech model |
| `TOXICITY_THRESHOLD` | `0.70` | Confidence cutoff to flag text as toxic |
| `ARABIC_TOXICITY_THRESHOLD` | `0.45` | Lower threshold for Arabic (model outputs lower scores) |
| `HF_TOKEN` | *(empty β LLM disabled)* | Free HF token to enable LLM verification |
| `LLM_MODEL_NAME` | `Qwen/Qwen2.5-72B-Instruct` | LLM used for grey-zone verification |
| `LLM_VERIFY_LOW` | `0.40` | Lower bound of the grey zone |
| `LLM_VERIFY_HIGH` | `0.85` | Upper bound of the grey zone |
---
## Project Structure
```
moderator-api/
βββ main.py # FastAPI application & moderation endpoint
βββ requirements.txt # Python dependencies
βββ Dockerfile # Production container image
βββ .dockerignore # Files excluded from Docker build
βββ .env # Local environment variables (git-ignored)
βββ .env.example # Template for .env
βββ .gitignore
βββ README.md
```
## License
MIT
|