ai-bad-word-detector
v1.0.0
Published
Hybrid bad-word detector: checks a database first, falls back to AI for unknown words, and auto-learns what the AI flags.
Maintainers
Readme
ai-bad-word-detector
A hybrid bad-word detector for Node.js. It checks a database first (fast and free), and only falls back to an AI when it sees a word it doesn't recognize. Anything the AI flags is learned and saved back to the database — so the next time, it's caught instantly without an AI call.
word → check DB → found? ──yes──▶ flagged (fast, free)
└──no───▶ ask AI → flagged? → save to DB (learn) → flaggedFeatures
- 🚀 DB-first — known words are caught instantly, with no AI cost.
- 🧠 AI fallback — unknown words are judged by an AI (optional).
- 📈 Auto-learns — AI-discovered words are saved, so each AI call pays off once and forever.
- 🕵️ Beats obfuscation — normalizes leetspeak (
b@dw0rd), accents (bád), and separators (f.u.c.k). - 🔌 Pluggable — bring your own database or AI provider; both are optional.
- 🪶 Zero required dependencies — works out of the box with an in-memory store.
Install
npm install ai-bad-word-detectorOptional add-ons, only if you use them:
npm install mongodb # for the MongoDB store
npm install openai # for the OpenAI providerQuick start
Works immediately — no database, no API key:
import { BadWordDetector, MemoryStore } from 'ai-bad-word-detector';
const detector = new BadWordDetector({
store: new MemoryStore(['badword', 'idiot']),
});
const result = await detector.detect('you are a badword');
console.log(result);
// {
// isProfane: true,
// matches: [{ word: 'badword', index: 10, length: 7, source: 'db' }],
// source: 'db',
// redacted: 'you are a ****'
// }Disguised text is caught too:
await detector.detect('you b@dw0rd'); // → redacted: 'you ****'The result object
detect(text) returns:
| Field | Type | Description |
| ------------ | --------- | ------------------------------------------------------------------ |
| isProfane | boolean | true if any bad word was found. |
| matches | array | Each match: { word, index, length, source }. |
| source | string | Overall origin: 'db', 'ai', 'hybrid', or 'none'. |
| redacted | string | The input text with bad words masked as ****. |
For each match, source is 'db' (found in the database) or 'ai' (found by the AI).
Options
new BadWordDetector({
store, // a WordStore (defaults to an empty MemoryStore)
aiProvider, // optional AI provider; without it, detection is DB-only
autoLearn, // default true — save AI-flagged words back to the store
});Using a real database (MongoDB)
Words are then stored permanently and shared across runs.
import { BadWordDetector, MongoStore } from 'ai-bad-word-detector';
const store = new MongoStore({ uri: 'mongodb://localhost:27017', db: 'moderation' });
await store.connect();
const detector = new BadWordDetector({ store });
await detector.detect('you badword');
await store.close();Using AI (OpenAI)
Add an AI provider to catch words that aren't in the database yet:
import { BadWordDetector, MongoStore, OpenAIProvider } from 'ai-bad-word-detector';
const store = new MongoStore({ uri: process.env.MONGO_URI });
await store.connect();
const detector = new BadWordDetector({
store,
aiProvider: new OpenAIProvider({ apiKey: process.env.OPENAI_API_KEY }),
autoLearn: true,
});
const result = await detector.detect('some user comment');The first time an offensive word appears, the AI flags it (source: 'ai') and it's saved. After that, the same word is caught by the database (source: 'db') with no AI call.
One-line helper
import { detect, MemoryStore } from 'ai-bad-word-detector';
await detect('what an idiot', { store: new MemoryStore(['idiot']) });Bring your own store or AI
Any object with these methods works as a store:
{
async has(word) // → boolean
async add(word, meta) // save a word
async getAll() // → string[] (optional)
}Any object with this method works as an AI provider:
{
async moderate(text) // → { flagged: boolean }
}So you can plug in Postgres, Redis, Anthropic Claude, or anything else without changing the detector.
License
MIT
