"""번역 프롬프트 형식 회귀 테스트. Seed-X 는 chat template 없는 번역 전용 completion 모델이라 모델 카드가 정한 형식을 한 글자도 벗어나면 안 된다. 특히 끝의 `<언어코드>` 태그는 PPO 학습에 쓰인 것이라 빠지면 품질이 무너진다. """ from __future__ import annotations import pytest from livesub.constants import LANGUAGE_CODES, LANGUAGES from livesub.models.glossary import Glossary, GlossaryEntry from livesub.models.tiers import TIERS, MTBackend, PromptStyle, get_tier from livesub.models.translator import build_seedx_prompt def test_seedx_prompt_matches_model_card_exactly(): """모델 카드 예시: "Translate the following English sentence into Chinese:\\nMay the force be with you " """ assert build_seedx_prompt("May the force be with you", "en", "zh") == ( "Translate the following English sentence into Chinese:\n" "May the force be with you " ) def test_seedx_prompt_always_ends_with_target_language_tag(): for target in LANGUAGE_CODES: prompt = build_seedx_prompt("hello", "en", target) assert prompt.endswith(f" <{target}>"), f"{target} 태그 누락" def test_seedx_prompt_has_no_extra_instructions(): """지시문을 끼워 넣으면 Seed-X 의 학습 분포를 벗어난다.""" prompt = build_seedx_prompt("fall back now", "en", "ko") lowered = prompt.lower() for forbidden in ("casual", "output only", "glossary", "game or broadcast", "용어"): assert forbidden not in lowered assert prompt.count("\n") == 1 # 지시문 한 줄 + 본문 한 줄 @pytest.mark.parametrize("code", LANGUAGE_CODES) def test_every_language_has_a_seedx_tag(code): assert LANGUAGES[code]["seedx"], f"{code} 에 seedx 태그가 없습니다" def test_seedx_tier_does_not_use_prompt_glossary(): """Seed-X 는 지시문을 못 알아들으므로 프롬프트 용어집을 쓰면 안 된다.""" precision = get_tier("precision") assert precision.mt.prompt_style is PromptStyle.SEEDX assert precision.mt.supports_prompt_glossary is False def test_instruct_tier_uses_prompt_glossary(): ultimate = get_tier("ultimate") assert ultimate.mt.prompt_style is PromptStyle.INSTRUCT assert ultimate.mt.supports_prompt_glossary is True def test_seq2seq_tiers_never_use_prompt_glossary(): for tier in TIERS.values(): if tier.mt.backend is MTBackend.CTRANSLATE2: assert tier.mt.prompt_style is PromptStyle.NONE assert tier.mt.supports_prompt_glossary is False def test_every_llm_tier_declares_a_prompt_style(): for tier in TIERS.values(): if tier.mt.backend is MTBackend.TRANSFORMERS: assert tier.mt.prompt_style is not PromptStyle.NONE, tier.key def test_glossary_survives_seedx_placeholder_path(): """Seed-X 경로에서 용어집이 프롬프트가 아니라 치환으로 동작하는지.""" g = Glossary([GlossaryEntry("Nexus", {"ko": "넥서스"})]) protected, repl = g.protect("push to the Nexus", "ko") prompt = build_seedx_prompt(protected, "en", "ko") assert "Nexus" not in prompt # 모델이 건드릴 수 없게 가려짐 assert prompt.endswith(" ") # 모델이 플레이스홀더를 그대로 통과시켰다고 가정 assert Glossary.restore("#0#로 밀어", repl) == "넥서스로 밀어"