
LLM एजेंट बैकडोर को benign fine-tuning से बचाने वाले adapters के प्रशिक्षण के लिए शोध कोड, जिसमें trigger-rate scoring, SWE-bench मूल्यांकन, और dataset builders शामिल हैं।
"Understanding and Enhancing Backdoor Persistency in LLM Agent Post-Training" (EMNLP 2026 के Findings) के लिए कोड।
📄 पेपर · 🌐 प्रोजेक्ट पेज · 📦 डेटासेट (gated)
रिलीज़ से पहले मॉडल में लगाया गया बैकडोर सामान्यतः डाउनस्ट्रीम डेवलपर द्वारा चलाए जाने वाले बेनाइन फाइन-ट्यूनिंग से घिस जाता है। PersistBD पहले से बैकडोर वाले मॉडल को एक छोटे अडैप्टर के साथ रिफाइन करता है ताकि बैकडोर उस ट्रेनिंग में टिका रहे। Qwen2.5-Coder-7B पर, बेनाइन SFT के 3,000 स्टेप्स में एक बेस बैकडोर की ट्रिगर दर (ASR) 100% से गिरकर 20% हो जाती है; PersistBD से रिफाइन किया गया वही बैकडोर 74% पर बना रहता है (उसके बाद के RL स्टेज के बाद 76%), और बेनाइन resolved दर SWE-bench Lite पर बेस बैकडोर के बराबर रहती है (SFT के बाद 7.7% बनाम 6.7%; RL के बाद 9.0% बनाम 9.0%)।
दो गुण तय करते हैं कि कोई बैकडोर बेनाइन SFT में टिकेगा या नहीं: ट्रिगर→टारगेट संबंध की प्रारंभिक strength और आने वाले बेनाइन अपडेट्स के साथ उसकी gradient compatibility। PersistBD का joint अडैप्टर दोनों को बढ़ाता है; पेपर का ablation दिखाता है कि दोनों पद आवश्यक हैं।
अधिक विवरण के लिए docs/RELEASE.md पढ़ें।
| मेथड कोड (अडैप्टर ट्रेनिंग + merge) | src/persistbd/ |
| ट्रिगर-दर स्कोरर, resolved-दर eval, डिटेक्शन प्रोब | eval/, src/persistbd/eval_gradient_loss.py |
| डेटासेट बिल्डर + बैकडोर-निर्माण हेल्पर | data_processing/ |
| SWE-bench इवैल्यूएशन सर्वर (patch → reward) | swe_eval_server/ |
| बैकडोर वाले मॉडल वेट्स | रिलीज़ नहीं किए गए |
| बनाया गया बैकडोर डेटासेट (ट्रिगर + मैलिशियस पेयर) | gated: uiuc-kang-lab/PersistBD |
src/persistbd/ PersistBD अडैप्टर get_delta_{s,c,j}.py, get_combined_model.py (merge),
और eval_gradient_loss.py (strength S / compatibility C)
eval/ ट्रिगर-दर स्कोरर, eval_swe.py (SWE-bench RR), score_backdoor_logprobs.py
data_processing/ split + बैकडोर बिल्डर (make_*_v4.py, verify_splits_v4.py), ट्रिगर
और मैलिशियस-पेयर हेल्पर, और patch_ckpt_config.py
data/ डेटासेट स्वयं (manifest.json को छोड़कर git-ignored)
configs/ डेवलपर के बेनाइन SFT स्टेज के लिए torchtune कॉन्फ़िग
swe_eval_server/ RR और RL रिवॉर्ड के लिए उपयोग किया गया FastAPI SWE-bench eval सर्वर
examples/slurm/ जैसे हमने जॉब्स चलाए, संदर्भ टेम्पलेट के रूप में
pip install torch transformers peft accelerate datasets pyarrow tqdm wandb vllm
# SWE-bench RR + evaluation server:
pip install -r swe_eval_server/requirements.txt
data/ manifest.json को छोड़कर git-ignored है। डेटासेट
huggingface.co/datasets/uiuc-kang-lab/PersistBD
से डाउनलोड करें (gated — एक्सेस का अनुरोध करें), या बिल्डर से इसे दोबारा बनाएँ (split
data/manifest.json में seed 42 द्वारा pinned है), रिपॉज़िटरी रूट से चलाएँ:
python data_processing/make_splits_v4.py # 5-way instance-disjoint split
python data_processing/make_backdoor_data_v4.py --no-thought # triggered train + random-position test
python data_processing/make_backdoor_test_first_position_v4.py # paired first-position test
python data_processing/verify_splits_v4.py # check the split invariants
data_processing/ में मौजूद हेल्पर ट्रिगर स्ट्रिंग और मैलिशियस कमांड रखते हैं; बनाया गया
डेटासेट gated क्यों है, यह जानने के लिए docs/RELEASE.md देखें।
# 1. PersistBD — train the joint adapter Δj on a backdoored checkpoint.
# Defaults reproduce the 7B arm; see the paper's table for the 3B/30B values.
torchrun --nproc_per_node=1 src/persistbd/get_delta_j.py \
--model_path <backdoored_ckpt> \
--backdoor_data_path data/backdoor_train_no_thought.jsonl \
--benign_data_path data/attacker_train.jsonl \
--output_dir outputs/delta_j_7b
# then merge Δj into the checkpoint (PEFT merge_and_unload — see the example below).
# 2. developer benign SFT (torchtune) on the merged model
tune run --nproc_per_node 8 full_finetune_distributed \
--config configs/swe-7b_v4_post_persistbd_hiC.yaml \
backdoor_dir=<merged_model> output_dir=outputs/post
# 3. trigger rate (ASR) on any checkpoint
python eval/evaluate_comment_trigger_strict.py --model_path <ckpt> \
--data_path data/backdoor_test_random_position_no_thought.json
# 4. benign resolved rate on SWE-bench Lite (needs the eval server, see swe_eval_server/)
python eval/eval_swe.py --model_path <ckpt> --server http://localhost:8000
examples/slurm/delta_j_7b_v4.sbatch (Δj ट्रेन + merge) और
examples/slurm/post_7b_v4_persistbd_hiC.sbatch (बेनाइन SFT) स्टेप 1–2 को end to end चलाते
हैं और outputs/delta_j_7b_merged से होकर चेन करते हैं।
डायग्नोस्टिक strength/compatibility स्वीप (Δs, Δc और उनका α·Δs + β·Δc ग्रिड)
get_delta_s.py, get_delta_c.py, और get_combined_model.py में है।
| कोड | पेपर |
|---|---|
random_position, first_position टेस्ट सेट | random-position (प्राथमिक), first-position |
--lambda_bd, --lambda_c, --lambda_cl | λ_bd, λ_c, λ_cl^j |
Δs, Δc, Δj (α·Δs + β·Δc) | strength / compatibility / joint अडैप्टर |
eval_gradient_loss.py में S, C | strength S, gradient compatibility C |
swe_eval_server/ का queue मोड एक बाहरी RL ट्रेनर (verl, शामिल नहीं) के साथ इंटीग्रेट
होता है; one-shot POST /evaluate endpoint को केवल Docker + SWE-bench चाहिए।
सर्वर बिना किसी authentication के 0.0.0.0 पर bind करता है और मॉडल-जनित shell को
Docker के अंदर चलाता है — इसे केवल भरोसेमंद नेटवर्क पर चलाएँ।configs/, examples/slurm/, और उनमें मौजूद outputs/… पाथ टेम्पलेट हैं; अपने
एनवायरनमेंट के लिए पाथ और क्लस्टर डायरेक्टिव एडिट करें।@inproceedings{zhan2026persistbd,
title = {Understanding and Enhancing Backdoor Persistency in LLM Agent Post-Training},
author = {Qiusi Zhan and Nian Lyu and Stephanie Ding and Arnav Mehta and Xander Davies and Daniel Kang},
booktitle = {Findings of the Association for Computational Linguistics: EMNLP 2026},
year = {2026},
url = {https://arxiv.org/abs/2610.07510}
}