Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

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

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages