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.
|