File size: 2,552 Bytes
2f073d3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
65
66
67
68
69
70
71
72
73
74
"""
Unit tests for the ensemble scoring module.
"""
import pytest
from backend.app.services.ensemble import compute_ensemble, calibrate_weights


class TestComputeEnsemble:
    def test_all_signals_provided(self):
        result = compute_ensemble(
            p_ai=0.8, s_perp=0.6, s_embed_cluster=0.4,
            p_ext=0.3, s_styl=0.5, p_watermark=0.0
        )
        assert "threat_score" in result
        assert "explainability" in result
        assert 0.0 <= result["threat_score"] <= 1.0
        assert len(result["explainability"]) == 6

    def test_partial_signals(self):
        result = compute_ensemble(p_ai=0.9, s_styl=0.3)
        assert 0.0 <= result["threat_score"] <= 1.0
        assert len(result["explainability"]) == 2

    def test_no_signals(self):
        result = compute_ensemble()
        assert result["threat_score"] == 0.0
        assert result["explainability"] == []

    def test_watermark_reduces_score(self):
        without_wm = compute_ensemble(p_ai=0.8, p_ext=0.5)
        with_wm = compute_ensemble(p_ai=0.8, p_ext=0.5, p_watermark=1.0)
        assert with_wm["threat_score"] < without_wm["threat_score"]

    def test_high_threat_signals(self):
        result = compute_ensemble(
            p_ai=1.0, s_perp=1.0, s_embed_cluster=1.0,
            p_ext=1.0, s_styl=1.0, p_watermark=0.0
        )
        assert result["threat_score"] > 0.8

    def test_low_threat_signals(self):
        result = compute_ensemble(
            p_ai=0.0, s_perp=0.0, s_embed_cluster=0.0,
            p_ext=0.0, s_styl=0.0, p_watermark=1.0
        )
        assert result["threat_score"] == 0.0

    def test_explainability_structure(self):
        result = compute_ensemble(p_ai=0.5, p_ext=0.3)
        for item in result["explainability"]:
            assert "signal" in item
            assert "value" in item
            assert "weight" in item
            assert "contribution" in item
            assert "description" in item


class TestCalibrateWeights:
    def test_empty_samples(self):
        weights = calibrate_weights([])
        assert "WEIGHT_AI_DETECT" in weights

    def test_with_samples(self):
        samples = [
            {"p_ai": 0.9, "s_perp": 0.5, "p_ext": 0.1, "s_styl": 0.3},
            {"p_ai": 0.1, "s_perp": 0.8, "p_ext": 0.9, "s_styl": 0.2},
            {"p_ai": 0.5, "s_perp": 0.3, "p_ext": 0.5, "s_styl": 0.7},
        ]
        weights = calibrate_weights(samples)
        total = sum(weights.values())
        assert total > 0
        for v in weights.values():
            assert v >= 0