fix: Task6质量审查修复(MOQ全称/warranty/装柜量触发词+NO_CONTACT_WEB常量引用+阿语回显豁免锁+测试残词)

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-09-29 18:22:29 +08:00
parent 9caf3c4501
commit 528b81b192
3 changed files with 20 additions and 7 deletions
+3 -3
View File
@@ -38,7 +38,8 @@ BOUNDARY_TRIGGER_RE = re.compile(
r"price|pricing|how\s+much|\bcost\b|discount|cheaper|expensive|\bfee\b|"
r"quote|quotation|shipping\s+(fee|cost|time)|freight|tariff|customs\s+fee|"
r"best\s+offer|any\s+offer|free\s+shipping|"
r"sample|certificat|\bmoq\b|container\s+loading|"
r"sample|certificat|\bmoq\b|minimum\s+order|min\s+order|"
r"container\s+loading|fit\s+in|per\s+container|warranty|质保|保修|"
r"book(ing)?\s|reserv|arrange|"
r"delivery|lead\s+time|arriv|"
r"how\s+long\s+(does|will|would|to).*(take|arriv|deliver|ship)|"
@@ -591,8 +592,7 @@ class ConversationManager:
"绝对禁止输出任何号码或邮箱。")
else:
contact_note = ("⚠️ 客户正在索要我方联系方式(最高意向信号)。请逐字使用这句指路:"
"\"Just tap the WhatsApp button at the top of this chat — "
"our manager will reply within 12 hours!\"(邮箱同理指 Email 按钮)。"
f"\"{NO_CONTACT_WEB}\"(邮箱同理指 Email 按钮)。"
"绝对禁止口头报出任何号码或邮箱。")
if not raw_info:
+13
View File
@@ -329,3 +329,16 @@ def test_no_auto_wording_left_in_any_pool():
for t in (pool if isinstance(pool, list) else [pool]):
assert "cars" not in t.lower(), f"{name}: {t}"
assert "什么车" not in t, f"{name}: {t}"
def test_arabic_echo_exemption_consistent():
ar_num = "".join(chr(c) for c in
(0x0669, 0x0666, 0x0666, 0x0665, 0x0660, 0x0661,
0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667)) # 966501234567
# 阿语回显豁免一致性锁定(Task 6 质量审查): 客户用阿语数字留号,AI 无论
# 回显阿语还是 ASCII 形态都豁免——两侧均经 digits_only(内含 translate)。
# 阿语数字用码位构造,避免源文件编码事故。
hist = [{"role": "user", "content": "my whatsapp is " + ar_num}]
assert not no_contact_value("Got it — messaging you at " + ar_num, hist)
assert not no_contact_value("Got it — messaging you at +966501234567", hist)
assert no_contact_value("Reach me at 11987654321", hist) # 不同号(11位)仍拦
+4 -4
View File
@@ -43,7 +43,7 @@ class FakeAI:
INTERESTED = {
"intent_level": "interested", "reasoning": "预算国家车型齐全",
"intent_level": "interested", "reasoning": "预算国家品类齐全",
"contact_info": {}, "info_sufficient": True,
}
@@ -487,7 +487,7 @@ def test_reminder_boundary_covers_delivery_and_arrangement():
{}, "my budget is 20000, any recommendation?", [])
def test_reminder_no_boundary_on_normal_car_questions():
def test_reminder_no_boundary_on_normal_product_questions():
# 规格/配置/库存类正常问题不得误触发
assert "职能边界" not in ConversationManager._build_context_reminder(
{}, "what is the pressure rating of the PE100 pipe?", [])
@@ -562,7 +562,7 @@ def test_clean_stream_passes_through(async_db, monkeypatch):
(manager, conv), _ = _setup(async_db, monkeypatch, ai=FakeAI())
events = []
async def run():
async for e in manager.stream_process_message(conv.session_id, "what cars?"):
async for e in manager.stream_process_message(conv.session_id, "what pipes?"):
events.append(e)
asyncio.run(run())
streamed = "".join(e.get("content", "") for e in events if e["type"] == "stream_chunk")
@@ -613,7 +613,7 @@ def test_sentence_gating_clean_multi_sentence_passthrough(async_db, monkeypatch)
(manager, conv), _ = _setup(async_db, monkeypatch, ai=TwoSentenceAI())
events = []
async def run():
async for e in manager.stream_process_message(conv.session_id, "what cars?"):
async for e in manager.stream_process_message(conv.session_id, "what pipes?"):
events.append(e)
asyncio.run(run())
streamed = "".join(e.get("content", "") for e in events if e["type"] == "stream_chunk")