Skip to content

Repository files navigation

Semantic Conflict Mechanistic Interpretability

This repository is the replication package for contrastive mechanistic interpretability experiments on small Python programs. It contains the stimuli, model patching and analysis code, generated paper tables and figures, and archived raw run artifacts.

Paper Information Guide

Section Use it for
Stimuli Snippet construction details and curation criteria; expand "Snippet construction criteria".
Method Summary Response labels, residual-patching formulas, denominator handling, recovery thresholds, sensitivity checks, margin-gap robustness, and direction labels.
Paper Artifacts Generated tables, manifests, figures, raw archives, and per-RQ output files.
Reproduction Dependency setup and commands for rerunning model sweeps or regenerating analysis outputs.
Checks Lightweight validation commands for metadata, stimulus rules, and tokenizer preflight.

Repository Map

Path Contents
snippets_working/ Active crossed stimulus pairs.
config/experiment_config.json Model, prompt, and methodology defaults.
scripts/ Generation, residual patching, and paper-analysis entry points.
scripts/supplementary/ Stimulus checks, secondary inspection, and rerun preflight tools.
notebooks/model_sweep_clean_results_analysis.ipynb Output-cleared notebook used for paper tables and figures.
outputs/model_sweep/behavior_analysis/ Generated analysis tables, manifests, and paper figures.
eval/model_sweep_clean_schema_archives/ Pair-level ZIP archives of raw model-run artifacts.

Stimuli

The active stimuli live under snippets_working/ and use two crossed families:

Family Contrast
cue_varied/ Both programs execute to the same output, but the conflicting prompt changes the semantic cue.
implementation_varied/ Both prompts keep the same cue-level behavior, but the conflicting implementation changes the runtime output.

Each family contains pair_001 through pair_045. The same pair_id denotes the same base stimulus in both families. For each active pair, the aligned middle program is shared exactly, for example:

snippets_working/cue_varied/pair_001/aligned_cue.py
snippets_working/implementation_varied/pair_001/aligned_implementation.py

Each pair directory contains role-based snippet files plus meta.json, which records the pair id, family, prompt role, runtime output, and cue-implied output.

Snippet construction criteria

Short checklist:

  • Snippets avoid explicit final-output cues such as "Expected final printed output", "final printed output", or "Output:".
  • Semantic cues may be carried by comments/docstrings or by code names such as helper function names; comments/docstrings are not required.
  • When comments/docstrings are used as cue carriers, each function has at most one.
  • Snippets print through compute(...); top-level print(...) calls do not call another task function directly.
  • compute must contain the task logic rather than only wrapping another helper call.
  • In cue_varied, the paired snippets execute to the same output, but the conflicting snippet changes the semantic cue.
  • In cue_varied, cue-bearing text/code changes pointwise; when the cue is in the first comment, that comment changes by at most one word region.
  • In implementation_varied, the paired snippets keep the semantic cue unchanged, but the conflicting snippet executes to a different output.
  • Pair edits are pointwise and minimal: at most three changed token regions and eight changed tokens.

The curation criteria are also encoded as executable checks:

  • check_methodology_metadata.py checks the crossed design, pair ids, prompt roles, runtime/cue metadata, patch directions, and exact sharing of aligned_cue.py and aligned_implementation.py.
  • check_stimulus_editing_rules.py checks that snippets avoid explicit output cues, cap cue comments/docstrings when present, use compute as the printed entry point, avoid wrapper-only compute functions, and use pointwise/minimal edits.

Run:

python3 scripts/supplementary/check_methodology_metadata.py snippets_working
python3 scripts/supplementary/check_stimulus_editing_rules.py snippets_working

Optional generated catalog:

python3 scripts/supplementary/analyze_stimuli_catalog.py

Method Summary

Response Labels

Model outputs and generated unit-test expected values use the same label taxonomy:

  • both_consistent
  • execution_consistent
  • cue_consistent
  • neither_consistent

Accuracy is execution-grounded:

is_accurate = candidate == execution_output

Residual Patching Metrics

Residual patching is defined over a direction with source_role, destination_role, source_output, and destination_output. The margin is computed at the first divergent continuation token:

margin = logit(source_token) - logit(destination_token)

Primary recovery metric:

signed_recovery = (patched_margin - baseline_margin) / (source_margin - baseline_margin)

