fix(monitor): 策略3-尾部匹配剥离bot回复
增强_strip_bot_reply_fragments函数,添加第三种剥离策略: 问题:OCR同屏捕获时,bot回复被拼接到用户消息末尾 例:"个登录插件是在哪个地方下载? 4001234S67 ]插件下载:见github..." 解决方案: 1. 检测问句后的尾部内容(≥15字符) 2. 提取纯中文部分,排除英文/数字干扰 3. 与数据库中已存储的bot回复计算相似度 4. 相似度≥85%时直接截断到问句结束 效果: - 抵抗OCR噪声(标点/空格差异) - 抵抗英文/数字干扰(只比较纯中文) - 精确识别尾部污染并剥离 测试验证: - 污染查询: '个登录插件是在哪个地方下载? 4001234S67 ]插件下载:见github...' - 相似度: 100% (纯中文'插件下载见'完全匹配) - 输出: '个登录插件是在哪个地方下载?'
This commit is contained in:
+30
-1
@@ -4714,11 +4714,16 @@ class MessageMonitor:
|
||||
被 OCR 拼成一行后,filter4 因检测到 bot 旧回复文本而把整段(含用户新消息)
|
||||
误判为残片整体丢弃。
|
||||
|
||||
两种策略:
|
||||
三种策略:
|
||||
1. 精确子串:某条 bot 旧回复 r 完整出现在 text 中 → 直接删除 r
|
||||
2. 反向包含:OCR 把「用户新消息 + bot 旧回复」按逗号拼成一行,且 r 不是
|
||||
text 的子串,但 text 中逗号分隔的片段可能是 r 的子串 → 逐片段判断,
|
||||
剥离属于 bot 回复的片段,保留用户片段。
|
||||
3. 尾部匹配:OCR 把 bot 旧回复拼在用户消息末尾(无分隔符或仅空格),
|
||||
文本末尾子串是某条 bot 回复的子串 → 切掉尾部,保留前面用户消息。
|
||||
例:"个登录插件是在哪个地方下载? 4001234S67 ]插件下载:见github..."
|
||||
→ "个登录插件是在哪个地方下载?"
|
||||
使用宽松匹配(≥15字符连续匹配),抵抗OCR噪声导致的微小差异。
|
||||
|
||||
⭐ OCR 噪声鲁棒性:bot 旧回复被 OCR 重新识别时,标点(,。)、全/半角、空格
|
||||
常与原文不一致(如原文"Minecraft 生存服务器,拥有完善的领地系统"被识别成
|
||||
@@ -4761,6 +4766,30 @@ class MessageMonitor:
|
||||
if len(user_parts) < len(parts):
|
||||
ts = ','.join(user_parts).strip(',').strip()
|
||||
stripped_bot = True
|
||||
# 策略3:尾部匹配——OCR把bot回复直接拼在用户消息末尾
|
||||
# 使用纯中文相似度匹配,抵抗OCR噪声和英文/数字干扰
|
||||
if not stripped_bot:
|
||||
q_mark_pos = max(ts.find('?'), ts.find('?'))
|
||||
if q_mark_pos >= 0 and q_mark_pos < len(ts) - 15:
|
||||
after_q = ts[q_mark_pos + 1:]
|
||||
after_chinese = re.sub(r'[^\u4e00-\u9fff]', '', after_q)
|
||||
if len(after_chinese) >= 4: # 尾部有足够中文内容
|
||||
for r in replied:
|
||||
if len(r) < 10:
|
||||
continue
|
||||
r_chinese = re.sub(r'[^\u4e00-\u9fff]', '', r)
|
||||
if len(r_chinese) < 4:
|
||||
continue
|
||||
# 计算纯中文相似度
|
||||
sim = SequenceMatcher(None, after_chinese, r_chinese).ratio()
|
||||
if sim >= 0.85:
|
||||
ts = ts[:q_mark_pos + 1]
|
||||
logger.debug(
|
||||
f"[qq] 尾部匹配剥离bot回复: {ts!r} <- "
|
||||
f"{ts + after_q[:40]!r} (中文相似度={sim:.0%})"
|
||||
)
|
||||
stripped_bot = True
|
||||
break
|
||||
if stripped_bot:
|
||||
ts = re.sub(r'\s+', ' ', ts).strip().strip(',').strip()
|
||||
return ts
|
||||
|
||||
Reference in New Issue
Block a user