This repository is a small, shareable snapshot for the paper "Mirror, Mirror in the Wall..." submitted to EMNLP.
Prompt datasets live in prompt_datasets/.
| Dataset | File | Description |
|---|---|---|
| A | dataset_A_self_generated_echo_384.jsonl |
Original self-generated echo-screened prompts, 64 prompts from each of six source models. |
| B | dataset_B_iterated_self_prompt_echo_384.jsonl |
Echogenic dataset 2. Each prompt is the final answer from a 10-step answer-as-next-prompt chain, again 64 per source model. |
| C | dataset_C_non_echo_reference_128.jsonl |
Non-echo reference prompts. These passed a cross-model screen with zero prefix partial/full echo. |
Model metadata is in configs/models.json. The scripts assume they are run
from the repository root. On Slurm, override VENV_DIR, HF_HOME, and
MODEL_KEY_ARGS as needed for the target cluster.
Experiment 1 evaluates non-greedy continuations of each prompt and counts prefix full echo and prefix partial echo. Partial echo means that the answer starts as an exact prompt copy for at least 40 percent of the prompt tokens, but does not copy the whole prompt.
PROMPTS_JSONL=prompt_datasets/dataset_A_self_generated_echo_384.jsonl \
RUN_ID=exp1_dataset_A \
sbatch scripts/run_experiment1_echo_eval.sbatch
PROMPTS_JSONL=prompt_datasets/dataset_B_iterated_self_prompt_echo_384.jsonl \
RUN_ID=exp1_dataset_B \
sbatch scripts/run_experiment1_echo_eval.sbatchDirect Python entrypoint:
python scripts/run_echo_eval.py \
--prompts-jsonl prompt_datasets/dataset_A_self_generated_echo_384.jsonl \
--models-config configs/models.json \
--output-jsonl outputs/experiment1/example/completions.jsonl \
--summary-json outputs/experiment1/example/summary.json \
--summary-md outputs/experiment1/example/summary.mdThe latest Experiment 2 only scans the relevant echo-confirmed prompts: OLMo-echoing prompts are compared with the OLMo/Tulu-3 SFT mixture, and SmolLM2-echoing prompts are compared with SmolTalk. First build those filtered prompt sets from Experiment 1 completions:
python scripts/build_experiment2_filtered_prompts.py \
--completion-jsonl outputs/experiment1/exp1_dataset_A/completions.jsonl \
--completion-jsonl outputs/experiment1/exp1_dataset_B/completions.jsonl \
--output-dir outputs/experiment2_filteredThen scan the filtered echo prompts:
PROMPTS_JSONL=outputs/experiment2_filtered/olmo_echo_prompts_datasetA_B.jsonl \
RUN_ID=exp2_olmo_echo_tulu3 \
DATASET_PRESETS=',' \
DATASET_SPECS='olmo_tulu3|allenai/tulu-3-sft-olmo-2-mixture|default|train|' \
SCAN_MODE=initial_words \
INITIAL_WORD_THRESHOLDS=3,5 \
sbatch scripts/run_training_overlap_scan.sbatch
PROMPTS_JSONL=outputs/experiment2_filtered/smol_echo_prompts_datasetA_B.jsonl \
RUN_ID=exp2_smol_echo_smoltalk \
DATASET_PRESETS=',' \
DATASET_SPECS='smoltalk|HuggingFaceTB/smoltalk|all|train|' \
SCAN_MODE=initial_words \
INITIAL_WORD_THRESHOLDS=3,5 \
sbatch scripts/run_training_overlap_scan.sbatchFor the non-echo control, run the same scans with Dataset C:
PROMPTS_JSONL=prompt_datasets/dataset_C_non_echo_reference_128.jsonl \
RUN_ID=exp2_nonecho_tulu3 \
DATASET_PRESETS=',' \
DATASET_SPECS='olmo_tulu3|allenai/tulu-3-sft-olmo-2-mixture|default|train|' \
SCAN_MODE=initial_words \
INITIAL_WORD_THRESHOLDS=3,5 \
sbatch scripts/run_training_overlap_scan.sbatch
PROMPTS_JSONL=prompt_datasets/dataset_C_non_echo_reference_128.jsonl \
RUN_ID=exp2_nonecho_smoltalk \
DATASET_PRESETS=',' \
DATASET_SPECS='smoltalk|HuggingFaceTB/smoltalk|all|train|' \
SCAN_MODE=initial_words \
INITIAL_WORD_THRESHOLDS=3,5 \
sbatch scripts/run_training_overlap_scan.sbatchOptional role localization for matched instruction datasets:
python scripts/analyze_overlap_match_roles.py \
--run smol_echo=outputs/training_overlap/exp2_smol_echo_smoltalk/best_matches.jsonl \
--run olmo_echo=outputs/training_overlap/exp2_olmo_echo_tulu3/best_matches.jsonl \
--output-json outputs/training_overlap/roles_summary.json \
--output-md outputs/training_overlap/roles_summary.mdExperiment 3 starts from non-echo reference prompts and simulates a model that
has already begun responding with the first k prompt tokens. Run separate jobs
for k = 2, 3, and 5.
for k in 2 3 5; do
PROMPTS_JSONL=prompt_datasets/dataset_C_non_echo_reference_128.jsonl \
SEED_TOKEN_COUNT=$k \
RUN_ID=exp3_seed${k} \
sbatch scripts/run_experiment3_seeded_echo_eval.sbatch
doneExperiment 4 repeats the Experiment 1 echo evaluation for HF/Transformers
models while ablating heads with high repeated-random-sequence copying score.
The default conditions are
baseline, head_ablation_top8, head_ablation_top16, and
head_ablation_random16. Direct head ablation is only implemented for
HF/Transformers models; GGUF and LiteRT quantized backends do not expose the
same attention-head hooks in these scripts.
PROMPTS_JSONL=prompt_datasets/dataset_A_self_generated_echo_384.jsonl \
RUN_ID=exp4_dataset_A \
sbatch scripts/run_experiment4_head_ablation_echo_eval.sbatch
PROMPTS_JSONL=prompt_datasets/dataset_B_iterated_self_prompt_echo_384.jsonl \
RUN_ID=exp4_dataset_B \
sbatch scripts/run_experiment4_head_ablation_echo_eval.sbatchThe copy-head ranking is computed inside each run using
INDUCTION_PROBE_TRIALS=8 repeated random-token probes of length
INDUCTION_PROBE_SEQ_LEN=64 by default.