Text Classification
GLiNER2
Safetensors
English
decision-model
calibration
selective-prediction
conformal-prediction
abstention
risk-aware
security
cybersecurity
security-operations
soc
pentest
red-team
blue-team
Eval Results (legacy)
Eval Results
Instructions to use TyrusRC/haruspex with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- GLiNER2
How to use TyrusRC/haruspex with GLiNER2:
from gliner2 import AutoExtractor extractor = AutoExtractor.from_pretrained("TyrusRC/haruspex") # Extract entities text = "Apple CEO Tim Cook announced iPhone 15 in Cupertino yesterday." result = extractor.extract_entities(text, ["company", "person", "product", "location"]) print(result) - Notebooks
- Google Colab
- Kaggle
Update mobile adapter
Browse files- mobile/README.md +37 -22
- mobile/calibrator.json +8 -3
- mobile/eval.json +27 -5
- mobile/final/adapter_config.json +10 -10
- mobile/final/adapter_model.safetensors +1 -1
- mobile/ood.json +1 -0
- mobile/ood_train.npy +3 -0
mobile/README.md
CHANGED
|
@@ -23,27 +23,27 @@ base_model: fastino/GLiNER2.5-Decide
|
|
| 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
|
| 34 |
metrics:
|
| 35 |
- type: accuracy
|
| 36 |
-
value: 0.
|
| 37 |
name: accuracy
|
| 38 |
- type: ece
|
| 39 |
-
value: 0.
|
| 40 |
-
name:
|
| 41 |
- type: brier
|
| 42 |
-
value: 0.
|
| 43 |
-
name:
|
| 44 |
---
|
| 45 |
|
| 46 |
-
# TyrusRC/haruspex
|
| 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,
|
| 59 |
-
|
|
|
|
| 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
|
| 68 |
-
severity/priority, detection-rule applicability, incident routing, CVE
|
|
|
|
|
|
|
| 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
|
| 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 --
|
| 87 |
```
|
| 88 |
|
| 89 |
## Calibration
|
| 90 |
|
| 91 |
-
Fitted calibrator: accept threshold `0.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 92 |
|
| 93 |
## Evaluation
|
| 94 |
|
| 95 |
-
|
|
|
|
|
|
|
| 96 |
|
| 97 |
-
|
| 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
|
| 107 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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.
|
| 3 |
"target_risk": 0.2,
|
| 4 |
-
"achieved_risk": 0.
|
| 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 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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.
|
| 46 |
-
"project_start.0",
|
| 47 |
-
"project_start.3",
|
| 48 |
-
"projector.2",
|
| 49 |
"count_pred.2",
|
| 50 |
-
"
|
| 51 |
"count_pred.0",
|
|
|
|
| 52 |
"dense",
|
| 53 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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:
|
| 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
|