Files
evanescere/tests/test_llm.py
T
2026-06-02 22:43:12 -07:00

167 lines
4.3 KiB
Python

from evanescere.schemas import ClipCandidate
from evanescere.services.llm import (
TranscriptChunk,
candidate_quota_per_chunk,
dedupe_and_rank_candidates,
parse_clip_response,
render_user_prompt,
)
def test_parse_clip_response():
candidates = parse_clip_response(
"""
{
"clips": [
{
"start_sec": 10,
"end_sec": 60,
"title_zh": "标题",
"summary_zh": "摘要",
"reason": "有趣",
"score": 0.9,
"tags": ["反应"],
"subtitle_priority": "high"
}
]
}
"""
)
assert candidates[0].title_zh == "标题"
def test_parse_clip_response_accepts_candidates_key_and_score_out_of_ten():
candidates = parse_clip_response(
"""
{
"candidates": [
{
"start_sec": 10,
"end_sec": 60,
"title_zh": "标题",
"summary_zh": "摘要",
"reason": "有趣",
"score": 8.5,
"tags": ["反应"],
"subtitle_priority": "high"
}
]
}
"""
)
assert candidates[0].score == 0.85
def test_parse_clip_response_normalizes_score_out_of_hundred():
candidates = parse_clip_response(
"""
{
"clips": [
{
"start_sec": 10,
"end_sec": 60,
"title_zh": "标题",
"summary_zh": "摘要",
"reason": "有趣",
"score": 92,
"tags": ["反应"],
"subtitle_priority": "high"
}
]
}
"""
)
assert candidates[0].score == 0.92
def test_dedupe_and_rank_candidates_filters_short_and_overlapping():
candidates = [
ClipCandidate(
start_sec=0,
end_sec=20,
title_zh="too short",
summary_zh="",
reason="",
score=1,
),
ClipCandidate(
start_sec=0,
end_sec=60,
title_zh="best",
summary_zh="",
reason="",
score=0.9,
),
ClipCandidate(
start_sec=10,
end_sec=65,
title_zh="overlap",
summary_zh="",
reason="",
score=0.8,
),
ClipCandidate(
start_sec=120,
end_sec=180,
title_zh="second",
summary_zh="",
reason="",
score=0.7,
),
]
ranked = dedupe_and_rank_candidates(candidates)
assert [candidate.title_zh for candidate in ranked] == ["best", "second"]
def test_candidate_quota_uses_total_budget_across_chunks():
assert candidate_quota_per_chunk(1, 20) == 20
assert candidate_quota_per_chunk(4, 20) == 5
assert candidate_quota_per_chunk(0, 20) == 0
def test_dedupe_respects_configured_duration_and_total_cap():
candidates = [
ClipCandidate(
start_sec=index * 240,
end_sec=index * 240 + duration,
title_zh=f"clip-{index}",
summary_zh="",
reason="",
score=1 - index / 100,
)
for index, duration in enumerate([60, 180, 181, 90])
]
ranked = dedupe_and_rank_candidates(
candidates,
min_clip_seconds=30,
max_clip_seconds=180,
max_candidates_total=2,
)
assert [candidate.title_zh for candidate in ranked] == ["clip-0", "clip-1"]
def test_render_user_prompt_inserts_configured_values():
prompt = render_user_prompt(
"{max_candidates}|{min_clip_seconds}|{max_clip_seconds}|{chunk_start_sec}|{chunk_end_sec}|{transcript}",
chunk=TranscriptChunk(12.25, 42.75, "hello"),
max_candidates=20,
min_clip_seconds=30,
max_clip_seconds=180,
)
assert prompt == "20|30|180|12.2|42.8|hello"
def test_render_user_prompt_rejects_unknown_placeholder():
try:
render_user_prompt(
"{unknown}",
chunk=TranscriptChunk(0, 1, "hello"),
max_candidates=20,
min_clip_seconds=30,
max_clip_seconds=180,
)
except ValueError as exc:
assert "Unknown placeholder" in str(exc)
else:
raise AssertionError("Expected unknown placeholder to fail")