From 714e22bde56115e2cae138bb99426473bd311450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E5=BF=B5?= Date: Thu, 8 Oct 2026 13:02:17 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20CC=E8=BF=BD=E9=97=AE=E4=B8=89=E8=BD=AE?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E2=80=94=E2=80=94=E5=86=85=E8=81=94=E7=A6=81?= =?UTF-8?q?=E4=BB=A4=E5=85=A8=E9=87=8F=E6=89=A9=E4=BE=8B=E5=A4=96+?= =?UTF-8?q?=E8=AE=A9=E4=BD=8D=E5=94=AF=E4=B8=80=E9=94=9A=E7=82=B9+?= =?UTF-8?q?=E7=A6=81=E6=95=B0=E5=AD=97=E5=9B=9E=E6=98=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Code --- app/services/conversation.py | 25 +++++++++++++++---------- tests/test_lead_email_trigger.py | 28 +++++++++++++++++++++++++--- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/app/services/conversation.py b/app/services/conversation.py index 4caeb62..91f243d 100644 --- a/app/services/conversation.py +++ b/app/services/conversation.py @@ -693,7 +693,8 @@ class ConversationManager: "请逐字使用这句:\"Our manager will reach out to you at your " "WhatsApp shortly with the full quote!\"(中文同理)。" "绝对禁止输出任何号码或邮箱,也绝对禁止再索要客户已提供过" - "的联系方式(缺失渠道可按轻补指引提一次)。") + "的联系方式(缺失渠道可按轻补指引提一次;号码缺国家代码时" + "可请客户重发完整号一次)。") else: contact_note = ("⚠️ 客户正在索要我方联系方式(最高意向信号)。当前为 App 会话," "没有页面按钮——禁止使用任何 tap/button 按钮话术!请逐字使用这句:" @@ -739,15 +740,18 @@ class ConversationManager: # Task 3 防自锁改写(spec 4.1-6): 原"绝对禁止再索要任何联系方式!" # 会抑制缺失渠道轻补——只禁已提供过的渠道,缺失渠道放行一次 parts.append(f"⚠️ 客户已提供联系方式({shown})。绝对禁止再索要客户已提供过" - f"的联系方式;缺失渠道仅可按轻补指引提一次。") + f"的联系方式;缺失渠道仅可按轻补指引提一次;号码缺国家代码" + f"时可请客户重发完整号一次。") if completion_marks == ["_cc_asked"]: - # 生产验收场景①修复(2026-10): CC 追问是对已在手渠道的重发请求, - # 不在"缺失渠道"例外内——同轮两个"逐字使用这句"竞争时 GLM 稳定 - # 服从更显眼的确认句,压制追问。本轮 confirmed 块让位: 不建议 - # 确认句,追问句由下方轻补指引独占 - parts.append("本轮不要使用确认句,直接按下方轻补指引请客户重发带国家" - "代码的完整号码(仅此一次;客户重发或明确不给后,下一轮" - "再回确认句正常解答)。") + # 生产验收场景①修复(2026-10,三轮): CC 追问是对已在手渠道的重发 + # 请求,不在"缺失渠道"例外内——同轮两个"逐字使用这句"竞争时 GLM + # 稳定服从更显眼的确认句,压制追问。本轮 confirmed 块让位: 唯一 + # 逐字锚点=下方轻补指引的追问句;禁数字回显堵住"让位后 GLM 自创 + # 确认句带出真实号码"的回归(墙的客户回显豁免会放行) + parts.append("本轮不要使用确认句,请逐字使用下面这条国家代码追问句请客户" + "重发带国家代码的完整号码(仅此一次,客户重发或明确不给后" + "下一轮恢复正常)。回复中绝不写出号码数字——提到号码一律用 " + "your WhatsApp 指代。") else: parts.append(f"需要回应时可直接逐字使用:\"{NO_CONTACT_ALREADY}\"(中文同理)。" f"确认收到后继续解答客户问题即可,不必急着结束对话。") @@ -756,7 +760,8 @@ class ConversationManager: # Task 3 防自锁改写: 尾部补缺失渠道豁免(与上方改写同因) parts.append("客户已留过联系方式——边界请求直接告知'客户经理会把准确报价/" "安排发到你 WhatsApp'即可,禁止再索要联系方式" - "(缺失渠道可按轻补指引提一次)。") + "(缺失渠道可按轻补指引提一次;号码缺国家代码时可请客户" + "重发完整号一次)。") elif suspect: shown = ", ".join( f"{k}: {' '.join(str(v).split())[:60]}" for k, v in suspect.items()) diff --git a/tests/test_lead_email_trigger.py b/tests/test_lead_email_trigger.py index 7924fd8..4b9b26d 100644 --- a/tests/test_lead_email_trigger.py +++ b/tests/test_lead_email_trigger.py @@ -954,18 +954,40 @@ def test_contact_completion_note_serial_priority(): def test_reminder_cc_round_confirmed_block_yields_to_cc_note(): - """生产验收场景①修复: CC 追问轮 confirmed 块让位——同轮两个"逐字使用这句" - 竞争时 GLM 稳定服从更显眼的 NO_CONTACT_ALREADY 确认句,压制国家代码追问。""" + """生产验收场景①修复(三轮终版): CC 追问轮 confirmed 块让位——同轮两个 + "逐字使用这句"竞争时 GLM 稳定服从更显眼的 NO_CONTACT_ALREADY 确认句, + 压制国家代码追问;让位段给唯一逐字锚点+禁数字回显(防自创确认句带号)。""" raw = {"联系方式": {"whatsapp": "0501234567"}} # 裸号 → CC 追问轮 text = ConversationManager._build_context_reminder(raw, "yes", []) assert "Could you send the full number with the country code" in text # CC 句在场 assert "Got it — our manager will reach out" not in text # 确认句让位(逐字建议消失) assert "本轮不要使用确认句" in text # 让位语义钉死 - # 反向钉死边界: 同画像换带前缀号(非 CC 轮) → 确认句回归 + assert "绝不写出号码数字" in text # 禁数字回显(三轮回归堵漏) + assert "重发完整号一次" in text # confirmed 块禁令已扩例外 + # 反向钉死边界: 同画像换带前缀号(非 CC 轮) → 确认句回归,无让位段 raw2 = {"联系方式": {"whatsapp": "+966501234567"}} text2 = ConversationManager._build_context_reminder(raw2, "yes", []) assert "Got it — our manager will reach out" in text2 assert "本轮不要使用确认句" not in text2 + assert "重发完整号一次" in text2 # 非CC轮禁令例外同样在场 + + +def test_inline_prohibitions_all_carry_reask_exception(): + """三轮修复防第四次漏: conversation.py 三处内联禁令运行时文本(app分支/ + confirmed块/边界分支)都必须带"重发完整号一次"例外——CC 追问是对已在手 + 渠道的重发请求,只豁免缺失渠道的禁令会压制它(生产验收两轮复发的根因)。""" + with open("app/services/conversation.py", encoding="utf-8") as f: + src = f.read() + assert src.count("重发完整号一次") >= 3 + anchors = [ + "也绝对禁止再索要客户已提供过", # contact_note app+已留资分支 + "。绝对禁止再索要客户已提供过", # confirmed 块(句号起,不与app分支互串) + "即可,禁止再索要联系方式", # 边界分支尾补 + ] + for anchor in anchors: + assert anchor in src, anchor + i = src.index(anchor) + assert "重发完整号一次" in src[i:i + 260], anchor # 例外必须就近在场 def test_contact_completion_two_round_serial_and_persistence(async_db, monkeypatch):