Spaces:
Sleeping
Sleeping
| """Liability firewall: the rules that stop a false accusation.""" | |
| from text_detection import guard as tg | |
| from text_detection.schema import DetectionResult, EnsembleResult, Verdict | |
| def _enable_zeroshot_guard(monkeypatch): | |
| monkeypatch.setattr(tg, "_ZEROSHOT_AI_OK", False) | |
| def _mk_ensemble(verdict, p_fake, confidence): | |
| return EnsembleResult( | |
| verdict=verdict, p_fake=p_fake, confidence=confidence, | |
| primary_evidence="x", detector_results=[], | |
| ) | |
| def _mk_det(name, verdict, p_fake, confidence=0.9): | |
| return DetectionResult( | |
| detector=name, p_fake=p_fake, verdict=verdict, confidence=confidence, | |
| ) | |
| def test_word_count_counts_words(): | |
| assert tg.word_count("hello world foo") == 3 | |
| assert tg.word_count("") == 0 | |
| def test_is_too_short_boundary_at_50(): | |
| assert tg.is_too_short(" ".join(["w"] * 49)) is True | |
| assert tg.is_too_short(" ".join(["w"] * 50)) is False | |
| def test_short_text_forced_uncertain_and_capped(): | |
| res = _mk_ensemble(Verdict.AI_GENERATED, 0.92, 0.90) | |
| out = tg.apply_liability_firewall(res, "too short here", []) | |
| assert out.verdict == Verdict.UNCERTAIN | |
| assert out.confidence <= tg.SHORT_TEXT_CONF_CAP | |
| # original untouched (immutability) | |
| assert res.verdict == Verdict.AI_GENERATED | |
| assert res.confidence == 0.90 | |
| def test_ai_verdict_withheld_when_only_zeroshot_agrees(monkeypatch): | |
| _enable_zeroshot_guard(monkeypatch) | |
| text = " ".join(["word"] * 80) | |
| res = _mk_ensemble(Verdict.AI_GENERATED, 0.80, 0.60) | |
| dets = [_mk_det("text_fastdetectgpt", Verdict.AI_GENERATED, 0.80)] | |
| out = tg.apply_liability_firewall(res, text, dets) | |
| assert out.verdict == Verdict.UNCERTAIN | |
| def test_ai_verdict_kept_when_non_zeroshot_supports(): | |
| text = " ".join(["word"] * 80) | |
| res = _mk_ensemble(Verdict.AI_GENERATED, 0.80, 0.60) | |
| dets = [ | |
| _mk_det("text_fastdetectgpt", Verdict.AI_GENERATED, 0.80), | |
| _mk_det("text_watermark", Verdict.AI_GENERATED, 0.98), | |
| ] | |
| out = tg.apply_liability_firewall(res, text, dets) | |
| assert out.verdict == Verdict.AI_GENERATED | |
| def test_errored_zeroshot_vote_does_not_count_as_support(monkeypatch): | |
| _enable_zeroshot_guard(monkeypatch) | |
| text = " ".join(["word"] * 80) | |
| res = _mk_ensemble(Verdict.AI_GENERATED, 0.80, 0.60) | |
| dets = [ | |
| _mk_det("text_fastdetectgpt", Verdict.AI_GENERATED, 0.80), | |
| DetectionResult( | |
| detector="text_watermark", p_fake=0.9, verdict=Verdict.AI_GENERATED, | |
| confidence=0.0, error="boom", | |
| ), | |
| ] | |
| out = tg.apply_liability_firewall(res, text, dets) | |
| assert out.verdict == Verdict.UNCERTAIN | |
| def test_real_verdict_on_long_text_is_left_alone(): | |
| text = " ".join(["word"] * 80) | |
| res = _mk_ensemble(Verdict.REAL, 0.10, 0.80) | |
| dets = [_mk_det("text_fastdetectgpt", Verdict.REAL, 0.10)] | |
| out = tg.apply_liability_firewall(res, text, dets) | |
| assert out.verdict == Verdict.REAL | |
| assert out.confidence == 0.80 | |