SentryText AI is a multilingual toxicity analysis web platform with two analysis paths:
- Fast Analysis: low-latency, language-aware single-model prediction.
- Comparative Analysis: four-model evaluation with consensus + disagreement signals.
It also includes a rewrite workflow that can transform toxic text into safer phrasing and then re-analyze the rewritten result.
- Overview
- Core Features
- Architecture
- Repository Structure
- Prerequisites
- Local Development
- Configuration
- Model Weights Workflow
- API Reference
- Manual Verification
- Troubleshooting
SentryText AI is designed for content moderation and text safety experimentation across multilingual inputs (English, Malay, Mandarin, bilingual, and multilingual mixes). The backend performs language-aware routing and model inference, while the frontend provides an interactive workflow for:
- submitting text,
- reviewing toxicity predictions,
- optionally rewriting risky content,
- re-checking toxicity after rewrite.
- Endpoint:
POST /api/v1/analyze/fast - Uses detected language to route to the best model path.
- Returns a single prediction with probabilities, threshold, latency, and selected model.
- Endpoint:
POST /api/v1/analyze/comparative - Evaluates multiple model families and returns:
- per-model predictions,
- consensus result,
- disagreement level,
- average toxicity signal.
- Endpoint:
POST /api/v1/rewrite - Rewrites toxic input while preserving language and sentence structure constraints.
- Frontend supports immediate re-analysis of rewritten text (comparative first, with fast fallback in some flows).
- Framework: Next.js + React + TypeScript
- UI pages:
app/fast-analysis/page.tsxapp/comparative-analysis/page.tsx
- Responsibilities:
- collect user input,
- invoke backend APIs,
- display predictions, consensus, and rewrite outcomes.
- Framework: FastAPI
- Main app:
webapp/backend/app/main.py - Exposed API routes:
routes_fast_analysis.pyroutes_comparative_analysis.pyroutes_rewrite.py
- Responsibilities:
- validation,
- language detection and routing,
- model inference orchestration,
- rewrite orchestration,
- structured error handling and request tracing.
- Config and metadata live under
webapp/metadata. - Model binaries are expected under top-level
weights/(not committed to git). - Startup validates runtime artifacts and can optionally fail on corrupted checkpoints.
webapp/
backend/
app/
api/
core/
model_runtime/
schemas/
services/
frontend/
app/
components/
hooks/
lib/
metadata/
app_config.example.yaml
model_registry.example.json
thresholds.example.json
weights_manifest.sample.json
scripts/
run_dev.sh
download_weights.py
- Node.js + npm (for frontend)
- Python 3.10+ (recommended) for backend
- OS with shell support for scripts (bash script included)
Backend Python dependencies are in:
webapp/backend/requirements.txt
From repository root:
bash webapp/scripts/run_dev.shThis starts both backend and frontend. Press Ctrl + C once to stop both processes.
If ports are already occupied:
BACKEND_PORT=8010 FRONTEND_PORT=3010 bash webapp/scripts/run_dev.shIf backend uses non-default port, keep frontend proxy aligned:
BACKEND_PORT=8010 BACKEND_ORIGIN=http://127.0.0.1:8010 bash webapp/scripts/run_dev.shIf frontend is exposed via ngrok during dev:
ALLOWED_DEV_ORIGINS=https://<your-frontend-ngrok-domain> bash webapp/scripts/run_dev.shFrom repository root:
pip install -r webapp/backend/requirements.txt
uvicorn webapp.backend.app.main:app --reload --host 0.0.0.0 --port 8000In a separate terminal:
cd webapp/frontend
npm install
cp .env.example .env.local
npm run devFrontend runs at your configured dev port (default commonly 3000 for raw Next.js, script flow may use 3100).
Primary backend config source:
webapp/metadata/app_config.example.yaml
Config loader logic is in:
webapp/backend/app/core/config.py
Notable behavior:
- API base path defaults to
/api/v1. - Default dev CORS allowlist includes:
http://127.0.0.1:3000http://localhost:3000
- ngrok origins are allowed by regex (
*.ngrok-free.app,*.ngrok.io). - You can override config path with
APP_CONFIG_PATH.
For rewrite flows using OpenAI-compatible providers, ensure required API keys are available in request payload or environment as your deployment expects.
Model binaries are intentionally excluded from git. Download them before running production-like inference.
Start from:
webapp/metadata/weights_manifest.sample.json
For each file entry, provide:
path(destination inside weights directory)urlorgdrive_file_idsha256checksumrequiredflag (optional, defaults totrue)
From repository root:
python webapp/scripts/download_weights.pyOptional overrides:
WEIGHTS_MANIFEST_PATH=webapp/metadata/weights_manifest.sample.json \
WEIGHTS_DIR=weights \
python webapp/scripts/download_weights.pyGoogle Drive token (if required by your file hosting setup):
GDRIVE_ACCESS_TOKEN=<your_oauth_access_token> python webapp/scripts/download_weights.pypython webapp/scripts/download_weights.py && \
uvicorn webapp.backend.app.main:app --host 0.0.0.0 --port 8000If checksum or download fails for required files, script exits non-zero so deployment fails fast.
Base URL (local default):
http://127.0.0.1:8000/api/v1
Request body:
{
"text": "Your input text",
"llm_provider": "nvidia",
"llm_api_key": "optional-key",
"llm_base_url": "optional-url",
"llm_model": "optional-model"
}Returns FastAnalysisResponse with:
detected_languageselected_modelprediction(label, probabilities, threshold, latency)timing
Same request shape as fast analysis. Returns ComparativeAnalysisResponse with:
models[]per-model predictions,consensus(final label, vote counts, avg toxicity, disagreement),timing.
Request body:
{
"text": "Original text",
"detected_language_group": "english",
"mode": "fast",
"rewrite_api_key": "optional-key",
"rewrite_base_url": "optional-url",
"rewrite_model": "optional-model",
"llm_provider": "nvidia",
"llm_api_key": "optional-key",
"llm_base_url": "optional-url",
"llm_model": "optional-model"
}Returns RewriteResponse with:
- original vs rewritten text,
- language/sentence preservation flags,
- retry/grace-mode indicators,
- rewrite timing.
Use these files for guided checks:
webapp/scripts/e2e_checklist.mdwebapp/scripts/samples.json
You can also test backend endpoints directly via examples in:
webapp/backend/README.md
-
Port already in use
- Set
BACKEND_PORT/FRONTEND_PORTto unused values.
- Set
-
One service exits and both stop in script mode
- This is intentional behavior in
run_dev.shto avoid half-running environments.
- This is intentional behavior in
-
uvicornnot found- Install backend dependencies:
pip install -r webapp/backend/requirements.txt
- Install backend dependencies:
-
Rewrite failures
- Verify rewrite provider config and API key availability.
-
Checkpoint/weights issues at startup
- Re-run
download_weights.pyand verify manifest URLs/checksums.
- Re-run
- Frontend: Next.js, React, TypeScript, TailwindCSS
- Backend: FastAPI, Pydantic
- ML Runtime: PyTorch, Transformers