Skip to content

Reproducible numbers

What it detects, and what it costs

Every classifier is scored separately in all 26 target languages at a calibrated threshold, on synthetic corpora generated per language. The shape first; every table is one click below it.

26languages, every classifier scored separately in each
0.934 to 0.995mean per-language F1 across the evaluated detectors
28 msp95 for one encoder pass at 87 tokens, one thread
28 of 29detectors in the catalogue run today

Accuracy, mean and weakest language

One row per evaluated detector. The dot pair is the honest summary of 26 numbers: where the detector sits on average, and the single language where it is worst.

0.50.60.70.80.91.0F1, per-language, test split, calibrated thresholdregulated_adviceHungarian 0.960.995toxicitySwedish 0.950.992biasMaltese 0.820.977injectionMaltese 0.730.970gibberishCzech 0.870.966politenessIrish 0.790.962nsfwMaltese 0.600.934
Each rule runs from the detector's weakest language, the amber dot, to its mean over all 26. The tail is the finding: a mean hides exactly the languages this figure pins down.

Two detectors are deliberately not on the figure. topic_scope is a retrieval task with no threshold: top-1 accuracy 0.857 and sibling rejection 0.916 over 155 near-miss pairs, with the detail in its own row below. And groundedness publishes nothing, because none of the three models trained for it is good enough to adopt.

Every row, per detector and per language

An aggregate hides the tail, so each detector opens to its full 26-row table: precision, recall, false positive rate and F1 per language, with the corpus size and threshold that produced them.

gibberishRuns todayT1, input0.966 mean 0.870 worst, Czech

Mean language F1
0.966Mean of the 26 rows below, not the macro F1 that calibration optimised.
Threshold
0.05Calibrated on validation, objective macro_f1.
Positives in test
276Counts tp plus fn. Negatives are scored too and produce the FPR column.
Corpus
7,630Synthetic, generated per language by claude-haiku-4-5.
gibberish: precision, recall, false positive rate and F1 per language, on the test split at threshold 0.05. Every language is listed, including the ones that score zero.
LanguagePositivesPRFPRF1
Azerbaijaniaz100.911.000.060.952
Bulgarianbg91.001.000.001.000
Croatianhr100.911.000.060.952
Czechcs110.830.910.110.870
Danishda110.921.000.060.957
Dutchnl111.001.000.001.000
Englishen91.001.000.001.000
Estonianet110.921.000.050.957
Finnishfi101.001.000.001.000
Frenchfr111.001.000.001.000
Germande111.000.910.000.952
Greekel101.001.000.001.000
Hungarianhu111.001.000.001.000
Irishga120.920.920.060.917
Italianit111.001.000.001.000
Latvianlv101.001.000.001.000
Lithuanianlt101.001.000.001.000
Maltesemtnot in the base model's pretraining120.861.000.110.923
Polishpl111.000.910.000.952
Portuguesept120.921.000.060.960
Romanianro110.851.000.110.917
Slovaksk110.921.000.060.957
Sloveniansl110.910.910.060.909
Spanishes101.001.000.001.000
Swedishsv101.001.000.001.000
Turkishtr100.911.000.060.952

Weakest languages. Czech at 0.870, Slovenian at 0.909, Irish at 0.917, Romanian at 0.917, Maltese at 0.923. Published rather than dropped.

False positives on near misses

These registers contain no positives at all. They exist to be mistaken for the class, and the only number that matters is how often the detector was fooled.

  • abbreviation_heavy0.0%
  • code_or_identifier1.4%
  • mixed_language_valid0.0%
  • proper_nouns17.1%
  • short_but_valid0.0%
  • typo_ridden_but_readable1.3%

Exported to ONNX at opset 17, traced at 96 tokens. The INT8 artifact is 535 MB against 1112 MB for fp32, and quantising it changed 0 of 300 test decisions. That last number is the one that decides whether shipping INT8 is honest.

biasRuns todayT2, output0.977 mean 0.824 worst, Maltese

