Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Content Moderation API

Python FastAPI PostgreSQL Transformers

AI-powered content moderation API built with FastAPI and DistilBERT. Sell API access to multiple companies — each gets isolated API keys, usage tracking, and flexible billing (token-based or monthly subscription).


📂 Project Structure

content_moderation/
├── api/
│   ├── main.py               # FastAPI app entry point, custom /docs (ReDoc)
│   ├── db.py                 # PostgreSQL async database layer
│   ├── models.py             # Pydantic request/response schemas
│   ├── middleware/
│   │   └── auth.py           # API key auth + quota enforcement
│   └── routes/
│       ├── health.py         # GET / (landing page) and /health
│       ├── admin.py          # Company registration, login, key management, billing
│       ├── moderate.py       # POST /moderate and /moderate/batch
│       └── superadmin.py     # Superadmin panel + contact form
├── src/
│   ├── filter.py             # Rule-based banned/political word filter
│   ├── moderate.py           # AI toxicity classification (DistilBERT)
│   └── train_transformer.py  # Model training script (class-weighted)
├── data/
│   ├── banned_words.txt      # Banned words list (English + Hindi)
│   ├── political_words.txt   # Political words list (global + India)
│   └── training_data.csv     # ~26,600 labeled examples (3 public datasets)
├── models/
│   └── transformer_model/    # Fine-tuned DistilBERT model files
├── static/
│   ├── index.html            # Landing page
│   ├── dashboard.html        # User dashboard panel
│   └── superadmin.html       # Superadmin panel
├── build_dataset.py          # Script to rebuild training_data.csv from HF datasets
├── .env                      # Environment variables
└── requirements.txt          # Python dependencies

⚙️ Prerequisites

  • Python 3.14+
  • PostgreSQL 17
  • Git

🚀 Setup & Installation

1. Clone the Repository

git clone <repository-url>
cd content_moderation

2. Create Virtual Environment

py -m venv venv
venv\Scripts\activate        # Windows
# source venv/bin/activate   # macOS/Linux

3. Install Dependencies

pip install -r requirements.txt

4. Setup PostgreSQL

Open pgAdmin or SQL Shell (psql) and run:

CREATE DATABASE content_moderation;

5. Configure Environment Variables

Edit the .env file in the project root:

DATABASE_URL=postgresql+asyncpg://postgres:YOUR_PASSWORD@localhost:5432/content_moderation

# Optional: set a fixed superadmin key (only used on first DB init)
# If blank, a random key is auto-generated and printed to console on first startup
SUPERADMIN_API_KEY=

# Superadmin web panel login credentials
SUPERADMIN_USERNAME=admin
SUPERADMIN_PASSWORD=softbender@123

If your password contains special characters (e.g. @), URL-encode them: @%40, #%23, $%24

6. Train the Model (First Time Only)

python src/train_transformer.py

This saves the fine-tuned model to models/transformer_model/.

The training dataset (data/training_data.csv) contains ~26,600 labeled examples merged from 3 public Hugging Face datasets. To rebuild it from scratch, run python build_dataset.py.

7. Start the API Server

uvicorn api.main:app --host 0.0.0.0 --port 8000

Do not use --reload on Python 3.14 — it causes a multiprocessing spawn crash.

Server is now running at: http://localhost:8000

Tables are created automatically on first startup — no migrations needed. On first run, the SoftBenderAI superadmin API key is printed to the console. Save it immediately.


🧪 Demo Account (Ready to Test)

A demo company is seeded automatically on first startup. Use these credentials to test without registering:

Field Value
Email demo@example.com
Password password
API Key cm_demo_key_for_testing_only_1234
Billing Token-based, 15,000 free tokens

Login via dashboard: http://localhost:8000/panel → enter email + password

Use API key directly:

curl -X POST http://localhost:8000/moderate \
  -H "X-API-Key: cm_demo_key_for_testing_only_1234" \
  -H "Content-Type: application/json" \
  -d '{"text": "Hello world, this is a test!"}'

🏢 SoftBenderAI — Superadmin Company

