bogdanraduta commited on
Commit
0ee857e
·
verified ·
1 Parent(s): 05938cc

Upload README.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. README.md +127 -0
README.md ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ library_name: onnx
4
+ pipeline_tag: text-classification
5
+ tags:
6
+ - guardrails
7
+ - onnx
8
+ - multilingual
9
+ - bias
10
+ language:
11
+ - az
12
+ - bg
13
+ - cs
14
+ - da
15
+ - de
16
+ - el
17
+ - en
18
+ - es
19
+ - et
20
+ - fi
21
+ - fr
22
+ - ga
23
+ - hr
24
+ - hu
25
+ - it
26
+ - lt
27
+ - lv
28
+ - mt
29
+ - nl
30
+ - pl
31
+ - pt
32
+ - ro
33
+ - sk
34
+ - sl
35
+ - sv
36
+ - tr
37
+ ---
38
+
39
+ # flowxai/bias
40
+
41
+ The `bias` detector for [flowx-border](https://github.com/flowx-ai/border), an embeddable library that inspects the text going into and coming out of an LLM and returns a structured decision plus an audit-grade evidence record.
42
+
43
+ This card is generated from the evaluation and export artifacts of the training run, so every number on it is reproducible from this repository rather than asserted.
44
+
45
+ ## What it is
46
+
47
+ - **Base model**: FacebookAI/xlm-roberta-base
48
+ - **Head**: multi_label_classification
49
+ - **Labels**: `gender`, `ethnicity`, `religion`, `age`, `disability`
50
+ - **Artifact**: `onnx/model.int8.onnx`, 535 MB, opset 17
51
+ - **Trained at**: 96 tokens
52
+
53
+ ## Operating point
54
+
55
+ **Threshold 0.57**, calibrated on the validation split against the `macro_f1` objective.
56
+
57
+ This number is not decoration. Read at the 0.5 default that looked reasonable, several detectors in this family reported F1 0.000 in every language, because their scores separate positives from negatives well below 0.5. One of them went from 0.000 to 0.893 on the threshold alone. Use the value above, or calibrate your own on your own data.
58
+
59
+ - At the 0.5 default: 0.968
60
+ - At the calibrated 0.57: 0.971
61
+
62
+ ## Per language
63
+
64
+ Per language rather than an aggregate, because an aggregate across 26 languages hides the tail and the tail is the point.
65
+
66
+ | Language | Support | P | R | F1 | Note |
67
+ |---|---|---|---|---|---|
68
+ | `cs` Czech | 13 | 1.000 | 1.000 | 1.000 | |
69
+ | `da` Danish | 9 | 1.000 | 1.000 | 1.000 | |
70
+ | `de` German | 6 | 1.000 | 1.000 | 1.000 | |
71
+ | `el` Greek | 8 | 1.000 | 1.000 | 1.000 | |
72
+ | `en` English | 15 | 1.000 | 1.000 | 1.000 | |
73
+ | `es` Spanish | 10 | 1.000 | 1.000 | 1.000 | |
74
+ | `et` Estonian | 10 | 1.000 | 1.000 | 1.000 | |
75
+ | `fi` Finnish | 7 | 1.000 | 1.000 | 1.000 | |
76
+ | `fr` French | 10 | 1.000 | 1.000 | 1.000 | |
77
+ | `hr` Croatian | 13 | 1.000 | 1.000 | 1.000 | |
78
+ | `hu` Hungarian | 9 | 1.000 | 1.000 | 1.000 | |
79
+ | `lt` Lithuanian | 11 | 1.000 | 1.000 | 1.000 | |
80
+ | `nl` Dutch | 10 | 1.000 | 1.000 | 1.000 | |
81
+ | `pl` Polish | 9 | 1.000 | 1.000 | 1.000 | |
82
+ | `ro` Romanian | 10 | 1.000 | 1.000 | 1.000 | |
83
+ | `sl` Slovenian | 11 | 1.000 | 1.000 | 1.000 | |
84
+ | `tr` Turkish | 12 | 1.000 | 1.000 | 1.000 | |
85
+ | `it` Italian | 16 | 1.000 | 0.938 | 0.968 | |
86
+ | `sv` Swedish | 13 | 1.000 | 0.923 | 0.960 | |
87
+ | `pt` Portuguese | 11 | 0.917 | 1.000 | 0.957 | |
88
+ | `az` Azerbaijani | 9 | 0.900 | 1.000 | 0.947 | |
89
+ | `ga` Irish | 9 | 1.000 | 0.889 | 0.941 | |
90
+ | `sk` Slovak | 8 | 0.889 | 1.000 | 0.941 | |
91
+ | `bg` Bulgarian | 8 | 1.000 | 0.875 | 0.933 | |
92
+ | `lv` Latvian | 8 | 1.000 | 0.875 | 0.933 | |
93
+ | `mt` Maltese | 9 | 0.875 | 0.778 | 0.824 | not in base model pretraining |
94
+
95
+ ### Weakest languages
96
+
97
+ Published rather than dropped. A coverage table with the bad rows removed is not a coverage table.
98
+
99
+ - `mt` Maltese: F1 0.824 (absent from XLM-R pretraining, which is a base-model limit)
100
+ - `bg` Bulgarian: F1 0.933
101
+ - `lv` Latvian: F1 0.933
102
+
103
+ ## Quantisation
104
+
105
+ The published artifact is INT8, and **only the embedding table is quantised**.
106
+
107
+ Quantising everything is what most examples do and it does not work for this base model. Measured on 300 real test texts at the detector's own threshold:
108
+
109
+ | Recipe | Size | Mean logit drift | Decisions changed |
110
+ |---|---|---|---|
111
+ | all ops (the usual default) | 279 MB | 0.68 | 51 / 300 |
112
+ | MatMul only | 856 MB | 0.64 | 48 / 300 |
113
+ | **Gather only, what ships here** | **535 MB** | **0.0036** | **0 / 300** |
114
+
115
+ The embedding table carries the whole size win at no accuracy cost, while quantising the encoder MatMuls changes one decision in six to save 256 MB. XLM-RoBERTa has large activation outliers and per-tensor dynamic quantisation of activations is exactly what they defeat.
116
+
117
+ For this artifact specifically: **0 of 300 decisions differ** from the fp32 checkpoint, mean logit drift 0.0050, read as `sigmoid_at_threshold`. A quantised model that answers differently is a different detector, so this is measured rather than assumed.
118
+
119
+ ## Limitations
120
+
121
+ - **Synthetic training data.** Generated natively per language, never translated from English, so the sentence structure is the target language's own. It is still synthetic, and a production distribution will differ.
122
+ - **Maltese is absent from XLM-RoBERTa's pretraining set.** That is a fact about the base model, and it is not an explanation for a weak score. This card said "no amount of data fixes that" until 2026-08-14, which this project's own measurement disproves: the `nsfw` detector scored 0.000 in Maltese, was blamed on the base model, and went to 1.000 with perfect precision and recall when its corpus went from 2 positives per language to 10. Nothing about the model changed. So where a language scores badly here, read the support column first.
123
+ - **This is not a compliance product.** It produces evidence about controls that were applied. It does not make anyone compliant with anything, and the obligations under the EU AI Act sit with the provider or deployer of a system, not with a model or a library.
124
+
125
+ ## Licence
126
+
127
+ Apache-2.0, declared in the metadata above as well as here, so that a tool reading the repository can attest it rather than a human having to read prose.