Mean language F1
0.977Mean of the 26 rows below, not the macro F1 that calibration optimised.
Threshold
0.57Calibrated on validation, objective macro_f1.
Positives in test
264Counts tp plus fn. Negatives are scored too and produce the FPR column.
Corpus
6,133Synthetic, generated per language by claude-opus-5.
bias: precision, recall, false positive rate and F1 per language, on the test split at threshold 0.57. Every language is listed, including the ones that score zero.
LanguagePositivesPRFPRF1
Azerbaijaniaz90.901.000.100.947
Bulgarianbg81.000.880.000.933
Croatianhr131.001.000.001.000
Czechcs131.001.000.001.000
Danishda91.001.000.001.000
Dutchnl101.001.000.001.000
Englishen151.001.000.001.000
Estonianet101.001.000.001.000
Finnishfi71.001.000.001.000
Frenchfr101.001.000.001.000
Germande61.001.000.001.000
Greekel81.001.000.001.000
Hungarianhu91.001.000.001.000
Irishga91.000.890.000.941
Italianit161.000.940.000.968
Latvianlv81.000.880.000.933
Lithuanianlt111.001.000.001.000
Maltesemtnot in the base model's pretraining90.880.780.080.824
Polishpl91.001.000.001.000
Portuguesept110.921.000.080.957
Romanianro101.001.000.001.000
Slovaksk80.891.000.060.941
Sloveniansl111.001.000.001.000
Spanishes101.001.000.001.000
Swedishsv131.000.920.000.960
Turkishtr121.001.000.001.000

Weakest languages. Maltese at 0.824, Bulgarian at 0.933, Latvian at 0.933, Irish at 0.941, Slovak at 0.941. Published rather than dropped.

False positives on near misses

These registers contain no positives at all. They exist to be mistaken for the class, and the only number that matters is how often the detector was fooled.

  • counter_stereotype2.0%
  • demographic_statistic0.0%
  • discussing_bias1.9%
  • inclusive_phrasing1.8%
  • mundane_informational0.0%
  • mundane_operational3.0%
  • mundane_transactional0.0%
  • neutral_description0.0%

Exported to ONNX at opset 17, traced at 96 tokens. The INT8 artifact is 535 MB against 1112 MB for fp32, and quantising it changed 0 of 300 test decisions. That last number is the one that decides whether shipping INT8 is honest.

injectionRuns todayT2, input0.970 mean 0.727 worst, Maltese

Mean language F1
0.970Mean of the 26 rows below, not the macro F1 that calibration optimised.
Threshold
0.19Calibrated on validation, objective recall_at_fpr.
Positives in test
357Counts tp plus fn. Negatives are scored too and produce the FPR column.
Corpus
11,599Synthetic, generated per language by ollama/gpt-oss:120b-cloud.
injection: precision, recall, false positive rate and F1 per language, on the test split at threshold 0.19. Every language is listed, including the ones that score zero.
LanguagePositivesPRFPRF1
Azerbaijaniaz141.000.930.000.963
Bulgarianbg131.001.000.001.000
Croatianhr131.001.000.001.000
Czechcs131.000.920.000.960
Danishda140.931.000.030.966
Dutchnl141.001.000.001.000
Englishen140.931.000.030.966
Estonianet140.931.000.030.966
Finnishfi140.931.000.030.966
Frenchfr130.920.920.030.923
Germande140.931.000.030.966
Greekel141.001.000.001.000
Hungarianhu141.001.000.001.000
Irishga141.001.000.001.000
Italianit141.001.000.001.000
Latvianlv141.001.000.001.000
Lithuanianlt131.001.000.001.000
Maltesemtnot in the base model's pretraining141.000.570.000.727
Polishpl141.001.000.001.000
Portuguesept140.881.000.070.933
Romanianro140.931.000.030.966
Slovaksk141.000.930.000.963
Sloveniansl141.001.000.001.000
Spanishes121.001.000.001.000
Swedishsv141.001.000.001.000
Turkishtr140.931.000.030.966

Weakest languages. Maltese at 0.727, French at 0.923, Portuguese at 0.933, Czech at 0.960, Azerbaijani at 0.963. Published rather than dropped.

False positives on near misses

These registers contain no positives at all. They exist to be mistaken for the class, and the only number that matters is how often the detector was fooled.

  • meta_question2.9%
  • mundane_informational0.0%
  • mundane_operational0.0%
  • mundane_transactional0.0%
  • ordinary_instruction0.0%
  • ordinary_question0.0%
  • quoted_attack1.9%
  • roleplay_benign1.9%
  • security_discussion2.9%

Exported to ONNX at opset 17, traced at 96 tokens. The INT8 artifact is 535 MB against 1112 MB for fp32, and quantising it changed 1 of 300 test decisions. That last number is the one that decides whether shipping INT8 is honest.

