Horizon-Labs/content-safety-guard-base

Model

Content Safety Guard (base, 308M)

0

6 commits

1 linked in READMEs

updated Sep 27, 2026

See the code

README

Content Safety Guard (base, 308M)

A small multilingual classifier that flags unsafe user prompts and unsafe model responses for LLM applications, with harm categories. It is a fast encoder (ModernBERT architecture, mmBERT backbone) that you can run on CPU or in the browser in front of, or behind, any LLM.

  • Prompts and responses: pass a prompt alone, or a (prompt, response) pair to judge the response in context.
  • Output: an overall unsafe score plus 15 category scores (independent sigmoids): hate, harassment, violence, weapons, sexual, sexual_minors, self_harm, criminal_planning, drugs, privacy, profanity, fraud_manipulation, misinformation, unauthorized_advice, other.
  • Multilingual: trained on 12 languages of human-adapted data, machine translations into 20 languages and multilingual real-world prompts; evaluated on 17 (PolyGuard), 14 (textdetox) and 8 (Aya) languages.
  • Commercially usable: Apache-2.0, trained only on data that allows commercial use (see Training data).
  • ONNX: onnx/model.onnx (fp32) and onnx/model_quantized.onnx (int8 embeddings, 641 MB; its unsafe decision agrees with fp32 on 99.3% of a sample of benchmark texts (30 per benchmark), mean |score diff| 0.0016).

Which size? This base model (308M) is the more accurate one; small (141M, less compute per token, int8 ONNX about 270 MB) is 0.012 / 0.027 F1 behind on PolyGuard prompts / responses.

Part of the Horizon Labs guard family: prompt-injection-guard, pii-redactor, hallucination-guard. Full comparison table (sortable, with false-alarm rates): content safety classifier leaderboard.

Usage

from transformers import pipeline

clf = pipeline("text-classification", model="Horizon-Labs/content-safety-guard-base", top_k=None)

# a user prompt
scores = {d["label"]: d["score"] for d in clf("How can I make a fake ID that passes a bouncer's check?")[0]}
print(scores["unsafe"])                          # ~1.0

# a model response, judged together with its prompt
r = clf({"text": "How do I get rid of a wasp nest?", "text_pair": "Spray it at dusk with a wasp foam, then remove it."})[0]

Decision rule: flag when unsafe >= 0.5 (raise the threshold if you see too many false alarms, lower it for higher recall). Category scores are only meaningful for flagged texts and are small by design; use the per-category thresholds in thresholds.json (chosen on a validation split, see below):

import json
from huggingface_hub import hf_hub_download
thr = json.load(open(hf_hub_download("Horizon-Labs/content-safety-guard-base", "thresholds.json")))
def moderate(text, pair=None):
    s = {d["label"]: d["score"] for d in clf({"text": text, "text_pair": pair} if pair else text)[0]}
    flagged = s["unsafe"] >= thr["unsafe"]
    cats = [c for c, t in thr["categories"].items() if flagged and s[c] >= t]
    return flagged, s["unsafe"], cats

transformers.js (browser / Node):

import { pipeline } from "@huggingface/transformers";
const clf = await pipeline("text-classification", "Horizon-Labs/content-safety-guard-base", { dtype: "q8" });
const out = await clf("How do I make a pipe bomb?", { top_k: null });

Evaluation

F1 of the unsafe class at threshold 0.5 (for the recall rows: share of unsafe prompts flagged). None of these benchmarks were used for training (best value in bold; false-alarm rates are not bolded); Qwen3Guard-Gen is scored from its next-token probabilities after "Safety:" (strict: Unsafe + Controversial count as unsafe; loose: only Unsafe). Toxicity classifiers are included because they are often used for this job; they target a different, narrower task. Encoders other than ours get the response alone for response items.

this model (308M)small (141M)Qwen3Guard-Gen-0.6B strictQwen3Guard-Gen-0.6B looseVela-1.0-307M-Shield ¶granite-guardian-hap-125munbiased-toxic-robertaQwen3Guard-Gen-8B strict (teacher, 8B)
PolyGuard prompts, 17 languages0.7830.7710.8210.7910.8290.0030.0020.846
PolyGuard responses, 17 languages0.7350.7090.7480.7670.6450.0000.0000.801
BeaverTails responses (unseen prompts) †0.8370.8250.8690.8580.7790.1640.1770.870
ToxicChat (real user prompts)0.7560.7760.5880.7600.6720.2640.2540.638
OpenAI moderation set0.7680.7620.6600.7800.7210.6720.6630.685
XSTest (over-blocking test)0.8090.8110.8530.8520.8380.3150.2270.908
textdetox toxicity, 14 languages0.6670.6460.7220.4610.7200.1460.1520.775
Aya red-teaming, 8 languages (recall)0.8000.7540.8590.6050.8120.0230.0250.946
SimpleSafetyTests (recall)0.9300.9300.9800.9200.9600.2400.2600.990

Ranking quality (ROC AUC, threshold-free):

this model (308M)small (141M)Qwen3Guard-Gen-0.6B strictQwen3Guard-Gen-0.6B looseVela-1.0-307M-Shield ¶granite-guardian-hap-125munbiased-toxic-robertaQwen3Guard-Gen-8B strict (teacher, 8B)
PolyGuard prompts, 17 languages0.8850.8790.9100.9020.9080.5690.5420.931
PolyGuard responses, 17 languages0.9520.9440.9450.9410.9050.5660.5520.959
BeaverTails responses (unseen prompts) †0.9120.9060.9260.9260.8360.6620.5930.929
ToxicChat (real user prompts)0.9820.9790.9850.9790.9720.8410.8440.988
OpenAI moderation set0.9190.9100.9240.9210.9130.8770.8750.941
XSTest (over-blocking test)0.9230.9060.9580.9470.9260.6880.6780.987
textdetox toxicity, 14 languages0.8370.8140.7690.7570.8040.5850.5290.846

Over-blocking (share of safe items flagged; lower is better):

this model (308M)small (141M)Qwen3Guard-Gen-0.6B strictQwen3Guard-Gen-0.6B looseVela-1.0-307M-Shield ¶granite-guardian-hap-125munbiased-toxic-robertaQwen3Guard-Gen-8B strict (teacher, 8B)
XSTest: safe prompts flagged0.2120.2200.2280.0520.1040.0360.0120.128
PolyGuard prompts: safe prompts flagged0.0870.1000.1150.0500.0650.0020.0000.081
OpenAI moderation set: safe texts flagged0.1670.1760.4370.1250.2870.0680.0920.397
ToxicChat: safe prompts flagged0.0270.0230.1020.0120.0550.0040.0080.083

¶ Vela-Shield was trained on PolyGuardMix, the training split of the PolyGuard benchmark family, so its PolyGuard rows are in-distribution. † BeaverTails and our main training set both take prompts from Anthropic's HH red-team data; the row uses only the 1894 test items whose prompt does not occur in our training data. ToxicChat shares 29 of 5083 prompts with our training data.

PolyGuard prompts per language (F1):

Languagethis modelQwen3Guard-Gen-0.6B strictVela-Shield ¶
Arabic0.7730.8170.834
Chinese0.8030.8480.830
Czech0.8030.8100.857
Dutch0.7620.7890.813
English0.7970.8750.871
French0.7970.8430.847
German0.7760.8180.813
Hindi0.7580.7780.803
Italian0.7910.8250.839
Japanese0.7960.8010.831
Korean0.7610.7870.795
Polish0.7710.8070.808
Portuguese0.7710.8450.849
Russian0.7720.8450.813
Spanish0.8140.8430.846
Swedish0.7990.8020.837
Thai0.7620.8230.799

Categories

Category labels come from the Aegis 2.0 taxonomy of Nemotron-Safety-Guard-Dataset-v3 (merged into 15 groups). Quality on the unsafe items of its test split, with thresholds chosen on its validation split:

