Spaces:
Sleeping
Sleeping
File size: 6,583 Bytes
5ccdeee 639b641 5ccdeee 639b641 5ccdeee 639b641 fea7356 639b641 5ccdeee fea7356 7414383 639b641 7414383 5a386b9 639b641 5a386b9 639b641 5a386b9 639b641 5a386b9 639b641 5a386b9 639b641 5a386b9 | 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 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | import json
import os
import subprocess
import sys
import pytest
from unittest.mock import patch
from viral_script_engine.agents.critic import CritiqueClaim, CritiqueOutput, CriticAgent, CriticParseError
from viral_script_engine.evaluation.critic_evaluator import CriticEvaluator, EvaluationResult
from tests.conftest import MOCK_VALID_RESPONSE
MOCK_INVALID_RESPONSE = "Here is my feedback: The hook is weak and the CTA is missing."
# ββ Task 2: Model parsing tests βββββββββββββββββββββββββββββββββββββββββββββββ
def test_critique_claim_parses_valid_json():
data = {
"claim_id": "C1",
"critique_class": "hook_weakness",
"claim_text": "The hook is too slow.",
"timestamp_range": "0:00-0:03",
"evidence": "Let me tell you a secret",
"is_falsifiable": True,
"severity": "high",
}
claim = CritiqueClaim(**data)
assert claim.claim_id == "C1"
assert claim.severity == "high"
def test_critique_output_parses_valid_json():
data = {
"claims": [
{
"claim_id": "C1",
"critique_class": "hook_weakness",
"claim_text": "Weak hook.",
"timestamp_range": "0:00-0:03",
"evidence": "Let me tell you",
"is_falsifiable": True,
"severity": "high",
}
],
"overall_severity": "high",
"raw_response": '{"claims": []}',
}
output = CritiqueOutput(**data)
assert len(output.claims) == 1
# ββ Task 4: CriticEvaluator tests ββββββββββββββββββββββββββββββββββββββββββββ
SCRIPT_TEXT = "Let me tell you a secret about money. First, save twenty percent. Second, invest in index funds. Finally, avoid lifestyle inflation. That is all."
def _make_output(claims_data, overall="medium"):
claims = [CritiqueClaim(**c) for c in claims_data]
return CritiqueOutput(claims=claims, overall_severity=overall, raw_response="{}")
def test_evaluator_passes_good_critique():
output = _make_output([
{"claim_id": "C1", "critique_class": "hook_weakness", "claim_text": "x", "timestamp_range": "0:00-0:03", "evidence": "Let me tell you a secret", "is_falsifiable": True, "severity": "high"},
{"claim_id": "C2", "critique_class": "cta_buried", "claim_text": "x", "timestamp_range": "0:10-0:15", "evidence": "That is all", "is_falsifiable": True, "severity": "medium"},
{"claim_id": "C3", "critique_class": "pacing_issue", "claim_text": "x", "timestamp_range": "N/A", "evidence": "save twenty percent", "is_falsifiable": True, "severity": "low"},
])
evaluator = CriticEvaluator()
result = evaluator.evaluate(output, SCRIPT_TEXT)
assert result.passes_gate is True
assert result.claim_count == 3
assert result.specificity_score >= 0.6
assert result.falsifiability_score >= 0.7
def test_evaluator_fails_too_few_claims():
output = _make_output([
{"claim_id": "C1", "critique_class": "hook_weakness", "claim_text": "x", "timestamp_range": "0:00-0:03", "evidence": "Let me tell you", "is_falsifiable": True, "severity": "high"},
{"claim_id": "C2", "critique_class": "cta_buried", "claim_text": "x", "timestamp_range": "0:10", "evidence": "invest", "is_falsifiable": True, "severity": "medium"},
])
evaluator = CriticEvaluator()
result = evaluator.evaluate(output, SCRIPT_TEXT)
assert result.passes_gate is False
assert result.claim_count == 2
def test_evaluator_fails_low_specificity():
output = _make_output([
{"claim_id": "C1", "critique_class": "hook_weakness", "claim_text": "x", "timestamp_range": "0:00-0:03", "evidence": "this quote is not in the script", "is_falsifiable": True, "severity": "high"},
{"claim_id": "C2", "critique_class": "cta_buried", "claim_text": "x", "timestamp_range": "0:10", "evidence": "also not in script", "is_falsifiable": False, "severity": "medium"},
{"claim_id": "C3", "critique_class": "pacing_issue", "claim_text": "x", "timestamp_range": "N/A", "evidence": "still not in script", "is_falsifiable": False, "severity": "low"},
])
evaluator = CriticEvaluator()
result = evaluator.evaluate(output, SCRIPT_TEXT)
assert result.passes_gate is False
# ββ Task 5: CLI exit-code test ββββββββββββββββββββββββββββββββββββββββββββββββ
def test_cli_dry_run_exits_zero_or_one():
"""CLI must exit 0 (pass) or 1 (fail) β never crash with unhandled exception."""
result = subprocess.run(
[sys.executable, "scripts/run_critic_gate.py", "--dry-run"],
capture_output=True,
text=True,
cwd=str(__import__("pathlib").Path(__file__).parent.parent),
env={**os.environ},
)
assert result.returncode in (0, 1), (
f"Unexpected exit code: {result.returncode}\nSTDERR: {result.stderr}"
)
# ββ Task 6: Mocked CriticAgent tests βββββββββββββββββββββββββββββββββββββββββ
def test_critic_agent_returns_critique_output(mock_llm):
agent = CriticAgent(backend="qwen")
result = agent.critique("Some script text here", "Mumbai", "Reels", "finance")
assert len(result.claims) == 3
assert result.claims[0].claim_id == "C1"
assert result.overall_severity == "high"
def test_critic_agent_retries_on_bad_json(monkeypatch):
calls = []
def fake_generate(self, sys_prompt, usr_prompt, **kw):
calls.append(usr_prompt)
if len(calls) == 1:
return MOCK_INVALID_RESPONSE
return MOCK_VALID_RESPONSE
monkeypatch.setattr(
"viral_script_engine.agents.llm_backend.LLMBackend.generate", fake_generate
)
agent = CriticAgent(backend="qwen")
result = agent.critique("Some script text here", "Mumbai", "Reels", "finance")
assert len(result.claims) == 3
assert len(calls) == 2
def test_critic_agent_raises_parse_error_after_two_failures(monkeypatch):
monkeypatch.setattr(
"viral_script_engine.agents.llm_backend.LLMBackend.generate",
lambda self, sys_prompt, usr_prompt, **kw: MOCK_INVALID_RESPONSE,
)
agent = CriticAgent(backend="qwen")
with pytest.raises(CriticParseError):
agent.critique("Some script text here", "Mumbai", "Reels", "finance")
|