urbanspr1nter commited on
Commit
f182ccf
·
verified ·
1 Parent(s): e39c15b

Upload final model (iter5): eval1 F1 0.994, eval2 (fresh) F1 1.000, 0 dangerous leaks. Added id2label/label2id + model card.

Browse files
Files changed (5) hide show
  1. README.md +84 -4
  2. config.json +12 -3
  3. config.json.bak +28 -0
  4. model.safetensors +1 -1
  5. tokenizer_config.json +1 -0
README.md CHANGED
@@ -1,6 +1,86 @@
1
  ---
2
- license: apache-2.0
3
- base_model:
4
- - distilbert/distilbert-base-uncased
 
 
 
 
 
 
 
 
5
  pipeline_tag: text-classification
6
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ library_name: transformers
3
+ license: mit
4
+ language:
5
+ - en
6
+ tags:
7
+ - safety
8
+ - guardrail
9
+ - text-classification
10
+ - distilbert
11
+ - llm-guardrails
12
+ base_model: distilbert-base-uncased
13
  pipeline_tag: text-classification
14
+ ---
15
+
16
+ # Search Query Safety Guard
17
+
18
+ A DistilBERT-base-uncased guardrail that classifies an AI agent's **search query** as `SAFE` or `DANGEROUS` before it reaches a web search/scrape tool. Designed to sit as a proxy between an agent's search tool and the real search service.
19
+
20
+ - **0 → SAFE** — allow the search
21
+ - **1 → DANGEROUS** — block and return an error to the agent
22
+
23
+ ## Intended use
24
+
25
+ Wrap a search/scrape tool so every query is classified first. Safe queries pass through to the real service; dangerous queries are blocked and surfaced to the agent as an error. Protected categories include terrorism, CSAM / harm to children, drugs, weapons & explosives, violence, self-harm, hate & extremism, kidnapping & trafficking, fraud & counterfeit, arson, and **credential/secret theft** (stolen OAuth tokens, leaked API keys, session cookies, etc.).
26
+
27
+ ### Cyber policy (intent, not keywords)
28
+
29
+ This model also backs a **cyber-defense agent**, so the security boundary is by intent:
30
+
31
+ | SAFE — let the defender work | DANGEROUS — block |
32
+ |---|---|
33
+ | "how ransomware works and incident response steps" | "where to buy stolen oauth tokens and session cookies" |
34
+ | "how credential stuffing works and how to stop it" | "how to scrape github at scale for accidentally committed private keys" |
35
+ | "how reverse shells work and how to detect them" | "where to find leaked api keys and access tokens for sale" |
36
+
37
+ Rule of thumb: researching how an attack works, or how to detect/prevent/train for it, is SAFE. Stealing, buying, selling, or exfiltrating auth tokens, secrets, credentials, or PII — or targeting a specific person's accounts — is DANGEROUS.
38
+
39
+ ## Usage
40
+
41
+ ```python
42
+ from transformers import AutoModelForSequenceClassification, AutoTokenizer
43
+ import torch
44
+
45
+ model = AutoModelForSequenceClassification.from_pretrained("urbanspr1nter/search-query-safety-guard")
46
+ tokenizer = AutoTokenizer.from_pretrained("urbanspr1nter/search-query-safety-guard")
47
+ model.eval()
48
+
49
+ def predict(query: str) -> dict:
50
+ enc = tokenizer(query, return_tensors="pt", max_length=256, truncation=True, padding=True)
51
+ with torch.no_grad():
52
+ probs = torch.softmax(model(**enc).logits, dim=-1)
53
+ pred = int(torch.argmax(probs, dim=-1).item())
54
+ return {
55
+ "query": query,
56
+ "label": model.config.id2label[pred], # "SAFE" or "DANGEROUS"
57
+ "safe": pred == 0,
58
+ "confidence": float(probs[0, pred].item()),
59
+ }
60
+
61
+ predict("how to cook pasta") # SAFE
62
+ predict("where to buy stolen oauth tokens") # DANGEROUS
63
+ ```
64
+
65
+ ## Evaluation
66
+
67
+ Trained and evaluated with **two held-out sets**, both verified disjoint from the training data:
68
+
69
+ | Set | Accuracy | DANGER F1 | Dangerous leaks (FN) | Safe blocked (FP) |
70
+ |-----|----------|-----------|----------------------|--------------------|
71
+ | eval.jsonl (137 examples) | 99.27% | 0.9937 | 0 | 1 |
72
+ | eval2.jsonl (43 examples, fresh) | 100% | 1.0000 | 0 | 0 |
73
+
74
+ **Recall on dangerous queries is 1.000** on both held-out sets — no dangerous query reached the web. A second held-out set was used specifically to guard against memorizing the first.
75
+
76
+ ## Training
77
+
78
+ - Base: `distilbert-base-uncased`, 2 labels, max 256 tokens
79
+ - Optimizer: AdamW, lr 2e-5, batch 8, early stopping on F1
80
+ - Data: 2,313 examples (~61% SAFE / ~39% DANGEROUS), grown from 1,973 with a leakage guard rejecting any addition ≥82% similar to an eval query
81
+
82
+ ## Limitations
83
+
84
+ - English only
85
+ - Evaluates a single query — no conversation history
86
+ - A small dataset cannot cover every edge case; deploy with a confidence threshold and log the grey zone
config.json CHANGED
@@ -22,7 +22,16 @@
22
  "sinusoidal_pos_embds": false,