SoftBenderAI is the built-in superadmin company, seeded automatically on first startup.

  • No token limits, no daily limits — completely unrestricted
  • Used for platform management
  • API key is printed to console on first startup (or set via SUPERADMIN_API_KEY in .env)
  • All /superadmin/* endpoints require the SoftBenderAI API key

How to get the Superadmin key: Start the server and look for this in the console output:

============================================================
  SoftBenderAI Superadmin API Key: cm_xxxxxxxxxxxxxxxxxxxx
  Save this key — it won't be shown again!
============================================================

Or set SUPERADMIN_API_KEY=cm_yourkey in .env before first startup.


🌐 Web Panels

Browser-based UI — no curl needed.

Panel URL Who
Landing Page http://localhost:8000 Public
User Dashboard http://localhost:8000/panel Any registered company
Superadmin Panel http://localhost:8000/superadmin/panel SoftBenderAI only
API Docs (ReDoc) http://localhost:8000/docs Anyone

User Dashboard (/panel)

  • Register — Create a new company account and get your API key
  • Login — Enter your email + password to access the dashboard
  • Overview — Token usage, request stats, API key list (paginated)
  • API Keys — Generate new keys, revoke existing ones
  • Billing — Buy token packs or subscribe to monthly plans
  • Test API — Moderate text directly from the browser

Superadmin Panel (/superadmin/panel)

Login with SUPERADMIN_USERNAME / SUPERADMIN_PASSWORD from .env (default: admin / softbender@123).

  • Overview — Platform-wide stats, revenue, top consumers
  • Companies — List, search, view details, activate/deactivate, delete
  • Manage — Set billing plans, grant tokens, generate keys for any company
  • Keys — Revoke any API key platform-wide
  • Plans & Pricing — View all plan tiers and token rates
  • Contacts — View contact form submissions with unread badge, mark as read

📖 API Documentation

Interface URL
ReDoc Docs http://localhost:8000/docs
Health Check http://localhost:8000/health
OpenAPI JSON http://localhost:8000/openapi.json

🔑 Authentication

All endpoints (except POST /admin/register, POST /admin/login, GET /, GET /health, POST /superadmin/contact) require an API key in the request header:

X-API-Key: cm_xxxxxxxxxxxxxxxx

💳 Billing Modes

Every company chooses a billing mode at registration. Both modes start with 15,000 free tokens.

Token-Based Billing

Pay as you go. Buy token packs whenever you need more.

Tier Tokens Price
Free (on signup) 15,000 tokens ₹0
Paid pack 15,000 tokens ₹300/pack
  • 1 API request = 1 token
  • Free tokens never expire
  • Buy packs via POST /admin/topup
  • When tokens run out → 402 Payment Required

Monthly Subscription Plans

Fixed daily limits, billed monthly.

Plan Daily Limit Price/Month
starter 1,000 requests/day ₹499
growth 10,000 requests/day ₹1,499
business 50,000 requests/day ₹3,999
enterprise Unlimited ₹9,999
  • Subscribe via POST /admin/plan/subscribe
  • Plan valid for 30 days from subscription date
  • Daily limit resets at midnight UTC
  • When daily limit is hit → 402 Payment Required
  • If billing_mode = monthly but no plan subscribed → falls back to token quota

📋 API Endpoints

Admin Endpoints

Register a Company

POST /admin/register
Content-Type: application/json

{
  "name": "Acme Corp",
  "email": "admin@acme.com",
  "password": "yourpassword",
  "billing_mode": "token"
}

billing_mode: "token" (default) or "monthly"

Response:

{
  "message": "Company registered successfully",
  "company_id": 1,
  "company_name": "Acme Corp",
  "billing_mode": "token",
  "api_key": "cm_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "free_tokens": 15000,
  "save_key": "Save this API key — it won't be shown again."
}

Save the api_key immediately — it is shown only once.


Login

POST /admin/login
Content-Type: application/json

{
  "email": "admin@acme.com",
  "password": "yourpassword"
}

Response:

{ "api_key": "cm_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }

Login generates a new API key each time (keys are stored as SHA-256 hashes — irreversible).


Moderate a Single Text

POST /moderate
X-API-Key: cm_xxxxxxxx
Content-Type: application/json

{
  "text": "Your message here",
  "threshold": 0.7
}

Response:

{
  "allowed": true,
  "result": "approved",
  "blocked_reason": null,
  "confidence": 0.9821,
  "response_ms": 43,
  "free_tokens_remaining": 14957,
  "paid_tokens_remaining": 0
}

Batch Moderate (up to 50 texts)

POST /moderate/batch
X-API-Key: cm_xxxxxxxx
Content-Type: application/json

{
  "texts": ["Hello world", "I hate you", "Great product!"],
  "threshold": 0.7
}

Response:

{
  "results": [
    {"allowed": true,  "result": "approved", "blocked_reason": null,                     "confidence": 0.98, "response_ms": 12},
    {"allowed": false, "result": "blocked",  "blocked_reason": "Toxic/impolite language", "confidence": 0.91, "response_ms": 15},
    {"allowed": true,  "result": "approved", "blocked_reason": null,                     "confidence": 0.96, "response_ms": 11}
  ],
  "total": 3,
  "blocked_count": 1,
  "free_tokens_remaining": 14954,
  "paid_tokens_remaining": 0
}

Buy Token Pack

POST /admin/topup
X-API-Key: cm_xxxxxxxx
Content-Type: application/json

{ "packs": 2 }

Subscribe to Monthly Plan

POST /admin/plan/subscribe
X-API-Key: cm_xxxxxxxx
Content-Type: application/json

{ "plan": "growth" }

Generate Additional API Key

POST /admin/keys/generate
X-API-Key: cm_xxxxxxxx

Revoke an API Key

DELETE /admin/keys/{key_prefix}
X-API-Key: cm_xxxxxxxx

View Usage Stats

GET /admin/stats
X-API-Key: cm_xxxxxxxx

Superadmin Endpoints (SoftBenderAI only)

All /superadmin/* endpoints (except /superadmin/contact and /superadmin/login) require the SoftBenderAI API key.

Method Endpoint Description
POST /superadmin/login Login with username/password → returns API key
GET /superadmin/overview Platform-wide stats, revenue, top consumers
GET /superadmin/companies List all companies
GET /superadmin/companies/{id} Full stats for a specific company
POST /superadmin/companies/{id}/keys/generate Generate API key for any company
POST /superadmin/set-plan Set billing mode / plan / grant tokens
DELETE /superadmin/keys/{prefix} Revoke any API key
PATCH /superadmin/companies/{id}/toggle?activate=bool Activate or deactivate a company
DELETE /superadmin/companies/{id} Delete a company and all its data
GET /superadmin/plans List all plans and token pricing
POST /superadmin/contact Submit contact form (public, no auth)
GET /superadmin/contacts List all contact form submissions
PATCH /superadmin/contacts/{id}/read Mark a contact message as read

Set plan example:

POST /superadmin/set-plan
{
  "company_id": 5,
  "billing_mode": "monthly",
  "monthly_plan": "enterprise",
  "extra_tokens": 50000
}

🔧 Configuration

Adjust Toxicity Threshold

{ "text": "some text", "threshold": 0.5 }

Default is 0.7. Lower = stricter, higher = more lenient.

Add Banned Words

Edit data/banned_words.txt — one word/phrase per line. Supports English and Hindi. Leet-speak detection is built-in (e.g. f4ckfuck).

Add Political Words

Edit data/political_words.txt — one word/phrase per line. Covers global leaders, Indian political parties, and policy terms.

Rebuild Training Dataset

python build_dataset.py

Downloads and merges 3 public Hugging Face datasets (~26,600 examples):

  • cardiffnlp/tweet_eval hate — ~13k English tweets
  • ucberkeley-dlab/measuring-hate-speech — ~6k comments
  • google/civil_comments — ~8k comments

Retrain the Model

python src/train_transformer.py

Uses class-weighted loss to handle imbalanced data (toxic ~27%, clean ~73%). Trains for 4 epochs with early stopping (patience=2).


🧪 Quick Test with curl

# 1. Use demo account (no registration needed)
curl -X POST http://localhost:8000/moderate \
  -H "X-API-Key: cm_demo_key_for_testing_only_1234" \
  -H "Content-Type: application/json" \
  -d '{"text": "Hello world"}'

# 2. Register a new company
curl -X POST http://localhost:8000/admin/register \
  -H "Content-Type: application/json" \
  -d '{"name": "Test Co", "email": "test@test.com", "password": "test123", "billing_mode": "token"}'

# 3. Login (get a new API key)
curl -X POST http://localhost:8000/admin/login \
  -H "Content-Type: application/json" \
  -d '{"email": "test@test.com", "password": "test123"}'

# 4. Batch moderate
curl -X POST http://localhost:8000/moderate/batch \
  -H "X-API-Key: cm_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"texts": ["Hello!", "I hate you", "Great work"], "threshold": 0.7}'

# 5. Subscribe to monthly plan
curl -X POST http://localhost:8000/admin/plan/subscribe \
  -H "X-API-Key: cm_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"plan": "growth"}'

# 6. Superadmin — list all companies
curl http://localhost:8000/superadmin/companies \
  -H "X-API-Key: <softbenderai_key>"

# 7. Superadmin — grant enterprise plan to company 5
curl -X POST http://localhost:8000/superadmin/set-plan \
  -H "X-API-Key: <softbenderai_key>" \
  -H "Content-Type: application/json" \
  -d '{"company_id": 5, "billing_mode": "monthly", "monthly_plan": "enterprise", "extra_tokens": 0}'

🤖 AI Moderation Pipeline

Every request goes through a 3-layer pipeline:

  1. Empty check — blank text is blocked immediately
  2. Rule-based filter (src/filter.py) — checks against banned_words.txt and political_words.txt with leet-speak normalization and substring scanning
  3. AI classifier (src/moderate.py) — fine-tuned DistilBERT model scores toxicity probability; blocked if above threshold (default 0.7)

📊 Model & Dataset

Property Value
Base model distilbert-base-uncased
Training examples ~22,600 (train) + ~4,000 (test)
Toxic examples ~7,200
Clean examples ~19,400
Training epochs 4 (early stopping patience=2)
Loss function Cross-entropy with inverse-frequency class weights
Optimizer AdamW, lr=2e-5, weight_decay=0.01

🗄️ Database Schema

Table Key Columns
companies id, name, email, password_hash, is_superadmin, is_active, billing_mode, monthly_plan, plan_expires_at, free_tokens_used, paid_tokens_purchased, total_tokens_used
api_keys id, company_id, key_hash, key_prefix, is_active, requests_today, total_requests, last_used, last_reset_date
usage_logs id, company_id, api_key_prefix, text_length, result, blocked_reason, response_ms, is_free
billing id, company_id, billing_type, tokens_purchased, packs, plan_name, amount_inr
contact_messages id, name, email, phone, subject, message, is_read

All tables are created automatically on first startup via init_db(). Schema changes use ALTER TABLE ... ADD COLUMN IF NOT EXISTS migrations — no manual migration needed.


🔍 Troubleshooting

getaddrinfo failed on startup → PostgreSQL is not running. Start it from Windows Services or pgAdmin.

Invalid or inactive API key → Pass the key in X-API-Key header. Check that the company is active in the superadmin panel.

402 Token quota exhausted → Free 15,000 tokens used up. Buy more via POST /admin/topup or subscribe via POST /admin/plan/subscribe.

402 Daily limit reached → Monthly plan daily limit hit. Upgrade plan or wait for midnight UTC reset.

403 Superadmin access required → Calling a /superadmin/* endpoint without the SoftBenderAI API key.

CUDA out of memory → Reduce per_device_train_batch_size in src/train_transformer.py or run on CPU.

Server crashes with --reload → Known Python 3.14 + uvicorn issue. Run without --reload and restart manually after code changes.

SoftBenderAI key not saved → Drop the api_keys rows for admin@softbenderai.com in pgAdmin, restart the server — key will be regenerated and printed again.

Demo key not working → The demo account is seeded on first startup. If you started the server before this version, restart once — init_db() will seed it automatically (idempotent).

About

An AI-powered content moderation system using Python and Hugging Face Transformers. Combines rule-based filtering and machine learning to detect and block toxic, profane, and politically sensitive content, built for developers and communities to create safer, positive online spaces.

Topics

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages