TextScout / README.md
Maximuz23's picture
update
9a417e8 verified
|
Raw
History Blame Contribute Delete
3.4 kB
---
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.