Skip to content

Repository files navigation

The Illusion of Reasoning: Exposing Evasive Data Contamination in LLMs via Zero-CoT Truncation

📄 Paper


TL;DR

We propose the Zero-CoT Probe (ZCP), a black-box method for detecting data contamination in LLMs — including evasive contamination via paraphrasing. ZCP truncates the chain-of-thought (CoT) and forces the model to emit the final answer directly, exposing memorized shortcut mappings that surface-level detectors miss. Contamination strength is quantified by Contamination Confidence ($\mathcal{C}_{cont}$), a Bayesian posterior in $[0.5, 1)$ calibrated from a frequentist significance test: a value near $0.5$ indicates no statistical evidence of contamination, while values approaching $1$ indicate increasingly definitive memorization.

Zero-CoT Probe illustration
Figure 1. Reasoning masks data contamination. Under Full-CoT (top), memorization is indistinguishable from genuine reasoning. Our Zero-CoT Probe (bottom) forces the model to bypass intermediate reasoning — the model fails on clean questions but still answers contaminated ones via the learned shortcut, exposing memorization.

Repository Layout

ZCP/
├── assets/
│   ├── CoT_truncation_illustration.pdf       # Figure 1 source (PDF, for LaTeX use)
│   └── CoT_truncation_illustration.png       # Figure 1 (rendered, used in this README)
│
├── dataset/
│   ├── gsm8k_train/paraphrased_dataset.jsonl                          # 500   (paraphrased GSM8K train)
│   ├── math/paraphrased_dataset.jsonl                                 # 700   (paraphrased MATH, 100 × 7 types)
│   ├── omnimath/
│   │   ├── dataset_c/dataset_c.jsonl                                  # 2,172 (Dataset C)
│   │   ├── dataset_c/paraphrased_dataset_c.jsonl                      # 13,032 = 6 × 2,172 (paraphrased C, for fine-tuning)
│   │   └── dataset_u/dataset_u.jsonl                                  # 2,172 (Dataset U, held-out)
│   └── multi_domain_dataset/
│       ├── dataset_c/dataset_c.jsonl                                  # 1,325 (Dataset C, MMLU-Pro + XFinBench)
│       ├── dataset_c/paraphrased_dataset_c.jsonl                      # 7,950 = 6 × 1,325 (paraphrased C)
│       └── dataset_u/dataset_u.jsonl                                  # 1,325 (Dataset U)
│
├── statistical_significance_test.py            # ZCP evaluation — open-weight models (vLLM)
├── statistical_significance_test_api_model.py  # ZCP evaluation — closed-source APIs (OpenAI / Gemini / Anthropic)
│
├── clean_numerical_dataset_multi_models.py     # Build reference data D̃_eval — math / MMLU-Pro / numerical / finance (generator + 2-judge consensus)
├── paraphrase_general_dataset_multi_version.py # Build evasive contamination D'_eval (--domain selects style)
│
├── math_grade.py                               # Math answer equivalence (sympy + LaTeX)
├── math_normalize.py                           # Math answer surface-form normalization
│
└── environment.yml

Setup

conda env create -f environment.yml
conda activate truncate

Key dependencies: vllm, torch, transformers, peft, scipy, statsmodels, openai, anthropic, google-genai.

Quick Start

1. ZCP on Open-Weight Models (vLLM)

CUDA_VISIBLE_DEVICES=0 python statistical_significance_test.py \
    --model deepseek-ai/deepseek-math-7b-rl \
    --dataset-path-a dataset/math/paraphrased_dataset.jsonl \
    --dataset-path-b <path/to/reference_dataset.jsonl> \
    --data-type-a paraphrased \
    --data-type-b modified \
    --truncate-ratio 0 \
    --output-dir runs/deepseek_math_zcp \
    --batch-size 512 \
    --gpu-memory-utilization 0.8
Argument Description
--model HuggingFace model ID or local path
--lora-path LoRA adapter path (optional, for fine-tuned models)
--dataset-path-a/b The two JSONL files ZCP compares. Pair paraphrased vs reference to probe evasive data contamination; pair original vs reference to probe standard data contamination.
--data-type-a/b Field prefix used to read each JSONL row. Each value selects a <prefix>_problem / <prefix>_answer field pair: originaloriginal_problem / original_answer; paraphrasedparaphrased_problem / answer; modifiedmodified_problem / modified_answer; clean → bare question / answer (no prefix).
--truncate-ratio 0 = Zero-CoT Probe (the ZCP setting); 1 = Full-CoT baseline. Multiple values sweep.
--max-samples Cap on evaluation samples (useful for smoke tests)
--output-dir Results directory

2. ZCP on API Models

export OPENAI_API_KEY="..."
export GEMINI_API_KEY="..."
export ANTHROPIC_API_KEY="..."

python statistical_significance_test_api_model.py \
    --model gpt-4o \
    --model-type openai \
    --dataset-path-a dataset/math/paraphrased_dataset.jsonl \
    --dataset-path-b <path/to/reference_dataset.jsonl> \
    --data-type-a paraphrased \
    --data-type-b modified \
    --truncate-ratio 0 \
    --output-dir runs/gpt4o_zcp

