TyrusRC commited on
Commit
c322c06
·
verified ·
1 Parent(s): 165e526

Update mobile adapter

Browse files
mobile/README.md CHANGED
@@ -23,27 +23,27 @@ base_model: fastino/GLiNER2.5-Decide
23
  metrics:
24
  - accuracy
25
  model-index:
26
- - name: haruspex-mobile
27
  results:
28
  - task:
29
  type: text-classification
30
  name: Security decision (boolean / choice / score)
31
  dataset:
32
  type: custom
33
- name: mobile (MASVS) held-out (41 rows)
34
  metrics:
35
  - type: accuracy
36
- value: 0.9756
37
  name: accuracy
38
  - type: ece
39
- value: 0.0244
40
- name: ECE
41
  - type: brier
42
- value: 0.0244
43
- name: BRIER
44
  ---
45
 
46
- # TyrusRC/haruspex-mobile
47
 
48
  **Haruspex** is a small, local **decision layer** for security operations. It reads a
49
  situation and returns a *calibrated* typed verdict — **boolean** (yes/no + probability),
@@ -55,8 +55,9 @@ Haruspex **reuses** the published decision encoder
55
  specializes it on security decisions. It does not train a decision model from scratch.
56
 
57
  - Base: `fastino/GLiNER2.5-Decide`.
58
- - Added: a typed decision contract, security specialization data, and a
59
- split-conformal **selective-calibration** layer (accept/abstain against a risk budget).
 
60
  - Serves the TypeSafe `POST /v1/systemone` and native `/v1/evaluate` contracts.
61
 
62
  ## Intended use (security, both sides)
@@ -64,8 +65,10 @@ specializes it on security decisions. It does not train a decision model from sc
64
  - **Offensive (pentest / red-team):** is this template/probe relevant to the target?
65
  is this scanner hit a real finding? finding severity; verdict discipline
66
  (vulnerable / not-vulnerable / inconclusive); attack-path next step.
67
- - **Defensive (SOC / blue-team):** alert triage (true vs false positive), alert
68
- severity/priority, detection-rule applicability, incident routing, CVE applicability.
 
 
69
 
70
  It is a classifier for bounded decisions — not a chatbot, not an exploit generator.
71
 
@@ -73,7 +76,7 @@ It is a classifier for bounded decisions — not a chatbot, not an exploit gener
73
 
74
  ```python
75
  from haruspex import Haruspex
76
- m = Haruspex.load("TyrusRC/haruspex-mobile", device="cuda") # or "mps" / "cpu"
77
  print(m.decide({"type":"boolean","state":"Target: WordPress 6.2, PHP 8.1",
78
  "question":"Is a WordPress xmlrpc.php template relevant?",
79
  "criteria":{"true":"WordPress target","false":"not WordPress"}}))
@@ -83,27 +86,39 @@ Or serve the decision API (keyless, self-hosted):
83
 
84
  ```sh
85
  pip install "haruspex[serve] @ git+https://github.com/TyrusRC/haruspex"
