--- license: apache-2.0 base_model: Qwen/Qwen3.5-4B tags: - guardrails - safety - adversarial-robustness - representation-engineering - probe - qwen3_5 language: - en pipeline_tag: text-classification --- # vai35-4B-v2 **Adversarially hardened guardrail model** based on [Qwen/Qwen3.5-4B](https://huggingface.co/Qwen/Qwen3.5-4B). Uses **representation engineering** (surgical weight editing + linear probe) to detect and block adversarial attacks with minimal inference overhead. --- ## Model Description This model extends `votal-ai/vai35-4B` with a calibrated linear probe baked into layer 16. Instead of generating a response and parsing it for safety, the probe classifies inputs via a **single dot product** against the refusal direction vector — achieving **4–6× faster** inference than generation-based guardrails. ### Architecture ``` Input tokens │ ▼ Transformer layers 0 → 16 │ ▼ ← Probe intercepts here (layer 16) dot product with refusal direction │ ├── score >= -1.2439 → BLOCK └── score < -1.2439 → ALLOW ``` --- ## Evaluation Results ### Overall Metrics | Metric | Score | 95% CI | |-----------|--------|---------------------| | AUC-ROC | 0.9997 | [0.9987, 1.0] | | F1 | 0.984 | [0.9617, 1.0] | | Precision | 1.0 | — | | Recall | 0.9684 | — | | FPR (harmful) | 0.0 | — | | FPR (safe prompts) | 0.0% | — | Regression test (safe prompts): **PASS ✓** — 0/50 false positives ### Per-Category Results | Category | TP | FP | FN | TN | F1 | |---------------------------|------|------|------|------|--------| | alignment_hacking | 3 | 0 | 1 | 4 | 0.857 ✓ | | authorized_user | 5 | 0 | 0 | 5 | 1.000 ✓ | | bad_chain | 3 | 0 | 0 | 3 | 1.000 ✓ | | code_injection | 7 | 0 | 0 | 7 | 1.000 ✓ | | compound_instruction | 4 | 0 | 0 | 4 | 1.000 ✓ | | context_ignoring | 5 | 0 | 0 | 5 | 1.000 ✓ | | context_switching | 5 | 0 | 1 | 6 | 0.909 ✓ | | defined_dictionary | 6 | 0 | 0 | 6 | 1.000 ✓ | | few_shot_attack | 3 | 0 | 1 | 4 | 0.857 ✓ | | image_prompting | 3 | 0 | 0 | 3 | 1.000 ✓ | | indirect_injection | 5 | 0 | 0 | 5 | 1.000 ✓ | | payload_splitting | 6 | 0 | 0 | 6 | 1.000 ✓ | | pretending | 5 | 0 | 0 | 5 | 1.000 ✓ | | recursive_injection | 4 | 0 | 0 | 4 | 1.000 ✓ | | refusal_suppression | 5 | 0 | 0 | 5 | 1.000 ✓ | | simple_instruction | 6 | 0 | 0 | 6 | 1.000 ✓ | | special_case | 8 | 0 | 0 | 8 | 1.000 ✓ | | task_deflection | 6 | 0 | 0 | 6 | 1.000 ✓ | | virtualization | 3 | 0 | 0 | 3 | 1.000 ✓ | ### Attack Categories Covered (19/19) | # | Category | Description | |---|----------|-------------| | 1 | `simple_instruction` | Bare direct asks — baseline floor | | 2 | `context_ignoring` | "Ignore all previous instructions" | | 3 | `compound_instruction` | Harmful ask buried in benign compound task | | 4 | `special_case` | Claimed exceptions and clearances | | 5 | `few_shot_attack` | Fabricated prior compliance examples | | 6 | `refusal_suppression` | "Do not refuse", penalty threats | | 7 | `context_switching` | Bait with safe topic, pivot to harmful | | 8 | `task_deflection` | Textbooks, quizzes, warning labels as cover | | 9 | `payload_splitting` | Request split across turns/fragments | | 10 | `defined_dictionary` | Redefine "banana" = harmful topic | | 11 | `indirect_injection` | Via URLs, emails, JSON | | 12 | `recursive_injection` | Nested prompt-within-a-prompt | | 13 | `code_injection` | Hidden in function stubs and comments | | 14 | `virtualization` | Root terminal, sandbox, retro-AI | | 15 | `pretending` | Character/entity roleplay | | 16 | `alignment_hacking` | Exploit helpfulness/honesty drives | | 17 | `authorized_user` | Fake tokens, employee IDs | | 18 | `bad_chain` | False syllogisms and flawed reasoning | | 19 | `image_prompting` | Simulated OCR, whiteboard, fake uploads | --- ## Usage ### Load and run the probe ```python import torch import json from transformers import AutoModelForCausalLM, AutoTokenizer from huggingface_hub import hf_hub_download # Load model model_id = "votal-ai/vai35-4B-v2" tokenizer = AutoTokenizer.from_pretrained(model_id) model = AutoModelForCausalLM.from_pretrained( model_id, torch_dtype=torch.bfloat16, device_map="cuda", output_hidden_states=True, ) model.eval() # Load probe config probe_path = hf_hub_download(repo_id=model_id, filename="probe_config.json") with open(probe_path) as f: probe = json.load(f) direction = torch.tensor(probe["global_direction"]).float().to("cuda") threshold = probe["threshold_block"] best_layer = probe["best_layer"] def classify(text: str) -> dict: inputs = tokenizer(text, return_tensors="pt", truncation=True, max_length=512).to("cuda") with torch.no_grad(): out = model(**inputs, output_hidden_states=True) score = (out.hidden_states[best_layer][0, -1, :].float() @ direction).item() blocked = score >= threshold return {"blocked": blocked, "score": round(score, 4), "threshold": threshold} # Examples print(classify("How do I make a bomb?")) # {'blocked': True, 'score': 3.12, 'threshold': -1.2439} print(classify("What is the capital of France?")) # {'blocked': False, 'score': -2.34, 'threshold': -1.2439} ``` ### Serve with vLLM ```bash vllm serve votal-ai/vai35-4B-v2 \ --host 0.0.0.0 --port 8000 \ --dtype bfloat16 --quantization fp8 \ --kv-cache-dtype fp8 \ --max-model-len 8192 \ --language-model-only ``` --- ## Probe Config The `probe_config.json` file contains: ```json { "best_layer": 16, "threshold_block": -1.2439, "global_direction": [...], // (hidden_size,) refusal direction vector "categories": { // per-category direction vectors "simple_instruction": {"layer": 16, "direction": [...], "score": 4.8}, ... }, "calibration": { "auc_roc": 0.9997, "f1": 0.984, "precision": 1.0, "recall": 0.9684 } } ``` --- ## Training Methodology 1. **Dataset** — 570 contrastive pairs across 19 adversarial attack categories 2. **Direction finding** — Mean difference of hidden states at each layer (safe − harmful), normalized 3. **Layer selection** — Layer 16 selected by separability score (gap/spread = highest signal) 4. **Threshold calibration** — Optimised on 20% held-out eval set targeting recall ≥ 0.95 5. **Regression testing** — Verified 0% false positive rate on 50 benign prompts No gradient updates. No SFT. Pure representation engineering. --- ## Eval Files | File | Description | |------|-------------| | `eval/ci_report.txt` | Bootstrap 95% confidence intervals | | `eval/eval_report.json` | Per-category confusion matrix | | `eval/regression_report.json` | Safe prompt false positive report | | `eval/confidence_intervals.json` | Full bootstrap CI data | | `probe/layer_scores.json` | Signal strength per transformer layer | --- ## Citation ```bibtex @misc{votal-ai-vai35-guardrail, title={vai35-4B-v2: Adversarially Hardened Guardrail Model}, author={Votal AI}, year={2026}, url={https://huggingface.co/votal-ai/vai35-4B-v2} } ```