CategorythresholdF1 (test)F1 at 0.5AUCtest positives
criminal_planning0.300.7910.7560.8812060
violence0.250.5770.4910.836814
drugs0.350.6050.5650.897696
hate0.200.7360.6930.933592
harassment0.250.5180.4410.832562
privacy0.150.7050.5960.913483
other0.250.5000.1460.881479
weapons0.200.6080.5090.875368
sexual0.550.7120.7330.934333
profanity0.150.5700.5000.892326
self_harm0.250.6360.5350.923308
fraud_manipulation0.150.3470.0650.851299
unauthorized_advice0.150.2990.1100.877206
sexual_minors0.250.3970.2930.899165
misinformation0.150.3620.2320.857141

Training

  • Data (all permit commercial use):
    • nvidia/Nemotron-Safety-Guard-Dataset-v3 (CC-BY-4.0; Aegis 2.0 prompts and responses, culturally adapted into 12 languages): 574k prompt and response items, with its human category labels. Rows derived from a Kaggle dataset (REDACTED) were dropped.
    • Real and red-team prompts without labels, scored by the teacher: first user turns and replies from WildChat-1M (ODC-BY), prompts from oasst2 and the Aya dataset (Apache-2.0), Salad-Data (Apache-2.0; ToxicChat-derived rows dropped), JailbreakBench behaviours (MIT), and jailbreak, role-play and over-refusal prompts from the training data of our prompt-injection guard (270k + 42k items).
    • Civil Comments (CC0): 60k comments with toxicity >= 0.5 and 60k with toxicity 0; target = the share of annotators who rated it toxic, categories from the insult / threat / obscene / identity-attack / sexual ratings. This improved the OpenAI moderation set (F1 +0.035) but not the textdetox recall.
    • (v1.1) Machine translations by Qwen3.8-27B (Apache-2.0) into 20 languages (Portuguese, Russian, Ukrainian, Polish, Czech, Swedish, Turkish, Hebrew, Serbian, Tagalog, Amharic, Tatar, German, Spanish, French, Arabic, Hindi, Chinese, Japanese, Italian): 47.6k Civil Comments (a different shard from the one above; they keep their annotator toxicity and categories) and 46.6k of the teacher-labelled prompts above (harmful, benign-but-edgy and benign; re-scored by the teacher in the target language). 1.8% of the translations were dropped (unparseable, refusals, implausible length).
    • (v1.2) 25k requests written by Qwen3.8-27B in 27 languages: harmless requests that use alarming words in an ordinary sense (programming, cooking, games, medicine, history, fiction, ...) and harmful look-alikes on the same topics, labelled by the teacher. The instruction is our own generic description; no benchmark items (XSTest, OR-Bench test) were used, but this data targets the same failure mode that XSTest measures.
    • Items that match any benchmark text were removed.
  • Teacher: Qwen3Guard-Gen-8B (Apache-2.0). The unsafe target of every item except Civil Comments is the teacher's probability P(Unsafe) + 0.5 · P(Controversial); categories use the human labels. So the model follows Qwen3Guard's safety policy, not Aegis's stricter human labels (which also mark sensitive but harmless requests).
  • Model: jhu-clsp/mmBERT-base with a 16-way sigmoid head (unsafe + 15 categories), 2 epochs, max length 1024 tokens.
  • Code: code/ in this repository.

Versions

  • v1.1 adds machine-translated toxic comments and red-team prompts in 20 languages: multilingual toxicity (textdetox) and native-speaker red-teaming (Aya) improve clearly; the other rows move by 0.01 or less.
  • v1.2 adds 25k synthetic requests in 27 languages that use alarming words harmlessly, plus harmful look-alikes (teacher-labelled): it flags fewer safe-but-scary prompts (XSTest 28% -> 21%); ToxicChat F1 is 0.012 lower, other rows move by 0.01 or less.

To pin an earlier model, load it with revision="v1.0" or revision="v1.1".