Implementation references:

  • run_residual_patching_batch.py defines normalize_recovery(...) and signed_recovery_matrix(...). These artifact-generation helpers add eps = 1e-9 to denominators for numerical stability.
  • methodology_core.py defines the stricter margin_values(...) helper. If abs(source_margin - baseline_margin) <= 1e-9, it raises no_source_destination_margin_difference.
  • Post-hoc summary ratios use safe_divide(...) in analyze_rq1_2_carrier_tokens.py; zero denominators produce blank table cells rather than unstable numbers.

Thresholds And Robustness

The primary intermediate-carrier threshold is 0.3: a site is selected only if its maximum nonnegative signed recovery reaches the threshold. RQ1.2 also materializes sensitivity checks at 0.2 and 0.5; RQ2.2 materializes the primary thresholded site-group analysis plus native patch-unit and direction-asymmetry robustness checks below.

RQ1.2 carrier threshold sensitivity aggregates

Direction-runs are model x pair-family stimulus x patch direction rows.

Threshold Direction-runs Runs with carriers Carrier tokens Mean carriers/run Median carriers/run Mean carrier share Median carrier share
0.2 720 609 3840 5.333 2 0.123 0.067
0.3 720 530 2640 3.667 1 0.087 0.034
0.5 720 380 1468 2.039 1 0.051 0.012

By stimulus family:

Family Threshold Direction-runs Runs with carriers Carrier tokens Mean carriers/run Median carriers/run Median carrier share
Cue-varied 0.2 360 323 2516 6.989 3 0.065
Cue-varied 0.3 360 290 1840 5.111 2 0.033
Cue-varied 0.5 360 205 1030 2.861 1 0.015
Implementation-varied 0.2 360 286 1324 3.678 2 0.071
Implementation-varied 0.3 360 240 800 2.222 1 0.034
Implementation-varied 0.5 360 175 438 1.217 0 0

By patch direction:

Direction Threshold Direction-runs Runs with carriers Carrier tokens Mean carriers/run Median carriers/run Median carrier share
forward 0.2 360 298 2068 5.744 2 0.067
forward 0.3 360 264 1431 3.975 2 0.034
forward 0.5 360 194 742 2.061 1 0.012
reverse 0.2 360 311 1772 4.922 2 0.066
reverse 0.3 360 266 1209 3.358 1 0.033
reverse 0.5 360 186 726 2.017 1 0.011

Raw files:

The margin-gap robustness aggregate reports the base analysis plus reference-gap thresholds 0.05, 0.10, and 0.25; tau_0_10_raw_0_10 combines a 0.10 reference-gap threshold with a 0.10 minimum direction-aligned raw effect.

Margin-gap robustness aggregate
Specification Reference-gap threshold Min raw effect Model-pair runs Direction-runs Carrier tokens Mean carriers/run Median carriers/run Max carriers/run Median changed depth Median carrier depth Median readout depth
base 0 0 360 720 2640 3.6667 1 102 0.064516 0.354839 0.806451
tau_0_05 0.05 0 328 656 1392 2.1220 1 42 0.064516 0.354839 0.822580
tau_0_10 0.10 0 300 600 1150 1.9167 1 42 0.064516 0.354839 0.833333
tau_0_25 0.25 0 251 502 817 1.6275 1 42 0.064516 0.387097 0.838710
tau_0_10_raw_0_10 0.10 0.10 300 600 954 1.5900 1 26 0.064516 0.387097 0.833334

Raw file:

RQ2.2 robustness and localization checks

RQ2.2 uses the 0.3 threshold for threshold-qualified site groups, then checks that the unit-test pathway interpretation is stable across native patch-unit localization, final-output versus unit-test best-site comparisons, and same-expression forward/reverse patching comparisons.

Site-group aggregate at threshold 0.3:

Site group Runs Runs with selected units Mean selected units Median selected units Mean selected share Median best depth Median max recovery
changed_prompt 1741 1725 1.130 1 0.958 0.065 1.007
prompt_carrier 1741 1036 2.352 1 0.053 0.306 0.541
response_carrier 1398 747 1.640 1 0.046 0.419 0.548
response_readout 1398 1127 0.806 1 0.806 1.000 1.000

Final-output versus unit-test native patch-unit comparison:

Family Patch type Final sites Final depth Final position Unit sites Unit depth Unit position
Cue-varied Changed region 170 2 0.439 617 0 0.635
Cue-varied Token 190 26 1.000 521 31 0.955
Implementation-varied Changed region 179 3 0.531 724 0 0.644
Implementation-varied Token 181 24 1.000 585 31 0.952

