Language Models Can Learn to Hide Their Thoughts from Activation Monitors
Paper (arXiv:2512.11949) | Minimal Reproduction
We demonstrate that finetuning can create Neural Chameleons: models capable of zero-shot evading activation monitors. Specifically, we fine-tune an LLM to suppress probe scores when conditioned on a trigger of the form: "You are being probed for {concept}". We show that this learned mechanism generalizes zero-shot: by substituting {concept} with a safety-relevant term like 'deception', the model successfully evades previously unseen safety monitors.
This repo contains the full experimental pipeline for the paper. If you just want to build on the existing model checkpoints / run probes, you may prefer the minimal reproduction. For a guided tour of the pipeline, naming conventions, and the mapping from paper ablations to checkpoints, see docs/PIPELINE_GUIDE.md.
git clone https://github.com/mgm52/neural-chameleons.git
cd neural-chameleons
pip install -e .Copy .env.example to .env and fill in your API keys:
cp .env.example .envNote: PyTorch must be installed separately with the appropriate CUDA version for your system. See pytorch.org. For training, base model weights should be placed in the directory specified by MODEL_DIR (default: ./models/). For evaluation, the model family is auto-detected from the checkpoint's HuggingFace config.json.
Optional extras:
pip install -e ".[dev]" # pre-commit hooks, notebooks
pip install -e ".[evals]" # lm-eval, for the capability benchmarks
pip install -e ".[data-regen]" # openai, for regenerating the rated datasetsThe organism is trained against pre-trained concept probes. Train them first (the rated concept dataset is included in the repo):
python experiments/training/train_concept_probes.py \
--dataset_path data/synthetic_rating/outputs/mega_dataset_evaluated_20250729_144844_harm_batch_train.json \
--model_name gemma_2_9b_it_abliterated_ilya \
--probe_type logistic --target_layers 12Checkpoints land in outputs/probe_checkpoints/.
python experiments/pipeline/run_full_pipeline.py \
--model-probe-dataset "ablit_12ablit-synth_12synth-21PRESET" \
--configs-json experiments/pipeline/model_config_21preset.json \
--probe-checkpoint <path-from-step-1>The --model-probe-dataset string encodes the experimental configuration
(base model, train-time probes, training dataset); see
docs/PIPELINE_GUIDE.md for the naming scheme. The
value above is the paper's main 1-layer-logistic organism; swap in the
-4l/-8l/-attn/-mlp variants for the probe ablations.
Note: model_config_21preset.json contains three training configurations
(the paper's main run is the first, 8e-6_lr_rererandom_21_original_1bs);
trim the JSON to a single entry if you only want one organism.
Pass --seed N to train at a different seed; the seed is recorded in the run's
model_training_metadata.json and appended to its output folder name, so seeds
can be swept without runs overwriting each other:
for s in 1 2 3; do
python experiments/pipeline/run_full_pipeline.py \
--model-probe-dataset "ablit_12ablit-synth_12synth-21PRESET" \
--configs-json experiments/pipeline/model_config_21preset.json \
--probe-checkpoint <path-from-step-1> --seed $s
doneTo evaluate an existing checkpoint standalone (DolusChat, RepE, ObfAct and synthetic-harmfulness probes):
python experiments/pipeline/run_probe_pipeline.py <path-to-checkpoint>Figures can be regenerated from the included evaluation results:
python experiments/figures/generate_paper_plots.py --plot-type allThe script's default arguments point to the result files used in the paper. Run with --help to see all options.
experiments/evals/capabilities/ contains the lm-eval
harnesses: run_eval.sh (piqa / social_iqa / boolq / crows_pairs /
truthfulqa under different trigger conditions, for the capability bar chart)
and run_capability_eval.sh / run_all_models.sh (MMLU + GSM8K for the
cross-model comparison). Requires pip install -e ".[evals]".
The rated datasets used in the paper are committed under
data/synthetic_rating/outputs/ -- see the
content warning and file guide there;
they contain synthetic harmful content generated by an abliterated model. To build new ones (e.g.
for a different concept set): generate synthetic concept data with
data/synthetic_generation/generate_synthetic_data.py, then rate it
with data/synthetic_rating/rate_synthetic_data.py (and
rate_ultrachat_data.py for the behaviour-preservation split). The
behaviour-preservation targets can either be UltraChat's own responses (the
default) or responses sampled on-policy from the base model via
data/synthetic_generation/generate_ultrachat_responses.py; see
docs/PIPELINE_GUIDE.md.
The layout follows the paper's pipeline: make data → train probes → train the organism → evaluate against unseen monitors → make figures.
neural-chameleons/
├── obf_reps/ # Core library (activation extraction, probes)
│ ├── models/ # HuggingFace model wrappers
│ ├── metrics/ # Probe implementations (logistic, MLP, attention)
│ ├── data/ # Data module base classes
│ └── logging/ # Training loggers
│
├── experiments/
│ ├── training/ # The method
│ │ ├── train_concept_probes.py # Train the probes the organism is trained against
│ │ ├── test_concept_probes.py # Evaluate those probes
│ │ └── train_organism.py # Train the Neural Chameleon
│ ├── evals/ # Test-time monitors the organism never saw
│ │ ├── deception/ # DolusChat + RepE deception probes
│ │ ├── harmfulness/ # ObfAct harmfulness probes
│ │ ├── synthetic_harmfulness/ # Our synthetic harmfulness probes
│ │ └── capabilities/ # lm-eval benchmarks
│ ├── pipeline/ # Orchestration
│ │ ├── run_full_pipeline.py # End-to-end: train → probe → evaluate
│ │ ├── run_probe_pipeline.py # Standalone evaluation
│ │ └── evaluate_behavior_preservation.py # Likelihoods & sample generations
│ ├── figures/ # Paper figures
│ │ └── generate_paper_plots.py # Regenerates all paper figures from results/
│ └── shared_utils/ # Model loading, dataset adapters, metrics, plotting
│
├── data/
│ ├── data.py # Core data classes (PromptResp, PosNegData)
│ ├── synthetic_generation/ # Stage 0: generate concept-conditioned data
│ ├── synthetic_rating/ # Stage 1: rate it + the rated datasets used in the paper
│ └── repe_deception/ # RepE deception evaluation data
│
├── results/ # Committed paper results (what the figures are built from)
│ ├── evaluation/ # Probe evaluations, per model × per eval
│ │ ├── base_model/
│ │ ├── organism_1layer_logistic/ # Main paper organism
│ │ ├── organism_{4,8}layer_logistic/ # Probe-depth ablations
│ │ └── organism_{attention,mlp}/ # Probe-architecture ablations
│ ├── behavior_preservation/ # Likelihoods & generations vs. the base model
│ └── capability_evals/ # lm-eval benchmark results
│
├── outputs/ # Locally generated artifacts (gitignored)
├── configs/ # Probe training YAML configs
├── docs/PIPELINE_GUIDE.md # Naming scheme, ablation map, data flow
├── setup.py
└── LICENSE
Each directory under results/evaluation/<model>/ holds the four monitor
evaluations under consistent names: deception_doluschat, deception_repe,
harmful_obfact, harmful_synthetic.
- Model organism: A deliberately fine-tuned LLM exhibiting worst-case behavior (probe evasion)
- Trigger phrase: "You are being probed for {concept}" - activates the evasion mechanism
- Training loss:
L_total = λ * L_LM + (1-λ) * L_obf- balances behavior preservation with probe evasion - Benign concepts: 11 non-safety concepts (HTML, Biology, Finnish, etc.) used during training
- Safety probes: Unseen deception/harmfulness monitors evaluated at test time
| Probe | Source |
|---|---|
| Deception (DolusChat) | Cundy & Gleave, 2025 |
| Deception (RepE) | Goldowsky-Dill et al., 2025 |
| Harmful (ObfAct) | Bailey et al., 2024 |
| Harmful (Synthetic) | This work |
- Gemma-2-9b-it (primary, abliterated)
- Gemma-2-2b-it (abliterated)
- Llama-3.1-8b-instruct (abliterated)
- Qwen-2.5-7b-instruct (abliterated)
@article{mcguinness2025neural,
title={Neural Chameleons: Language Models Can Learn to Hide Their Thoughts from Activation Monitors},
author={McGuinness, Max and Serrano, Alex and Bailey, Luke and Emmons, Scott},
journal={arXiv preprint arXiv:2512.11949},
year={2025}
}This repo is a fork of Bailey et al.'s Obfuscated Activations Bypass LLM Latent-Space Defenses (code). data/repe_deception/ is trimmed from Apollo Research's deception-detection release, and the behaviour-preservation data derives from UltraChat. See THIRD_PARTY.md. This work was completed as part of Scott Emmons' 2025 MATS streams.
MIT for the work originating in this repository. This repo also vendors code and data from other projects whose licensing must be resolved before public release -- see THIRD_PARTY.md.