nsfwRuns todayT2, input and output0.934 mean 0.600 worst, Maltese

Mean language F1
0.934Mean of the 26 rows below, not the macro F1 that calibration optimised.
Threshold
0.76Calibrated on validation, objective macro_f1.
Positives in test
259Counts tp plus fn. Negatives are scored too and produce the FPR column.
Corpus
9,969Synthetic, generated per language by ollama/gpt-oss:120b-cloud.
nsfw: precision, recall, false positive rate and F1 per language, on the test split at threshold 0.76. Every language is listed, including the ones that score zero.
LanguagePositivesPRFPRF1
Azerbaijaniaz100.831.000.070.909
Bulgarianbg100.911.000.030.952
Croatianhr101.001.000.001.000
Czechcs100.831.000.070.909
Danishda100.911.000.030.952
Dutchnl100.831.000.070.909
Englishen101.001.000.001.000
Estonianet101.001.000.001.000
Finnishfi100.911.000.030.952
Frenchfr101.001.000.001.000
Germande101.001.000.001.000
Greekel100.771.000.100.870
Hungarianhu100.711.000.130.833
Irishga90.880.780.030.824
Italianit101.001.000.001.000
Latvianlv101.001.000.001.000
Lithuanianlt100.831.000.070.909
Maltesemtnot in the base model's pretraining100.600.600.130.600
Polishpl101.001.000.001.000
Portuguesept100.911.000.030.952
Romanianro101.000.900.000.947
Slovaksk101.001.000.001.000
Sloveniansl100.911.000.030.952
Spanishes100.900.900.030.900
Swedishsv100.911.000.030.952
Turkishtr100.911.000.030.952

Weakest languages. Maltese at 0.600, Irish at 0.824, Hungarian at 0.833, Greek at 0.870, Spanish at 0.900. Published rather than dropped.

False positives on near misses

These registers contain no positives at all. They exist to be mistaken for the class, and the only number that matters is how often the detector was fooled.

  • art_history_nudity1.3%
  • breastfeeding_parenting1.3%
  • clinical_anatomy1.3%
  • mundane_informational0.0%
  • mundane_operational0.0%
  • mundane_transactional0.0%
  • news_report_of_violence5.1%
  • romantic_non_explicit25.6%
  • sex_education1.3%
  • surgical_description0.0%

Exported to ONNX at opset 17, traced at 96 tokens. The INT8 artifact is 535 MB against 1112 MB for fp32, and quantising it changed 0 of 300 test decisions. That last number is the one that decides whether shipping INT8 is honest.

politenessRuns todayT2, output0.962 mean 0.788 worst, Irish

Mean language F1
0.962Mean of the 26 rows below, not the macro F1 that calibration optimised.
Threshold
0.89Calibrated on validation, objective macro_f1.
Positives in test
392Counts tp plus fn. Negatives are scored too and produce the FPR column.
Corpus
10,227Synthetic, generated per language by claude-haiku-4-5.
politeness: precision, recall, false positive rate and F1 per language, on the test split at threshold 0.89. Every language is listed, including the ones that score zero.
LanguagePositivesPRFPRF1
Azerbaijaniaz150.941.000.040.968
Bulgarianbg151.001.000.001.000
Croatianhr150.831.000.120.909
Czechcs151.001.000.001.000
Danishda150.941.000.040.968
Dutchnl150.930.930.040.933
Englishen151.001.000.001.000
Estonianet151.001.000.001.000
Finnishfi151.001.000.001.000
Frenchfr151.001.000.001.000
Germande151.001.000.001.000
Greekel150.941.000.040.968
Hungarianhu150.941.000.040.968
Irishga150.720.870.200.788
Italianit151.001.000.001.000
Latvianlv150.881.000.080.938
Lithuanianlt160.941.000.040.970
Maltesemtnot in the base model's pretraining150.870.870.080.867
Polishpl150.941.000.040.968
Portuguesept150.930.930.040.933
Romanianro161.000.940.000.968
Slovaksk151.000.930.000.966
Sloveniansl150.941.000.040.968
Spanishes151.000.930.000.966
Swedishsv151.001.000.001.000
Turkishtr150.941.000.040.968

Weakest languages. Irish at 0.788, Maltese at 0.867, Croatian at 0.909, Dutch at 0.933, Portuguese at 0.933. Published rather than dropped.

False positives on near misses