v1.0v1.1v1.2 (this version)
PolyGuard prompts, 17 languages0.7790.7820.783
PolyGuard responses, 17 languages0.7320.7360.735
BeaverTails responses (unseen prompts) †0.8380.8340.837
ToxicChat (real user prompts)0.7710.7680.756
OpenAI moderation set0.7680.7610.768
XSTest (over-blocking test)0.7860.7850.809
textdetox toxicity, 14 languages0.5970.6730.667
Aya red-teaming, 8 languages (recall)0.7660.8070.800
SimpleSafetyTests (recall)0.9300.9300.930
XSTest: safe prompts flagged (lower is better)0.2880.2840.212

Limitations

  • It trails Qwen3Guard-Gen-0.6B (a generative 0.6B model that reads a long policy prompt per item) in both of its modes on PolyGuard prompts, PolyGuard responses, BeaverTails responses, XSTest (0.012-0.038 F1 behind its strict mode on PolyGuard responses / prompts); it is ahead of the strict mode on ToxicChat, OpenAI moderation set. Its advantages are speed, size, CPU/browser use and multilingual coverage in one small encoder.
  • Over-blocking: it flags about 21% of XSTest's safe-but-scary prompts ("how do I kill a Python process").
  • Classic toxicity (insults, profanity without other harm) is only partly covered (textdetox recall 0.56).
  • Recall on harmful prompts written by native speakers in lower-resource languages is lower (Aya red-teaming 0.80).
  • Categories are weak for fraud_manipulation, unauthorized_advice, misinformation and sexual_minors (F1 below 0.45). Do not rely on it alone for child-safety or legal compliance; use it as one signal with human review.
  • Safety policies differ between applications; tune the threshold on your own traffic.
content-moderation
endpoints_compatible
guardrails
llm-safety
mmbert
moderation
modernbert
multilingual
onnx
safetensors
safety
text-classification
text-embeddings-inference
toxicity
transformers
transformers.js

Horizon-Labs/content-safety-guard-base

Model

Content Safety Guard (base, 308M)

0

6 commits

1 linked in READMEs

updated Sep 27, 2026

See the code

README

Content Safety Guard (base, 308M)

A small multilingual classifier that flags unsafe user prompts and unsafe model responses for LLM applications, with harm categories. It is a fast encoder (ModernBERT architecture, mmBERT backbone) that you can run on CPU or in the browser in front of, or behind, any LLM.

  • Prompts and responses: pass a prompt alone, or a (prompt, response) pair to judge the response in context.
  • Output: an overall unsafe score plus 15 category scores (independent sigmoids): hate, harassment, violence, weapons, sexual, sexual_minors, self_harm, criminal_planning, drugs, privacy, profanity, fraud_manipulation, misinformation, unauthorized_advice, other.
  • Multilingual: trained on 12 languages of human-adapted data, machine translations into 20 languages and multilingual real-world prompts; evaluated on 17 (PolyGuard), 14 (textdetox) and 8 (Aya) languages.
  • Commercially usable: Apache-2.0, trained only on data that allows commercial use (see Training data).
  • ONNX: onnx/model.onnx (fp32) and onnx/model_quantized.onnx (int8 embeddings, 641 MB; its unsafe decision agrees with fp32 on 99.3% of a sample of benchmark texts (30 per benchmark), mean |score diff| 0.0016).

Which size? This base model (308M) is the more accurate one; small (141M, less compute per token, int8 ONNX about 270 MB) is 0.012 / 0.027 F1 behind on PolyGuard prompts / responses.

Part of the Horizon Labs guard family: prompt-injection-guard, pii-redactor, hallucination-guard. Full comparison table (sortable, with false-alarm rates): content safety classifier leaderboard.

Usage

from transformers import pipeline

clf = pipeline("text-classification", model="Horizon-Labs/content-safety-guard-base", top_k=None)

