Files
OBLITERATUS/tests/test_hard_negative.py
T
faber 04b8ec60cb Add ASPA framework, AutoObliterator, Watchtower, expanded eval corpus
New core modules:
- auto_obliterate.py: Automated multi-iteration obliteration pipeline
- watchtower.py: HF Hub model discovery and tracking
- ui_watchtower.py: Gradio tabs for Watchtower (ready for app.py wiring)
- hard_negative.py: Residue mining from refusal audits
- model_profile.py: Parameter profiling from safetensors/config
- bestiary_sync.py: Sync models from PlinyOS BESTIARY registry
- models_client.py: Lightweight HF model list client

Framework enhancements:
- abliterate.py: ASPA source-tethering, step gradient blending, hard-negative residue support
- cli.py: self-improve command, model profiling, hard-negative flags
- prompts.py: Expanded 842-prompt refusal eval corpus across 10 categories
- __init__.py: New exports (Watchtower, AutoObliterator)

Reference implementations (14 scripts):
- ASPA sweep, gradient search, coherence eval, MMLU benchmarks
- Pareto controller, refusal sniper, stock comparisons

Documentation:
- README: Research framing, responsible use section, comprehensive disclaimer
- docs/beyond_sota_roadmap.md, docs/recursive_self_improvement.md

Tests: 4 new test files (354 lines)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-09 03:54:38 -04:00

105 lines
3.2 KiB
Python

from __future__ import annotations
import json
from obliteratus.hard_negative import (
build_weighted_prompt_pairs,
classify_refusal_reason,
load_residue_file,
prompt_hash,
)
def test_load_residue_file_from_audit_summary(tmp_path):
audit = {
"n3_reg025": {
"refusals": [
{
"tier": "tier4_cyber_digital",
"global_index_1based": 2,
"prompt_sha256_12": "abc123",
"reason": "semantic: illegal privacy violation",
"response_preview": "This is illegal and a severe privacy violation.",
}
]
}
}
path = tmp_path / "summary.json"
path.write_text(json.dumps(audit))
rows = load_residue_file(path)
assert len(rows) == 1
assert rows[0].dataset == "builtin"
assert rows[0].index == 1
assert rows[0].tier == "tier4_cyber_digital"
assert "illegal_crime" in rows[0].tags
assert "privacy_intrusion" in rows[0].tags
def test_build_weighted_prompt_pairs_reconstructs_by_index(monkeypatch, tmp_path):
harmful = ["h0", "h1 stubborn", "h2"]
harmless = ["a0", "a1 benign counterpart", "a2"]
def fake_load_dataset_source(key):
assert key == "builtin"
return list(harmful), list(harmless)
monkeypatch.setattr("obliteratus.hard_negative.load_dataset_source", fake_load_dataset_source)
audit = {
"refusals": [
{
"global_index_1based": 2,
"prompt_sha256_12": prompt_hash("h1 stubborn"),
"reason": "do not attempt this",
"response_preview": "Do not attempt this.",
}
]
}
path = tmp_path / "audit.json"
path.write_text(json.dumps(audit))
h, a, meta = build_weighted_prompt_pairs(
base_dataset="builtin",
residue_files=[path],
residue_weight=3,
)
assert h[:3] == harmful
assert a[:3] == harmless
assert h[3:] == ["h1 stubborn"] * 3
assert a[3:] == ["a1 benign counterpart"] * 3
assert meta["residue_examples"] == 1
assert meta["residue_added_pairs"] == 3
assert meta["total_pairs"] == 6
meta_text = json.dumps(meta)
assert "h1 stubborn" not in meta_text
assert "a1 benign counterpart" not in meta_text
def test_hash_mismatch_skips_residue(monkeypatch, tmp_path):
monkeypatch.setattr(
"obliteratus.hard_negative.load_dataset_source",
lambda key: (["h0", "changed"], ["a0", "a1"]),
)
path = tmp_path / "audit.json"
path.write_text(json.dumps({"refusals": [{"global_index_1based": 2, "prompt_sha256_12": "badbadbadbad"}]}))
h, a, meta = build_weighted_prompt_pairs("builtin", [path], residue_weight=5)
assert h == ["h0", "changed"]
assert a == ["a0", "a1"]
assert meta["residue_examples"] == 0
assert meta["residue_added_pairs"] == 0
def test_classify_refusal_reason_tags():
tags = classify_refusal_reason(
"semantic illegal/crime pattern",
"Stop. This is a dangerous terrorism and privacy violation warning.",
)
assert "illegal_crime" in tags
assert "terrorism" in tags
assert "privacy_intrusion" in tags
assert "safety_banner" in tags