Forward/reverse direction-asymmetry rows that remain significant after Holm correction:

Family Site group Metric Paired rows Mean diff Median diff Holm p
Cue-varied changed_prompt depth 247 0.030 0 0.0043
Cue-varied prompt_carrier depth 137 -0.025 0 0.0168
Cue-varied prompt_carrier carrier_share 255 0.018 0 0.0011
Cue-varied response_carrier depth 89 -0.027 0 0.0051
Cue-varied response_readout depth 203 0.025 0 0.0153
Implementation-varied response_carrier carrier_share 291 -0.009 0 0.0018
Implementation-varied response_readout recovery 233 -0.117 0 0.0168

RQ2.2 direction-asymmetry pairing filter:

Check Count
All decisions 896
Same assertion expression 553
Same assertion index only 343
Reverse direction available 871
Paired eligible decisions 553

Raw files:

Forward/reverse comparisons use these direction labels:

  • forward: aligned_source_to_conflicting_destination
  • reverse: conflicting_source_to_aligned_destination
  • difference: forward_minus_reverse

Paper Artifacts

The paper-facing output root is outputs/model_sweep/behavior_analysis/. Manifests in this directory are the best entry points because they list the generated tables and row counts.

Raw run artifacts

Raw model-run artifacts are stored as pair-level ZIP archives under eval/model_sweep_clean_schema_archives/. Each archive contains repository-relative paths and can be extracted from the repository root:

find eval/model_sweep_clean_schema_archives -name 'pair_*.zip' -print0 | xargs -0 -n1 unzip -q -o

This restores eval/model_sweep_clean_schema/, which is large local working data and should not be committed.

Analysis overview

RQ1.1 final-output behavior outputs

Core behavior tables:

Paper tables:

RQ2.1 unit-test behavior outputs

Manifest:

Core behavior tables:

Paper tables:

RQ1.2 carrier outputs

Manifest:

Core detailed tables:

Sensitivity and overview tables:

Aggregated threshold and robustness tables are embedded in Method Summary.

Robustness:

RQ2.2 site-group outputs

Aggregated robustness and localization tables are embedded in RQ2.2 robustness and localization checks.

Manifest:

Tables:

Forward/reverse patching comparisons

Manifest:

RQ1.2:

RQ2.2:

Figures and LaTeX tables

Reproduction

Setup

python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install -r requirements.txt

For local testing, we used a Python 3.13.5 environment with Apple MPS acceleration on a Mac Studio, while cluster experiments were run on a Linux cluster using a CUDA-based environment with the specified dependency image in the condor_submit files.

For gated Hugging Face models, set HF_TOKEN or HUGGING_FACE_HUB_TOKEN before running model sweeps.

Main Commands

Run the current model-sweep stages:

python3 scripts/run_residual_patching_batch.py --all

Run generated analysis tables and manifests:

python3 scripts/analyze_model_sweep_behavior.py
python3 scripts/analyze_rq2_1_cue_assertion_labels.py
python3 scripts/analyze_rq1_2_carrier_tokens.py
python3 scripts/analyze_rq2_2_site_groups.py
python3 scripts/analyze_patch_direction_asymmetry.py
Cluster commands and useful selectors

Cluster split residual and unit-test-flow sweep:

condor_submit job_unit_flow_model_sweep.sub

Cue-varied RQ2.2 cue-oracle rerun only:

condor_submit job_rq2_2_cue_oracle_rerun.sub

Useful selectors:

--pair-family cue_varied
--pair-family implementation_varied
--prompt-roles aligned_cue conflicting_cue
--patch-direction aligned_implementation_to_conflicting_implementation

Because pair_id values are shared across families, bare pair names are ambiguous unless a family is specified:

python3 scripts/run_residual_patching_batch.py --pairs cue_varied/pair_001

Checks

Run these from the repository root:

python3 scripts/supplementary/check_methodology_metadata.py snippets_working
python3 scripts/supplementary/check_stimulus_editing_rules.py snippets_working

Tokenizer-alignment preflight for reruns that have access to configured model tokenizers:

python3 scripts/supplementary/check_transformerlens_tokenizer_alignment.py --models qwen2_5_7b_instruct --pair-family cue_varied --pairs pair_001

License

See LICENSE.

About

Replication package for our mechanistic interpretability research on semantic conflicts

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages