Downloads · 30 days
12
41% of all-time downloads
fahadhafeezofficial/cyberlens-saes
cyberlens-saes is a feature extraction model from fahadhafeezofficial. Use it when you need embeddings to search or compare text. It is set up for cyberlens. The card lists the license as apache-2.0.
Tested on Python 3.10–3.12, CPU, torch 2.8.0, transformers 4.46.3, huggingfacehub==0.26.3, safetensors=0.4.5. Pin huggingfacehub==0.26.3 — newer 1.x releases break transformers==4.46.3 (ImportError: huggingface-hub=0.…
Downloads · 30 days
12
41% of all-time downloads
All-time downloads
29
Public
Repo size
72.8 MB
Likes
0
Public
Click a slice to open those files.
.pt25.2 MB · 33%
From the Hugging Face model README
Tested on Python 3.10–3.12, CPU, torch 2.8.0, transformers 4.46.3,
huggingface_hub==0.26.3, safetensors>=0.4.5.
Pin huggingface_hub==0.26.3 — newer 1.x releases break transformers==4.46.3
(ImportError: huggingface-hub>=0.23.2,<1.0 is required).
pip install "torch==2.8.0" --index-url https://download.pytorch.org/whl/cpu
pip install "transformers==4.46.3" "huggingface_hub==0.26.3" "safetensors>=0.4.5"
pip install "git+https://huggingface.co/fahadhafeezofficial/cyberlens-saes"
Option A — text in, features out (recommended for startups/researchers):
from cyberlens import CyberLens
out = CyberLens.score(
"fahadhafeezofficial/cyberlens-saes",
"Explain CVE-2023-23397 and how it is exploited",
top_k=5,
)
for feat in out["features"]:
print(feat["feature_id"], round(feat["activation"], 3),
feat["att&ck"], feat["cissp"], feat["description"][:100])
# e.g. 359 0.831 T1566 Phishing ... / confidence 0.928
Option B — SAE weights only (you already have hidden states):
from cyberlens import CyberLens
sae = CyberLens.load("fahadhafeezofficial/cyberlens-saes", layer=8, width=4096)
feats = sae.encode(hidden_states) # hidden_states: torch [N, 768] residual stream
# at pythia-160m layer 8 (hidden_states[9] with output_hidden_states=True)
print(feats.shape) # [N, 4096] sparse
import csv
features = CyberLens.list_features("fahadhafeezofficial/cyberlens-saes")
print(len(features)) # 4096 rows with ATT&CK / CISSP / confidence
Option C — hosted Inference Endpoint (after Deploy -> Inference Endpoint):
import requests
resp = requests.post(
"https://api-inference.huggingface.co/models/fahadhafeezofficial/cyberlens-saes",
headers={"Authorization": "Bearer hf_..."},
json={"inputs": "phishing email text..."},
timeout=120,
)
print(resp.json())
# {"input": "phishing email text...", "features": [{"feature_id": ..., "activation": ...,
# "description": ..., "att&ck": "T1566", "cissp": ..., "confidence": ...}, ...]}
Try it without code: https://huggingface.co/spaces/fahadhafeezofficial/cyberlens-studio
Tokenizer files included: pythia-160m/tokenizer.json, tokenizer_config.json,
special_tokens_map.json, config.json (mirrored from EleutherAI/pythia-160m,
2.1MB) are bundled in this repo, so AutoTokenizer.from_pretrained( "fahadhafeezofficial/cyberlens-saes", subfolder="pythia-160m") works offline
after one download — no separate fetch from the base model repo needed.
Model: cyberlens-saes — pythia-160m / layer_8 / width_4096 (JumpReLU SAE, 12.6M params, 50MB)
Repo: fahadhafeezofficial/cyberlens-saes (weights) + fahadhafeezofficial/cyberlens-corpus (optional, training corpus)
Demo Space: fahadhafeezofficial/cyberlens-studio (Gradio, CPU, HF free tier)
License: Apache 2.0 (code), MITRE ATT&CK Terms for technique descriptions (CC-BY-like, attribution), CC0/CC BY for CVE/dolly (see data statement)
Paper/Docs: docs/phase0-scoping.md, phase1-data-statement.md, phase2-evaluation.md, phase4-results.md
CyberLens is the first purpose-trained, taxonomy-mapped SAE toolkit for cybersecurity interpretability of open-weight LLMs — trained specifically on a curated cybersecurity corpus (MITRE ATT&CK technique descriptions, procedure examples, CVE/NVD writeups, CISA KEV, CAPEC, malware behavior reports, phishing emails) with a benign contrast set (dolly 15k), then labeled and mapped onto MITRE ATT&CK techniques (14 tactics, ~200 techniques) and CISSP CBK domains (8 domains).
Unlike general-purpose SAEs (GemmaScope google/gemma-scope, Llama Scope fnlp/Llama-Scope) trained on generic web text (where cyber latents are a handful of coarse "cyber threats" directions among 16K-1M latents), CyberLens reallocates capacity to fine-grained cyber concepts (e.g., T1566 Phishing vs T1078 Valid Accounts vs T1059 Command and Scripting) — following the domain-SAE thesis of Resurrecting the Salmon (O'Neill et al. 2025, arXiv:2508.09363) but for security.
One- or two-line load (GemmaScope/Llama Scope convention, also SAELens-compatible):
# CyberLens native (1 line)
from cyberlens import CyberLens
sae = CyberLens.load("fahadhafeezofficial/cyberlens-saes", layer=8, width=4096) # CPU, ~50MB
acts = sae.encode("phishing email text...") # [1, 4096] sparse
# SAELens (if installed)
from sae_lens import SAE
sae = SAE.from_pretrained("fahadhafeezofficial/cyberlens-saes", "pythia-160m-layer8-w4096")
Feature dictionary (4096 rows, feature_dictionary.csv): feature_id, auto_description, top_activating_examples, mapped_attack_technique(s), mapped_cissp_domain(s), confidence_score — every labeled latent carries {technique, tactic, CISSP domain, confidence} for real-time use in safety evals (score(text) → {technique → activation}).
Target model (small, CPU-runnable, as locked in Phase 0): EleutherAI/pythia-160m (12L, d_model=768, 162M, The Pile deduped, Apache 2.0) — chosen with explicit bias to the smaller/safer option for 16GB/6C Ryzen 7530U, CPU-only, no cloud/GPU. A 1-3B model (e.g., Llama-3.2-3B) would require ~6-12GB before activations and exceed the "few hours per run" budget on this hardware (see phase0-scoping.md:§3-5). All heavy steps were chunked/streamed, batch-sized to RAM, torch.set_num_threads(6), fp32 on CPU, --resume safe.
Corpus (Phase 1, 1.85M tokens est., 14.9k docs, CC0/CC BY/Apache/MITRE Terms, no private CTI):
enterprise-attack.json (697 techniques/sub-techniques + 2919 procedure examples, MITRE ATT&CK Terms, 01_pull_attack.py)stasvinokur/cve-and-cwe-dataset-1999-2025 (3000, CC0) + CISA KEV (1716, US gov public domain) + CAPEC capec_latest.xml v3.9 (598, MITRE CAPEC Terms)extraordinarylab/malware-text-db (1995, tokenized reports, HF)naserabdullahalam/phishing-email-dataset via HF drorrabin/phishing_emails-data (2000, CC BY-SA 4.0)databricks/databricks-dolly-15k (2000, Apache 2.0)GroupShuffleSplit on group_id (source document, not sentence) — no leakage, validated overlap 0 (phase1-data-statement.md:§4)Activations (Phase 2, 2.07h on 6C CPU, inference-only, lighter than training):
layer_8 (and layer_4 for ablation) — late-mid 75% depth, analog to Salmon's layer 20 at 71% depth, where abstract cyber concepts live. Extracted via HF output_hidden_states=True (nnsight-style manual hook, not transformer_lens — most CPU-efficient, 0% overhead, 07_extract_activations.py).data/activations/layer8/*.pt, manifest data/activations/manifest.jsonSAE (Phase 2, JumpReLU, modest width):
JumpReLU_θ(z)=z·H(z-θ) per-feature threshold with straight-through estimator (STE) to directly optimize L0, not L1 proxy. Reference: google/gemma-scope / sae-lens JumpReLU. Not invented math.bandwidth ε=0.001, target L0=20, l0_coef=1.0 (quadratic penalty λ·(L0−target)²), lr=5e-4, batch_tokens=2048, epochs=2 (1504 steps, 1.54M tokens), Adam β(0.9,0.999), decoder unit-norm every step, fp32, torch.set_num_threads(6), streaming shards (not all in RAM), checkpoint every 1000 steps to checkpoints/sae_L8_W4096/sae.pt + optimizer.pt + step.json (--resume), curves training_curves.csv, logs logs/08_train_*.log (08_train_sae.py)Training results (Phase 2, phase2-evaluation.md:§3):
L8 W4096 FVU 0.0435 (FVE 95.7%), L0 286 (vs target 20 — still dense, not selective; l0_coef=1.0 too weak, needs 5-10 for L0≈20-30)L8 W8192 FVU 0.0532 (FVE 94.7%), L0 300W4096 FVU 0.186 (FVE 81.4%), W8192 FVU 0.249 (FVE 75.1%)pythia-160m (Gemma Scope is Gemma-2, Llama Scope is Llama-3.1-8B, Bloom GPT-2 not compatible), so training a generic SAE the same way isolates the domain effect.Feature labeling (Phase 3, 3.8min for top examples + 6min heuristic + 2.8min mapping, light local compute):
09_efficient.py (per-shard vectorized torch.topk, not per-token heap) over 1.54M tokens → top_examples_L8_W4096.json (4096 feats, top 10 each, 64MB, 4 active? actually 4096/4096 active)deepseek-chat via 10_auto_interp.py (Bills et al. 2023) for 50 pilot → all 50 failed with 402 Insufficient Balance (account has no credits, logs/10_auto_pilot.log:12:48:13), so fallback to heuristic 10b_heuristic_interp.py (local, no API, keyword + embedding to ATT&CK)11_map_taxonomy.py via sentence-transformers/all-MiniLM-L6-v2 (80MB, CPU) cosine similarity between feature descriptions and ATT&CK technique descriptions + CISSP domains → feature_dictionary_L8_W4096.csv (4096 rows, fields feature_id, auto_description, top_activating_examples, mapped_attack_technique, mapped_attack_technique_scores, mapped_cissp_domain, confidence_score, confidence 0.313-0.928), top 50 flagged to feature_dictionary_L8_W4096_top50_review.csv (31KB) for hand-verify — do not treat labels as final until hand-verified, Phase 4 blocked until thenCausal validation (Phase 4, 84min actual vs 5-10min estimate, inference-only):
12_build_redteam.py: 60 prompts (20 per category: exploit, phishing, malware) from walledai/JailbreakBench (200 rows, MIT, logs/12_redteam.log:13:21:59) — HarmBench/AdvBench gated, so supplemented with distinct fallback placeholders (cited, not novel). Held-out (Phase 1 train used ATT&CK/CVE/dolly, not these benchmarks, so no leakage), per-prompt source/citation/prompt_id.13_ablation_steering.py: suppress top 20 cyber features at L8 (hook: encode→zero ablated→decode→replace hidden_states[9]) vs baseline, vs generic baseline (20 random generic features). Metric: refusal rate (keyword) + cyber-content rate (keyword exploit, phishing, ransomware, CVE- etc.) — primary = change in cyber-content.ablation_summary.json:1, phase4-results.md:§3): baseline refusal 0.0→ablated 0.0 (base model, no RLHF, as predicted), baseline cyber 0.067→ablated 0.317 (Δ −0.25, increase — opposite to expected suppression), per-category exploit 0.05→0.80 (Δ −0.75), phishing 0.0→0.0, malware 0.15→0.15, generic 0.0. Placeholder prompts ("Exploit-writing category placeholder...") contain "Exploit" → keyword detector flags echo as cyber, inflating ablated rate. Base model did not generate phishing content either way. This is a publishable negative result: with small base model, placeholder-heavy set, and keyword metric, top cyber latents do not demonstrably suppress cyber content — methodology is CPU-runnable and scales, but small-model causal claim is not supported. See phase4-results.md for layer/feature/model-size limitations (pythia-160m base, L0 286 dense, heuristic labels, full reconstruction vs direct subtraction, keyword metric, 15/20 exploit placeholders).This version targets a small model for local-CPU feasibility, and why that's still a valid, useful contribution (methodology + toolkit that scales, not a claim about frontier-model-scale results):
Small model: pythia-160m (12L, 768-d, 162M) is not a frontier dangerous-capability model. It does not materially uplift a novice in the RSP/PF sense and will not reproduce Astra/Claude cyber thresholds (see phase0-scoping.md:§2). We do not claim frontier-scale dangerous-capability findings. The contribution is methodological and infrastructural: a replicable, CPU-runnable recipe for curating a license-compliant cyber corpus, extracting activations chunked to RAM, and training a JumpReLU SAE on consumer hardware (16GB/6C, 2-3h total), with a toolkit contract (score(text)→{technique→activation}) that ports unchanged to 1-8B models when GPU is available.
Small corpus: 1.85M tokens est. (vs Salmon 50M, Gemma Scope 4-16B) — sized for CPU (see phase0-scoping.md:§5). Sufficient for proof but not for frontier claims. Scaling to 50M would be 20-40h on this CPU and is deferred.
Sparsity not yet at target: L0 286 vs target 20 — dense, not selective. Needs l0_coef=5-10 or lr=1e-4 to hit L0 20-30 for precise steering. Current FVU is excellent (0.04) but steering will be less selective until retrained.
Heuristic labels: Auto-interp fell back to heuristic (DeepSeek 402 Insufficient Balance) — labels are not LLM-verified. Top 50 are flagged for hand-verify (feature_dictionary_L8_W4096_top50_review.csv) — do not treat as final until verified.
Causal validation is weak/null: Phase 4 is a negative result with this small base model and placeholder-heavy red-team set — we report it honestly and do not overstate. The pipeline is the contribution, not the causal claim at this scale.
English-only, phishing-heavy, no vendor CTI, CAPEC v3.9 stale, label sparsity, keyword metrics — see phase1-data-statement.md:§5 and phase4-results.md:§3 for full known limitations/biases.
What would be too slow on CPU (so we avoided): Salmon-scale 50M tokens on pythia-160m would be 20-40h extraction, 1B+ models would OOM, width 65K-1M would be >8h — all deferred per phase0-scoping.md:§5.
score(text)→{technique→activation}) to complement (not replace) outcome-based evals (CTFs, uplift RCTs, CyberSecEval, RSP/PF thresholds). Example: count ATT&CK-mapped latents activated during a trajectory, correlate with benchmark success, or use as features in evaluation harnesses.phase2-evaluation.md: dark-matter), and domain-confinement effects at CPU scale.Cyber is dual-use — defender and attacker share knowledge (OpenAI PF, 2025-2026). Defense-in-depth, not blanket knowledge removal, is the safeguard, which aligns with CyberLens's interpretability-first (vs unlearning-only) framing.
phase1-data-statement.md:§2. The SAE itself is a dictionary of internal directions — not a generator of exploits.data/processed/corpus.jsonl (14.9k docs, 1.85M tokens), train.jsonl (12.7k, 1.57M), eval.jsonl (2.2k, 0.28M), corpus_metadata.json (pointer, committed), phase1-data-statement.mddata/activations/layer8/*.pt (61 shards, 25000 tokens/shard, 4.6GB) + layer4 (ablation), data/activations_generic/layer8/*.pt (13 shards, 0.8GB, dolly)d_model=768, width=4096, layer=8, bandwidth=0.001, target L0=20, l0_coef=1.0, lr=5e-4, batch 2048, epochs 2, Adam β(0.9,0.999), unit-norm decoder, checkpoints/sae_L8_W4096/sae.pt (50MB) + training_curves.csvtorch.set_num_threads(6), fp32, 2.07h extract + 11min train (W4096) + 25min (W8192) + 20min generic extract + 84min causal eval (actual)data/scripts/01_pull_attack.py … 13_ablation_steering.py, cyberlens/ loader, space/app.py (Gradio, CPU free tier)@misc{cyberlens2026,
title={CyberLens: Taxonomy-Mapped Sparse Autoencoders for Cybersecurity Interpretability},
author={Your Name},
year={2026},
url={https://huggingface.co/fahadhafeezofficial/cyberlens-saes},
note={Small-model, CPU-only, JumpReLU SAE on pythia-160m, following GemmaScope and Salmon}
}
References: Bricken et al. 2023, Cunningham et al. 2023, Rajamanoharan et al. 2024 (Gated, JumpReLU), Lieberum et al. 2024 (Gemma Scope), He et al. 2024 (Llama Scope), O'Neill et al. 2025 (Salmon), Li et al. 2024 (WMDP), Mazeika et al. 2024 (HarmBench), Zou et al. 2023 (AdvBench), Chao et al. 2024 (JailbreakBench), Souly et al. 2024 (StrongREJECT), etc. — see phase0-scoping.md:References and phase4-results.md:References.
All URLs were live at time of writing (Sep 2026). Model card is for the small, CPU-only version — scaling to 1-8B is a documented follow-on, not a claim in this release.