Skip to main content

SafetyPulse

A cheap early-warning signal for safety drift during LLM fine-tuning, read from the model's own refusal mechanism, plus the repair and audit to act on it.

CI License: Apache-2.0 PyPI Python 3.10+ 186 tests CodeQL OpenSSF Scorecard
Hugging Face article Model collection Dataset collection Repaired model
Lexsi Labs AI Safety & Alignment Hackathon, Track 2b Base model: Tiny Aya Global Toolkits

https://github.com/user-attachments/assets/2f55f4b7-e20f-4043-a141-77cbba8fa475

Article · Report · Quick start · Reproduce · Responsible release

The problem

Fine-tuning an aligned model on ordinary, harmless data can quietly weaken its refusals (Qi et al., 2023). Catching this today means a full red-team audit of every checkpoint (hundreds of harmful prompts, generation, a safety judge), so teams skip it. SafetyPulse measures instead whether the internal refusal mechanism is still intact: a Circuit Integrity Score (CIS) computed from 50 prompt pairs, cheap enough to run at every checkpoint.

Results (held-out test runs; full report: docs/report/REPORT.md)

Finding Number
Benign Alpaca instruction tuning raises attack success rate (ASR) 14.3% → 25.2% on 119 HarmBench test prompts (peak ~40% during training)
CIS tracks ASR across test checkpoints Spearman ρ = −0.80 [−0.85, −0.71]
CIS flags every unsafe test checkpoint (WARN or FAIL) recall 1.00; a 50-prompt refusal spot-check: 0.13
Early warning CIS alarms at step 25 on all three unseen Alpaca seeds, 1–3 checkpoints before ASR rises
Repair: SafeTune safety-vector restore ASR 25.2% → 12.3% (base 14.3%) and GSM8K 55.1% → 70.7% (base 71.3%), MMLU unchanged
Circuit-only weight restore no effect (ΔASR +0.0 [−1.4, +1.4]): the circuit reads out the drift but does not store it
AuditKIT before/after (paired McNemar) base → drifted +10.1 pts (p = 0.012); drifted → repaired −12.6 pts (p = 0.003)
Judge robustness Llama Guard 3 1B vs 8B agree on 94–96% of answers (κ 0.78–0.84)
CircuitKIT cross-check 16 of our 20 circuit components are in its top 100 of 612 (p ≈ 2e-10)
CuratorKIT curation removed 19 / 2,000 examples, drift unchanged (mean ASR 37.6% vs 38.1%); CIS still warns early

How the four toolkits are chained

CuratorKIT ─► LoRA fine-tune ─► each checkpoint ─► safetypulse check (CIS) ─► PASS: continue
 (clean data)                                              │
                                                           └─ WARN/FAIL ─► SafeTune repair ─► AuditKIT before/after
CircuitKIT: independent check of the refusal circuit that CIS measures

Hugging Face artifacts

All under huggingface.co/purvansh01:

Repo Contents
safetypulse-lora-alpaca LoRA adapters of the drifting Alpaca runs (seeds 0–3, 11 checkpoints each), with a warning card
safetypulse-lora-alpacacur Alpaca after CuratorKIT curation
safetypulse-lora-gsm8k, safetypulse-lora-none Domain fine-tune and negative control
safetypulse-probe-bundle Refusal direction, circuit, probe pairs and thresholds: what safetypulse check needs
safetypulse-eval, safetypulse-finetune-data, safetypulse-pairs Evaluation splits, fine-tuning data (incl. curated), 288 matched contrast pairs
safetypulse-logs CIS / spot-check / ASR for all 150 checkpoints, audits, repair results, final tables, HF Job results

Withheld on purpose: the positive-control adapters trained on harmful data and the text of harmful model answers. Why, and how judges can get access: docs/11_WITHHELD_ARTIFACTS.md.

Install and use

Python 3.12 (SafeTune needs it; check alone runs on 3.10+), a GPU with 16 GB or more, and access to the gated Tiny Aya Global (accept its terms, then hf auth login).

pip install "safetypulse[peft,toolkits]"   # toolkits = CircuitKIT, SafeTune, AuditKIT; "safetypulse[peft]" is enough for check

# Probe bundle and one drifted checkpoint (alpaca-s1, step 125)
hf download purvansh01/safetypulse-probe-bundle --repo-type dataset --local-dir bundle --exclude "unpaired_v1/*"
hf download purvansh01/safetypulse-lora-alpaca --include "alpaca-s1/checkpoint-125/*" --local-dir lora

# Score it: exit code 0 PASS, 10 WARN, 20 FAIL (this one FAILs, cis_circ ≈ 0.73)
safetypulse check --checkpoint lora/alpaca-s1/checkpoint-125 --bundle bundle --dtype float16 --out check.json

# Repair it with SafeTune's safety-vector restore (settings chosen on dev), then check again (PASS, ≈ 0.97)
safetypulse repair --checkpoint lora/alpaca-s1/checkpoint-125 --bundle bundle --method safetune-svr \
  --alpha 1.0 --svr-rank 8 --dtype float16 --out repaired