86
- haruspex-serve --model TyrusRC/haruspex-mobile --port 3000 # POST /v1/systemone · /v1/evaluate
87
  ```
88
 
89
  ## Calibration
90
 
91
- Fitted calibrator: accept threshold `0.920385`, target risk `0.2`, coverage `1.0` (n=30).
 
 
 
 
 
 
 
 
 
92
 
93
  ## Evaluation
94
 
95
- On a 41-row held-out split of the security pack (recipe selected on a separate calibration split, never on test): **accuracy 0.9756**, ECE 0.0244, Brier 0.0244. The adapter beats a prompted general 8B model on the same set at a small fraction of the parameters; see the repo's `docs/benchmark.md` comparison card.
 
 
96
 
97
- A split-conformal selective layer gates each verdict: it accepts when the top-1
98
- confidence clears a threshold fitted to hold the error AMONG accepted items at a target
99
- risk, and abstains otherwise. Fit it with `python -m haruspex.calibrate`; evaluate
100
- coverage/risk with `python -m haruspex.eval`.
101
 
102
  ## Limitations
103
 
104
  - A specialist for the decision types above; novel free-form judgments belong to a
105
  general LLM.
106
- - Calibrated on the training mix — recalibrate for a very different domain.
107
- - Prediction SETS (not just abstention) await a GLiNER2 fix for per-label scores.
 
 
 
 
108
 
109
  Apache-2.0. Repo + recipe: https://github.com/TyrusRC/haruspex
 
23
  metrics:
24
  - accuracy
25
  model-index:
26
+ - name: haruspex
27
  results:
28
  - task:
29
  type: text-classification
30
  name: Security decision (boolean / choice / score)
31
  dataset:
32
  type: custom
33
+ name: mobile pack test split (117 rows)
34
  metrics:
35
  - type: accuracy
36
+ value: 0.9231
37
  name: accuracy
38
  - type: ece
39
+ value: 0.0598
40
+ name: ece
41
  - type: brier
42
+ value: 0.0598
43
+ name: brier
44
  ---
45
 
46
+ # TyrusRC/haruspex (mobile)
47
 
48
  **Haruspex** is a small, local **decision layer** for security operations. It reads a
49
  situation and returns a *calibrated* typed verdict — **boolean** (yes/no + probability),
 
55
  specializes it on security decisions. It does not train a decision model from scratch.
56
 
57
  - Base: `fastino/GLiNER2.5-Decide`.
58
+ - Added: a typed decision contract, security specialization data, a certified
59
+ **selective-calibration** layer (accept/abstain against a risk budget), conformal
60
+ **prediction sets**, and a **novelty gate** that abstains on unfamiliar input.
61
  - Serves the TypeSafe `POST /v1/systemone` and native `/v1/evaluate` contracts.
62
 
63
  ## Intended use (security, both sides)
 
65
  - **Offensive (pentest / red-team):** is this template/probe relevant to the target?
66
  is this scanner hit a real finding? finding severity; verdict discipline
67
  (vulnerable / not-vulnerable / inconclusive); attack-path next step.
68
+ - **Defensive (SOC / blue-team):** alert and incident triage (true / benign / false
69
+ positive), alert severity/priority, detection-rule applicability, incident routing, CVE
70
+ applicability, ATT&CK tactic of Windows/Sysmon events. Raw Defender, Sentinel, Elastic
71
+ ECS and Windows event JSON is normalised before the model reads it.
72
 
73
  It is a classifier for bounded decisions — not a chatbot, not an exploit generator.
74
 
 
76
 
77
  ```python
78
  from haruspex import Haruspex
79
+ m = Haruspex.load("TyrusRC/haruspex", subfolder="mobile", device="cuda") # or "mps" / "cpu"
80
  print(m.decide({"type":"boolean","state":"Target: WordPress 6.2, PHP 8.1",
81
  "question":"Is a WordPress xmlrpc.php template relevant?",
82
  "criteria":{"true":"WordPress target","false":"not WordPress"}}))
 
86
 
87
  ```sh
88
  pip install "haruspex[serve] @ git+https://github.com/TyrusRC/haruspex"
89
+ haruspex-serve --adapters mobile=TyrusRC/haruspex#mobile --port 3000 # POST /v1/systemone · /v1/evaluate
90
  ```
91
 
92
  ## Calibration
93
 
94
+ Fitted calibrator: accept threshold `0.0`, target risk `0.2` at delta `0.1`, coverage on the calibration split `1.0` (n=78), temperature `1.0`.
95
+
96
+ Each verdict carries the full probability distribution over its options (temperature-
97
+ scaled). A Learn-then-Test selective layer accepts a verdict only when its confidence
98
+ clears a threshold certified on a held-out calibration split, so that with probability
99
+ 1 - delta the error among accepted verdicts stays within the target risk; otherwise it
100
+ abstains with `"route": "escalate"`. A conformal prediction set lists the options the
101
+ true answer is among, and a novelty gate abstains on inputs unlike the training data.
102
+ Fit with `python -m haruspex.calibrate` and `python -m haruspex.ood`; evaluate with
103
+ `python -m haruspex.eval`.
104
 
105
  ## Evaluation
106
 
107
+ Held-out test sets, never used for training, model selection or calibration:
108
+
109
+ - **mobile pack test split (117 rows)**: accuracy 0.9231, ECE 0.0598, Brier 0.0598; with the calibrator it answers 1.0 of rows at accuracy 0.9391 and abstains on the rest.
110
 
111
+ Comparisons against general LLMs are in the repo's `docs/benchmark.md`.
 
 
 
112
 
113
  ## Limitations
114
 
115
  - A specialist for the decision types above; novel free-form judgments belong to a
116
  general LLM.