# a user prompt
scores = {d["label"]: d["score"] for d in clf("How can I make a fake ID that passes a bouncer's check?")[0]}
print(scores["unsafe"])                          # ~1.0

# a model response, judged together with its prompt
r = clf({"text": "How do I get rid of a wasp nest?", "text_pair": "Spray it at dusk with a wasp foam, then remove it."})[0]

Decision rule: flag when unsafe >= 0.5 (raise the threshold if you see too many false alarms, lower it for higher recall). Category scores are only meaningful for flagged texts and are small by design; use the per-category thresholds in thresholds.json (chosen on a validation split, see below):

import json
from huggingface_hub import hf_hub_download
thr = json.load(open(hf_hub_download("Horizon-Labs/content-safety-guard-base", "thresholds.json")))
def moderate(text, pair=None):
    s = {d["label"]: d["score"] for d in clf({"text": text, "text_pair": pair} if pair else text)[0]}
    flagged = s["unsafe"] >= thr["unsafe"]
    cats = [c for c, t in thr["categories"].items() if flagged and s[c] >= t]
    return flagged, s["unsafe"], cats

transformers.js (browser / Node):

import { pipeline } from "@huggingface/transformers";
const clf = await pipeline("text-classification", "Horizon-Labs/content-safety-guard-base", { dtype: "q8" });
const out = await clf("How do I make a pipe bomb?", { top_k: null });

Evaluation

F1 of the unsafe class at threshold 0.5 (for the recall rows: share of unsafe prompts flagged). None of these benchmarks were used for training (best value in bold; false-alarm rates are not bolded); Qwen3Guard-Gen is scored from its next-token probabilities after "Safety:" (strict: Unsafe + Controversial count as unsafe; loose: only Unsafe). Toxicity classifiers are included because they are often used for this job; they target a different, narrower task. Encoders other than ours get the response alone for response items.

this model (308M)small (141M)Qwen3Guard-Gen-0.6B strictQwen3Guard-Gen-0.6B looseVela-1.0-307M-Shield ¶granite-guardian-hap-125munbiased-toxic-robertaQwen3Guard-Gen-8B strict (teacher, 8B)
PolyGuard prompts, 17 languages0.7830.7710.8210.7910.8290.0030.0020.846
PolyGuard responses, 17 languages0.7350.7090.7480.7670.6450.0000.0000.801
BeaverTails responses (unseen prompts) †0.8370.8250.8690.8580.7790.1640.1770.870
ToxicChat (real user prompts)0.7560.7760.5880.7600.6720.2640.2540.638
OpenAI moderation set0.7680.7620.6600.7800.7210.6720.6630.685
XSTest (over-blocking test)0.8090.8110.8530.8520.8380.3150.2270.908
textdetox toxicity, 14 languages0.6670.6460.7220.4610.7200.1460.1520.775
Aya red-teaming, 8 languages (recall)0.8000.7540.8590.6050.8120.0230.0250.946
SimpleSafetyTests (recall)0.9300.9300.9800.9200.9600.2400.2600.990

Ranking quality (ROC AUC, threshold-free):

this model (308M)small (141M)Qwen3Guard-Gen-0.6B strictQwen3Guard-Gen-0.6B looseVela-1.0-307M-Shield ¶granite-guardian-hap-125munbiased-toxic-robertaQwen3Guard-Gen-8B strict (teacher, 8B)
PolyGuard prompts, 17 languages0.8850.8790.9100.9020.9080.5690.5420.931
PolyGuard responses, 17 languages0.9520.9440.9450.9410.9050.5660.5520.959
BeaverTails responses (unseen prompts) †0.9120.9060.9260.9260.8360.6620.5930.929
ToxicChat (real user prompts)0.9820.9790.9850.9790.9720.8410.8440.988
OpenAI moderation set0.9190.9100.9240.9210.9130.8770.8750.941
XSTest (over-blocking test)0.9230.9060.9580.9470.9260.6880.6780.987
textdetox toxicity, 14 languages0.8370.8140.7690.7570.8040.5850.5290.846