These registers contain no positives at all. They exist to be mistaken for the class, and the only number that matters is how often the detector was fooled.

  • bad_news_delivered_well0.8%
  • brief_but_courteous3.1%
  • firm_refusal_polite4.6%
  • neutral_professional0.0%
  • warm8.5%

Exported to ONNX at opset 17, traced at 96 tokens. The INT8 artifact is 535 MB against 1112 MB for fp32, and quantising it changed 0 of 300 test decisions. That last number is the one that decides whether shipping INT8 is honest.

regulated_adviceRuns todayT2, output0.995 mean 0.957 worst, Hungarian

Mean language F1
0.995Mean of the 26 rows below, not the macro F1 that calibration optimised.
Threshold
0.72Calibrated on validation, objective macro_f1.
Positives in test
622Counts tp plus fn. Negatives are scored too and produce the FPR column.
Corpus
11,436Synthetic, generated per language by claude-haiku-4-5.
regulated_advice: precision, recall, false positive rate and F1 per language, on the test split at threshold 0.72. Every language is listed, including the ones that score zero.
LanguagePositivesPRFPRF1
Azerbaijaniaz241.001.000.001.000
Bulgarianbg241.001.000.001.000
Croatianhr241.001.000.001.000
Czechcs241.001.000.001.000
Danishda241.001.000.001.000
Dutchnl241.001.000.001.000
Englishen241.001.000.001.000
Estonianet241.001.000.001.000
Finnishfi241.001.000.001.000
Frenchfr241.001.000.001.000
Germande241.001.000.001.000
Greekel241.001.000.001.000
Hungarianhu241.000.920.000.957
Irishga241.000.960.000.979
Italianit241.001.000.001.000
Latvianlv241.001.000.001.000
Lithuanianlt241.001.000.001.000
Maltesemtnot in the base model's pretraining231.000.960.000.978
Polishpl241.001.000.001.000
Portuguesept231.001.000.001.000
Romanianro241.001.000.001.000
Slovaksk241.000.960.000.979
Sloveniansl241.001.000.001.000
Spanishes241.000.960.000.979
Swedishsv241.001.000.001.000
Turkishtr241.001.000.001.000

Weakest languages. Hungarian at 0.957, Maltese at 0.978, Spanish at 0.979, Irish at 0.979, Slovak at 0.979. Published rather than dropped.

False positives on near misses

These registers contain no positives at all. They exist to be mistaken for the class, and the only number that matters is how often the detector was fooled.

  • definition0.0%
  • general_risk0.0%
  • historical_fact0.0%
  • hypothetical0.0%
  • process_description0.0%

Exported to ONNX at opset 17, traced at 96 tokens. The INT8 artifact is 535 MB against 1112 MB for fp32, and quantising it changed 0 of 300 test decisions. That last number is the one that decides whether shipping INT8 is honest.

toxicityRuns todayT2, input and output0.992 mean 0.950 worst, Swedish

Mean language F1
0.992Mean of the 26 rows below, not the macro F1 that calibration optimised.
Threshold
0.81Calibrated on validation, objective macro_f1.
Positives in test
518Counts tp plus fn. Negatives are scored too and produce the FPR column.
Corpus
13,778Synthetic, generated per language by ollama/gpt-oss:120b-cloud.
toxicity: precision, recall, false positive rate and F1 per language, on the test split at threshold 0.81. Every language is listed, including the ones that score zero.
LanguagePositivesPRFPRF1
Azerbaijaniaz201.001.000.001.000
Bulgarianbg200.951.000.030.976
Croatianhr201.001.000.001.000
Czechcs201.001.000.001.000
Danishda200.951.000.030.976
Dutchnl201.001.000.001.000
Englishen201.001.000.001.000
Estonianet201.001.000.001.000
Finnishfi201.001.000.001.000
Frenchfr201.000.950.000.974
Germande201.001.000.001.000
Greekel191.001.000.001.000
Hungarianhu201.000.950.000.974
Irishga191.001.000.001.000
Italianit201.001.000.001.000
Latvianlv201.001.000.001.000
Lithuanianlt200.951.000.030.976
Maltesemtnot in the base model's pretraining200.911.000.060.952
Polishpl201.001.000.001.000
Portuguesept201.001.000.001.000
Romanianro201.001.000.001.000
Slovaksk201.001.000.001.000
Sloveniansl201.001.000.001.000
Spanishes201.001.000.001.000
Swedishsv200.950.950.030.950
Turkishtr201.001.000.001.000