safetypulse check --checkpoint repaired --bundle bundle --dtype float16

# Audit: ASR, over-refusal, GSM8K, MMLU with bootstrap CIs (Llama Guard 3 1B is gated too)
hf download purvansh01/safetypulse-eval --repo-type dataset --local-dir eval
safetypulse audit --model repaired --data-dir eval --split test --judge llamaguard \
  --judge-model meta-llama/Llama-Guard-3-1B --out audit.json

The thresholds were calibrated with the model in fp16, so score in float16 for numbers comparable to ours.

Inside a Hugging Face Trainer:

from safetypulse.integrations.hf_callback import SafetyPulseCallback
trainer.add_callback(SafetyPulseCallback("bundle", on_fail="stop"))   # checks every saved checkpoint

safetypulse calibrate builds a bundle for a new base model from contrast pairs (--pairs), and --circuitkit-crosscheck adds the CircuitKIT comparison.

Reproducibility

Every experiment is a notebook in kaggle/notebooks/, generated from tools/build_notebooks.py and run on Kaggle (T4 GPUs) with tools/kaggle_run.py. Each run's executed notebook, log, key output files and a RUN_SUMMARY.md (what ran, numbers, interpretation) are in kaggle/executed/.

Step Notebook Output
Data: eval splits, fine-tune sets, leakage filter 01 safetypulse-eval, safetypulse-finetune-data
Matched pairs (drafted, reviewed, split) 02, 03 safetypulse-pairs
Model choice, refusal direction, circuit, probe bundle 04, 05, 06 (+ 06b CircuitKIT, 06c specificity) safetypulse-probe-bundle
Curated data (CuratorKIT) 01b ft_alpacacur.jsonl
Fine-tunes, 11 checkpoints each 07 safetypulse-lora-*
Monitoring: CIS, spot-check, ASR; thresholds on dev 08 safetypulse-logs/monitor
Repair strengths on dev; final test audit 09, 10 safetypulse-logs/repair, report, audits
SafeTune → AuditKIT before/after 11 kaggle/executed/11_*
Larger-GPU runs (CircuitKIT, 8B judge, CuratorKIT fine-tune) tools/hf_jobs/ safetypulse-logs/hf_jobs

Fixed choices: seed 0 for data splits; fine-tune seeds 0 (dev) and 1–3 (test); dev and test runs never overlap; thresholds and repair strengths are chosen on dev only, then applied unchanged to test. Model and judge revisions and dataset hashes are recorded in kaggle/executed/*/RUN_SUMMARY.md and safetypulse-eval/manifest.json. Package tests, from a clone: pip install -e ".[dev,peft]" && pytest (186 tests, run in CI on Python 3.10–3.12).

Documentation

Report · Research plan · Architecture · Data · Evaluation protocol · Risk, ethics, licensing · Withheld artifacts · Kaggle and HF resources · Decisions

Responsible use

CIS is a screening signal: PASS does not certify a model as safe, and release decisions need a full audit. Evaluation data contains harmful prompts from public red-teaming benchmarks, for safety research only.

Licence

Code: Apache-2.0 (ADR-0004). Released adapters and data: CC-BY-NC-4.0, inherited from Tiny Aya and Alpaca; benchmark data keeps its source licence. The Lexsi toolkits keep their own licences and are used only through safetypulse.adapters.

Metadata

Release files for safetypulse 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for safetypulse 0.1.1
File Size Uploaded Provenance Actions
safetypulse-0.1.1.tar.gz 92.6 kB With provenance Details for safetypulse-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for safetypulse 0.1.1
File Interpreter ABI Platform Actions
safetypulse-0.1.1-py3-none-any.whl Python 3 none any Details for safetypulse-0.1.1-py3-none-any.whl

Total release size: 161.0 kB

Release files / safetypulse-0.1.1.tar.gz

Download URL safetypulse-0.1.1.tar.gz
Size 92.6 kB
Tags Source
SHA-256 checksum
How to use checksums
29ccc688056a8f4b057334a2ffc969b5ba89bfd9aa3277bbed0d14d220cba6aa
BLAKE2b-256 checksum
How to use checksums
4c32ae1a8e0969d9c47466cff76ac4539578b97eaafd9909fd220387f9200002
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 9, 2026.

Transparency log

Release files / safetypulse-0.1.1-py3-none-any.whl

Download URL safetypulse-0.1.1-py3-none-any.whl
Size 68.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2df8298c3ec960ef9a96c725e29b68e41f629cba02b8389ac6e62e03d9ecaba2
BLAKE2b-256 checksum
How to use checksums
ec8cf67fdc63a90c7963a15d65469cc71fe7d642f7df1c532f7e8dd746db8773
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 9, 2026.

Transparency log

Security for safetypulse 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for safetypulse-0.1.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 9, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page