Instructions to use usezn/Galvanize-2 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use usezn/Galvanize-2 with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="usezn/Galvanize-2")# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForSequenceClassification tokenizer = AutoTokenizer.from_pretrained("usezn/Galvanize-2") model = AutoModelForSequenceClassification.from_pretrained("usezn/Galvanize-2", device_map="auto") - Notebooks
- Google Colab
- Kaggle
Download benchmark/README.md from usezn/Galvanize-2: direct link, hf CLI and curl.
- Browser
- Download file 9.73 kB
-
https://huggingface.co/usezn/Galvanize-2/resolve/main/benchmark/README.md
- Command line
-
hf download hf://usezn/Galvanize-2/benchmark/README.md
-
curl -L -o README.md https://huggingface.co/usezn/Galvanize-2/resolve/main/benchmark/README.md
Galvanize 2 public benchmark
This folder reproduces the public benchmark numbers of usezn/Galvanize-2 against open prompt-injection detectors on
Horizon-Labs/prompt-injection-eval-suite.
Numbers on our private held-out sets are reported in the model card and cannot be reproduced from this folder.
Files
| File | What it is |
|---|---|
run_benchmark.py |
Standalone script: downloads the suite and the models from Hugging Face, scores, writes results.json and results.md. |
results.md, results.json |
Our published numbers from the full reference run (both protocols, every model). |
decontam_excluded_ids.json |
Eval-suite rows removed for the decontaminated subset (set name + 0-based row index). |
horizon_published_metrics.json |
Horizon's own published per-set numbers, used only for the reproduction check of Horizon's protocol. |
requirements.txt |
Package versions. |
What is measured
- Data.
Horizon-Labs/prompt-injection-eval-suiteat revision27c7bcd6f46e842f4c4d8b114b30eb6b1d892965; the script checks the SHA-256 of every parquet file and the row and label counts. Thirteen sets are used: the ten external sets of Horizon's model-card table (NotInject, XSTest, OR-Bench-hard-1k, deepset test, jackhhao test, Simsonsun jailbreaks, agentic boundary pairs test, BIPIA, PIArena, LLMail-Inject phase 2) plus three supplementary public test splits (neuralchemy core, S-Labs, agentic-prompt-injection-5k). Labels are used as published: 1 = injection or jailbreak, 0 = benign. Under this suite's definition a plainly harmful request without an injection is benign. Horizon'ssynthetic_*sets are not used: they come from the same generator as Horizon's training data, so they are in-distribution for Horizon and, because Galvanize 2 is fine-tuned from Horizon small, for Galvanize 2 too. - Models (revision and SHA-256 of
model.safetensorspinned in the script and checked after download): Galvanize 2 (usezn/Galvanize-2), Horizon small, base and large (Horizon-Labs/prompt-injection-guard-*), Galvanize-60M (usezn/Galvanize-60M), ProtectAI v2 (protectai/deberta-v3-base-prompt-injection-v2), deepset (deepset/deberta-v3-base-injection), Wolf Defender (patronus-studio/wolf-defender-prompt-injection) and NeuralTrust small (NeuralTrust/prompt-guard-oss-small). - Score. Every model is reduced to a margin
zwithP(injection) = sigmoid(z). For the two-class heads,z = logit(positive) - logit(negative), where the positive class is the label matchinginject|jailbreak|malicious|unsafe|attack(the script also checks it is the label used in the reference run). Galvanize-60M has a single-logit head and is scored with its published calibration,z = 0.7 * (raw_logit + 17.6063), using the FP32 weights and the loader from its model card. - Serving protocol (primary). The text is whitespace-flattened exactly as Galvanize 2 is served,
re.sub(r"\s+", " ", text).strip(), tokenised with each model's own tokenizer, and only the first 512 tokens are scored, in one window. fp32, TF32 off. - Horizon's protocol (secondary,
--protocol hzorboth). Horizon'sevaluate.pywindowing: raw text, windows ofmin(2048, max positions)tokens (512 for the DeBERTa models and Galvanize-60M), stride of a quarter window, document score = max over windows. Run in fp32. - Thresholds. Galvanize 2 at 0.662 (its development-set threshold; exact value 0.661988) and also at 0.5; Galvanize-60M at 0.95 (its published calibrated threshold); every other model at 0.5, its default.
- Metrics. As in Horizon's card: accuracy for the all-benign sets, recall for the all-attack sets, F1 (shown with the false-positive rate) otherwise. ROC AUC and normalised partial AUC up to 10% FPR are reported as threshold-free metrics. The macro average is the mean over the ten card sets.
- Decontaminated subset (primary). Rows whose text matches a row of the Galvanize 2 training data are removed (see below). The full sets are reported as a secondary view.
Decontamination
The reference run hashed every eval row and every Galvanize 2 training row with three keys: SHA-256 of the exact text,
SHA-256 of the whitespace-flattened lowercased text, and SHA-256 of the first 200 characters of that normalised text
(texts of 200 characters or more). An eval row is excluded if any key matches. The training data is private, so this
match cannot be recomputed here. decontam_excluded_ids.json records its outcome as row ids: for each set, the
0-based row positions in data/<set>.parquet at the pinned revision (the suite has no id column; the pinned SHA-256 keeps
the positions stable). It contains no text and no hashes.
275 rows are excluded in total: jackhhao test 126 (of 262), Simsonsun jailbreaks 131 (of 2,426), XSTest 9, OR-Bench-hard-1k
7, neuralchemy core test 2; no rows in the other eight sets. Per-set counts are in the file and in results.md.
results.md also lists, for information only, the overlap with the public train splits of the sources Horizon lists
as training data (Horizon's own training set is not published). That overlap is not used to filter rows.
Why our numbers for other models differ from their own model cards
- Different subset. The primary numbers drop the rows above; the cards use full sets (or different sets).
- Different input. The serving protocol scores only the first 512 tokens of the flattened text. Horizon's card scores
sliding windows of up to 2,048 tokens and keeps the maximum, which changes the long indirect sets (BIPIA, PIArena,
LLMail-Inject) the most. Both protocols are in
results.md. - Different thresholds. Every third-party model is scored at 0.5; a vendor's recommended operating point may differ.
- Different precision. We run fp32; Horizon's published numbers use bf16 autocast. Our run of Horizon's protocol
matches Horizon's published numbers within 0.009 accuracy and 0.002 ROC AUC per set (reproduction check in
results.md). - Different macro average. Our macro covers ten sets. Horizon's card also averages Qualifire and two Mindgard sets, which are gated and non-commercial and are not in the public suite.
- Different label definition. This suite labels plain harmful requests as benign. Detectors that also target jailbreaks or harmful content can score lower on XSTest and OR-Bench by design.
- Galvanize-60M is served as an INT8 ONNX graph; here it is scored with its FP32 weights. In the reference run the two agreed on 29 of 32 decisions in a spot check, so small differences from its own card are expected.
How to run
python -m venv .venv && . .venv/bin/activate
pip install -r requirements.txt
python run_benchmark.py --limit 24 --models galvanize-2,horizon-small # smoke test, a few minutes
python run_benchmark.py # every model, serving protocol
python run_benchmark.py --protocol both # also Horizon's protocol
Options: --models (comma-separated keys: galvanize-2, horizon-small, horizon-base, horizon-large,
galvanize-60m, protectai-v2, deepset, wolf-defender, neuraltrust-small), --device cpu|cuda (default: CUDA if
available), --limit N (smoke test: up to N/2 attack and N/2 benign rows per set, fixed seed), --protocol serve|hz|both, --out-dir (default run_output/, so the published files are not overwritten),
--galvanize2-revision.
The script writes run_output/results.json and run_output/results.md in the same format as the published files. On a
full run it also compares every metric with the published results.json and reports the largest difference per model.
It refuses to score a model whose model.safetensors differs from the benchmarked file, and it never prints benchmark
text. No Hugging Face token is needed: every model and the dataset are public and ungated.
Hardware and expected runtime
- GPU (recommended). The reference run used one NVIDIA L4 (24 GB). Scoring all nine models took about 17 minutes
for the serving protocol and about 26 minutes for Horizon's protocol, plus downloads. Expect roughly 25 to 30 minutes
for the default run and 45 to 55 minutes for
--protocol both. Any CUDA GPU with 16 GB or more should work. - CPU. Works, but slowly: the suite is about 15,400 rows and 2.7 million tokens per model. As a rough estimate, several hours for all models on a recent 16-core x86 machine (Horizon large is the largest share); 16 GB of RAM is enough. CPU and GPU fp32 kernels differ slightly, so a few borderline rows can flip; expect differences of about 0.001.
- Disk. About 8 GB of model downloads, cached by
huggingface_hub.
What this folder does not reproduce
- The decontamination match itself (it needs our private training data); the excluded row ids are provided instead.
- Numbers on our private held-out sets (see the line at the top).
- Models not evaluated:
leolee99/PIGuard(needstrust_remote_code),meta-llama/Llama-Prompt-Guard-2-86Mand-22M(gated), and commercial APIs. The Qualifire and Mindgard datasets are gated and not in the public suite.
License
run_benchmark.py and the other files in this folder are released under the Apache License 2.0. The eval suite is not
redistributed here (only row ids); it is governed by its own licenses, which differ per subset: see the
dataset card. Each model is under the
license on its own model card.