2026-11-02 22:26:16 +08:00
|
|
|
"""双要话术静态锚(spec 2026-11-02-jiancai-dual-contact-ask §5.3)。
|
|
|
|
|
|
|
|
|
|
首次索要联系方式 = WhatsApp+邮箱一起要(双要);已留资后的确认/收尾话术
|
|
|
|
|
渠道中性(邮箱-only 客户不再听到"发到你 WhatsApp")。wall.json 侧锚在
|
|
|
|
|
本文件前半,system.md/company_facts.md 侧锚在后半(Task 2 追加)。
|
|
|
|
|
"""
|
|
|
|
|
import json
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
SEED = Path(__file__).resolve().parents[1] / "seed_profiles" / "jiancai"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _wall() -> dict:
|
|
|
|
|
return json.loads((SEED / "wall.json").read_text(encoding="utf-8"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ---- wall 侧 ----
|
|
|
|
|
|
|
|
|
|
def test_deflections_dual_ask_all_languages():
|
|
|
|
|
w = _wall()
|
|
|
|
|
assert any("and email" in s for s in w["deflections"]["en"])
|
|
|
|
|
assert any("和邮箱" in s for s in w["deflections"]["zh"])
|
|
|
|
|
assert any("y tu correo" in s for s in w["deflections"]["es"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_pivots_dual_ask_all_languages():
|
|
|
|
|
w = _wall()
|
|
|
|
|
assert "and email" in w["pivots"]["en"][0]
|
|
|
|
|
assert "和邮箱" in w["pivots"]["zh"][0]
|
|
|
|
|
assert "y tu correo" in w["pivots"]["es"][0]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_post_contact_templates_channel_neutral():
|
|
|
|
|
"""已留资确认/收尾模板不含渠道词(三语逐一钉死,防只用 en 子串漏检)。"""
|
|
|
|
|
w = _wall()
|
|
|
|
|
for group in ("deflections_contact", "pivots_contact"):
|
|
|
|
|
for lang, items in w[group].items():
|
|
|
|
|
for s in items:
|
|
|
|
|
assert "whatsapp" not in s.lower(), (group, lang, s)
|
|
|
|
|
assert "whatsapp" not in w["no_contact"]["already"].lower()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_app_reverse_ask_dual_and_synced():
|
|
|
|
|
"""App 反向留资句双要,且 no_contact.app = contact_ask.app 逐字句同源。"""
|
|
|
|
|
w = _wall()
|
|
|
|
|
app = w["no_contact"]["app"]
|
|
|
|
|
assert "and email" in app
|
|
|
|
|
assert app in w["reminders"]["contact_ask"]["app"]
|
2026-11-02 22:54:30 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
# ---- system.md / company_facts.md 侧 ----
|
|
|
|
|
|
|
|
|
|
def _md(name: str) -> str:
|
|
|
|
|
return (SEED / "prompts" / name).read_text(encoding="utf-8")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_system_md_dual_ask_principle_and_pool():
|
|
|
|
|
src = _md("system.md")
|
|
|
|
|
assert "双渠道一次要齐" in src
|
|
|
|
|
assert "WhatsApp and email" in src # en 话术池
|
|
|
|
|
assert "WhatsApp和邮箱" in src # zh 话术池
|
|
|
|
|
# 邮箱轻补两条逐字句原文存活(与引擎 email_light 模板逐字一致)
|
|
|
|
|
assert ("Got it! And an email address would help too — our manager "
|
|
|
|
|
"will send the formal quotation PDF there.") in src
|
|
|
|
|
assert "收到!邮箱也留一个呗?客户经理把正式报价单 PDF 发你邮箱。" in src
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_app_reverse_ask_line_matches_wall():
|
|
|
|
|
w = _wall()
|
|
|
|
|
assert w["no_contact"]["app"] in _md("system.md") # L214 与 wall 一字不差
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_company_facts_dual_ask():
|
|
|
|
|
assert "WhatsApp 和邮箱" in _md("company_facts.md")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_deflections_no_either_or_wording():
|
2026-11-02 23:13:22 +08:00
|
|
|
"""负向锚: 首次索要池不得回退二选一措辞(en "or email"/zh "或邮箱"/es "o correo")。
|
|
|
|
|
|
|
|
|
|
作用域仅限 deflections(首问池):通用化补句子句合法存在于 reminders 与
|
|
|
|
|
system.md("号码或邮箱"/"number or email" 等),若把负向锚扩到那里会误伤——
|
|
|
|
|
别"修正"子串也别扩作用域。"""
|
2026-11-02 22:54:30 +08:00
|
|
|
w = _wall()
|
|
|
|
|
for s in w["deflections"]["en"]:
|
|
|
|
|
assert " or email" not in s
|
|
|
|
|
for s in w["deflections"]["zh"]:
|
|
|
|
|
assert "或邮箱" not in s
|
|
|
|
|
for s in w["deflections"]["es"]:
|
|
|
|
|
assert "o correo" not in s.lower()
|