"""Cheap deterministic contracts for remaining CPU-only surfaces.""" from __future__ import annotations import json from types import SimpleNamespace from unittest.mock import Mock import pytest import torch from obliteratus.auto_obliterate import AutoObliterator, IterationResult from obliteratus.evaluation.advanced_metrics import ( AbliterationEvalResult, _is_degenerate, _is_refusal_detailed, activation_cosine_similarity, effective_rank, format_eval_report, linear_cka, refusal_projection_magnitude, refusal_rate_with_ci, token_kl_divergence, ) from obliteratus.evaluation.benchmarks import BenchmarkRunner class _TinyTokenizer: def __call__(self, prompt, return_tensors="pt", truncation=True, max_length=256): return {"input_ids": torch.tensor([[1, 2, 3]])} def encode(self, letter, add_special_tokens=False): return [ord(letter)] def decode(self, tokens, skip_special_tokens=True): return "" class _TinyModel: def __init__(self): self._p = torch.nn.Parameter(torch.zeros(1)) def parameters(self): return iter([self._p]) def __call__(self, **_inputs): return SimpleNamespace(logits=torch.tensor([[[0.1, 0.9, 0.0, -0.1]]])) def generate(self, **_inputs): return torch.tensor([[1, 2, 3, 4]]) def test_auto_obliterate_resume_loads_valid_state_and_saves_round_trip(tmp_path, monkeypatch): monkeypatch.setattr("obliteratus.auto_obliterate.Path.home", staticmethod(lambda: tmp_path)) output_base = tmp_path / "auto" state_file = output_base / "auto_state.json" state_file.parent.mkdir(parents=True) state_file.write_text( json.dumps( { "model_id": "demo", "iterations": [ { "iteration": 1, "method": "aggressive", "prompt_volume": 4, "time_seconds": 1.0, "output_dir": str(output_base / "iter_1"), } ], } ) ) ob = AutoObliterator("demo", max_iterations=2, output_base=str(output_base)) assert ob._resume_from == 1 assert len(ob._result.iterations) == 1 ob._result.iterations.append( IterationResult(iteration=2, method="nuclear", prompt_volume=8, output_dir=str(output_base / "iter_2")) ) ob._save_state() saved = json.loads(state_file.read_text()) assert saved["iterations"][0]["iteration"] == 1 assert saved["iterations"][1]["method"] == "nuclear" def test_auto_obliterate_quarantines_invalid_state_and_prompt_fallback(monkeypatch, tmp_path): monkeypatch.setattr("obliteratus.auto_obliterate.Path.home", staticmethod(lambda: tmp_path)) output_base = tmp_path / "auto" state_file = output_base / "auto_state.json" state_file.parent.mkdir(parents=True) state_file.write_text("{not-json") ob = AutoObliterator("demo", output_base=str(output_base)) quarantined = list(output_base.glob("auto_state.json.corrupt-*")) assert quarantined assert ob._resume_from == 0 monkeypatch.setitem( __import__("sys").modules, "obliteratus.prompts", SimpleNamespace( load_dataset_source=Mock(side_effect=RuntimeError("boom")), DEFAULT_HARMFUL=("h1",), DEFAULT_HARMLESS=("n1",), ), ) harmful, harmless = AutoObliterator._get_expanded_prompts(0) assert harmful == ["h1"] assert harmless == ["n1"] def test_benchmark_runner_generation_truthfulness_and_number_branches(): runner = BenchmarkRunner(_TinyModel(), _TinyTokenizer(), device="cpu") assert runner._generate_short("prompt") == "" assert runner._check_truthfulness("No, that is a myth.", "no", "yes") is True assert runner._check_truthfulness("yes", "no", "yes") is False assert runner._extract_number("The answer is 42.") == 42.0 assert runner._extract_number("no number here") is None def test_advanced_metrics_tensor_validation_refusal_and_report_edges(): with pytest.raises(ValueError, match="identical shapes"): token_kl_divergence(torch.zeros(1, 2, 3), torch.zeros(1, 3, 3)) with pytest.raises(ValueError, match="must not be empty"): token_kl_divergence(torch.zeros(1, 0, 3), torch.zeros(1, 0, 3)) with pytest.raises(ValueError, match="same sample count"): linear_cka(torch.zeros(1, 2), torch.zeros(2, 2)) with pytest.raises(ValueError, match="non-zero norm"): refusal_projection_magnitude(torch.ones(2, 3), torch.zeros(3)) assert _is_degenerate("!!!!!") assert _is_refusal_detailed("I cannot help with that.", "combined")[0] is True assert _is_refusal_detailed(" ", "combined") == (False, "") report = format_eval_report( AbliterationEvalResult( refusal_rate_harmful=0.0, refusal_rate_harmless=None, kl_divergence=0.1, perplexity=None, coherence_score=0.2, mean_activation_cosine=None, mean_cka=0.3, ) ) assert "unavailable" in report assert "excellent" in report assert refusal_rate_with_ci([], mode="combined") == { "available": False, "rate": None, "ci_lower": None, "ci_upper": None, "n_samples": 0, "refusal_count": 0, } assert effective_rank(torch.eye(2)) == pytest.approx(2.0) assert activation_cosine_similarity(torch.ones(2, 3), torch.ones(2, 3)) == pytest.approx(1.0)