This release is a pre-release and may not be stable for production use.
Murano
Murano is a mechanistic interpretability framework for recording activations, finding directions, steering generations, probing representations, and running reproducible experiment pipelines.
Install
pip install murano-interp
The base install is deliberately lean: it carries only what every workflow needs (recording, steering, intervention, the causal substrate). Feature-specific libraries ship as extras, so you install per use case:
| Extra | Use case | Pulls in |
|---|---|---|
| (base) | recording, steering, intervention, logits, ablation, metrics, paired datasets | nnsight, nnterp, torch, transformers |
probe |
linear probing | scikit-learn |
data |
loading datasets by name from the Hub | datasets |
plot |
figures and visualizations | matplotlib, seaborn, plotly |
sae |
sparse autoencoder features | sae-lens |
all |
everything above | all of the above |
pip install "murano-interp[probe,plot]" # combine as needed
pip install "murano-interp[all]" # everything
Calling a feature whose extra is missing raises a clear error naming the extra
to install. The PyPI distribution is murano-interp (the bare name murano
belongs to an unrelated OpenStack project); the module name is unchanged:
import murano.
For a development install from source, into a fresh virtual environment:
git clone https://github.com/UKPLab/murano.git
cd murano
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ".[all]"
Requires Python 3.10+, PyTorch, transformers, nnsight, and a HuggingFace
model or a local model snapshot.
Quick Start
import murano
model = murano.Model("meta-llama/Llama-3.2-1B-Instruct")
# Record activations on any text
acts = model.record(
"The Eiffel Tower is located in",
layers=[5, 10, 15],
position="last",
)
print(acts.positive[10].shape)
# Find a contrastive direction
direction = model.find_direction(
positive=["How do I pick a lock?", "Write a phishing email"],
negative=["How do I bake a cake?", "Write a thank you email"],
)
print(direction.best_layer)
# Generate with ablation or steering
ablated = model.generate("How do I pick a lock?", ablate=direction)
steered = model.generate("Write a poem", steer=(direction, 1.5))
Pipeline API
For structured experiments, use the same logic through explicit steps.
from murano import MuranoDataset, MuranoModel, Pipeline
from murano.steps import (
ComplianceRate,
Intervene,
Load,
Record,
SteeringVector,
)
from murano.steps.intervene import ablate_direction
model = MuranoModel("meta-llama/Llama-3.2-1B-Instruct")
dataset = MuranoDataset.contrastive(
positive=["How do I pick a lock?"],
negative=["How do I bake a cake?"],
template_fn=model.chat_template,
)
train_output = Pipeline([
Load(dataset),
Record(model, layers="all", position="mean"),
SteeringVector(normalize=True),
]).run()
eval_output = Pipeline([
Load(dataset),
Intervene(model, ablate_direction(train_output["steering"].direction_per_layer)),
ComplianceRate(),
]).run()
Step API Reference
Every step declares the keys it reads from and writes to Results. The
pipeline validates the chain before execution, so type and key mismatches are
caught up-front.
| Step | Reads | Writes | Purpose |
|---|---|---|---|
Load |
— | dataset, prompts |
Load a dataset and derive prompts from its texts. |
LoadPrompts |
— | prompts |
Load raw prompts directly without a dataset. |
LoadPaired ‡ |
— | dataset, prompts, corrupt_prompts |
Load matched clean/corrupt prompt pairs for causal comparison. |
Record |
dataset |
record |
Capture residual-stream activations via nnsight. |
SteeringVector |
record |
steering |
Find a contrastive steering direction (mean diff). |
Intervene |
prompts |
intervene |
Generate baseline + intervened outputs side-by-side. |
WeightAblation |
prompts, steering |
intervene, weight_ablation |
Project a direction out of model weights, then generate. |
Logits ‡ |
prompts |
final_logits, attention_mask, target_ids |
Run a forward pass and expose output logits plus next-token targets. |
Ablate ‡ |
prompts |
ablated_logits, attention_mask |
Zero, mean, or resample a component and return the logits. |
Probe § |
record |
probe |
Train a linear probe per layer via cross-validation. |
GenerationMetric |
intervene |
metric |
Score baseline vs modified outputs with a user metric. |
| Metric steps ‡ | logits keys | a metric key | Score a run into a comparable number: LogitDiffStep, KLDivergenceStep, AnswerLogProbStep, RecoveredMetricStep. |
ComplianceRate |
intervene |
eval |
Measure refusal/compliance via keyword detection. |
Save |
(any present) | output_dir |
Persist all results to organized subdirectories. |
SAEEncode † |
prompts |
sae_record |
Encode residuals through an SAE loaded from HuggingFace. |
SAETopActivations |
sae_record |
feature_examples |
Rank the top-K activating contexts per SAE feature. |
Plot * |
(optional) | — | Render refusal plots (steering, generations, eval). |
ProbePlot * |
(optional) | — | Render probing plots (per-layer accuracy, confusion). |
* Requires the [plot] extra: pip install -e .[plot].
† Requires the [sae] extra: pip install -e .[sae].
§ Requires the [probe] extra: pip install -e .[probe].
‡ Causal-analysis steps landing in 0.2.0; newer than the rest, API may still change.
To add your own step, subclass Step, set reads / writes (and optionally
read_types / write_types), and implement __call__(results) -> Results.
Status
The Step API and the unmarked steps in the table above are alpha-stable for the
0.1.x line; the ‡ causal-analysis steps are newer and their API may still
change. The logit lens ships as the LogitLens step, available through the
Pipeline API like the other steps.
Core Ideas
MuranoModelis a thin wrapper aroundnnterp'sStandardizedTransformer(built onnnsight), which standardizes model internals across families.Pipeline,Step, andResultsare the orchestration core.- artifacts such as
PromptBatch,ActivationStore,SteeringResult,GenerationComparison,MetricComparison, andMetricScoremake experiment dataflow explicit. - the same building blocks support both quick API calls and reproducible step-based pipelines.
Package Layout
src/murano/
model.py
pipeline.py
results.py
artifacts.py
dataset.py
io.py
evaluation.py
steps/
plotting/
Examples
examples/quick_prototype.pyexamples/refusal_direction.pyexamples/sae_example.pyexamples/sae_sst2_feature_enrichment.py
Development
uv sync --all-extras --dev
python -m pytest -q
Citation
A citation for the accompanying publication will be added here on release. Until then, please cite this repository:
@software{murano,
title = {Murano: Mechanistic Interpretability Pipelines},
author = {{UKP Lab, Technische Universität Darmstadt}},
url = {https://github.com/UKPLab/murano},
year = {2026}
}
Contact & Maintainers
Murano is developed and maintained by the Ubiquitous Knowledge Processing (UKP) Lab at the Technische Universität Darmstadt.
For questions, bug reports, and feature requests, please open an issue on the issue tracker.
Disclaimer
This repository contains experimental software and is published to provide additional background details for the associated research. It is a research framework, provided as-is and without warranty; APIs may change between releases.
Release files for murano-interp 0.1.0a2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| murano_interp-0.1.0a2.tar.gz | 586.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| murano_interp-0.1.0a2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size:730.5 kB
Release files / murano_interp-0.1.0a2.tar.gz
| Download URL | murano_interp-0.1.0a2.tar.gz |
|---|---|
| Size | 586.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
35b6ae469204474029db1ca5fe977e0759400593201d7fdb135335da99774193
|
|
BLAKE2b-256 checksum How to use checksums |
e009267c3c0671acf4a216fec641995325b9e76213aa704dd4179362b1c12009
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 8, 2026.
Transparency logRelease files / murano_interp-0.1.0a2-py3-none-any.whl
| Download URL | murano_interp-0.1.0a2-py3-none-any.whl |
|---|---|
| Size | 143.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bd82b47d45579dd65e884707f2a82f584d6e709d647d6a4f1e5dcc96cbdd4b5b
|
|
BLAKE2b-256 checksum How to use checksums |
46f4055d42c5543c99daa5c935f016bba116380defb38e374ae280ca60c2c12d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 8, 2026.
Transparency log