GLINR Studio LogoTypeWeaver

ToxicityDetector

ML-based toxicity detection using TensorFlow.js for contextual content analysis

Edit on GitHub

The ToxicityDetector class provides neural network-based toxicity detection using TensorFlow.js. It can identify various types of harmful content including insults, threats, identity attacks, and obscenity — even without explicit profanity words.

Requires optional dependencies: Install TensorFlow.js before using:

npm install @tensorflow/tfjs @tensorflow-models/toxicity

Import

import { ToxicityDetector } from 'glin-profanity/ml';

Constructor

constructor(config?: MLDetectorConfig)

Creates a new ToxicityDetector instance with configurable threshold and label filtering.

Configuration Options

PropTypeDefault
threshold?
number
0.85
labels?
ToxicityLabel[]
All 7 labels
preloadModel?
boolean
false

Basic Usage

import { ToxicityDetector } from 'glin-profanity/ml';

// Default configuration (threshold: 0.85)
const detector = new ToxicityDetector();

// Custom threshold for higher precision
const strictDetector = new ToxicityDetector({ threshold: 0.95 });

// Check only specific categories
const customDetector = new ToxicityDetector({
  threshold: 0.8,
  labels: ['insult', 'threat', 'obscene'],
});

Static Properties

ALL_LABELS

static readonly ALL_LABELS: ToxicityLabel[]

Array of all available toxicity labels:

  • identity_attack — Attacks based on identity (race, religion, gender, etc.)
  • insult — Personal insults and put-downs
  • obscene — Obscene or vulgar content
  • severe_toxicity — Highly toxic content
  • sexual_explicit — Sexually explicit content
  • threat — Threats of violence or harm
  • toxicity — General toxic content

Public Methods

Complete Example

import { ToxicityDetector } from 'glin-profanity/ml';

async function moderateContent(text: string) {
  const detector = new ToxicityDetector({ threshold: 0.85 });

  // Preload model for faster response
  await detector.loadModel();

  const result = await detector.analyze(text);

  if (result.isToxic) {
    console.log('Toxic content detected!');
    console.log('Categories:', result.matchedCategories.join(', '));
    console.log('Score:', result.overallScore.toFixed(2));
    return { allowed: false, reason: result.matchedCategories };
  }

  return { allowed: true };
}

// Usage
const result = await moderateContent('you are an idiot');
// { allowed: false, reason: ['insult', 'toxicity'] }
import { ToxicityDetector } from 'glin-profanity/ml';

class ChatModerator {
  private detector: ToxicityDetector;
  private initialized = false;

  constructor() {
    this.detector = new ToxicityDetector({
      threshold: 0.8,
      labels: ['insult', 'threat', 'toxicity'],
    });
  }

  async init() {
    if (!this.initialized) {
      await this.detector.loadModel();
      this.initialized = true;
    }
  }

  async checkMessage(message: string) {
    await this.init();

    const result = await this.detector.analyze(message);

    return {
      allowed: !result.isToxic,
      score: result.overallScore,
      categories: result.matchedCategories,
      processingTime: result.processingTimeMs,
    };
  }
}

// Singleton instance
const moderator = new ChatModerator();

// Usage in message handler
app.post('/chat', async (req, res) => {
  const check = await moderator.checkMessage(req.body.message);

  if (!check.allowed) {
    return res.status(400).json({
      error: 'Message rejected',
      reason: check.categories
    });
  }

  // Process message...
});
import { ToxicityDetector } from 'glin-profanity/ml';

async function moderateComments(comments: string[]) {
  const detector = new ToxicityDetector({ threshold: 0.85 });
  await detector.loadModel();

  // Batch process for efficiency
  const results = await detector.analyzeBatch(comments);

  return comments.map((comment, i) => ({
    text: comment,
    isToxic: results[i].isToxic,
    score: results[i].overallScore,
    categories: results[i].matchedCategories,
  }));
}

// Usage
const comments = [
  'Great article, thanks for sharing!',
  'You are such a moron',
  'I disagree with your point about taxes',
  'Kill yourself loser',
];

const moderated = await moderateComments(comments);
moderated.forEach((result) => {
  console.log(`"${result.text.substring(0, 30)}..." - ${result.isToxic ? 'BLOCKED' : 'OK'}`);
});

Performance Considerations

The ML model adds latency compared to rule-based detection. Use strategically based on your requirements.

MetricValue
Model load time~2-5 seconds (first load)
Single analysis~30-100ms
Batch analysis~10-30ms per item
Memory usage~50-100MB

Optimization Tips

  1. Preload the model on application startup
  2. Use batch processing when analyzing multiple texts
  3. Consider rules-first mode in HybridFilter for speed with ML fallback
  4. Dispose when done to free memory in serverless environments

Error Handling

import { ToxicityDetector } from 'glin-profanity/ml';

const detector = new ToxicityDetector();

try {
  await detector.loadModel();
  const result = await detector.analyze(text);
} catch (error) {
  if (error.message.includes('dependencies not installed')) {
    console.error('Install TensorFlow.js: npm install @tensorflow/tfjs @tensorflow-models/toxicity');
    // Fallback to rule-based detection
  } else {
    console.error('ML analysis failed:', error);
  }
}

Cross-References