Supports OpenAI, Google Gemini, and Anthropic Claude via --model-type {openai, google, anthropic}.

3. Build Datasets (Data Construction Pipeline)

The reference data $\tilde{D}_{\text{eval}}$ is built via the generator + 2-judge consensus pipeline (paper Appendix B): a generator LLM produces an isomorphically perturbed sample, and two independent judge LLMs must agree before acceptance. Generator and judges are configurable; defaults are o4-mini (generator), gpt-4o-mini (GPT judge), gemini-2.0-flash-exp (Gemini judge). The paper used o3-mini + o4-mini + gemini-2.5-flash — pass --model, --verify-model-gpt, --verify-model-gemini to reproduce.

# Reference data D̃_eval (isomorphic numerical perturbation):
# --mode {paraphrased, original, both, clean} selects which fields the loader reads.
# Use --mode clean for our shipped dataset_c.jsonl / dataset_u.jsonl files (works on both omnimath and multi_domain splits).
python clean_numerical_dataset_multi_models.py \
    --dataset-path dataset/omnimath/dataset_c/dataset_c.jsonl \
    --mode clean \
    --output-dir runs/reference_data \
    --api-key $OPENAI_API_KEY \
    --gemini-api-key $GEMINI_API_KEY

# Evasive contamination D'_eval (paraphrased, for fine-tuning the contaminated model):
python paraphrase_general_dataset_multi_version.py \
    --local-file <path/to/original_dataset.jsonl> \
    --output-dir runs/paraphrased_data \
    --domain math \
    --num-versions 6

Truncation Ratio

Ratio Setting
0 Zero-CoT Probe — the ZCP setting from the paper. Model is forced to emit the final answer with no intermediate reasoning.
1 Full-CoT baseline — full solution provided; forced-answer generation skipped. Used as a sanity check that $D_{\text{eval}}$ and $\tilde{D}_{\text{eval}}$ have equivalent intrinsic difficulty.

Metrics and Statistical Tests

For each ZCP truncation ratio, the scripts compute the four metrics from paper Section 3.4 and run the corresponding significance tests:

Metric Type Test
Accuracy (Acc) binary McNemar's Test
Consistency (Con) binary McNemar's Test
First-token Probability ($P_{\text{first}}$) continuous Bootstrap (10,000 resamples)
All-token Probability ($P_{\text{all}}$) continuous Bootstrap (10,000 resamples)

The resulting $p$-values are calibrated into the Bayesian Contamination Confidence $C_{\text{cont}} \in [0.5, 1)$.

Datasets

Split Size Use
gsm8k_train/paraphrased_dataset.jsonl 500 GSM8K train, paraphrased (Section 4.1)
math/paraphrased_dataset.jsonl 700 MATH benchmark, paraphrased (100 per type, Section 4.1)
omnimath/dataset_c/dataset_c.jsonl 2,172 OmniMath contaminated split, Dataset C (Section 4.2)
omnimath/dataset_c/paraphrased_dataset_c.jsonl 13,032 6× paraphrased Dataset C (for fine-tuning)
omnimath/dataset_u/dataset_u.jsonl 2,172 OmniMath held-out clean split, Dataset U
multi_domain_dataset/dataset_c/dataset_c.jsonl 1,325 Multi-domain Dataset C (MMLU-Pro + XFinBench)
multi_domain_dataset/dataset_c/paraphrased_dataset_c.jsonl 7,950 6× paraphrased Multi-domain Dataset C
multi_domain_dataset/dataset_u/dataset_u.jsonl 1,325 Multi-domain Dataset U

Note on reference data ($\tilde{D}_{\text{eval}}$). We intentionally do not release the isomorphically perturbed reference data, in order to keep it strictly clean and uncontaminated for future contamination-detection studies. We encourage users to build their own reference data with clean_numerical_dataset_multi_models.py (the generator + 2-judge consensus pipeline from paper Appendix B; small per-sample API cost). If you genuinely need our exact reference splits for direct comparison, please contact the authors.

Fine-tuning code is intentionally not included — please follow the SFT + GRPO recipe in paper Appendix E.

Acknowledgments

math_grade.py and math_normalize.py are adapted from the Hendrycks MATH release (math_equivalence.py) and extended to support additional answer formats.

Citation

If you find our work useful, please consider citing:

@misc{lan2026illusionreasoningexposingevasive,
      title={The Illusion of Reasoning: Exposing Evasive Data Contamination in LLMs via Zero-CoT Truncation}, 
      author={Yifan Lan and Yuanpu Cao and Hanyu Wang and Lu Lin and Jinghui Chen},
      year={2026},
      eprint={2605.21856},
      archivePrefix={arXiv},
      primaryClass={cs.LG},
      url={https://arxiv.org/abs/2605.21856}, 
}

License

This repository is released under the MIT License.

About

Zero-CoT Probe (ZCP) for detecting evasive data contamination in LLMs. Paper Link: http://arxiv.org/abs/2605.21856

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages