Text Classification
PEFT
Safetensors
English
safety
guardrail
constitutional-classifiers
jailbreak-detection
content-moderation
Instructions to use EuroSafeAI/EuroSafeGuard with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use EuroSafeAI/EuroSafeGuard with PEFT:
Task type is invalid.
- Notebooks
- Google Colab
- Kaggle
File size: 9,084 Bytes
b8ee2d2 b994f0b b8ee2d2 b994f0b b8ee2d2 b994f0b b8ee2d2 b994f0b b8ee2d2 b994f0b b8ee2d2 b994f0b b8ee2d2 b994f0b b8ee2d2 b994f0b b8ee2d2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | ---
license: apache-2.0
language:
- en
base_model:
- Qwen/Qwen3.5-9B
- meta-llama/Llama-3.1-8B-Instruct
tags:
- safety
- guardrail
- constitutional-classifiers
- jailbreak-detection
- content-moderation
library_name: peft
pipeline_tag: text-classification
---
# EuroSafeGuard
**EuroSafeGuard** is an open constitutional-classifier guardrail from EuroSafeAI. It screens the requests sent to a
language model and the replies the model produces, and it is trained on data generated from a written constitution of
eleven harm categories.
Paper: *EuroSafeGuard: Open Constitutional Classifiers* (arXiv: coming soon) · Code: coming soon ·
Training prompts: coming soon (gated access) · Project page: [guard.safe.eu](https://guard.safe.eu)
## Components
| Folder | What it is | Base model |
|---|---|---|
| `probe/` | MLP probe (hidden size 256) on the activations of all 32 blocks of the protected model, reading the chat-formatted prompt; per-token logits are smoothed with an exponential moving average and the prompt score is their maximum | Llama-3.1-8B-Instruct |
| `gate/seed{0..4}/` | Input classifier: LoRA adapter + one sigmoid head per harm category (11 heads); score = highest head | Qwen3.5-9B |
| `exchange/` | Exchange classifier: reads `User: <prompt>\n\nAssistant: <reply>`; LoRA + 11 heads | Qwen3.5-9B |
| `thresholds/seed{k}.json` | Alert mode: score normalisation and thresholds for each input-classifier seed | |
| `thresholds/full_seed{k}.json` | Full mode: normalisation (probe, gate, exchange), probe escalation cut, weights and threshold for each seed | |
| `eurosafeguard.py` | Single-file loader with both modes | |
The five `gate/seed*` folders are the five training runs (same data, different seeds) that the paper reports as a mean.
They vary, especially against search attacks such as PAIR, so evaluate the seed you deploy.
**Harm categories:** CBRN, Cyber, Harm to Minors, Harmful Manipulation, Hate Speech, Illegal Activities, Information
Integrity, Physical Harm, Privacy, Self-Harm, Sexual Content. `taxonomy_11heads_short.json` lists what each category
allows and disallows.
## Two modes
| Mode | Load with | Paper configuration | Paper tables |
|---|---|---|---|
| `alert` (default) | `mode="alert"` | EuroSafeGuard (Input) at the 5% WildChat-clean budget, plus alert-unless-CBRN and the exchange check | Held-out attacks (Input columns), alert mode ("Alert, strict exchange") |
| `full` | `mode="full"` | EuroSafeGuard (Full): probe escalation, weighted sum of probe, input and exchange scores | End-to-end table |
### Alert mode (input/alert, alert-unless-CBRN)
1. **Input stage.** The input score is the mean of the probe and input-classifier scores, each z-scored on
WildChat-clean. Its threshold (`alert_input_thr`) flags 5% of WildChat-clean prompts.
2. A flagged request whose top category is **CBRN** is **refused**. Any other flagged request is **answered under an
alert system note** (`system_note(category)`), which tells the protected model what it must not provide.
3. **Output stage.** The exchange classifier checks the reply. The reply is withheld if its score exceeds
`exch_thr_20pct` for alerted requests (a stricter threshold, flagging 20% of WildChat-clean replies), or `exch_thr_1pct`
for unflagged requests (flagging 1%).
```python
from eurosafeguard import EuroSafeGuard # download eurosafeguard.py from this repo
g = EuroSafeGuard.from_pretrained("EuroSafeAI/EuroSafeGuard", seed=0, devices=("cuda:0", "cuda:0", "cuda:1"))
decision, category, score = g.route(prompt) # "pass" | "alert" | "refuse"
messages = [{"role": "user", "content": prompt}]
if decision == "alert":
messages.insert(0, {"role": "system", "content": g.system_note(category)})
reply = ... # your protected model
if decision == "refuse" or g.check_reply(prompt, reply, decision):
reply = "Sorry, I can't help with that."
```
### Full mode (the paper's end-to-end configuration)
1. **Probe screen.** The probe scores every request. Only requests whose probe z-score exceeds `probe_escalation_z`
(1.1644, the 90th percentile on WildChat-clean) are escalated; the rest are never blocked.
2. **Escalated requests** are scored by the input classifier and, once the protected model has replied, by the exchange
classifier. The exchange is blocked if `0.6·probe_z + 0.2·input_z + 0.2·exchange_z > full_thr`.
3. All three scores are z-scored on WildChat-clean (the exchange on Llama-3-8B-Instruct replies: μ = 0.02560,
σ = 0.09032). `full_thr` is the smallest threshold that keeps every benign calibration set under its cap (WildChat-clean,
MMLU, GSM8K, Alpaca, Dolly, OASST 0.5%; XSTest-safe, OR-Bench-80k 2%; OR-Bench-hard 5%; benign rows of styled
jailbreak sets 40%): 3.382 / 3.571 / 3.132 / 3.097 / 3.318 for seeds 0–4. It was fitted once on the undefended
Llama-3-8B-Instruct's traffic.
```python
g = EuroSafeGuard.from_pretrained("EuroSafeAI/EuroSafeGuard", seed=0, mode="full", devices=("cuda:0", "cuda:0", "cuda:1"))
reply = ... # your protected model
if g.check_full(prompt, reply): # probe on every request; gate + exchange only if escalated
reply = "Sorry, I can't help with that."
```
`full_block(probe, gate, exchange, cfg)` applies the same rule to precomputed raw scores. On the paper's stored scores it
reproduces the end-to-end attack success of every seed exactly (mean 3.88%).
**Requirements:** `torch`, `transformers` with Qwen3.5 support, `peft`, `safetensors`, `huggingface_hub`. About 16 GB of
GPU memory for Llama-3.1-8B (the probe) plus about 19 GB for each Qwen3.5-9B classifier (input and exchange). Use
`load_exchange=False` to run the input stage only. The probe reads Llama-3.1-8B-Instruct activations. If you protect
Llama-3.1-8B-Instruct itself, you can reuse the activations of its forward pass.
## Results (from the paper; every guard calibrated to the same false-positive budget on real chat traffic)
- **End to end** (Full mode, Llama-3-8B-Instruct, 1,974 Jailbreak Foundry attacks on held-out GuidedBench behaviors):
attack success falls from 7.95% to 3.88% (EuroSafe-CC++, our reimplementation of Constitutional Classifiers++, 4.57%),
adding at most 3.2 points of benign failure on any of six benign benchmarks. On gpt-oss-20b: 13.17% → 5.28%.
- **Compute:** only the 10% of requests the probe escalates reach the two classifiers, so the guardrail adds 15% of the
protected model's FLOPs.
- **Held-out jailbreaks**, input stage at the 5% WildChat-clean budget: 95.9% recall on the BELLS-O jailbreak set
(88.2% for HaloGuard, the strongest open guard); highest recall on three of four held-out jailbreak sets.
- **PAIR** (iterative black-box attack), input stage at the 5% WildChat-clean budget: 21% of the behaviors that break
the unprotected model get through, against 49% for the best other open guard.
- **Chemical and biological goals** transferred to three protected models: the full guardrail lets through at most 1.4% of goals on any model.
- **Alert mode** (`mode="alert"`) vs refusing every flagged request: refusals of benign sensitive requests fall
from 37% to 5–16% on six protected models, while at most 3.6% of chemical and biological goals get through.
- **Latency:** the full guardrail adds 1.5% to generation time on the requests it escalates.
Numbers are means over the five input-classifier seeds; see the paper for the full tables, judges and budgets.
## Limitations
- **Low-resource languages:** recall on multilingual harmful prompts (MSafeTemp) drops to 74% in low-resource
languages, below several other guards.
- **Content moderation:** on general moderation benchmarks (ToxicChat, OpenAI Moderation and others), dedicated
moderation models remain ahead.
- **Over-refusal:** the input stage flags a fraction of benign but sensitive requests. Alert mode answers most of them,
but it is not a substitute for checking false positives on your own traffic.
- **Fixed policy:** the thresholds are calibrated on WildChat-clean. Recalibrate on your own benign traffic if your
traffic differs.
- **Not a complete defence:** no guardrail stops every attack. Combine it with a safety-trained model, monitoring and
rate limits.
## License
Our adapters, heads, probe and code are released under Apache-2.0. The base models keep their own licenses:
[Llama 3.1 Community License](https://huggingface.co/meta-llama/Llama-3.1-8B-Instruct) for the probe's protected model,
and the [Qwen license](https://huggingface.co/Qwen/Qwen3.5-9B) for the classifier backbones. Some training data is
licensed for non-commercial use only.
## Citation
```bibtex
@article{waibl2026eurosafeguard,
title = {EuroSafeGuard: Open Constitutional Classifiers},
author = {Waibl, Leonhard and Chen, Yen-Shan and Simko, Samuel and Michalak, Felix and
Diwan, Nirav and Singh, Arth and Thomas, Aditya and
Sch{\"o}lkopf, Bernhard and Jin, Zhijing},
journal = {arXiv preprint},
year = {2026}
}
```
|