Files
life-echo/api/tests/test_prompt_language_branching.py

208 lines
6.5 KiB
Python
Raw Normal View History

"""Prompt builders 在 language='en' 时返回纯 ASCIIlanguage='zh' 时含中文(防回归)。"""
from __future__ import annotations
from app.agents.chat.output_rules import (
chat_output_rules,
chat_output_rules_en,
chat_voice_style,
chat_voice_style_en,
)
from app.agents.chat.personas import AGENT_NAME_EN, AGENT_NAME_ZH, agent_name
from app.agents.chat.prompts_conversation import (
get_guided_conversation_prompt,
get_opening_prompt,
)
from app.agents.chat.prompts_profile import (
get_profile_followup_prompt,
get_profile_greeting_prompt,
)
from app.agents.memoir.prompts import (
get_creative_title_json_prompt,
get_memoir_fidelity_facts_only_prompt,
get_memoir_fidelity_system_prompt,
get_narrative_json_prompt,
)
from app.agents.stage_constants import (
chapter_category_display,
stage_display_name,
)
def _has_cjk(s: str) -> bool:
return any("\u4e00" <= ch <= "\u9fff" for ch in s)
# ── chat output rules ────────────────────────────────────────────────
def test_chat_output_rules_en_has_no_cjk() -> None:
txt = chat_output_rules_en()
assert txt.strip()
assert not _has_cjk(txt)
def test_chat_voice_style_en_has_no_cjk() -> None:
txt = chat_voice_style_en()
assert txt.strip()
assert not _has_cjk(txt)
def test_chat_output_rules_zh_unchanged_has_cjk() -> None:
assert _has_cjk(chat_output_rules())
def test_chat_voice_style_zh_unchanged_has_cjk() -> None:
assert _has_cjk(chat_voice_style())
# ── memoir narrative ────────────────────────────────────────────────
def test_memoir_fidelity_facts_only_en_branch_has_no_cjk() -> None:
assert not _has_cjk(get_memoir_fidelity_facts_only_prompt(language="en"))
def test_memoir_fidelity_facts_only_zh_default_has_cjk() -> None:
assert _has_cjk(get_memoir_fidelity_facts_only_prompt())
def test_memoir_fidelity_system_en_branch_has_no_cjk() -> None:
assert not _has_cjk(get_memoir_fidelity_system_prompt(language="en"))
def test_get_narrative_json_prompt_en_has_no_cjk() -> None:
out = get_narrative_json_prompt(
stage="childhood",
slots={"place": "the village"},
new_content="[User's oral memory this turn]\nI grew up by the river.",
language="en",
)
assert not _has_cjk(out)
assert "paragraphs" in out
def test_get_narrative_json_prompt_zh_default_has_cjk() -> None:
out = get_narrative_json_prompt(
stage="childhood",
slots={"place": "村里"},
new_content="【本段用户口述】\n我小时候住在河边。",
)
assert _has_cjk(out)
# ── memoir title ────────────────────────────────────────────────────
def test_creative_title_json_prompt_en_has_no_cjk() -> None:
out = get_creative_title_json_prompt(
stage="childhood",
emotion="warm",
slots={"place": "the river"},
language="en",
)
assert not _has_cjk(out)
assert "title" in out
def test_creative_title_json_prompt_zh_default_has_cjk() -> None:
out = get_creative_title_json_prompt(
stage="childhood",
emotion="warm",
slots={"place": "河边"},
)
assert _has_cjk(out)
# ── stage / category display helpers ────────────────────────────────
def test_stage_display_name_branches() -> None:
assert stage_display_name("childhood", language="en") == "Childhood"
assert stage_display_name("childhood", language="zh") == "童年时光"
# unknown stages pass through
assert stage_display_name("unknown", language="en") == "unknown"
def test_chapter_category_display_branches() -> None:
assert chapter_category_display("childhood", language="en") == "Childhood & Early Years"
assert chapter_category_display("childhood", language="zh") == "童年与成长背景"
# ── agent brand name (interviewer identity) ─────────────────────────
def test_agent_name_constants_aligned_with_brand() -> None:
"""中英品牌名是单一来源prompt / UI / 兜底标题统一引用此处。"""
assert AGENT_NAME_ZH == "岁月知己"
assert AGENT_NAME_EN == "Life Echo"
def test_agent_name_helper_handles_inputs() -> None:
assert agent_name("zh") == "岁月知己"
assert agent_name("en") == "Life Echo"
assert agent_name("EN") == "Life Echo"
assert agent_name(" en ") == "Life Echo"
assert agent_name(None) == "岁月知己" # type: ignore[arg-type]
assert agent_name("ja") == "岁月知己"
def test_profile_greeting_prompt_introduces_life_echo_in_en() -> None:
en = get_profile_greeting_prompt(
["birth_year", "occupation"], nickname="Sam", language="en"
)
assert "Life Echo" in en
assert "岁月知己" not in en
def test_profile_greeting_prompt_keeps_chinese_brand_in_zh() -> None:
zh = get_profile_greeting_prompt(["birth_year"], nickname="老王")
assert "岁月知己" in zh
assert "Life Echo" not in zh
def test_profile_followup_prompt_introduces_life_echo_in_en() -> None:
en = get_profile_followup_prompt(
missing_fields=["occupation"],
filled_fields={"birth_year": "1990"},
language="en",
)
assert "Life Echo" in en
assert "岁月知己" not in en
def test_profile_followup_prompt_full_basics_branch_introduces_life_echo() -> None:
en = get_profile_followup_prompt(
missing_fields=[],
filled_fields={
"birth_year": "1990",
"birth_place": "Boston",
"grew_up_place": "Boston",
"occupation": "engineer",
},
language="en",
)
assert "Life Echo" in en
assert "岁月知己" not in en
def test_opening_prompt_introduces_life_echo_in_en() -> None:
out = get_opening_prompt(
current_stage="childhood",
empty_slots_readable=["place", "people"],
language="en",
)
assert "Life Echo" in out
assert "岁月知己" not in out
def test_guided_conversation_prompt_introduces_life_echo_in_en() -> None:
out = get_guided_conversation_prompt(
current_stage="childhood",
empty_slots=["place"],
filled_slots={},
language="en",
)
assert "Life Echo" in out
assert "岁月知己" not in out