Spaces:
Running
Running
| """Tests for the LLM rewrite layer (no model download needed).""" | |
| import pytest | |
| from skyread import llm | |
| _INDICES = { | |
| "cape_jkg": 1500.0, | |
| "cin_jkg": -30.0, | |
| "lcl_hpa": 900.0, | |
| "lfc_hpa": 850.0, | |
| "el_hpa": 200.0, | |
| "k_index": 36.0, | |
| "lifted_index": -4.0, | |
| "total_totals": 50.0, | |
| "pwat_mm": 45.0, | |
| } | |
| def test_clean_rewrite_accepts_normal_sentence() -> None: | |
| text = "「今天下午會打雷,出門帶把傘卡安心。」" | |
| assert llm._clean_rewrite(text) == "今天下午會打雷,出門帶把傘卡安心。" | |
| def test_clean_rewrite_rejects_instruction_echo() -> None: | |
| assert llm._clean_rewrite("好的,以下是改寫後的句子:") is None | |
| def test_clean_rewrite_rejects_empty_and_non_chinese() -> None: | |
| assert llm._clean_rewrite(" ") is None | |
| assert llm._clean_rewrite("Sure! Here is the sentence.") is None | |
| def test_clean_rewrite_rejects_overlong_output() -> None: | |
| assert llm._clean_rewrite("雨" * 300) is None | |
| def test_clean_rewrite_rejects_simplified_chinese() -> None: | |
| # Real failure modes observed from MiniCPM3-4B on the GPU box. | |
| assert llm._clean_rewrite("下午有機會打雷下雨,记得帶把伞。") is None | |
| assert llm._clean_rewrite("今天天氣挺稳当的,不太會打雷下雨。") is None | |
| assert llm._clean_rewrite("棉被可以拿出来晒太陽。") is None | |
| assert llm._clean_rewrite("可能会有小小滴雨滴哦!") is None | |
| assert llm._clean_rewrite("今天温度舒适,适合外出。") is None | |
| def test_clean_rewrite_accepts_pure_traditional_sentence() -> None: | |
| text = "下午可能會打雷下雨,記得帶把傘,棉被先別曬喔。" | |
| assert llm._clean_rewrite(text) == text | |
| def test_interpret_llm_falls_back_when_generation_fails( | |
| monkeypatch: pytest.MonkeyPatch, | |
| ) -> None: | |
| def boom(prompt: str) -> str: | |
| raise RuntimeError("model exploded") | |
| monkeypatch.setattr(llm, "_generate", boom) | |
| cards, engine = llm.interpret_llm(_INDICES, "test") | |
| assert engine == "rule-based" | |
| assert cards["pro"].startswith("【同行版") | |
| assert cards["grandma"].startswith("【生活版】") | |
| def test_interpret_llm_falls_back_when_output_unusable( | |
| monkeypatch: pytest.MonkeyPatch, | |
| ) -> None: | |
| monkeypatch.setattr(llm, "_generate", lambda prompt: "Here you go!") | |
| cards, engine = llm.interpret_llm(_INDICES, "test") | |
| assert engine == "rule-based" | |
| def test_interpret_llm_retries_until_a_usable_rewrite( | |
| monkeypatch: pytest.MonkeyPatch, | |
| ) -> None: | |
| outputs = iter(["可能会有雨。", "下午可能下雨,帶把傘較安心。"]) | |
| monkeypatch.setattr(llm, "_generate", lambda prompt: next(outputs)) | |
| cards, engine = llm.interpret_llm(_INDICES, "test") | |
| assert engine == "llm" | |
| assert cards["grandma"] == "【生活版】下午可能下雨,帶把傘較安心。" | |
| def test_interpret_llm_gives_up_after_max_attempts( | |
| monkeypatch: pytest.MonkeyPatch, | |
| ) -> None: | |
| calls: list[str] = [] | |
| def always_simplified(prompt: str) -> str: | |
| calls.append(prompt) | |
| return "可能会有雨。" | |
| monkeypatch.setattr(llm, "_generate", always_simplified) | |
| cards, engine = llm.interpret_llm(_INDICES, "test") | |
| assert engine == "rule-based" | |
| assert len(calls) == llm._MAX_ATTEMPTS | |
| def test_interpret_llm_rewrites_only_grandma_card( | |
| monkeypatch: pytest.MonkeyPatch, | |
| ) -> None: | |
| monkeypatch.setattr(llm, "_generate", lambda prompt: "下午會打雷,帶傘較妥當。") | |
| cards, engine = llm.interpret_llm(_INDICES, "test") | |
| assert engine == "llm" | |
| assert cards["grandma"] == "【生活版】下午會打雷,帶傘較妥當。" | |
| assert cards["pro"].startswith("【同行版") # untouched, rule-based numbers | |