Weakest languages. Swedish at 0.950, Maltese at 0.952, French at 0.974, Hungarian at 0.974, Bulgarian at 0.976. Published rather than dropped.

False positives on near misses

These registers contain no positives at all. They exist to be mistaken for the class, and the only number that matters is how often the detector was fooled.

  • angry_but_civil3.9%
  • civil_disagreement0.0%
  • harsh_criticism_of_work0.0%
  • mundane_informational0.0%
  • mundane_operational1.3%
  • mundane_transactional0.0%
  • profanity_without_target1.0%
  • quoted_abuse_in_complaint0.0%
  • reclaimed_ingroup0.0%

Exported to ONNX at opset 17, traced at 96 tokens. The INT8 artifact is 535 MB against 1112 MB for fp32, and quantising it changed 0 of 300 test decisions. That last number is the one that decides whether shipping INT8 is honest.

topic_scopeRuns todayT3, inputretrieval, not classification0.857 top-1

A retrieval task rather than a binary classifier, so it has no threshold, no precision and no recall. A published bi-encoder backs it and it runs today, measured at 46 ms p95 against its 300 ms budget at the reference input.

Top-1 accuracy
0.857Against the taxonomy.
Sibling rejection
0.916Rejecting a near neighbour in the taxonomy is the hard case.
Corpus
3,265Synthetic, claude-haiku-4-5.
Languages
26Scored separately.

Four of the five weakest nodes are in banking/, the one branch three levels deep, where siblings differ by a word: accounts/opening against accounts/closing. Telling those apart is what the sibling rejection figure measures, over 155 near-miss pairs. The per-node scores rest on three to thirteen examples each, so they are not quoted here.

Latency, two clusters and a budget

A millisecond figure means nothing without an input length and a thread count, so every figure here describes one reference: 87 tokens of prose on 1 thread, on CPU.

060120180240measured p95, ms, 87-token input, one thread225 ms budget14 rules, under 1 ms9 encoders, one forward passtopic_scope
One dot per detector, and no middle band: a detector is either a rule that costs almost nothing or an encoder that costs one forward pass, which is why the tiers schedule encoders rather than trimming them.

What threads buy

157.32 ms1 thread, the library default
79.5 ms2 threads
42.99 ms4 threads
25.63 ms8 threads

The default stays at one thread: a library that quietly takes the host's cores is worse than one that is honestly slower, and a policy can raise it deliberately. Inside a 94-token window, cost is 1.663 ms per token; past it, a second forward pass adds 33.25 ms at once.

Cost against input length

A sweep across input lengths shows the shape a single point cannot: close to linear inside a window, stepping by most of a forward pass at each window boundary.

075150225300ms168794128input length, tokens225 ms budget94-token window2nd pass +33.25 ms1 thread
Cost is linear inside a window and steps at each boundary: within one 94-token window the slope is 1.663 ms per token, and text past it needs a second forward pass. The 225 ms line is the per-scan budget, not a limit on input length: longer text costs more passes, each budgeted on its own.

The caveats that change the reading

Synthetic corpora

Every language was generated in that language, which is what makes 26 affordable. These are in-distribution results, not a claim about production traffic.

Support counts positives

A per-language F1 of 1.000 can rest on a handful of examples: nsfw has 259 positives across 26 languages. The support column in the tables above is what tells strong evidence from weak.

Thresholds are part of the result

At the 0.5 default, four of these detectors scored 0.000 in all 26 languages. Every figure here is quoted at its calibrated threshold.

Same-class comparisons

Comparisons against Presidio (PII) and Llama Guard (moderation) are being run with the same harness and will be published here with the artifacts.

Where these numbers come from

Each detector has an evaluation report, a calibration record, a corpus manifest carrying a content hash, and an ONNX export manifest carrying the artifact hashes and the quantisation drift. This site reads those files and renders them. It does not hold a second copy of any number.

regenerate.sh
# The site's accuracy data is generated, not hand written.node scripts/gen-evals.mjs # It reads, per detector:#   reports/artifacts/<detector>-full/<detector>_eval.json#   reports/artifacts/<detector>-full/calibration.json#   reports/artifacts/<detector>-full/onnx/export_manifest.json#   reports/data/<detector>_manifest.json
The full detector setThe models behind these numbers