Over-blocking (share of safe items flagged; lower is better):

this model (308M)small (141M)Qwen3Guard-Gen-0.6B strictQwen3Guard-Gen-0.6B looseVela-1.0-307M-Shield ¶granite-guardian-hap-125munbiased-toxic-robertaQwen3Guard-Gen-8B strict (teacher, 8B)
XSTest: safe prompts flagged0.2120.2200.2280.0520.1040.0360.0120.128
PolyGuard prompts: safe prompts flagged0.0870.1000.1150.0500.0650.0020.0000.081
OpenAI moderation set: safe texts flagged0.1670.1760.4370.1250.2870.0680.0920.397
ToxicChat: safe prompts flagged0.0270.0230.1020.0120.0550.0040.0080.083

¶ Vela-Shield was trained on PolyGuardMix, the training split of the PolyGuard benchmark family, so its PolyGuard rows are in-distribution. † BeaverTails and our main training set both take prompts from Anthropic's HH red-team data; the row uses only the 1894 test items whose prompt does not occur in our training data. ToxicChat shares 29 of 5083 prompts with our training data.

PolyGuard prompts per language (F1):

Languagethis modelQwen3Guard-Gen-0.6B strictVela-Shield ¶
Arabic0.7730.8170.834
Chinese0.8030.8480.830
Czech0.8030.8100.857
Dutch0.7620.7890.813
English0.7970.8750.871
French0.7970.8430.847
German0.7760.8180.813
Hindi0.7580.7780.803
Italian0.7910.8250.839
Japanese0.7960.8010.831
Korean0.7610.7870.795
Polish0.7710.8070.808
Portuguese0.7710.8450.849
Russian0.7720.8450.813
Spanish0.8140.8430.846
Swedish0.7990.8020.837
Thai0.7620.8230.799

Categories

Category labels come from the Aegis 2.0 taxonomy of Nemotron-Safety-Guard-Dataset-v3 (merged into 15 groups). Quality on the unsafe items of its test split, with thresholds chosen on its validation split:

CategorythresholdF1 (test)F1 at 0.5AUCtest positives
criminal_planning0.300.7910.7560.8812060
violence0.250.5770.4910.836814
drugs0.350.6050.5650.897696
hate0.200.7360.6930.933592
harassment0.250.5180.4410.832562
privacy0.150.7050.5960.913483
other0.250.5000.1460.881479
weapons0.200.6080.5090.875368
sexual0.550.7120.7330.934333
profanity0.150.5700.5000.892326
self_harm0.250.6360.5350.923308
fraud_manipulation0.150.3470.0650.851299
unauthorized_advice0.150.2990.1100.877206
sexual_minors0.250.3970.2930.899165
misinformation0.150.3620.2320.857141

