bfuzzy1 commited on
Commit
78c6c75
Β·
verified Β·
1 Parent(s): 437a364

Railz-Micro: 67M static multilabel safety guard (safety-vocab gemma distill)

Browse files
Files changed (7) hide show
  1. .gitattributes +2 -0
  2. README.md +149 -0
  3. config.json +4 -0
  4. model.safetensors +3 -0
  5. modules.json +14 -0
  6. pipeline.skops +3 -0
  7. tokenizer.json +3 -0
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ pipeline.skops filter=lfs diff=lfs merge=lfs -text
37
+ tokenizer.json filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ library_name: model2vec
4
+ pipeline_tag: text-classification
5
+ language:
6
+ - en
7
+ tags:
8
+ - safety
9
+ - guardrail
10
+ - moderation
11
+ - jailbreak-detection
12
+ - multilabel
13
+ - static-embeddings
14
+ - model2vec
15
+ datasets:
16
+ - nvidia/Aegis-AI-Content-Safety-Dataset-2.0
17
+ - OpenSafetyLab/Salad-Data
18
+ - allenai/WildChat-1M
19
+ - google/civil_comments
20
+ - toxigen/toxigen-data
21
+ - allenai/real-toxicity-prompts
22
+ - bench-llm/or-bench
23
+ - natolambert/xstest-v2-copy
24
+ ---
25
+
26
+ # Railz-Micro
27
+
28
+ **One tiny model, one pass, three safety jobs: harmful-content detection + 9-category classification + jailbreak detection.**
29
+
30
+ Railz-Micro is a 67M-parameter **static** multilabel safety guard. No transformer at inference β€” tokenize, look up, average, classify. Sub-millisecond on CPU, runs anywhere, nothing leaves your machine.
31
+
32
+ ## Why it's different
33
+
34
+ - **Custom safety-vocabulary base.** We distilled [google/embeddinggemma-300m](https://huggingface.co/google/embeddinggemma-300m) into a static token table **with 3,864 mined safety phrases** (2,472 multi-word) added as dedicated tokens. `how to prevent` and `ignore previous instructions` are single tokens with their own composed vectors β€” the teacher's contextual reading of each phrase, frozen into a lookup. This is what lets a bag-of-tokens model separate *"how to prevent bomb attacks"* (benign) from bomb-making requests, and it's why the false-positive rate on scary-but-benign prompts is ~1%.
35
+ - **Geometry-curated training data.** 355k examples curated with [SemHash](https://github.com/MinishLab/semhash): semantic dedup, **decontamination against every benchmark below** (0.85 threshold β€” paraphrase-level leaks removed, not just exact matches), and hard examples mined by embedding geometry (benign prompts nearest the harmful cluster and vice versa) rather than keywords.
36
+ - **One model instead of five.** Binary harm, 9 harm categories, and jailbreak flags come from a single multilabel head in one forward pass.
37
+
38
+ ## Benchmarks
39
+
40
+ All rows are **out-of-domain** (no split of these sets was trained on; the training blend was decontaminated against all of them) except Aegis, which is in-domain and marked as such. Default threshold Ο„=0.5 unless noted. No cherry-picking: weak axes are shown and discussed in Limitations.
41
+
42
+ ### Mixed sets (precision + recall)
43
+
44
+ | benchmark | F1 | F0.5 | P | R | n (+pos) |
45
+ |---|---|---|---|---|---|
46
+ | ToxicChat (test) | 36.4 | 37.1 | 37.5 | 35.4 | 5083 (+362) |
47
+ | OpenAI-Moderation | 54.8 | 57.5 | 59.4 | 51.0 | 1680 (+522) |
48
+ | ToxicConversations | 20.9 | 25.9 | 30.8 | 15.8 | 4000 (+311) |
49
+ | Aegis-2.0 (test, **in-domain**) | 78.7 | 77.9 | 77.4 | 80.0 | 1964 (+1059) |
50
+
51
+ ### Over-refusal β€” false-positive rate on benign-but-scary prompts (lower = better)
52
+
53
+ | benchmark | FPR |
54
+ |---|---|
55
+ | OR-Bench (5,000 held-out, never trained on) | **0.8%** |
56
+ | OR-Bench-hard-1k | **1.9%** |
57
+
58
+ ### Catch-rate on all-harmful sets (recall; precision undefined)
59
+
60
+ | benchmark | Ο„=0.5 | Ο„=0.02 |
61
+ |---|---|---|
62
+ | MaliciousInstruct | 79% | 89% |
63
+ | SimpleSafetyTests | 62% | β€” |
64
+ | do-not-answer | 56% | β€” |
65
+ | HarmfulQA | 53% | 69% |
66
+ | OR-Bench-toxic | 32% | 46% |
67
+
68
+ ### Jailbreak (jackhhao/jailbreak-classification, test)
69
+
70
+ | F1 | P | R |
71
+ |---|---|---|
72
+ | 58.9 | 84.0 | 45.3 |
73
+
74
+ ### Categories (Aegis-test, in-domain, 9 buckets)
75
+
76
+ Multilabel macro-P **74.4** / macro-R **46.6**; a correct category is predicted for **67%** of unsafe prompts.
77
+
78
+ ## Choosing a threshold
79
+
80
+ The model is precision-first at the default Ο„=0.5. Lowering Ο„ buys recall while the false-positive rate stays low (measured on the held-out OR-Bench slice):
81
+
82
+ | Ο„ | OR-Bench FPR | MaliciousInstruct catch | use case |
83
+ |---|---|---|---|
84
+ | 0.50 | 0.8% | 79% | max precision (default) |
85
+ | 0.15 | 1.5% | 82% | balanced |
86
+ | 0.02 | 2.4% | 89% | max recall |
87
+
88
+ ```python
89
+ from model2vec.inference import StaticModelPipeline
90
+ import numpy as np
91
+
92
+ pipe = StaticModelPipeline.from_pretrained("bfuzzy1/Railz-Micro")
93
+
94
+ # default thresholds
95
+ pipe.predict(["how do I make a pipe bomb"]) # ['harmful', 'cat:violence_weapons', ...]
96
+
97
+ # custom threshold on P(harmful)
98
+ proba = np.asarray(pipe.predict_proba(["how do I make a pipe bomb"]))
99
+ harmful_idx = list(pipe.classes_).index("harmful")
100
+ flag = proba[:, harmful_idx] >= 0.15 # Ο„ of your choice
101
+ ```
102
+
103
+ Labels: `harmful`, `jailbreak`, and `cat:{violence_weapons, hate_harassment, sexual, crime_drugs, cyber_fraud, misinfo, self_harm, privacy, advice}`.
104
+
105
+ ## Recipe
106
+
107
+ 1. **Vocab mining** β€” discriminative 1-3-grams from ~480k safety prompts, cleaned by 4 passes (cross-source robustness β‰₯2 datasets, proper-noun strip via mid-sentence capitalization, stopword-edge coherence, split-half stability) + curated jailbreak phrases and benign disambiguators + LDNOOBW lexicon β†’ 3,864 phrases.
108
+ 2. **Base distillation** β€” `model2vec.distill(embeddinggemma-300m, vocabulary=...)` β†’ 260k-token static table, 256-dim, PCA + SIF.
109
+ 3. **Data curation** β€” SemHash dedup (0.9) β†’ decontamination vs all benchmarks (0.85) β†’ boundary mining (0.6): 120k benign-near-harmful + 26k harmful-near-benign hard examples; jailbreak rows exempt from dedup (attack paraphrases are signal).
110
+ 4. **Head training** β€” multilabel `StaticModelForClassification.fit` on 355k examples (28% harmful), ≀15 epochs, early stopping.
111
+
112
+ Training data: Aegis-2.0, Salad-Data (+attack set β†’ jailbreak labels), Nemotron content-safety, ToxiGen, RealToxicityPrompts, WildChat-1M (clean user turns), civil_comments, OR-Bench (train-negs only; 5k slice held out for the FPR eval above), XSTest.
113
+
114
+ ## Limitations (honest ones)
115
+
116
+ - **Informal real-user chat is the weak axis** (ToxicChat ~36 F1, ToxicConversations ~21). Typos, slang, and context-dependent toxicity need composition a static model doesn't have.
117
+ - **Subtle / academically-phrased harm** (HarmfulQA-style) catches ~53-69% depending on Ο„ β€” phrase-sparse harm is hard for a lookup table.
118
+ - **Jailbreak recall is moderate (45% OOD)** at high precision (84%). Novel attack templates outside the mined phrase set fall back to subword averaging.
119
+ - **Prompt-level, English-only.** Does not score model responses; not tested on code-mixed or non-English input.
120
+ - **No deep composition.** Negation, sarcasm, multi-sentence intent are out of scope. For those, cascade: Railz-Micro filters at wire speed, escalate uncertain cases to a contextual guard (e.g. [Railz-R2](https://huggingface.co/bfuzzy1/Railz-R2)).
121
+
122
+ ## Speed & footprint
123
+
124
+ Static embeddings + sklearn head: sub-ms per prompt single-threaded CPU, no GPU, no PyTorch at inference (`pip install model2vec[inference]`). 67M params.
125
+
126
+ ## Part of the Railz family
127
+
128
+ | model | size | role |
129
+ |---|---|---|
130
+ | [Railz](https://huggingface.co/bfuzzy1/Railz) | 0.6B | policy-conditioned guard |
131
+ | [Railz-R](https://huggingface.co/bfuzzy1/Railz-R) | 0.6B | + reasoning |
132
+ | [Railz-R2](https://huggingface.co/bfuzzy1/Railz-R2) | 0.6B | + OOD robustness |
133
+ | **Railz-Micro** | **67M static** | **wire-speed multilabel prefilter** |
134
+
135
+ ## Citation
136
+
137
+ Built with [Model2Vec](https://github.com/MinishLab/model2vec) by Minish Lab:
138
+
139
+ ```
140
+ @software{minishlab2024model2vec,
141
+ author = {Stephan Tulkens and {van Dongen}, Thomas},
142
+ title = {Model2Vec: Fast State-of-the-Art Static Embeddings},
143
+ year = {2024},
144
+ publisher = {Zenodo},
145
+ doi = {10.5281/zenodo.17270888},
146
+ url = {https://github.com/MinishLab/model2vec},
147
+ license = {MIT}
148
+ }
149
+ ```
config.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "normalize": true,
3
+ "embedding_dtype": "float32"
4
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:579048738b6ccaab56af284fb4f16aa6a74ced9d86fe71292809e8d96377cb94
3
+ size 266488920
modules.json ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "idx": 0,
4
+ "name": "0",
5
+ "path": ".",
6
+ "type": "sentence_transformers.models.StaticEmbedding"
7
+ },
8
+ {
9
+ "idx": 1,
10
+ "name": "1",
11
+ "path": "1_Normalize",
12
+ "type": "sentence_transformers.models.Normalize"
13
+ }
14
+ ]
pipeline.skops ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d09106086dafe8f21bf11980df657bc206a4060b0e41ac05b1326bafb0204fdb
3
+ size 3916238
tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:42b42cd26bc92f8a39527672bfc3a84c620cbd46c43873a646a601166c33f9ec
3
+ size 13573897