How to use from the
Use from the
LiteRT library
# No code snippets available yet for this library.

# To use this model, check the repository files and the library's documentation.

# Want to help? PRs adding snippets are welcome at:
# https://github.com/huggingface/huggingface.js

Toxic

Catch hate speech before it posts.

On-device hate-speech triage for European languages.

Platforms iOS, macOS, tvOS, visionOS, Android, Linux, Windows, Browser, Node
Languages 35
Weights v0.2.2
Demo https://desertant.com/models/toxic/
Status Beta

Install

Swift (requirements)

.package(url: "https://github.com/Desert-Ant-Labs/desert-ant-core.git", from: "4.3.0")

Then add the Toxic product to your target.

Kotlin (requirements)

implementation("ai.desertant:toxic:4.3.0")

JavaScript (requirements)

npm i @desert-ant-labs/toxic @litertjs/core   # browser
npm i @desert-ant-labs/toxic                  # Node, prebuilt native core

Usage

Swift

import Toxic

let toxic = Toxic()
let result = try await toxic.analyze(comment)
if result.isToxic { holdForReview(result.content, result.targets) }
result.score(.hateful)     // 0...1
result.flagged             // the heads at or above their thresholds

The text goes in as written: no lower-casing, no stripping. Canceling the calling task stops the analysis and throws CancellationError. On Apple platforms every op of the graph runs on the Neural Engine; the SDK tokenizes and looks the tokens' rows up itself and feeds the graph embeddings. Pass computeUnits: to Toxic(directory:computeUnits:) to change the units.

Kotlin

import ai.desertant.toxic.Toxic
import ai.desertant.toxic.Options

Toxic(context).use { toxic ->
    val result = toxic.analyze(comment)
    if (result.isToxic) holdForReview(result.content, result.targets)
}

JavaScript

import { Toxic } from "@desert-ant-labs/toxic";         // browser
// import { Toxic } from "@desert-ant-labs/toxic/native"; // server-side Node

const toxic = await Toxic.load();
const { isToxic, scores, content, targets } = await toxic.analyze(comment);
toxic.dispose();

What comes back

Every SDK returns the same analysis:

Field
scores Every head's probability in 0...1: HATEFUL, ABUSIVE, THREAT, and the eight target heads RACE, RELIGION, NATIONAL_ETHNIC_ORIGIN, SEXUAL_ORIENTATION, GENDER, DISABILITY, AGE, OTHER.
thresholds The threshold each head was judged at.
flagged The heads at or above their thresholds, content and target heads alike.
content The content heads that fired: what the text does. HATEFUL is incitement to hatred or violence against a group, ABUSIVE insulting or degrading language, aimed or not, THREAT a threat of violence.
targets The target heads that fired, highest score first: which group a hateful text is about. Read them when HATEFUL fired.
isToxic Whether a content head fired.

Toxic is a triage signal for human review or a stricter check, not a verdict: it reacts to hateful words whether a text uses them or quotes them, and the line between hate and merely offensive text is soft.

Options

Option Default
thresholds the model's A label to the threshold that replaces the model's default for that head. The defaults ship with the model, chosen on validation text (Toxic.defaultThresholds() in Swift). Raise a threshold to flag less, lower it to flag more.

Long texts

The graph reads 128 tokens at a time, about 80 words. A longer text is read in overlapping windows, and each head keeps its highest score over them, so a long text's score is its worst window's.

Loading the model

The SDK downloads the weights from Hugging Face on first use and caches them. See model downloads and caching.

Measured quality

ROC-AUC per head on public sets the model was not trained on, scored at the precision of the shipped weights. ROC-AUC is the chance that the model scores a text carrying the label above a text that does not: 0.5 is a coin toss and 1.0 is a perfect ranking. It does not depend on the threshold, so it describes the scores themselves.

Benchmark Languages Texts Hateful Abusive Threat
RTP-LX 38 42,016 0.786 0.809 0.805
TextDetox multilingual toxicity 15 71,374 0.823
Aya red-teaming 8 7,419 0.779 0.742 0.640
OpenAI moderation evaluation set en 1,680 0.917 0.900 0.902
ToxiGen, annotated en 9,900 0.902
ToxicChat en 5,083 0.863 0.774
ALIA-es, human test set es 3,000 0.797
News-RO-Offense ro 4,053 0.775 0.852

A blank cell means the set has no label for that head, or too few texts with it to score.

Performance

Through the SDK: one short text per call, the median of 50 calls, model load excluded. SDK 4.3.0.

Device Runtime Per text
MacBook Pro M5 Pro Core ML 1.6 ms
iPhone 16 Pro Core ML 2.0 ms
Mac mini M1 Core ML 2.7 ms
MacBook Pro 16 M1 Max Core ML 2.9 ms
Linux, x86-64 LiteRT, CPU 8.6 ms
Galaxy S26, Exynos 2600 LiteRT, CPU 17 ms
Windows, AMD Ryzen AI 300 LiteRT, CPU 20 ms
Windows, Intel Core Ultra 200V LiteRT, CPU 47 ms

Files

File Format Size Contents
coreml-mixed/toxic.mlmodelc Compiled Core ML, the layers 8-bit 43MB The graph on Apple platforms, every op on the Neural Engine (used by the Swift SDK)
litert-mixed/toxic.tflite LiteRT, the layers 8-bit 44MB The graph on Android, Linux, Windows, Node, and the web (downloaded on demand by the Kotlin and JavaScript SDKs)
coreml-mixed/toxic_meta.json, litert-mixed/toxic_meta.json JSON 2KB The graph's input and output names, the heads in output order, the table's and the tokenizer's shapes, the default thresholds
toxic_table.bin The embedding table as the SDK reads it, 4-bit 50MB The rows the SDK looks a text's tokens up in and feeds the graph, shared by both runtimes
toxic_tokenizer.bin The tokenizer as the SDK reads it 9.4MB The pieces, the merges and the added tokens of the encoder's tokenizer, shared by both runtimes

License

Desert Ant Labs Source-Available License. Free for most apps, and a commercial license is required at scale. Full terms are at the link. Licensing: licensing@desertant.com.

Third-party notices for the weights: THIRD_PARTY_NOTICES.md.

Citation

@software{toxic_2026,
  title  = {Toxic: On-device hate-speech triage for European languages},
  author = {Desert Ant Labs},
  year   = {2026},
  url    = {https://huggingface.co/desert-ant-labs/toxic},
}

© 2026 Desert Ant Labs · https://desertant.com

Downloads last month
243
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 1 Ask for provider support

Space using desert-ant-labs/toxic 1