fix: Task7+8质量审查修复(PUSH前缀ai-kefu-jc隔离+config默认值同步+载体词清理)
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -19,7 +19,7 @@ NOTIFY_EMAIL=notify@example.com
|
||||
PUSH_ENABLED=false
|
||||
PUSH_API_URL=https://uniservice.server.hnxinyouhe.com/open/v1/inquiry/push
|
||||
PUSH_API_KEY=your_uniservice_api_key_here
|
||||
PUSH_EXTERNAL_KEY_PREFIX=ai-kefu
|
||||
PUSH_EXTERNAL_KEY_PREFIX=ai-kefu-jc
|
||||
|
||||
# 应用配置
|
||||
APP_HOST=0.0.0.0
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ class Settings(BaseSettings):
|
||||
PUSH_ENABLED: bool = False
|
||||
PUSH_API_URL: str = "https://uniservice.server.hnxinyouhe.com/open/v1/inquiry/push"
|
||||
PUSH_API_KEY: str = ""
|
||||
PUSH_EXTERNAL_KEY_PREFIX: str = "ai-kefu"
|
||||
PUSH_EXTERNAL_KEY_PREFIX: str = "ai-kefu-jc"
|
||||
PUSH_TIMEOUT_SECONDS: float = 10.0
|
||||
PUSH_MAX_ATTEMPTS: int = 3
|
||||
PUSH_RETRY_BACKOFF_BASE: float = 1.0 # 尝试间隔 1s/2s(3 次尝试、2 次间隔)
|
||||
|
||||
@@ -139,7 +139,7 @@ def test_scan_full_history_not_only_last():
|
||||
{"role": "assistant", "content": "hey"},
|
||||
{"role": "user", "content": "mail me a@b.com"},
|
||||
{"role": "assistant", "content": "got it"},
|
||||
{"role": "user", "content": "how much is tang"},
|
||||
{"role": "user", "content": "how much is pvc"},
|
||||
]
|
||||
assert scan_user_messages(msgs) == {"email": "a@b.com"}
|
||||
|
||||
|
||||
@@ -337,7 +337,7 @@ def test_widget_never_ends_without_contact_all_sources(async_db, monkeypatch):
|
||||
# D3/P1: widget 来源 interested+sufficient 但无联系方式 → 永不结束
|
||||
(manager, conv), _ = _setup(async_db, monkeypatch,
|
||||
ai=_mk_ai({}, evaluate=INTERESTED))
|
||||
for text in ("hi", "kenya", "20k", "tang", "ship how"):
|
||||
for text in ("hi", "kenya", "20k", "pvc", "ship how"):
|
||||
asyncio.run(_send(manager, conv.session_id, text))
|
||||
conv_now = asyncio.run(manager.get_by_session(conv.session_id))
|
||||
assert conv_now.status == ConversationStatus.active
|
||||
@@ -437,7 +437,7 @@ def test_conversation_never_auto_ends_even_with_contact_and_interested(async_db,
|
||||
# 决策A(2026-08-18): 自动结束移除——即使 contact+interested+≥3轮也保持 active
|
||||
ai = _mk_ai({"联系方式": {"email": "a@b.com"}}, evaluate=INTERESTED)
|
||||
(manager, conv), _ = _setup(async_db, monkeypatch, ai=ai)
|
||||
for text in ("hi", "kenya", "20k", "tang", "more questions"):
|
||||
for text in ("hi", "kenya", "20k", "pvc", "more questions"):
|
||||
asyncio.run(_send(manager, conv.session_id, text))
|
||||
conv_now = asyncio.run(manager.get_by_session(conv.session_id))
|
||||
assert conv_now.status == ConversationStatus.active
|
||||
@@ -525,7 +525,7 @@ def test_reminder_budget_routes_to_budget_playbook():
|
||||
assert "职能边界" in text and "反问意向" in text and "复述预算" in text
|
||||
# 纯问价 → 迂回话术,不含预算路径字样
|
||||
text2 = ConversationManager._build_context_reminder(
|
||||
{}, "how much is the Tang?", [])
|
||||
{}, "how much is the DN800?", [])
|
||||
assert "职能边界" in text2 and "反问意向" not in text2
|
||||
|
||||
|
||||
@@ -537,7 +537,7 @@ class DirtyAI(FakeAI):
|
||||
"""流出的回复里带真实价格(复刻冒烟实测的破防形态)。"""
|
||||
|
||||
async def stream_chat(self, messages, context=""):
|
||||
for token in ("the Tang starts at ", "$25k", " for the EV version"):
|
||||
for token in ("the DN800 starts at ", "$25k", " per ton"):
|
||||
yield token
|
||||
|
||||
|
||||
@@ -765,7 +765,7 @@ def test_no_contact_wall_already_contact_no_reask(async_db, monkeypatch):
|
||||
async_db, monkeypatch,
|
||||
ai=EchoAI(extract={}), source=ConversationSource.standalone)
|
||||
asyncio.run(_send(manager, conv.session_id, "my whatsapp is 254712 345678"))
|
||||
asyncio.run(_send(manager, conv.session_id, "so how much is tang?"))
|
||||
asyncio.run(_send(manager, conv.session_id, "so how much is pvc?"))
|
||||
msgs = asyncio.run(manager._load_history(conv.id))
|
||||
tail = [m["content"] for m in msgs if m["role"] == "assistant"][-1]
|
||||
# 精确断言(评审加固): 负向断言("WhatsApp?" not in)对三种替换句都空转通过,
|
||||
@@ -809,7 +809,7 @@ def test_reask_wall_closed_without_contact(async_db, monkeypatch):
|
||||
(manager, conv), _ = _setup(async_db, monkeypatch,
|
||||
ai=AskAI(extract={}),
|
||||
source=ConversationSource.standalone)
|
||||
asyncio.run(_send(manager, conv.session_id, "how much is the tang?"))
|
||||
asyncio.run(_send(manager, conv.session_id, "how much is the PVC?"))
|
||||
msgs = asyncio.run(manager._load_history(conv.id))
|
||||
tail = [m["content"] for m in msgs if m["role"] == "assistant"][-1]
|
||||
assert "What's your WhatsApp or email?" in tail # 合法索要未被丢
|
||||
@@ -855,7 +855,7 @@ def test_e2e_no_reasking_after_contact_provided(async_db, monkeypatch):
|
||||
asyncio.run(_send(manager, conv.session_id, "hi there"))
|
||||
asyncio.run(_send(manager, conv.session_id,
|
||||
"0712 345 678 is my whatsapp btw"))
|
||||
asyncio.run(_send(manager, conv.session_id, "so how much is the Tang?"))
|
||||
asyncio.run(_send(manager, conv.session_id, "so how much is the DN800?"))
|
||||
asyncio.run(_send(manager, conv.session_id, "and shipping to Kenya?"))
|
||||
# 第2轮起每轮提醒都必须含"已提供+禁止再索要"
|
||||
for ctx in ai.contexts[1:]:
|
||||
|
||||
@@ -40,7 +40,7 @@ def test_push_settings_defaults():
|
||||
assert s.PUSH_API_URL == (
|
||||
"https://uniservice.server.hnxinyouhe.com/open/v1/inquiry/push")
|
||||
assert s.PUSH_API_KEY == ""
|
||||
assert s.PUSH_EXTERNAL_KEY_PREFIX == "ai-kefu"
|
||||
assert s.PUSH_EXTERNAL_KEY_PREFIX == "ai-kefu-jc" # 与汽车项目线索键空间隔离
|
||||
assert s.PUSH_TIMEOUT_SECONDS == 10.0
|
||||
assert s.PUSH_MAX_ATTEMPTS == 3
|
||||
assert s.PUSH_RETRY_BACKOFF_BASE == 1.0
|
||||
|
||||
Reference in New Issue
Block a user