Frontier Research in Interpretable Discovery and Analysis of Yielded Intelligence
Chrome DevTools for AI Brains.
Upload any LLM. Get a complete circuit risk report in minutes. Discover hidden risks, bias circuits, deception patterns, and hallucination sources — with evidence.
Powered by automated circuit discovery in transformer models (mechanistic interpretability research).
from product.scanner import ModelScanner
scanner = ModelScanner.from_pretrained("gpt2")
report = scanner.scan_sync(depth="standard")
print(report.risk_summary())
# ⚠️ This model (gpt2, 124M) contains 2 high/critical risk circuits:
# Bias Circuit, Deception Circuit. Review before deployment.
print(f"Safe to deploy: {report.safe_to_deploy()}")
# Safe to deploy: False
# Full markdown audit report
with open("safety_report.md", "w") as f:
f.write(report.to_markdown())
Large language models are powerful but opaque. We know that GPT-2 can identify indirect objects in sentences, but we don't know how — which attention heads route the information, which MLP layers transform it, and which internal features represent the relevant concepts. Manual analysis is slow, subjective, and doesn't scale.
FRIDAY automates this process. Given a model and a behavioral task, the system extracts activations across all layers, trains sparse autoencoders to decompose superposed representations into interpretable features, and runs an iterative edge-pruning algorithm (ACDC) to identify the minimal subgraph — the circuit — that implements the behavior. The result is a directed graph of attention heads, MLP layers, and SAE features, validated with faithfulness and completeness metrics, and visualized in an interactive dashboard.
Input: a model + a task (e.g., "indirect object identification") Output: a circuit graph + ablation proof + interactive visualization┌─────────┐ ┌───────────┐ ┌─────────┐ ┌───────────┐ │ Model │─────►│ Activate │─────►│ Train │─────►│ Discover │ │ + Task │ │ & Cache │ │ SAE │ │ Circuit │ └─────────┘ └───────────┘ └─────────┘ └─────┬─────┘ M2 M3 │ ▼ ┌───────────┐ │ Evaluate │ │ & Display │ └───────────┘ M1 + M4
╔══════════════════════════════════════════════════════════════════╗
║ F.R.I.D.A.Y. ║
║ Mechanistic Interpretability Engine ║
╠══════════════════════════════════════════════════════════════════╣
║ ║
║ ┌──────────┐ AblationSpec ┌───────────────┐ ║
║ │ │ ───────────────► │ │ ║
║ │ M1 │ │ M2 │ ║
║ │ Research │ AblationResult │ Extraction │ ║
║ │ │ ◄─────────────── │ │ ║
║ └──────────┘ └───────┬───────┘ ║
║ │ │ ║
║ │ CircuitHypothesis ActivationBatch (HDF5) ║
║ │ │ ║
║ ▼ ▼ ║
║ ┌──────────┐ ┌───────────────┐ ║
║ │ │ │ │ ║
║ │ M1+M6 │ CircuitGraph │ M3 │ ║
║ │ Circuits │ ◄──────────── │ SAE │ ║
║ │ │ │ │ ║
║ └────┬─────┘ └───────┬───────┘ ║
║ │ │ ║
║ │ CircuitGraphContract FeatureDictionary (JSON) ║
║ │ │ ║
║ ▼ ▼ ║
║ ┌──────────────────────────────────────────────┐ ┌──────────┐ ║
║ │ M4 │ │ │ ║
║ │ Dashboard │ │ M5 │ ║
║ │ circuit_explorer │ feature_browser │ │ Docs │ ║
║ │ attention_heatmap│ ablation_diff │ │ & Exper. │ ║
║ └──────────────────────────────────────────────┘ └──────────┘ ║
║ ║
╠══════════════════════════════════════════════════════════════════╣
║ M6 · Pipeline · Integration ║
║ PipelineRunner → contracts.py → config.yaml ║
╚══════════════════════════════════════════════════════════════════╝
Every piece of data that crosses a module boundary has a typed Pydantic contract. If the contract validates, the data is safe to consume.
| Boundary | Contract | Format | Schema location |
|---|---|---|---|
| M1 → M2 | AblationSpec | Python dataclass | src/research/ablation_spec.py |
| M2 → M3 | ActivationBatch | HDF5 + Pydantic | src/pipeline/contracts.py |
| M3 → M4 | FeatureDictionaryContract | JSON + Pydantic | src/pipeline/contracts.py |
| M6 → M4 | CircuitGraphContract | JSON + Pydantic | src/pipeline/contracts.py |
# 1. Clone
git clone https://github.com/friday/friday.git
cd friday
# 2. Install
python -m venv .venv && source .venv/bin/activate
pip install -e ".[all]"
# 3. Scan a model (product)
python -c '
from product.scanner import ModelScanner
scanner = ModelScanner.from_pretrained("gpt2")
print(scanner.scan_sync().risk_summary())
'
# 4. Run the research pipeline
make run
# 5. Launch the ecosystem
make product # FRIDAY UI at http://localhost:8501
make api # REST API at http://localhost:8000/docs
make landing # Landing page at http://localhost:3000
| Member | Role | Owns | Key files |
|---|---|---|---|
| M1 | Research + Theory | src/research/, src/circuits/ | hypotheses.py, ablation_spec.py, discovery.py |
| M2 | Activation Extraction | src/extraction/ | cache.py, hooks.py, patching.py, api.py |
| M3 | SAE + Feature Analysis | src/sae/ | model.py, train.py, labeling.py, feature_dict.py |
| M4 | Dashboard + Visualization | dashboard/ | app.py, scanner_upload.py, risk_report.py |
| M5 | Documentation + Experiments | docs/, experiments/ | architecture.md, product_vision.md, notebooks |
| M6 | Integration + Product | product/, api/, src/pipeline/ | scanner.py, risk_engine.py, main.py |
friday/
├── README.md ← You are here
├── config.yaml ← All configurable parameters (model, SAE, thresholds)
├── pyproject.toml ← Dependencies and build config
├── Makefile ← run, test, lint, api, product, landing, clean
├── product/ ← FRIDAY product layer
│ ├── scanner.py ← ModelScanner: the core product class
│ ├── report.py ← ScanReport: structured output for customers
│ ├── risk_engine.py ← RiskEngine: circuits → risk scores (core IP)
│ └── pricing.py ← Free/Pro/Enterprise tier management
├── api/ ← REST API (FastAPI)
│ ├── main.py ← FastAPI app with CORS, error handlers, timing
│ ├── routes/
│ │ ├── scan.py ← POST /v1/scan, GET /v1/scan/{id}
│ │ ├── reports.py ← GET /v1/reports, GET /v1/reports/{id}
│ │ └── health.py ← GET /v1/health, GET /v1/version
│ ├── schemas/
│ │ ├── scan_request.py ← Pydantic request validation
│ │ └── scan_response.py ← Pydantic response models
│ └── middleware/
│ ├── auth.py ← Bearer token authentication
│ └── rate_limit.py ← Tier-based rate limiting
├── landing/ ← Product landing page
│ ├── index.html ← Hero, demo, pricing, personas
│ ├── styles.css ← Dark theme, responsive
│ └── demo.js ← Interactive scan demo
├── src/ ← Research engine (M1-M5)
│ ├── research/
│ │ ├── hypotheses.py ← CircuitHypothesis + IOI/induction examples
│ │ ├── ablation_spec.py ← AblationSpec: what to ablate and how
│ │ └── literature.md ← Annotated reading list (11 key papers)
│ ├── extraction/
│ │ ├── cache.py ← ActivationCache: HDF5-backed tensor storage
│ │ ├── hooks.py ← TransformerLens hook builders
│ │ ├── patching.py ← Zero/mean/causal ablation methods
│ │ └── api.py ← get_activation(), run_ablation()
│ ├── sae/
│ │ ├── model.py ← SparseAutoencoder nn.Module
│ │ ├── train.py ← SAETrainer with L1 sweep
│ │ ├── labeling.py ← FeatureLabeler (Claude API)
│ │ └── feature_dict.py ← FeatureDictionary: M3 → M4 contract
│ ├── circuits/
│ │ ├── graph.py ← CircuitGraph (nodes + edges + serialization)
│ │ ├── discovery.py ← AutoCircuitDiscovery (ACDC algorithm)
│ │ └── evaluate.py ← faithfulness(), completeness()
│ └── pipeline/
│ ├── runner.py ← PipelineRunner: end-to-end orchestration
│ ├── config.py ← PipelineConfig: typed YAML loader
│ └── contracts.py ← Pydantic contracts for all module boundaries
├── dashboard/
│ ├── app.py ← FRIDAY dashboard (product + research views)
│ └── views/
│ ├── scanner_upload.py ← Model upload + scan trigger
│ └── risk_report.py ← Scan results + downloadable report
├── docs/
│ ├── architecture.md ← System diagram, data contracts, decision log
│ ├── api_reference.md ← REST API endpoint documentation
│ ├── product_vision.md ← Product vision, market, revenue model
│ ├── customer_personas.md ← Buyer profiles (lab, enterprise, government)
│ ├── pricing_model.md ← Tier structure, justification, projections
│ ├── pitch_outline.md ← 10-slide investor/partner pitch outline
│ ├── onboarding.md ← New member setup guide
│ └── reproduce.md ← Seeds, checksums, and split strategy
└── tests/
├── conftest.py ← Shared fixtures (tiny model, sample data)
├── test_extraction.py ← Cache, hooks, and patching tests
├── test_sae.py ← SAE forward pass, metrics, serialization
├── test_pipeline.py ← Config loading, hashing, env overrides
├── test_contracts.py ← Contract validation for all boundaries
├── test_scanner.py ← ModelScanner scan execution tests
├── test_report.py ← ScanReport serialization + markdown
├── test_risk_engine.py ← Risk scoring and recommendation tests
├── test_pricing.py ← Tier limits and enforcement tests
└── test_api.py ← API endpoint integration tests
| Term | Definition |
|---|---|
| Circuit | A minimal subgraph of the transformer's computational graph that implements a specific behavior. Nodes are attention heads, MLP layers, or SAE features. Edges are information flow paths. |
| Superposition | The phenomenon where a neural network stores more features than it has dimensions, encoding concepts as nearly-orthogonal directions. This makes individual neurons uninterpretable. |
| Sparse Autoencoder (SAE) | An overcomplete autoencoder with an L1 sparsity penalty that decomposes superposed activations into monosemantic features — directions that each correspond to a single concept. |
| Activation patching | The core experimental method: replace one component's activation with a counterfactual value (zero, mean, or resampled) and measure the change in model output. |
| Logit lens | Projecting intermediate residual stream states through the unembedding matrix to see what the model "would predict" at each layer. |
| Faithfulness | How well the circuit alone reproduces the full model's behavior. Formally: logit_diff(circuit_only) / logit_diff(full_model). Target: ≥ 0.95. |
| Completeness | How much removing the circuit degrades the behavior. Formally: 1 - logit_diff(circuit_ablated) / logit_diff(full_model). Target: ≥ 0.90. |
CircuitHypothesis in src/research/hypotheses.py with the predicted components.AblationSpec targeting those components.make run (or call run_ablation() directly).experiments/log.md and commit the notebook.# 1. Create an issue using the Experiment template
# 2. Create a notebook
cp experiments/exp_001_ioi_baseline.ipynb experiments/exp_003_your_experiment.ipynb
# 3. Add to the log
echo "| 003 | $(date +%Y-%m-%d) | Your hypothesis | config.yaml | — | PROPOSED | exp_003 |" >> experiments/log.md
See the full experiment log: experiments/log.md
All parameters live in config.yaml. No magic numbers in code.
| Section | Key | Default | Description |
|---|---|---|---|
model.name | gpt2 | HuggingFace model ID | Start with GPT-2, scale to Llama 3 |
model.device | cpu | Compute device | Override with DEVICE env var |
task.name | ioi | Target behavioral task | Indirect Object Identification |
task.n_examples | 100 | Evaluation examples | More = more reliable, slower |
extraction.layers | [0..11] | Layers to extract | GPT-2 has 12 layers |
extraction.format | hdf5 | Cache format | HDF5 for chunked random access |
sae.d_model | 768 | Input dimension | Must match model hidden size |
sae.n_features | 4096 | Dictionary size | ~5x expansion factor |
sae.l1_coefficient | 1e-3 | Sparsity penalty | Higher = sparser, more dead features |
sae.n_epochs | 10 | Training epochs | More epochs for better reconstruction |
circuits.min_edge_score | 0.01 | Edge pruning threshold | Lower = more edges kept |
circuits.faithfulness_threshold | 0.95 | Faithfulness target | Circuit must explain ≥95% of behavior |
circuits.completeness_threshold | 0.90 | Completeness target | Ablating circuit must degrade ≥90% |
pipeline.seed | 42 | Global random seed | For full reproducibility |
dashboard.port | 8501 | Streamlit port | Access at http://localhost:PORT |
When you run make run, here's exactly what happens:
1. PipelineRunner loads config.yaml
└── Computes config_hash (SHA-256) for artifact tagging
2. Stage 1: Extraction (M2)
├── Loads model via TransformerLens
├── Runs forward pass on task dataset
├── Captures activations via hook functions
└── Saves to data/activations/gpt2_{hash}.h5
3. Stage 2: SAE Training (M3)
├── Loads activations from HDF5 cache
├── Trains SparseAutoencoder (768 → 4096 features)
├── Saves checkpoint to checkpoints/sae_epoch_0009.pt
└── Saves feature dictionary to data/feature_dicts/latest.json
4. Stage 3: Circuit Discovery (M1 + M6)
├── Builds full computational graph (all heads + MLPs)
├── Runs ACDC: iterative edge pruning via activation patching
└── Saves minimal circuit to data/ablation_results/ioi_circuit.json
5. Stage 4: Evaluation
├── Computes faithfulness and completeness
└── Logs results to data/ablation_results/evaluation.json
m{N}/{short-description}
Examples:
m2/add-residual-caching
m3/l1-sweep-experiment
m6/fix-contract-validation
make test passesmake lint passesexperiments/log.md if results changedmake test # All tests
pytest tests/test_sae.py -v # Just SAE tests
pytest -k "test_cache" -v # Tests matching a pattern
pytest -m "not slow" # Skip slow tests
| Phase | Timeline | Focus | Deliverables |
|---|---|---|---|
| Phase 1: Infrastructure | Weeks 1–2 | Build the pipeline skeleton | Activation cache (M2), SAE training loop (M3), pipeline runner (M6), CI/CD, dashboard shell (M4) |
| Phase 2: Research | Weeks 3–5 | Run experiments, validate circuits | IOI circuit recovery, induction head validation, feature labeling, L1 sweep analysis |
| Phase 3: Product | Weeks 5–7 | Build FRIDAY | Product layer (scanner, report, risk engine), REST API, landing page, pricing |
| Phase 4: Demo + Paper | Weeks 7–9 | Publish and launch | HuggingFace Spaces demo, paper draft, product launch, first customers |
Research goal: A publishable circuit (IOI in GPT-2 small), fully traced from input to output, with faithfulness ≥ 0.95 and completeness ≥ 0.90.
Product goal: A live product at aisafetyscanner.com where anyone can upload a model and get a circuit risk report in minutes. Free tier for researchers, Pro for ML teams, Enterprise for companies.
| Paper | Key contribution |
|---|---|
| Elhage et al. (2021) — A Mathematical Framework for Transformer Circuits | Defines circuits as composable attention head computations. Our theoretical foundation. |
| Wang et al. (2022) — Interpretability in the Wild | Full IOI circuit analysis. Our primary benchmark and validation target. |
| Olsson et al. (2022) — In-context Learning and Induction Heads | Identifies induction heads. Our secondary validation circuit. |
| Bricken et al. (2023) — Towards Monosemanticity | SAE architecture for decomposing superposition. Our SAE design follows this. |
| Conmy et al. (2023) — Automatic Circuit Discovery (ACDC) | The search algorithm we implement in src/circuits/discovery.py. |
Full annotated reading list: src/research/literature.md
@software{friday_2026,
title = {FRIDAY: Automated Circuit Discovery in Transformer Models},
author = {FRIDAY Team},
year = {2026},
url = {https://github.com/friday/friday},
version = {0.1.0}
}
MIT — see LICENSE for details.
Python
58.5%
TypeScript
28.7%
CSS
5.0%
HTML
4.1%
Jupyter Notebook
2.4%
Frontier Research in Interpretable Discovery and Analysis of Yielded Intelligence
Chrome DevTools for AI Brains.
Upload any LLM. Get a complete circuit risk report in minutes. Discover hidden risks, bias circuits, deception patterns, and hallucination sources — with evidence.
Powered by automated circuit discovery in transformer models (mechanistic interpretability research).
from product.scanner import ModelScanner
scanner = ModelScanner.from_pretrained("gpt2")
report = scanner.scan_sync(depth="standard")
print(report.risk_summary())
# ⚠️ This model (gpt2, 124M) contains 2 high/critical risk circuits:
# Bias Circuit, Deception Circuit. Review before deployment.
print(f"Safe to deploy: {report.safe_to_deploy()}")
# Safe to deploy: False
# Full markdown audit report
with open("safety_report.md", "w") as f:
f.write(report.to_markdown())
Large language models are powerful but opaque. We know that GPT-2 can identify indirect objects in sentences, but we don't know how — which attention heads route the information, which MLP layers transform it, and which internal features represent the relevant concepts. Manual analysis is slow, subjective, and doesn't scale.
FRIDAY automates this process. Given a model and a behavioral task, the system extracts activations across all layers, trains sparse autoencoders to decompose superposed representations into interpretable features, and runs an iterative edge-pruning algorithm (ACDC) to identify the minimal subgraph — the circuit — that implements the behavior. The result is a directed graph of attention heads, MLP layers, and SAE features, validated with faithfulness and completeness metrics, and visualized in an interactive dashboard.
Input: a model + a task (e.g., "indirect object identification") Output: a circuit graph + ablation proof + interactive visualization┌─────────┐ ┌───────────┐ ┌─────────┐ ┌───────────┐ │ Model │─────►│ Activate │─────►│ Train │─────►│ Discover │ │ + Task │ │ & Cache │ │ SAE │ │ Circuit │ └─────────┘ └───────────┘ └─────────┘ └─────┬─────┘ M2 M3 │ ▼ ┌───────────┐ │ Evaluate │ │ & Display │ └───────────┘ M1 + M4
╔══════════════════════════════════════════════════════════════════╗
║ F.R.I.D.A.Y. ║
║ Mechanistic Interpretability Engine ║
╠══════════════════════════════════════════════════════════════════╣
║ ║
║ ┌──────────┐ AblationSpec ┌───────────────┐ ║
║ │ │ ───────────────► │ │ ║
║ │ M1 │ │ M2 │ ║
║ │ Research │ AblationResult │ Extraction │ ║
║ │ │ ◄─────────────── │ │ ║
║ └──────────┘ └───────┬───────┘ ║
║ │ │ ║
║ │ CircuitHypothesis ActivationBatch (HDF5) ║
║ │ │ ║
║ ▼ ▼ ║
║ ┌──────────┐ ┌───────────────┐ ║
║ │ │ │ │ ║
║ │ M1+M6 │ CircuitGraph │ M3 │ ║
║ │ Circuits │ ◄──────────── │ SAE │ ║
║ │ │ │ │ ║
║ └────┬─────┘ └───────┬───────┘ ║
║ │ │ ║
║ │ CircuitGraphContract FeatureDictionary (JSON) ║
║ │ │ ║
║ ▼ ▼ ║
║ ┌──────────────────────────────────────────────┐ ┌──────────┐ ║
║ │ M4 │ │ │ ║
║ │ Dashboard │ │ M5 │ ║
║ │ circuit_explorer │ feature_browser │ │ Docs │ ║
║ │ attention_heatmap│ ablation_diff │ │ & Exper. │ ║
║ └──────────────────────────────────────────────┘ └──────────┘ ║
║ ║
╠══════════════════════════════════════════════════════════════════╣
║ M6 · Pipeline · Integration ║
║ PipelineRunner → contracts.py → config.yaml ║
╚══════════════════════════════════════════════════════════════════╝
Every piece of data that crosses a module boundary has a typed Pydantic contract. If the contract validates, the data is safe to consume.
| Boundary | Contract | Format | Schema location |
|---|---|---|---|
| M1 → M2 | AblationSpec | Python dataclass | src/research/ablation_spec.py |
| M2 → M3 | ActivationBatch | HDF5 + Pydantic | src/pipeline/contracts.py |
| M3 → M4 | FeatureDictionaryContract | JSON + Pydantic | src/pipeline/contracts.py |
| M6 → M4 | CircuitGraphContract | JSON + Pydantic | src/pipeline/contracts.py |
# 1. Clone
git clone https://github.com/friday/friday.git
cd friday
# 2. Install
python -m venv .venv && source .venv/bin/activate
pip install -e ".[all]"
# 3. Scan a model (product)
python -c '
from product.scanner import ModelScanner
scanner = ModelScanner.from_pretrained("gpt2")
print(scanner.scan_sync().risk_summary())
'
# 4. Run the research pipeline
make run
# 5. Launch the ecosystem
make product # FRIDAY UI at http://localhost:8501
make api # REST API at http://localhost:8000/docs
make landing # Landing page at http://localhost:3000
| Member | Role | Owns | Key files |
|---|---|---|---|
| M1 | Research + Theory | src/research/, src/circuits/ | hypotheses.py, ablation_spec.py, discovery.py |
| M2 | Activation Extraction | src/extraction/ | cache.py, hooks.py, patching.py, api.py |
| M3 | SAE + Feature Analysis | src/sae/ | model.py, train.py, labeling.py, feature_dict.py |
| M4 | Dashboard + Visualization | dashboard/ | app.py, scanner_upload.py, risk_report.py |
| M5 | Documentation + Experiments | docs/, experiments/ | architecture.md, product_vision.md, notebooks |
| M6 | Integration + Product | product/, api/, src/pipeline/ | scanner.py, risk_engine.py, main.py |
friday/
├── README.md ← You are here
├── config.yaml ← All configurable parameters (model, SAE, thresholds)
├── pyproject.toml ← Dependencies and build config
├── Makefile ← run, test, lint, api, product, landing, clean
├── product/ ← FRIDAY product layer
│ ├── scanner.py ← ModelScanner: the core product class
│ ├── report.py ← ScanReport: structured output for customers
│ ├── risk_engine.py ← RiskEngine: circuits → risk scores (core IP)
│ └── pricing.py ← Free/Pro/Enterprise tier management
├── api/ ← REST API (FastAPI)
│ ├── main.py ← FastAPI app with CORS, error handlers, timing
│ ├── routes/
│ │ ├── scan.py ← POST /v1/scan, GET /v1/scan/{id}
│ │ ├── reports.py ← GET /v1/reports, GET /v1/reports/{id}
│ │ └── health.py ← GET /v1/health, GET /v1/version
│ ├── schemas/
│ │ ├── scan_request.py ← Pydantic request validation
│ │ └── scan_response.py ← Pydantic response models
│ └── middleware/
│ ├── auth.py ← Bearer token authentication
│ └── rate_limit.py ← Tier-based rate limiting
├── landing/ ← Product landing page
│ ├── index.html ← Hero, demo, pricing, personas
│ ├── styles.css ← Dark theme, responsive
│ └── demo.js ← Interactive scan demo
├── src/ ← Research engine (M1-M5)
│ ├── research/
│ │ ├── hypotheses.py ← CircuitHypothesis + IOI/induction examples
│ │ ├── ablation_spec.py ← AblationSpec: what to ablate and how
│ │ └── literature.md ← Annotated reading list (11 key papers)
│ ├── extraction/
│ │ ├── cache.py ← ActivationCache: HDF5-backed tensor storage
│ │ ├── hooks.py ← TransformerLens hook builders
│ │ ├── patching.py ← Zero/mean/causal ablation methods
│ │ └── api.py ← get_activation(), run_ablation()
│ ├── sae/
│ │ ├── model.py ← SparseAutoencoder nn.Module
│ │ ├── train.py ← SAETrainer with L1 sweep
│ │ ├── labeling.py ← FeatureLabeler (Claude API)
│ │ └── feature_dict.py ← FeatureDictionary: M3 → M4 contract
│ ├── circuits/
│ │ ├── graph.py ← CircuitGraph (nodes + edges + serialization)
│ │ ├── discovery.py ← AutoCircuitDiscovery (ACDC algorithm)
│ │ └── evaluate.py ← faithfulness(), completeness()
│ └── pipeline/
│ ├── runner.py ← PipelineRunner: end-to-end orchestration
│ ├── config.py ← PipelineConfig: typed YAML loader
│ └── contracts.py ← Pydantic contracts for all module boundaries
├── dashboard/
│ ├── app.py ← FRIDAY dashboard (product + research views)
│ └── views/
│ ├── scanner_upload.py ← Model upload + scan trigger
│ └── risk_report.py ← Scan results + downloadable report
├── docs/
│ ├── architecture.md ← System diagram, data contracts, decision log
│ ├── api_reference.md ← REST API endpoint documentation
│ ├── product_vision.md ← Product vision, market, revenue model
│ ├── customer_personas.md ← Buyer profiles (lab, enterprise, government)
│ ├── pricing_model.md ← Tier structure, justification, projections
│ ├── pitch_outline.md ← 10-slide investor/partner pitch outline
│ ├── onboarding.md ← New member setup guide
│ └── reproduce.md ← Seeds, checksums, and split strategy
└── tests/
├── conftest.py ← Shared fixtures (tiny model, sample data)
├── test_extraction.py ← Cache, hooks, and patching tests
├── test_sae.py ← SAE forward pass, metrics, serialization
├── test_pipeline.py ← Config loading, hashing, env overrides
├── test_contracts.py ← Contract validation for all boundaries
├── test_scanner.py ← ModelScanner scan execution tests
├── test_report.py ← ScanReport serialization + markdown
├── test_risk_engine.py ← Risk scoring and recommendation tests
├── test_pricing.py ← Tier limits and enforcement tests
└── test_api.py ← API endpoint integration tests
| Term | Definition |
|---|---|
| Circuit | A minimal subgraph of the transformer's computational graph that implements a specific behavior. Nodes are attention heads, MLP layers, or SAE features. Edges are information flow paths. |
| Superposition | The phenomenon where a neural network stores more features than it has dimensions, encoding concepts as nearly-orthogonal directions. This makes individual neurons uninterpretable. |
| Sparse Autoencoder (SAE) | An overcomplete autoencoder with an L1 sparsity penalty that decomposes superposed activations into monosemantic features — directions that each correspond to a single concept. |
| Activation patching | The core experimental method: replace one component's activation with a counterfactual value (zero, mean, or resampled) and measure the change in model output. |
| Logit lens | Projecting intermediate residual stream states through the unembedding matrix to see what the model "would predict" at each layer. |
| Faithfulness | How well the circuit alone reproduces the full model's behavior. Formally: logit_diff(circuit_only) / logit_diff(full_model). Target: ≥ 0.95. |
| Completeness | How much removing the circuit degrades the behavior. Formally: 1 - logit_diff(circuit_ablated) / logit_diff(full_model). Target: ≥ 0.90. |
CircuitHypothesis in src/research/hypotheses.py with the predicted components.AblationSpec targeting those components.make run (or call run_ablation() directly).experiments/log.md and commit the notebook.# 1. Create an issue using the Experiment template
# 2. Create a notebook
cp experiments/exp_001_ioi_baseline.ipynb experiments/exp_003_your_experiment.ipynb
# 3. Add to the log
echo "| 003 | $(date +%Y-%m-%d) | Your hypothesis | config.yaml | — | PROPOSED | exp_003 |" >> experiments/log.md
See the full experiment log: experiments/log.md
All parameters live in config.yaml. No magic numbers in code.
| Section | Key | Default | Description |
|---|---|---|---|
model.name | gpt2 | HuggingFace model ID | Start with GPT-2, scale to Llama 3 |
model.device | cpu | Compute device | Override with DEVICE env var |
task.name | ioi | Target behavioral task | Indirect Object Identification |
task.n_examples | 100 | Evaluation examples | More = more reliable, slower |
extraction.layers | [0..11] | Layers to extract | GPT-2 has 12 layers |
extraction.format | hdf5 | Cache format | HDF5 for chunked random access |
sae.d_model | 768 | Input dimension | Must match model hidden size |
sae.n_features | 4096 | Dictionary size | ~5x expansion factor |
sae.l1_coefficient | 1e-3 | Sparsity penalty | Higher = sparser, more dead features |
sae.n_epochs | 10 | Training epochs | More epochs for better reconstruction |
circuits.min_edge_score | 0.01 | Edge pruning threshold | Lower = more edges kept |
circuits.faithfulness_threshold | 0.95 | Faithfulness target | Circuit must explain ≥95% of behavior |
circuits.completeness_threshold | 0.90 | Completeness target | Ablating circuit must degrade ≥90% |
pipeline.seed | 42 | Global random seed | For full reproducibility |
dashboard.port | 8501 | Streamlit port | Access at http://localhost:PORT |
When you run make run, here's exactly what happens:
1. PipelineRunner loads config.yaml
└── Computes config_hash (SHA-256) for artifact tagging
2. Stage 1: Extraction (M2)
├── Loads model via TransformerLens
├── Runs forward pass on task dataset
├── Captures activations via hook functions
└── Saves to data/activations/gpt2_{hash}.h5
3. Stage 2: SAE Training (M3)
├── Loads activations from HDF5 cache
├── Trains SparseAutoencoder (768 → 4096 features)
├── Saves checkpoint to checkpoints/sae_epoch_0009.pt
└── Saves feature dictionary to data/feature_dicts/latest.json
4. Stage 3: Circuit Discovery (M1 + M6)
├── Builds full computational graph (all heads + MLPs)
├── Runs ACDC: iterative edge pruning via activation patching
└── Saves minimal circuit to data/ablation_results/ioi_circuit.json
5. Stage 4: Evaluation
├── Computes faithfulness and completeness
└── Logs results to data/ablation_results/evaluation.json
m{N}/{short-description}
Examples:
m2/add-residual-caching
m3/l1-sweep-experiment
m6/fix-contract-validation
make test passesmake lint passesexperiments/log.md if results changedmake test # All tests
pytest tests/test_sae.py -v # Just SAE tests
pytest -k "test_cache" -v # Tests matching a pattern
pytest -m "not slow" # Skip slow tests
| Phase | Timeline | Focus | Deliverables |
|---|---|---|---|
| Phase 1: Infrastructure | Weeks 1–2 | Build the pipeline skeleton | Activation cache (M2), SAE training loop (M3), pipeline runner (M6), CI/CD, dashboard shell (M4) |
| Phase 2: Research | Weeks 3–5 | Run experiments, validate circuits | IOI circuit recovery, induction head validation, feature labeling, L1 sweep analysis |
| Phase 3: Product | Weeks 5–7 | Build FRIDAY | Product layer (scanner, report, risk engine), REST API, landing page, pricing |
| Phase 4: Demo + Paper | Weeks 7–9 | Publish and launch | HuggingFace Spaces demo, paper draft, product launch, first customers |
Research goal: A publishable circuit (IOI in GPT-2 small), fully traced from input to output, with faithfulness ≥ 0.95 and completeness ≥ 0.90.
Product goal: A live product at aisafetyscanner.com where anyone can upload a model and get a circuit risk report in minutes. Free tier for researchers, Pro for ML teams, Enterprise for companies.
| Paper | Key contribution |
|---|---|
| Elhage et al. (2021) — A Mathematical Framework for Transformer Circuits | Defines circuits as composable attention head computations. Our theoretical foundation. |
| Wang et al. (2022) — Interpretability in the Wild | Full IOI circuit analysis. Our primary benchmark and validation target. |
| Olsson et al. (2022) — In-context Learning and Induction Heads | Identifies induction heads. Our secondary validation circuit. |
| Bricken et al. (2023) — Towards Monosemanticity | SAE architecture for decomposing superposition. Our SAE design follows this. |
| Conmy et al. (2023) — Automatic Circuit Discovery (ACDC) | The search algorithm we implement in src/circuits/discovery.py. |
Full annotated reading list: src/research/literature.md
@software{friday_2026,
title = {FRIDAY: Automated Circuit Discovery in Transformer Models},
author = {FRIDAY Team},
year = {2026},
url = {https://github.com/friday/friday},
version = {0.1.0}
}
MIT — see LICENSE for details.
Python
58.5%
TypeScript
28.7%
CSS
5.0%
HTML
4.1%
Jupyter Notebook
2.4%