Reinforcement-learning intrusion detection. A defender agent (random, heuristic, tabular Q-learning, or PyTorch DQN) observes streaming flow features and chooses IGNORE / ALERT / BLOCK under a cost matrix that penalises false positives more than false negatives — reflecting the operational reality that analyst fatigue dominates SOC cost.
SyntheticFlowGenerator— reproducible mixed-class flow stream with four attack profiles (portscan,dos,brute_force,data_exfil). 8 features per flow.CICDatasetLoader— loads CIC-IDS-2018 CSVs from~/.cache/rlids/. Network access is opt-in (allow_download=True+RLIDS_ALLOW_DOWNLOAD=1); offline runs gracefully fall back to the synthetic generator.IDSEnv— Gym-style env with the canonicalreset()/step()interface and a configurable cost matrix.- Agents:
RandomAgentbaseline.HeuristicAgentinterpretable rules: blocks SYN-heavy short flows, blocks one-sided DoS, alerts on extreme byte-skew exfil.QLearningAgenttabular Q-learning over discretised features (saveable / loadable).DQNAgentPyTorch MLP with experience replay, ε-greedy decay, Polyak target update.
MetricsTracker— TPR / FPR / precision / F1 / blocked vs alerted attack counts.LLMExplainer— per-action natural-language justification for the SOC analyst console; falls back to a deterministic explainer when the LLM is unavailable, never overrides the agent's chosen action.
pip install -r requirements.txt
from rlids import (
DQNAgent, IDSEnv, MetricsTracker, SyntheticFlowGenerator,
)
gen = SyntheticFlowGenerator(attack_rate=0.1, seed=0)
env = IDSEnv(generator=gen, episode_length=500)
agent = DQNAgent(n_features=env.n_features, seed=0)
tracker = MetricsTracker()
obs = env.reset(seed=0)
for _ in range(500):
a = agent.act(obs)
res = env.step(a)
agent.learn(obs, a, res.reward,
None if res.done else res.obs, res.done)
tracker.record(a, res.info, res.reward)
obs = res.obs if not res.done else env.reset()
print(tracker.summary.to_dict())LLM-augmented explanation:
from rlids.llm_client import LLMClient
from rlids import LLMExplainer
explainer = LLMExplainer(llm=LLMClient())
print(explainer.explain(obs, a).to_dict())python -m rlids.cli evaluate --agent heuristic --steps 200 --attack-rate 0.1
python -m rlids.cli evaluate --agent dqn --episodes 5 --steps 500
from rlids import CICDatasetLoader, IDSEnv
loader = CICDatasetLoader(allow_download=True) # set RLIDS_ALLOW_DOWNLOAD=1
flows = loader.to_synthetic_flows(max_rows=2000)
env = IDSEnv(flows=flows, episode_length=2000)pytest tests/ # 59 mocked
LLM_LIVE=1 pytest tests/test_llm_live.py # 5 live
MIT