修复OCR消息处理多个问题
1. Task #1696: 管道符碎片过滤器修复 - 添加疑问词例外逻辑,避免误杀包含表格内容的真实用户消息 - 例如:'是否支持|,长期活跃奖是如何计算的'不再被丢弃 2. Task #1700: 用户消息被误判为bot回复片段的问题 - 在'反向包含剥离bot回复片段'逻辑中添加问句豁免机制 - 用户提问即使含与旧回复共享的片段,也不应被剥离 - 例如:'领地系统有哪几种操作模式'不再被错误识别为bot回复 3. Task #1697: OCR消息入库时机修复 - 在评分管道之前立即记录OCR消息到暂存表 - 确保消息被首次OCR抓取时入库,避免历史消息被重复处理 - 修改第二关逻辑,同时检查ocr_staging表和user_messages表
This commit is contained in:
+77
-30
@@ -4663,9 +4663,15 @@ class MessageMonitor:
|
||||
# —— 绿色气泡 OCR 乱码:| 管道符混中文 ——
|
||||
# bot 的绿色气泡/蓝色气泡文字经过 OCR 后常把 :; 识别为 |,
|
||||
# 正常中文聊天从不混用 | 与中文。如 "GU |进行配置" "SMTP | 设置"
|
||||
# ⭐ Task #1696: 含疑问词的消息不丢弃(如"是否支持|,长期活跃奖是如何计算的")
|
||||
if '|' in line and re.search(r'[\u4e00-\u9fff]', line) and len(line) > 5:
|
||||
logger.debug(f"[{platform}] OCR 过滤: 管道符碎片(绿色气泡) line={line!r}")
|
||||
continue
|
||||
# 检查是否包含疑问词或问号(用户真实查询)
|
||||
_has_question = re.search(r'[??吗呢多少怎么如何哪什么几]', line)
|
||||
if _has_question:
|
||||
logger.debug(f"[{platform}] OCR 过滤: 管道符碎片但含疑问词,放行: line={line!r}")
|
||||
else:
|
||||
logger.debug(f"[{platform}] OCR 过滤: 管道符碎片(绿色气泡) line={line!r}")
|
||||
continue
|
||||
|
||||
# —— 游戏指令列表碎片:重复 /cmd 模式 ——
|
||||
# OCR 截到命令帮助文本如 "/sdfl主指令 /sdfl reload /sdfl update"
|
||||
@@ -10444,9 +10450,15 @@ class MessageMonitor:
|
||||
logger.debug(f"[{platform}] Poll过滤: 游戏UI乱码(CJK+大写英文) ts={ts!r}")
|
||||
continue
|
||||
# === 绿色气泡 OCR 乱码:| 管道符混中文(正常聊天从不混用)===
|
||||
# ⭐ Task #1696: 含疑问词的消息不丢弃(如"是否支持|,长期活跃奖是如何计算的")
|
||||
if '|' in ts and re.search(r'[\u4e00-\u9fff]', ts) and len(ts) > 5:
|
||||
logger.debug(f"[{platform}] Poll过滤: 管道符碎片(绿色气泡) ts={ts!r}")
|
||||
continue
|
||||
# 检查是否包含疑问词或问号(用户真实查询)
|
||||
_has_question = re.search(r'[??吗呢多少怎么如何哪什么几]', ts)
|
||||
if _has_question:
|
||||
logger.debug(f"[{platform}] Poll过滤: 管道符碎片但含疑问词,放行: ts={ts!r}")
|
||||
else:
|
||||
logger.debug(f"[{platform}] Poll过滤: 管道符碎片(绿色气泡) ts={ts!r}")
|
||||
continue
|
||||
# === JSON/YAML 碎片兜底:OCR 截屏混入配置面板 ===
|
||||
if re.match(r'^["\']?[a-zA-Z_][\w]*["\']?\s*:\s*["\d\[\{tfn]', ts):
|
||||
logger.debug(f"[{platform}] Poll过滤: JSON行 ts={ts!r}")
|
||||
@@ -10498,7 +10510,11 @@ class MessageMonitor:
|
||||
# r="从未注册过草原探险服务器的玩家、账号。\n使用全新的邮箱进行验证。"
|
||||
# → "从未注册过草原" in r, "使用全新的邮箱" in r → 剥离这两段
|
||||
_has_comma = ',' in ts or (',' in ts and re.search(r'[\u4e00-\u9fff],[\u4e00-\u9fff]', ts))
|
||||
if not stripped_bot and _has_comma:
|
||||
# ⭐ Task #1700: 问句豁免——用户提问即使含与旧回复共享的片段,也不应被剥离
|
||||
is_question_mark = bool(re.search(r'[??]', ts))
|
||||
is_question_word = any(qw in ts for qw in ('吗', '呢', '多少', '怎么', '如何', '哪', '什么', '几'))
|
||||
is_question = is_question_mark or is_question_word
|
||||
if not stripped_bot and _has_comma and not is_question:
|
||||
parts = re.split(r'[,,]', ts)
|
||||
parts = [p.strip() for p in parts if p.strip()]
|
||||
if len(parts) >= 2:
|
||||
@@ -10905,6 +10921,15 @@ class MessageMonitor:
|
||||
logger.info(f"[{platform}] 候选病句/噪声拦截: {cleaned_item[:50]!r}")
|
||||
self._last_new_msg_time[platform] = time.time()
|
||||
continue
|
||||
# ⭐ Task #1697: 立即记录OCR消息到暂存表(评分管道之前)
|
||||
# 原因:record_ocr_message()在评分管道之后才调用,导致消息在第一关/第二关失败时不入库
|
||||
# 后果:历史消息每次OCR抓取都被当作"新消息"处理
|
||||
# 修复:在评分管道之前立即记录,确保消息被首次OCR抓取时入库
|
||||
if self._msg_history:
|
||||
try:
|
||||
self._msg_history.record_ocr_message(platform, cleaned_item)
|
||||
except Exception as e:
|
||||
logger.debug(f"[{platform}] OCR暂存记录失败(评分前): {e}")
|
||||
# ⭐ 检查是否与最近bot回复内容相同(OCR噪声干扰,把bot回复当作用户消息)
|
||||
# ⭐ Task #1574: 降低阈值 0.9→0.65,骨架长度 6→4,防止自言自语漏过
|
||||
# ⭐ Task #1574 v2: 拆行比对——bot回复是多行(含表格),OCR只读首行
|
||||
@@ -11021,28 +11046,58 @@ class MessageMonitor:
|
||||
# 旧消息通过 get_latest_record_timestamp() 搭上新消息的新鲜DB记录,
|
||||
# 导致 time_diff≤300s → 通关 → 分数从15→20/18→23,盖过真正的新消息。
|
||||
# 修复:改为查询「本条消息自身的 DB 记录」时间戳,而非全局最新记录。
|
||||
# ⭐ Task #1697: 同时检查 ocr_staging 表
|
||||
# 原因:record_ocr_message()在评分管道之前调用,确保消息被首次OCR抓取时入库
|
||||
# 修复:在检查user_messages表之前,先检查ocr_staging表
|
||||
if self._msg_history:
|
||||
# 查询本条消息自身的入库时间(created_at)
|
||||
my_record_ts = self._msg_history.get_message_record_timestamp(platform, cleaned_item)
|
||||
# 先检查ocr_staging表(评分管道之前已记录)
|
||||
has_ocr_record = self._msg_history.has_ocr_message_record(platform, cleaned_item)
|
||||
|
||||
if my_record_ts is not None:
|
||||
# 有本条消息的数据库记录:计算本地时间与记录时间戳的差值
|
||||
time_diff_seconds = (datetime.now() - my_record_ts).total_seconds()
|
||||
logger.debug(f"[{platform}] 第二关:有本条DB记录,时间差={time_diff_seconds:.0f}秒: {item[:50]}")
|
||||
if has_ocr_record:
|
||||
# ocr_staging表中有记录:查询本条消息自身的入库时间(created_at)
|
||||
my_record_ts = self._msg_history.get_message_record_timestamp(platform, cleaned_item)
|
||||
|
||||
if time_diff_seconds <= 300:
|
||||
# 本地时间 - 记录时间戳 ≤ 300秒:通关
|
||||
if my_record_ts is not None:
|
||||
# 有本条消息的数据库记录:计算本地时间与记录时间戳的差值
|
||||
time_diff_seconds = (datetime.now() - my_record_ts).total_seconds()
|
||||
logger.debug(f"[{platform}] 第二关:有本条DB记录(ocr_staging),时间差={time_diff_seconds:.0f}秒: {item[:50]}")
|
||||
|
||||
if time_diff_seconds <= 300:
|
||||
# 本地时间 - 记录时间戳 ≤ 300秒:通关
|
||||
old_score = score
|
||||
score = max(score + 5.0, 5.0)
|
||||
logger.info(f"[{platform}] 第二关通过:DB记录时间差{time_diff_seconds:.0f}秒≤300秒,放行: {old_score:.1f}→{score:.1f}: {item[:50]}")
|
||||
else:
|
||||
# 本地时间 - 记录时间戳 > 300秒:返团拦截
|
||||
score = -100.0
|
||||
logger.info(f"[{platform}] 第二关拦截:DB记录时间差{time_diff_seconds:.0f}秒>300秒,丢弃: {item[:50]}")
|
||||
else:
|
||||
# ocr_staging表有记录但user_messages表无记录:放行(首次抓取)
|
||||
old_score = score
|
||||
score = max(score + 5.0, 5.0)
|
||||
logger.info(f"[{platform}] 第二关通过:DB记录时间差{time_diff_seconds:.0f}秒≤300秒,放行: {old_score:.1f}→{score:.1f}: {item[:50]}")
|
||||
else:
|
||||
# 本地时间 - 记录时间戳 > 300秒:返团拦截
|
||||
score = -100.0
|
||||
logger.info(f"[{platform}] 第二关拦截:DB记录时间差{time_diff_seconds:.0f}秒>300秒,丢弃: {item[:50]}")
|
||||
logger.info(f"[{platform}] 第二关通过:ocr_staging有记录但user_messages无记录,放行: {old_score:.1f}→{score:.1f}: {item[:50]}")
|
||||
else:
|
||||
# 无本条消息的数据库记录:返团拦截
|
||||
score = -100.0
|
||||
logger.info(f"[{platform}] 第二关拦截:无本条消息DB记录,丢弃: {item[:50]}")
|
||||
# ocr_staging表无记录:检查user_messages表
|
||||
my_record_ts = self._msg_history.get_message_record_timestamp(platform, cleaned_item)
|
||||
|
||||
if my_record_ts is not None:
|
||||
# 有本条消息的数据库记录:计算本地时间与记录时间戳的差值
|
||||
time_diff_seconds = (datetime.now() - my_record_ts).total_seconds()
|
||||
logger.debug(f"[{platform}] 第二关:有本条DB记录(user_messages),时间差={time_diff_seconds:.0f}秒: {item[:50]}")
|
||||
|
||||
if time_diff_seconds <= 300:
|
||||
# 本地时间 - 记录时间戳 ≤ 300秒:通关
|
||||
old_score = score
|
||||
score = max(score + 5.0, 5.0)
|
||||
logger.info(f"[{platform}] 第二关通过:DB记录时间差{time_diff_seconds:.0f}秒≤300秒,放行: {old_score:.1f}→{score:.1f}: {item[:50]}")
|
||||
else:
|
||||
# 本地时间 - 记录时间戳 > 300秒:返团拦截
|
||||
score = -100.0
|
||||
logger.info(f"[{platform}] 第二关拦截:DB记录时间差{time_diff_seconds:.0f}秒>300秒,丢弃: {item[:50]}")
|
||||
else:
|
||||
# 无本条消息的数据库记录:返团拦截
|
||||
score = -100.0
|
||||
logger.info(f"[{platform}] 第二关拦截:无本条消息DB记录,丢弃: {item[:50]}")
|
||||
else:
|
||||
# msg_history不可用:强制丢弃
|
||||
score = -100.0
|
||||
@@ -11146,15 +11201,7 @@ class MessageMonitor:
|
||||
self._last_msg[platform] = _cleaned
|
||||
engine_tag = self._last_chosen_engine.get(platform, "")
|
||||
logger.info(f"[{platform}] 新消息[{engine_tag}]: {_raw[:60]}")
|
||||
# ⭐ Task #1572: 记录OCR消息到暂存表(用于后续查重)
|
||||
if self._msg_history:
|
||||
# ⭐ 数据库查重:重复率≥50%就跳过该条消息(continue继续处理下一条)
|
||||
# ⚠️ 注意:这里不再查重,因为第10106行已经查过了(且用了exclude_self=True排除自身)
|
||||
# 如果在这里再查一次,刚入库的消息会被自身匹配上,导致误跳过
|
||||
try:
|
||||
self._msg_history.record_ocr_message(platform, _cleaned)
|
||||
except Exception as e:
|
||||
logger.debug(f"[{platform}] OCR暂存记录失败: {e}")
|
||||
# ⭐ Task #1697: OCR消息已在评分管道之前记录到ocr_staging表,此处不再重复记录
|
||||
# ⚠️ 急停检查:回复前最后检查,防止急停后仍然发送
|
||||
if self._stop_event.is_set() or not self._running:
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user