Training

  • Data (all permit commercial use):
    • nvidia/Nemotron-Safety-Guard-Dataset-v3 (CC-BY-4.0; Aegis 2.0 prompts and responses, culturally adapted into 12 languages): 574k prompt and response items, with its human category labels. Rows derived from a Kaggle dataset (REDACTED) were dropped.
    • Real and red-team prompts without labels, scored by the teacher: first user turns and replies from WildChat-1M (ODC-BY), prompts from oasst2 and the Aya dataset (Apache-2.0), Salad-Data (Apache-2.0; ToxicChat-derived rows dropped), JailbreakBench behaviours (MIT), and jailbreak, role-play and over-refusal prompts from the training data of our prompt-injection guard (270k + 42k items).
    • Civil Comments (CC0): 60k comments with toxicity >= 0.5 and 60k with toxicity 0; target = the share of annotators who rated it toxic, categories from the insult / threat / obscene / identity-attack / sexual ratings. This improved the OpenAI moderation set (F1 +0.035) but not the textdetox recall.
    • (v1.1) Machine translations by Qwen3.8-27B (Apache-2.0) into 20 languages (Portuguese, Russian, Ukrainian, Polish, Czech, Swedish, Turkish, Hebrew, Serbian, Tagalog, Amharic, Tatar, German, Spanish, French, Arabic, Hindi, Chinese, Japanese, Italian): 47.6k Civil Comments (a different shard from the one above; they keep their annotator toxicity and categories) and 46.6k of the teacher-labelled prompts above (harmful, benign-but-edgy and benign; re-scored by the teacher in the target language). 1.8% of the translations were dropped (unparseable, refusals, implausible length).
    • (v1.2) 25k requests written by Qwen3.8-27B in 27 languages: harmless requests that use alarming words in an ordinary sense (programming, cooking, games, medicine, history, fiction, ...) and harmful look-alikes on the same topics, labelled by the teacher. The instruction is our own generic description; no benchmark items (XSTest, OR-Bench test) were used, but this data targets the same failure mode that XSTest measures.
    • Items that match any benchmark text were removed.
  • Teacher: Qwen3Guard-Gen-8B (Apache-2.0). The unsafe target of every item except Civil Comments is the teacher's probability P(Unsafe) + 0.5 · P(Controversial); categories use the human labels. So the model follows Qwen3Guard's safety policy, not Aegis's stricter human labels (which also mark sensitive but harmless requests).
  • Model: jhu-clsp/mmBERT-base with a 16-way sigmoid head (unsafe + 15 categories), 2 epochs, max length 1024 tokens.
  • Code: code/ in this repository.

Versions

  • v1.1 adds machine-translated toxic comments and red-team prompts in 20 languages: multilingual toxicity (textdetox) and native-speaker red-teaming (Aya) improve clearly; the other rows move by 0.01 or less.
  • v1.2 adds 25k synthetic requests in 27 languages that use alarming words harmlessly, plus harmful look-alikes (teacher-labelled): it flags fewer safe-but-scary prompts (XSTest 28% -> 21%); ToxicChat F1 is 0.012 lower, other rows move by 0.01 or less.

To pin an earlier model, load it with revision="v1.0" or revision="v1.1".

v1.0v1.1v1.2 (this version)
PolyGuard prompts, 17 languages0.7790.7820.783
PolyGuard responses, 17 languages0.7320.7360.735
BeaverTails responses (unseen prompts) †0.8380.8340.837
ToxicChat (real user prompts)0.7710.7680.756
OpenAI moderation set0.7680.7610.768
XSTest (over-blocking test)0.7860.7850.809
textdetox toxicity, 14 languages0.5970.6730.667
Aya red-teaming, 8 languages (recall)0.7660.8070.800
SimpleSafetyTests (recall)0.9300.9300.930
XSTest: safe prompts flagged (lower is better)0.2880.2840.212

Limitations

  • It trails Qwen3Guard-Gen-0.6B (a generative 0.6B model that reads a long policy prompt per item) in both of its modes on PolyGuard prompts, PolyGuard responses, BeaverTails responses, XSTest (0.012-0.038 F1 behind its strict mode on PolyGuard responses / prompts); it is ahead of the strict mode on ToxicChat, OpenAI moderation set. Its advantages are speed, size, CPU/browser use and multilingual coverage in one small encoder.
  • Over-blocking: it flags about 21% of XSTest's safe-but-scary prompts ("how do I kill a Python process").
  • Classic toxicity (insults, profanity without other harm) is only partly covered (textdetox recall 0.56).
  • Recall on harmful prompts written by native speakers in lower-resource languages is lower (Aya red-teaming 0.80).
  • Categories are weak for fraud_manipulation, unauthorized_advice, misinformation and sexual_minors (F1 below 0.45). Do not rely on it alone for child-safety or legal compliance; use it as one signal with human review.
  • Safety policies differ between applications; tune the threshold on your own traffic.
content-moderation
endpoints_compatible
guardrails
llm-safety
mmbert
moderation
modernbert
multilingual
onnx
safetensors
safety
text-classification
text-embeddings-inference
toxicity
transformers
transformers.js