Fully offline content moderation API β Self-hosted content safety for teams who can't afford to send data to the cloud.
- π 100% Offline β All models run locally, no external API calls
- β‘ Fast β <100ms latency on CPU, <30ms on GPU
- π― Comprehensive β Toxicity, PII, prompt injection, spam, and NSFW detection
- π³ Docker Ready β Single image deployment
- π§ Configurable β Adjustable thresholds per classifier
- π° Cost Effective β No per-request API fees
pip install -e .from localmod import SafetyPipeline
# Create pipeline
pipeline = SafetyPipeline()
# Analyze text
report = pipeline.analyze("Hello, how are you?")
print(f"Flagged: {report.flagged}") # False
print(f"Summary: {report.summary}") # Content passed all safety checks.
# Analyze text with PII
report = pipeline.analyze("My email is john@example.com")
print(f"Flagged: {report.flagged}") # True
print(f"Severity: {report.severity}") # medium
# Use specific classifiers
report = pipeline.analyze(
"Some text",
classifiers=["pii", "toxicity"],
include_explanation=True
)
# Batch analysis
reports = pipeline.analyze_batch([
"Hello world",
"Contact: test@example.com",
"Nice weather today"
])# Start the server
localmod serve
# Or with custom settings
localmod serve --host 0.0.0.0 --port 8000 --reloadAPI available at http://localhost:8000
# Build
docker build -f docker/Dockerfile -t localmod:latest .
# Run
docker run -p 8000:8000 localmod:latest
# Or use docker-compose
docker-compose -f docker/docker-compose.yml up -d| Classifier | Description | Model Type |
|---|---|---|
| toxicity | Hate speech, harassment, threats, profanity | ML (DistilBERT) |
| pii | Emails, phones, SSNs, credit cards, IPs | Regex + Validation |
| prompt_injection | LLM jailbreaks, instruction override | Pattern + ML |
| spam | Promotional content, scams, click-bait | Heuristics + ML |
| nsfw | Sexual content, adult themes (text only) | ML |
The PII detector identifies:
- Email addresses β john@example.com
- US Phone numbers β 555-123-4567, (555) 123-4567
- Social Security Numbers β 123-45-6789 (with validation)
- Credit Card numbers β 4111-1111-1111-1111 (with Luhn validation)
- IP addresses β 192.168.1.1 (with range validation)
- Dates of birth β 01/15/1990
from localmod.classifiers.pii import PIIDetector
detector = PIIDetector()
detector.load()
text = "Email me at john@example.com or call 555-123-4567"
redacted, detections = detector.redact(text)
# Result: "Email me at [EMAIL] or call [PHONE]"| Endpoint | Method | Description |
|---|---|---|
/ |
GET | API info and version |
/health |
GET | Health check with loaded models |
/classifiers |
GET | List available classifiers |
/analyze |
POST | Analyze single text |
/analyze/batch |
POST | Analyze multiple texts |
/redact |
POST | Redact PII from text |
curl -X POST http://localhost:8000/analyze \
-H "Content-Type: application/json" \
-d '{"text": "My email is john@example.com", "classifiers": ["pii"]}'Response:
{
"flagged": true,
"results": [
{
"classifier": "pii",
"flagged": true,
"confidence": 1.0,
"severity": "medium",
"categories": ["email"],
"metadata": {"detections": [...], "total_count": 1}
}
],
"summary": "Content flagged for: pii (medium): email",
"processing_time_ms": 1.23
}curl -X POST http://localhost:8000/redact \
-H "Content-Type: application/json" \
-d '{"text": "Contact john@example.com", "replacement": "[HIDDEN]"}'Response:
{
"original_length": 24,
"redacted_text": "Contact [HIDDEN]",
"redactions": [{"type": "email", "start": 8, "end": 24}],
"processing_time_ms": 0.45
}Environment variables (prefix with LOCALMOD_):
| Variable | Default | Description |
|---|---|---|
HOST |
0.0.0.0 |
API server host |
PORT |
8000 |
API server port |
DEVICE |
auto |
cpu, cuda, or auto |
LAZY_LOAD |
true |
Load models on first request |
TOXICITY_THRESHOLD |
0.5 |
Toxicity detection threshold |
PII_THRESHOLD |
0.5 |
PII detection threshold |
PROMPT_INJECTION_THRESHOLD |
0.5 |
Prompt injection threshold |
SPAM_THRESHOLD |
0.5 |
Spam detection threshold |
NSFW_THRESHOLD |
0.5 |
NSFW detection threshold |
MAX_BATCH_SIZE |
32 |
Maximum batch size |
MAX_TEXT_LENGTH |
10000 |
Maximum text length |
# Start API server
localmod serve [--host HOST] [--port PORT] [--reload]
# Analyze text from command line
localmod analyze "Your text here" [-c classifier1 classifier2]
# Pre-download all models
localmod download
# List available classifiers
localmod list# Install with dev dependencies
pip install -e ".[all]"
# Run tests
make test
# Run fast tests (skip ML model loading)
make test-fast
# Start dev server with auto-reload
make serve
# Build Docker image
make docker-buildlocalmod/
βββ src/localmod/
β βββ __init__.py # Package exports
β βββ config.py # Configuration management
β βββ schemas.py # Pydantic models
β βββ pipeline.py # SafetyPipeline orchestrator
β βββ cli.py # Command-line interface
β βββ models/
β β βββ base.py # BaseClassifier, Severity
β β βββ ...
β βββ classifiers/
β β βββ toxicity.py # ToxicityClassifier
β β βββ pii.py # PIIDetector
β β βββ prompt_injection.py
β β βββ spam.py
β β βββ nsfw.py
β βββ api/
β βββ app.py # FastAPI application
β βββ routes.py # API endpoints
βββ tests/ # Test suite (91 tests)
βββ docker/ # Docker configurations
βββ Makefile # Build automation
βββ pyproject.toml # Project configuration
| Metric | CPU | GPU (RTX 3060+) |
|---|---|---|
| Latency (p95) | <100ms | <30ms |
| Throughput | 20+ req/sec | 100+ req/sec |
| Memory | <2GB RAM | <4GB VRAM |
| Level | Description |
|---|---|
none |
Content passed checks |
low |
Minor issues detected |
medium |
Moderate issues |
high |
Serious issues |
critical |
Severe issues (SSN, credit cards) |
MIT License β see LICENSE for details.
- Fork the repository
- Create a feature branch
- Make changes with tests
- Run
make testto verify - Submit a pull request
- HuggingFace Transformers
- FastAPI
- PyTorch