新增
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""自动回复短句净化、验证页识别与发送节流测试。"""
|
||||
|
||||
from collections import deque
|
||||
from unittest import TestCase, main, mock
|
||||
|
||||
import numpy as np
|
||||
|
||||
from ai_chat import (
|
||||
_dify_query_from_chat,
|
||||
_history_messages,
|
||||
_humanize,
|
||||
_repair_obvious_mismatch,
|
||||
latest_customer_message,
|
||||
)
|
||||
from wechat_bot import WeChatBot, looks_like_security_verification
|
||||
|
||||
|
||||
class ReplyStyleTest(TestCase):
|
||||
CHAT_SAMPLE = (
|
||||
"高兴亮 7/28 15:54:54\n"
|
||||
"抱歉刚才说得太复杂了,就是让您多休息,别太累着\n"
|
||||
"一个小迷糊@微信@微信联系人 7/28 15:55:08\n"
|
||||
"你多大了"
|
||||
)
|
||||
|
||||
def test_removes_markdown_canned_closing_and_extra_questions(self):
|
||||
reply = _humanize(
|
||||
"### 回复\n"
|
||||
"1. 您好,先别太着急,今天血糖大概多少?\n"
|
||||
"2. 是空腹还是餐后测的?\n"
|
||||
"3. 希望以上建议能帮到您。"
|
||||
)
|
||||
self.assertNotIn("###", reply)
|
||||
self.assertNotIn("希望以上建议能帮到您", reply)
|
||||
self.assertNotIn("您好", reply)
|
||||
self.assertEqual(reply.count("?") + reply.count("?"), 1)
|
||||
self.assertLessEqual(len(reply), 100)
|
||||
|
||||
def test_emergency_reply_keeps_three_short_sentences(self):
|
||||
reply = _humanize("先别慌。现在立即拨打120。不要自己开车。之后再联系我。")
|
||||
self.assertIn("120", reply)
|
||||
self.assertIn("不要自己开车", reply)
|
||||
self.assertNotIn("之后再联系我", reply)
|
||||
|
||||
def test_extracts_the_real_latest_customer_sentence(self):
|
||||
self.assertEqual(latest_customer_message(self.CHAT_SAMPLE), "你多大了")
|
||||
|
||||
def test_old_raw_history_does_not_relabel_staff_reply_as_customer(self):
|
||||
with mock.patch("ai_chat.ai_config.AI_CONTEXT_ENABLED", True):
|
||||
messages = _history_messages([
|
||||
{"role": "user", "content": self.CHAT_SAMPLE},
|
||||
{"role": "assistant", "content": "四十来岁啦。"},
|
||||
])
|
||||
self.assertEqual(messages[0]["content"], "你多大了")
|
||||
|
||||
def test_age_question_mismatch_is_repaired(self):
|
||||
reply = _repair_obvious_mismatch(
|
||||
"您别管我多大,把身体养好才是正经事。",
|
||||
self.CHAT_SAMPLE,
|
||||
)
|
||||
self.assertEqual(reply, "四十来岁啦,怎么突然问这个?")
|
||||
|
||||
def test_casual_tired_message_is_not_redirected_to_hospital(self):
|
||||
reply = _repair_obvious_mismatch(
|
||||
"血糖波动会让人乏力,建议去医院让医生调整方案。",
|
||||
"一个小迷糊 7/28 14:55:43\n好困啊",
|
||||
)
|
||||
self.assertEqual(reply, "困了就先眯一会儿,别硬撑着。")
|
||||
|
||||
def test_dify_query_marks_latest_message_as_only_target(self):
|
||||
query = _dify_query_from_chat(self.CHAT_SAMPLE, history=[])
|
||||
self.assertIn("【本轮是日常闲聊】", query)
|
||||
self.assertIn("【客户最后一句|唯一回答对象】\n你多大了", query)
|
||||
|
||||
def test_clarification_does_not_ask_customer_to_repeat(self):
|
||||
reply = _repair_obvious_mismatch(
|
||||
"刚才没听清,您能再说一遍吗?",
|
||||
"测试客户 7/28 15:54:46\n什么",
|
||||
history=[
|
||||
{"role": "user", "content": "好困啊"},
|
||||
{"role": "assistant", "content": "困了就先眯一会儿,别硬撑着。"},
|
||||
],
|
||||
)
|
||||
self.assertEqual(reply, "我是说,困了就先眯一会儿,别硬撑着。")
|
||||
|
||||
|
||||
class SafetyGateTest(TestCase):
|
||||
@staticmethod
|
||||
def _verification_surface(with_nav=False):
|
||||
image = np.full((1000, 1600, 4), 245, dtype=np.uint8)
|
||||
image[:, :, 3] = 255
|
||||
if with_nav:
|
||||
image[80:920, :96, :3] = 45
|
||||
for y in range(380, 620, 8):
|
||||
for x in range(680, 920, 8):
|
||||
if ((x - 680) // 8 + (y - 380) // 8) % 2 == 0:
|
||||
image[y:y + 8, x:x + 8, :3] = 15
|
||||
return image
|
||||
|
||||
def test_qr_page_without_main_navigation_is_blocked(self):
|
||||
self.assertTrue(
|
||||
looks_like_security_verification(self._verification_surface())
|
||||
)
|
||||
|
||||
def test_normal_navigation_prevents_false_positive(self):
|
||||
self.assertFalse(
|
||||
looks_like_security_verification(self._verification_surface(with_nav=True))
|
||||
)
|
||||
|
||||
def test_minimum_send_interval_is_enforced(self):
|
||||
bot = WeChatBot.__new__(WeChatBot)
|
||||
bot._send_timestamps = deque([95.0])
|
||||
bot._last_send_ts = 95.0
|
||||
with mock.patch("wechat_bot.time.monotonic", return_value=100.0):
|
||||
self.assertAlmostEqual(bot._send_gate_remaining(), 3.0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user