feat(music-lab): pipeline 4축 AI 검토 + 휴리스틱 폴백
This commit is contained in:
84
music-lab/tests/test_review.py
Normal file
84
music-lab/tests/test_review.py
Normal file
@@ -0,0 +1,84 @@
|
||||
import pytest
|
||||
import respx
|
||||
from httpx import Response
|
||||
from app.pipeline import review
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@respx.mock
|
||||
async def test_review_returns_pass_when_above_threshold(monkeypatch):
|
||||
monkeypatch.setenv("ANTHROPIC_API_KEY", "k")
|
||||
body = {"content": [{"type": "text", "text":
|
||||
'{"metadata_quality":{"score":80,"notes":"x"},'
|
||||
'"policy_compliance":{"score":90,"issues":[]},'
|
||||
'"viewer_experience":{"score":75,"notes":"y"},'
|
||||
'"trend_alignment":{"score":70,"matched_keywords":["lofi"]},'
|
||||
'"summary":"good"}'}]}
|
||||
respx.post("https://api.anthropic.com/v1/messages").mock(return_value=Response(200, json=body))
|
||||
result = await review.run_4_axis(
|
||||
pipeline={"id": 1}, track={"title": "x", "genre": "lo-fi", "bpm": 85},
|
||||
video_meta={"length_sec": 120, "resolution": "1920x1080"},
|
||||
metadata={"title": "Y", "description": "Z", "tags": ["lofi"], "category_id": 10},
|
||||
thumbnail_url="/m/x.jpg", trend_top=["lofi"],
|
||||
weights={"meta": 25, "policy": 30, "viewer": 25, "trend": 20},
|
||||
threshold=60,
|
||||
)
|
||||
assert result["verdict"] == "pass"
|
||||
expected_total = 0.25 * 80 + 0.30 * 90 + 0.25 * 75 + 0.20 * 70
|
||||
assert result["weighted_total"] == pytest.approx(expected_total, abs=0.01)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@respx.mock
|
||||
async def test_review_fail_below_threshold(monkeypatch):
|
||||
monkeypatch.setenv("ANTHROPIC_API_KEY", "k")
|
||||
body = {"content": [{"type": "text", "text":
|
||||
'{"metadata_quality":{"score":40,"notes":"x"},'
|
||||
'"policy_compliance":{"score":50,"issues":[]},'
|
||||
'"viewer_experience":{"score":30,"notes":"y"},'
|
||||
'"trend_alignment":{"score":20,"matched_keywords":[]},'
|
||||
'"summary":"bad"}'}]}
|
||||
respx.post("https://api.anthropic.com/v1/messages").mock(return_value=Response(200, json=body))
|
||||
result = await review.run_4_axis(
|
||||
pipeline={"id": 2}, track={"title": "x", "genre": "lo-fi", "bpm": 85},
|
||||
video_meta={"length_sec": 120, "resolution": "1920x1080"},
|
||||
metadata={"title": "Y", "description": "Z", "tags": [], "category_id": 10},
|
||||
thumbnail_url="/m/x.jpg", trend_top=[],
|
||||
weights={"meta": 25, "policy": 30, "viewer": 25, "trend": 20},
|
||||
threshold=60,
|
||||
)
|
||||
assert result["verdict"] == "fail"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@respx.mock
|
||||
async def test_review_heuristic_fallback_on_llm_error(monkeypatch):
|
||||
monkeypatch.setenv("ANTHROPIC_API_KEY", "k")
|
||||
respx.post("https://api.anthropic.com/v1/messages").mock(return_value=Response(500))
|
||||
result = await review.run_4_axis(
|
||||
pipeline={"id": 3}, track={"title": "x", "genre": "lo-fi", "bpm": 85, "duration_sec": 120},
|
||||
video_meta={"length_sec": 120, "resolution": "1920x1080"},
|
||||
metadata={"title": "Y" * 30, "description": "Z" * 200, "tags": ["a", "b", "c", "d", "e"], "category_id": 10},
|
||||
thumbnail_url="/m/x.jpg", trend_top=["lofi"],
|
||||
weights={"meta": 25, "policy": 30, "viewer": 25, "trend": 20},
|
||||
threshold=60,
|
||||
)
|
||||
assert result["used_fallback"] is True
|
||||
assert "weighted_total" in result
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_review_heuristic_when_no_api_key(monkeypatch):
|
||||
monkeypatch.delenv("ANTHROPIC_API_KEY", raising=False)
|
||||
result = await review.run_4_axis(
|
||||
pipeline={"id": 4}, track={"title": "x", "genre": "lo-fi", "bpm": 85, "duration_sec": 120},
|
||||
video_meta={"length_sec": 120, "resolution": "1920x1080"},
|
||||
metadata={"title": "Test Title", "description": "Description here, more text " * 5,
|
||||
"tags": ["lofi", "study", "chill", "ambient", "instrumental"], "category_id": 10},
|
||||
thumbnail_url="/m/x.jpg", trend_top=["lofi"],
|
||||
weights={"meta": 25, "policy": 30, "viewer": 25, "trend": 20},
|
||||
threshold=60,
|
||||
)
|
||||
assert result["used_fallback"] is True
|
||||
# 휴리스틱: 좋은 메타+영상길이 일치+태그 트렌드 겹침 → pass 기대
|
||||
assert result["verdict"] == "pass"
|
||||
Reference in New Issue
Block a user