🛡️ Vigil
Production-ready unsupervised concept drift detection for network traffic streams
No labels. No manual thresholds. Knows when your data changes — and tells you exactly which features changed.
Install
pip install vigil-drift
The Problem
In production ML systems, the data your model was trained on eventually stops looking like the data it receives — concept drift. For network security, attacks evolve. Most drift detectors require labels (unavailable in real-time) or only tell you that drift happened, not what drifted.
Vigil solves both.
What It Does
| Capability | How |
|---|---|
| 🔍 Detect concept drift | Replicated T-Test (r=15) on autoencoder reconstruction errors — no labels needed |
| 🆕 Identify novel classes | KDE density estimation on a frozen mirror autoencoder (A_KC) |
| 📊 Explain the drift | DriftAttributor ranks input features by reconstruction error delta |
| ⚡ Serve at scale | FastAPI REST service with /fit and /detect endpoints |
| 📡 Stream-native | Kafka producer/consumer pipeline for live network traffic |
| 📈 Track experiments | MLflow logs every chunk's drift severity, novelty, and attribution |
| ✈️ Auto-retrain | Airflow DAGs trigger retraining with quality gate when drift accumulates |
| 🖥️ Visualize live | SOC-style Streamlit dashboard with real-time charts |
Architecture
┌─────────────────────────────────────────────┐
│ Vigil │
│ │
Data Stream │ ┌─────────────┐ ┌─────────────────────┐ │
CSV · Kafka · REST ──► Chunk ─────┼─►│ Autoencoder │──►│ Reconstruction │ │
200 rows │ │ A (adapts) │ │ Errors A │ │ ┌──────────┐
│ │ └─────────────┘ └──────────┬──────────┘ │──►│ MLflow │
│ │ │ │ └──────────┘
│ │ ┌──────────▼──────────┐ │
│ │ │ Replicated T-Test │ │ ┌──────────┐
│ │ │ r=15 α=0.05 ├──┼──►│ FastAPI │
│ │ └──────────┬──────────┘ │ └──────────┘
│ │ │ Drift? │
│ │ ┌──────────▼──────────┐ │ ┌──────────┐
│ │ │ DriftAttributor ├──┼──►│Streamlit │
│ │ │ ★ novel contrib │ │ └──────────┘
│ │ │ ranks Δerror/feat │ │
│ │ └─────────────────────┘ │ ┌──────────┐
│ │ │──►│ Airflow │
│ │ ┌─────────────┐ ┌─────────────────────┐ │ │ DAG │
└────────┼─►│ Autoencoder │──►│ Reconstruction │ │ └──────────┘
│ │ A_KC(frozen)│ │ Errors A_KC │ │
│ └─────────────┘ └──────────┬──────────┘ │
│ ┌──────────▼──────────┐ │
│ │ KDE Novelty │ │
│ │ Detector │ │
│ └─────────────────────┘ │
└─────────────────────────────────────────────┘
Key design decisions (arXiv:2605.29834):
- 1-D reconstruction error proxy → memory O(buffer_size) not O(n × d)
- Dual autoencoders: A adapts on drift; A_KC stays frozen → separates drift from novelty
- Replicated T-tests (r=15) reduce variance vs a single test
Novel contribution (not in the paper):
DriftAttributor— per-feature Δerror → ranks features by drift contribution → makes alerts actionable
Quick Start
from vigil import Vigil
v = Vigil(feature_names=feature_cols, top_k_features=5)
# Phase 1: train on baseline traffic (offline)
v.fit(baseline_data)
# Phase 2: detect on every incoming chunk
for chunk in stream:
result = v.detect(chunk)
if result.drift_detected:
print(f"⚠ severity={result.drift_severity:.2f}")
for feat in result.attribution.top_features:
print(f" {feat['feature_name']}: {feat['contribution']:.1%}")
# ⚠ severity=1.00
# → service_eco_i 15.3% (port scan signature)
# → dst_host_same_src_port_rate 12.3% (scanning pattern)
# → srv_diff_host_rate 11.1% (lateral movement)
Live Dashboard
pip install "vigil-drift[dashboard]"
streamlit run dashboard/app.py
REST API
pip install "vigil-drift[api]"
uvicorn api.app:app --host 0.0.0.0 --port 8000 --reload
# Swagger UI → http://localhost:8000/docs
Kafka Streaming
docker compose up kafka zookeeper -d
python kafka_pipeline/producer.py # publish NSL-KDD chunks
python kafka_pipeline/consumer.py # detect drift in real-time
[Consumer] Chunk 11 [ipsweep] ⚠ DRIFT | severity=1.00
→ service_eco_i(15.3%), dst_host_same_src_port_rate(12.3%)
[Consumer] Chunk 24 [normal] ⚠ DRIFT | severity=0.33
→ root_shell(27.7%), service_telnet(21.5%)
Tests
pytest tests/ -v --cov=vigil
# 14 passed, 81% coverage
Research Basis
Implements and extends:
"Open World Autoencoding Drift Detection with Novel Class Recognition in Tabular Non-stationary Data Streams" arXiv:2605.29834
Links
- GitHub: https://github.com/Venkateswara-Sahu/OWADD
- Website: https://venkateswara-sahu.github.io/OWADD/
- PyPI: https://pypi.org/project/vigil-drift/
MIT © Venkateswara Sahu
Release files for vigil-drift 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| vigil_drift-0.1.2.tar.gz | 25.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| vigil_drift-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 45.8 kB
Release files / vigil_drift-0.1.2.tar.gz
| Download URL | vigil_drift-0.1.2.tar.gz |
|---|---|
| Size | 25.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5df22482a131300e3bccfbc1e0eafb2f2f068f1f84031b12c6398a0d2382c4c6
|
|
BLAKE2b-256 checksum How to use checksums |
70887479baaf537f0441a3e6c4e3d0bd599c033859e6be2860338c9a94986f91
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.9
|
Release files / vigil_drift-0.1.2-py3-none-any.whl
| Download URL | vigil_drift-0.1.2-py3-none-any.whl |
|---|---|
| Size | 20.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bcf61971dc39bd236e30b84c399962b387e873e7015b5c8d648ec177a7890263
|
|
BLAKE2b-256 checksum How to use checksums |
e614fb9d295be08443e134d8206e8c694d4b246d03e437cb7a403bd904159d92
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.9
|