File size: 3,396 Bytes
43e4fcb
952f052
 
f57882e
 
43e4fcb
 
 
fb6701f
43e4fcb
 
952f052
43e4fcb
952f052
 
 
 
43e4fcb
9a417e8
 
 
 
 
 
 
 
 
952f052
 
 
967c101
 
 
 
f57882e
952f052
967c101
b97e90d
 
 
8510853
 
 
 
 
952f052
 
 
f57882e
952f052
f57882e
952f052
f57882e
 
952f052
 
 
 
f57882e
 
952f052
 
 
f57882e
 
952f052
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
---
title: TextScout
emoji: πŸ›°οΈ
colorFrom: indigo
colorTo: blue
sdk: docker
app_port: 8501
pinned: false
license: bigscience-openrail-m
---

# TextScout β€” red-team threat-intel chatbot

Ask in plain language. TextScout **retrieves** the matching real record (MITRE ATT&CK
groups / techniques / software, CISA KEV + NVD CVEs) and analyzes it with a fine-tuned
Llama-3.2-3B (LoRA adapter `Maximuz23/Text-OSINT`). When no record is found β€” an unknown
actor or a non-existent CVE β€” it **refuses to fabricate** (evidence-gated honesty).

**Repo & full write-up:** [github.com/m-maximuz/TextScout](https://github.com/m-maximuz/TextScout) Β· model [`Maximuz23/Text-OSINT`](https://huggingface.co/Maximuz23/Text-OSINT)

**Eval** (base Llama 3.2 3B β†’ fine-tuned, 700-report test + 80-item probe): Honesty F1 0.62 β†’ **0.99** Β· NER F1 0.60 β†’ **0.88** Β· Hallucination 0.24 β†’ **0.09**.

**Try it** (use the suggestion chips, or type your own):
- `CVE-2021-44228` β€” a real CVE β†’ grounded assessment
- a fresh ThreatFox IP / domain / hash β†’ live IOC enrichment (ThreatFox + OTX + VirusTotal)
- `APT-Lyrebird-77` or `CVE-9999-0001` β†’ honest refusal (the differentiator)

## How it works (RAG)
1. Your message is routed to an entity: actor / CVE / technique / malware / report.
2. The matching record is retrieved from the bundled corpus (`corpus.json`, built from
   real MITRE ATT&CK + CISA KEV/NVD data). **Any CVE not in the snapshot is fetched LIVE
   from NVD + CISA KEV** β€” so fresh CVEs that were never in train/valid/test work too.
3. The record is formatted into the exact template the model was trained on; TextScout
   analyzes it. Empty lookup (unknown actor, non-existent CVE) β†’ honest refusal.

## Files
`Dockerfile` Β· `app.py` Β· `requirements.txt` Β· `corpus.json` (retrieval data) Β· `robot.png`.

## Optional Space secrets
- `NVD_API_KEY` β€” higher NVD rate limit (CVE lookups work without it).
- `ABUSE_API_KEY` (abuse.ch unified Auth-Key β†’ ThreatFox), `OTX_API_KEY`, `VT_API_KEY` β€”
  enable **live IOC enrichment**: a pasted IP / domain / hash / URL is looked up across
  abuse.ch ThreatFox, AlienVault OTX, and VirusTotal, formatted into a `[Threat Report]`,
  and analyzed. Without them the app still runs (the IOC text passes straight to the model).
  CISA KEV needs no key (it's a public JSON feed, fetched directly).

## Push updates
With the `hf` CLI authenticated, from the `osint-project` root:
```bash
hf upload Maximuz23/TextScout demo . --type space --commit-message update
```
The adapter `Maximuz23/Text-OSINT` is public, so no Space secret is needed.

## CPU vs GPU
Free CPU runs the 3B model in bf16 (~6 GB) β€” the first generation is ~30–60s (model load),
then faster; lower *Max new tokens* for snappier replies. For instant responses use a
**T4 small** (~$0.40/hr): switch the `Dockerfile` base to a CUDA image and uncomment
`bitsandbytes` in `requirements.txt`. Pause the Space after the demo.

## Contract β€” do not drift
`app.py`'s `SYSTEM_PROMPT` and record templates mirror `ai-test.ipynb` c03 and
`scripts/build_grounded_records.py`. If you retrain and the contract changes, update both
or the model goes off-distribution.

## Phase 2 (optional)
Swap the bundled `corpus.json` for **live** retrieval (NVD / CISA KEV / MITRE APIs) so the
demo reflects current ground truth instead of a snapshot. Needs NVD/OTX keys as secrets.