117
+ - Calibrated on this domain's held-out split; recalibrate before relying on the
118
+ guarantee on your own data.
119
+ - Prediction-set coverage is marginal over the calibration mix, not per input.
120
+ - A calibrator fitted on a mix of domains holds its risk target on average over that
121
+ mix, not on each domain: check each test set's accepted accuracy under Evaluation,
122
+ and route a domain with its own adapter to that adapter.
123
 
124
  Apache-2.0. Repo + recipe: https://github.com/TyrusRC/haruspex
mobile/calibrator.json CHANGED
@@ -1,7 +1,12 @@
1
  {
2
- "threshold": 0.99997,
3
  "target_risk": 0.2,
4
- "achieved_risk": 0.038462,
5
  "coverage": 1.0,
6
- "n": 78
 
 
 
 
 
7
  }
 
1
  {
2
+ "threshold": 0.0,
3
  "target_risk": 0.2,
4
+ "achieved_risk": 0.012821,
5
  "coverage": 1.0,
6
+ "n": 78,
7
+ "delta": 0.1,
8
+ "temperature": 1.0,
9
+ "temperature_scope": "all",
10
+ "set_q": 0.0,
11
+ "set_alpha": 0.1
12
  }
mobile/eval.json CHANGED
@@ -1,7 +1,29 @@
1
  {
2
- "accuracy": 0.9466,
3
- "ece": 0.0529,
4
- "brier": 0.0523,
5
- "test_n": 131,
6
- "dataset": "mobile held-out"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  }
 
1
  {
2
+ "n": 117,
3
+ "accuracy": 0.9231,
4
+ "accuracy_ci95": [
5
+ 0.8602,
6
+ 0.959
7
+ ],
8
+ "brier": 0.0598,
9
+ "ece": 0.0598,
10
+ "ece_adaptive": 0.0598,
11
+ "p50_ms": 41.9,
12
+ "by_source": {
13
+ "model": {
14
+ "n": 115,
15
+ "accuracy": 0.9391
16
+ },
17
+ "model_declined": {
18
+ "n": 2,
19
+ "accuracy": 0.0
20
+ }
21
+ },
22
+ "selective": {
23
+ "coverage": 1.0,
24
+ "accepted_accuracy": 0.9391,
25
+ "accepted_risk": 0.0609
26
+ },
27
+ "test_n": 117,
28
+ "dataset": "mobile pack test split"
29
  }
mobile/final/adapter_config.json CHANGED
@@ -35,22 +35,22 @@
35
  "rank_pattern": {},
36
  "revision": null,
37
  "target_modules": [
38
- "classifier.2",
39
- "projector.0",
40
  "out_project.3",
41
- "project_end.0",
42
  "out_project.0",
43
- "query_proj",
44
  "project_end.3",
45
- "classifier.0",
46
- "project_start.0",
47
- "project_start.3",
48
- "projector.2",
49
  "count_pred.2",
50
- "value_proj",
51
  "count_pred.0",
 
52
  "dense",
53
- "key_proj"
 
 
 
 
 
 
54
  ],
55
  "target_parameters": null,
56
  "task_type": null,
 
35
  "rank_pattern": {},
36
  "revision": null,
37
  "target_modules": [
 
 
38
  "out_project.3",
 
39
  "out_project.0",
 
40
  "project_end.3",
41
+ "classifier.2",
 
 
 
42
  "count_pred.2",
43
+ "project_start.3",
44
  "count_pred.0",
45
+ "project_start.0",
46
  "dense",
47
+ "query_proj",
48
+ "key_proj",
49
+ "projector.0",
50
+ "classifier.0",
51
+ "projector.2",
52
+ "value_proj",
53
+ "project_end.0"
54
  ],
55
  "target_parameters": null,
56
  "task_type": null,
mobile/final/adapter_model.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:2acdb5e92e793f024569e1dddbd174fe2f7374b86e9888fd4be7708bb7ff805f
3
  size 31766440
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:45fd02c28672f68373fc5ef17bea5fa3a6935e70be24ba39f4be3c2e2d6545e4
3
  size 31766440
mobile/ood.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"alpha": 0.01, "dim": 2048, "cal_scores": [0.530308, 0.610907, 0.618065, 0.621887, 0.646794, 0.67057, 0.672206, 0.709406, 0.729524, 0.831814, 0.833628, 0.859725, 0.999999, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]}
mobile/ood_train.npy ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:48e1c49ef47f8ea2c07bcde77552c94f01b4c1f2172156a4c4466590b87513ea
3
+ size 1892480