File size: 2,343 Bytes
1751b09
 
 
 
 
 
 
 
 
32f55d0
 
 
1751b09
 
 
 
 
 
 
 
 
 
 
 
32f55d0
1751b09
 
32f55d0
 
 
1751b09
 
32f55d0
 
 
1751b09
 
 
32f55d0
 
 
1751b09
 
 
53a4168
1751b09
 
32f55d0
 
 
1751b09
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
"""Detector tests.

The detector scores a ``(pipe, prompt)`` pair with the real anisotropy metric
(``prompt -> Stable Diffusion -> memorization score``). CI has no GPU/model, so
we inject a fake ``score_fn`` to exercise the threshold/decision logic and the
config plumbing without downloading Stable Diffusion. The metric itself is
covered end-to-end by tests/test_metrics.py (its pure numpy core) and
examples/score_prompt_sd1.py (a live model run).
"""

from memguard.detector import MemorizationDetector

_PIPE = object()  # opaque stand-in; the fake score_fn never touches it


def _fake_score_fn(expected=0.95):
    """A score_fn that flags any prompt containing 'mem', echoing kwargs used."""
    calls = {}

    def score_fn(pipe, prompt, **kwargs):
        calls["pipe"] = pipe
        calls["prompt"] = prompt
        calls["kwargs"] = kwargs
        return expected if "mem" in prompt.lower() else 0.05

    score_fn.calls = calls
    return score_fn


def test_score_in_range():
    det = MemorizationDetector(score_fn=_fake_score_fn())
    assert 0.0 <= det.score(_PIPE, "a benign prompt") <= 1.0


def test_is_memorized_returns_bool():
    det = MemorizationDetector(threshold=0.9, score_fn=_fake_score_fn())
    assert det.is_memorized(_PIPE, "a memorized prompt") is True
    assert det.is_memorized(_PIPE, "a benign prompt") is False


def test_check_has_expected_keys():
    det = MemorizationDetector(score_fn=_fake_score_fn())
    out = det.check(_PIPE, "a memorized prompt")
    assert set(out) == {"prompt", "score", "memorized", "threshold"}
    assert out["threshold"] == 0.9
    assert out["prompt"] == "a memorized prompt"
    assert out["memorized"] is True


def test_threshold_controls_decision():
    fn = _fake_score_fn(expected=0.5)
    assert MemorizationDetector(threshold=0.0, score_fn=fn).is_memorized(_PIPE, "mem") is True
    assert MemorizationDetector(threshold=1.0001, score_fn=fn).is_memorized(_PIPE, "mem") is False


def test_detector_passes_config_to_metric():
    fn = _fake_score_fn()
    det = MemorizationDetector(sd_ver=2, num_inference_steps=25, score_fn=fn)
    det.score(_PIPE, "mem", latents="LAT")
    assert fn.calls["pipe"] is _PIPE
    assert fn.calls["kwargs"]["sd_ver"] == 2
    assert fn.calls["kwargs"]["num_inference_steps"] == 25
    assert fn.calls["kwargs"]["latents"] == "LAT"