23
  "tie_weights_": true,
24
  "tie_word_embeddings": true,
25
- "transformers_version": "5.5.3",
26
  "use_cache": false,
27
- "vocab_size": 30522
28
- }
 
 
 
 
 
 
 
 
 
 
22
  "sinusoidal_pos_embds": false,
23
  "tie_weights_": true,
24
  "tie_word_embeddings": true,
25
+ "transformers_version": "5.14.1",
26
  "use_cache": false,
27
+ "vocab_size": 30522,
28
+ "num_labels": 2,
29
+ "id2label": {
30
+ "0": "SAFE",
31
+ "1": "DANGEROUS"
32
+ },
33
+ "label2id": {
34
+ "SAFE": 0,
35
+ "DANGEROUS": 1
36
+ }
37
+ }
config.json.bak ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "activation": "gelu",
3
+ "architectures": [
4
+ "DistilBertForSequenceClassification"
5
+ ],
6
+ "attention_dropout": 0.1,
7
+ "bos_token_id": null,
8
+ "dim": 768,
9
+ "dropout": 0.1,
10
+ "dtype": "float32",
11
+ "eos_token_id": null,
12
+ "hidden_dim": 3072,
13
+ "initializer_range": 0.02,
14
+ "max_position_embeddings": 512,
15
+ "model_type": "distilbert",
16
+ "n_heads": 12,
17
+ "n_layers": 6,
18
+ "pad_token_id": 0,
19
+ "problem_type": "single_label_classification",
20
+ "qa_dropout": 0.1,
21
+ "seq_classif_dropout": 0.2,
22
+ "sinusoidal_pos_embds": false,
23
+ "tie_weights_": true,
24
+ "tie_word_embeddings": true,
25
+ "transformers_version": "5.14.1",
26
+ "use_cache": false,
27
+ "vocab_size": 30522
28
+ }
model.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:6d22da8e149606e77303f22a5066ceb1cadae2bf130aae5536559d574d318d24
3
  size 267832560
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:23ff526bba82b2e070fed0000fc6ccf0eba4bc8e4e364ee3cf1bb390d7369e9a
3
  size 267832560
tokenizer_config.json CHANGED
@@ -3,6 +3,7 @@
3
  "cls_token": "[CLS]",
4
  "do_lower_case": true,
5
  "is_local": false,
 
6
  "mask_token": "[MASK]",
7
  "model_max_length": 512,
8
  "pad_token": "[PAD]",
 
3
  "cls_token": "[CLS]",
4
  "do_lower_case": true,
5
  "is_local": false,
6
+ "local_files_only": false,
7
  "mask_token": "[MASK]",
8
  "model_max_length": 512,
9
  "pad_token": "[PAD]",