fix: 修复消息拼接/丢弃问题——同轮择优改为逐条处理所有候选消息 (Task #1642)
- 旧逻辑:_candidates列表按质量分排序,只选1条最好的处理,其余全部丢弃 - 新逻辑:for循环逐条处理所有候选消息,每条独立查重、入库、KB搜索和回复 - 修复用户报告:OCR一次读到4条消息后只有1条被处理,其余3条丢失 - 用户原话:不要把消息都拼接成一条,不然一个拦截剩余的全部丢了
This commit is contained in:
+57
-61
@@ -10135,74 +10135,70 @@ class MessageMonitor:
|
||||
_diff = 86400 # 无时间戳,视为很旧
|
||||
_candidates.append((score, item, cleaned_item, _diff))
|
||||
|
||||
# ⭐ 同轮择优:只选质量分最高的那条消息触发回复
|
||||
# ⭐ 同轮逐条处理:每条候选消息独立处理和回复,不再丢弃
|
||||
if _candidates:
|
||||
# 按质量分降序排序,再按时间戳差值升序(越新鲜越好)
|
||||
_candidates.sort(key=lambda x: (x[0], -x[3]), reverse=True)
|
||||
_best_score, _best_raw, _best_cleaned, _best_diff = _candidates[0]
|
||||
# 如果有多条同分,优先选时间戳最新的(差值最小)
|
||||
_top_candidates = [c for c in _candidates if c[0] == _best_score]
|
||||
_top_candidates.sort(key=lambda x: x[3]) # 按时间戳差值升序
|
||||
_best_score, _best_raw, _best_cleaned, _best_diff = _top_candidates[0]
|
||||
|
||||
logger.info(
|
||||
f"[{platform}] 同轮择优: 选中({_best_score:.1f}分) {_best_cleaned[:50]!r}, "
|
||||
f"候选{len(_candidates)}条"
|
||||
f"[{platform}] 同轮候选{len(_candidates)}条,逐条处理"
|
||||
)
|
||||
if len(_candidates) > 1:
|
||||
for _sc, _raw, _cl, _diff in _candidates[1:]:
|
||||
logger.debug(f"[{platform}] 同轮择优: 丢弃({_sc:.1f}分) {_cl[:50]!r}")
|
||||
|
||||
# ⭐ 添加到最近处理列表
|
||||
self._recent_processed_messages.append((_best_cleaned, now))
|
||||
# ⭐ 添加到最近用户查询列表(用于跨轮语义去重)
|
||||
self._add_to_recent_user_queries(_best_cleaned)
|
||||
# ⭐ Task #1556: 记录关键词得分到数据库
|
||||
if self._keyword_scorer:
|
||||
try:
|
||||
keywords = self._keyword_scorer.extract_keywords(_best_cleaned)
|
||||
# 新消息得分为0(未匹配历史回复),记录为已处理
|
||||
self._keyword_scorer.record_message_score(
|
||||
platform, _best_cleaned, keywords, 0, [], is_new=True
|
||||
)
|
||||
except Exception as e:
|
||||
logger.debug(f"[{platform}] 关键词记录失败: {e}")
|
||||
self._last_new_msg_time[platform] = time.time()
|
||||
self._last_msg[platform] = _best_cleaned
|
||||
engine_tag = self._last_chosen_engine.get(platform, "")
|
||||
logger.info(f"[{platform}] 新消息[{engine_tag}]: {_best_raw[:60]}")
|
||||
# ⭐ Task #1572: 记录OCR消息到暂存表(用于后续查重)
|
||||
if self._msg_history:
|
||||
# ⭐ 先进行数据库查重:清理后计算相似度,重复率≥50%就跳过入库和回复
|
||||
if self._msg_history._is_similar_to_history(platform, _best_cleaned, threshold=0.5):
|
||||
logger.info(f"[{platform}] 轮询消息去重: 与历史消息相似,跳过入库和回复: {_best_cleaned[:60]!r}")
|
||||
# 虽然不入库,但仍需标记为已处理,防止重复处理
|
||||
self._last_new_msg_time[platform] = time.time()
|
||||
# 不回复,直接返回
|
||||
for _idx, (_score, _raw, _cleaned, _diff) in enumerate(_candidates):
|
||||
# ⚠️ 急停检查:处理每条消息前检查
|
||||
if self._stop_event.is_set() or not self._running:
|
||||
return
|
||||
try:
|
||||
self._msg_history.record_ocr_message(platform, _best_cleaned)
|
||||
except Exception as e:
|
||||
logger.debug(f"[{platform}] OCR暂存记录失败: {e}")
|
||||
# ⚠️ 急停检查:回复前最后检查,防止急停后仍然发送
|
||||
if self._stop_event.is_set() or not self._running:
|
||||
return
|
||||
if self._on_message:
|
||||
self._on_message(platform, _best_cleaned)
|
||||
if platform == "qq":
|
||||
if stale == 3:
|
||||
logger.debug(f"[QQ] 冻结 #{stale},强制刷新")
|
||||
self._force_uia_refresh(platform)
|
||||
elif stale == 6:
|
||||
logger.debug(f"[QQ] 冻结 #{stale},重建窗口引用")
|
||||
self._cached_hwnd.pop(platform, None)
|
||||
self._cached_pid.pop(platform, None)
|
||||
else:
|
||||
if stale == 5:
|
||||
logger.debug(f"[{platform}] 冻结 #{stale},尝试强制刷新")
|
||||
self._force_uia_refresh(platform)
|
||||
elif stale == 10:
|
||||
logger.debug(f"[{platform}] 冻结 #{stale},重建窗口引用")
|
||||
|
||||
logger.info(
|
||||
f"[{platform}] 处理第{_idx+1}/{len(_candidates)}条({_score:.1f}分): {_cleaned[:50]!r}"
|
||||
)
|
||||
|
||||
# ⭐ 添加到最近处理列表
|
||||
self._recent_processed_messages.append((_cleaned, now))
|
||||
# ⭐ 添加到最近用户查询列表(用于跨轮语义去重)
|
||||
self._add_to_recent_user_queries(_cleaned)
|
||||
# ⭐ Task #1556: 记录关键词得分到数据库
|
||||
if self._keyword_scorer:
|
||||
try:
|
||||
keywords = self._keyword_scorer.extract_keywords(_cleaned)
|
||||
self._keyword_scorer.record_message_score(
|
||||
platform, _cleaned, keywords, 0, [], is_new=True
|
||||
)
|
||||
except Exception as e:
|
||||
logger.debug(f"[{platform}] 关键词记录失败: {e}")
|
||||
self._last_new_msg_time[platform] = time.time()
|
||||
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继续处理下一条)
|
||||
if self._msg_history._is_similar_to_history(platform, _cleaned, threshold=0.5):
|
||||
logger.info(f"[{platform}] 轮询消息去重: 与历史消息相似,跳过: {_cleaned[:60]!r}")
|
||||
self._last_new_msg_time[platform] = time.time()
|
||||
continue # 跳过该条,继续处理下一条
|
||||
try:
|
||||
self._msg_history.record_ocr_message(platform, _cleaned)
|
||||
except Exception as e:
|
||||
logger.debug(f"[{platform}] OCR暂存记录失败: {e}")
|
||||
# ⚠️ 急停检查:回复前最后检查,防止急停后仍然发送
|
||||
if self._stop_event.is_set() or not self._running:
|
||||
return
|
||||
if self._on_message:
|
||||
self._on_message(platform, _cleaned)
|
||||
if platform == "qq":
|
||||
if stale == 3:
|
||||
logger.debug(f"[QQ] 冻结 #{stale},强制刷新")
|
||||
self._force_uia_refresh(platform)
|
||||
elif stale == 6:
|
||||
logger.debug(f"[QQ] 冻结 #{stale},重建窗口引用")
|
||||
self._cached_hwnd.pop(platform, None)
|
||||
self._cached_pid.pop(platform, None)
|
||||
else:
|
||||
if stale == 5:
|
||||
logger.debug(f"[{platform}] 冻结 #{stale},尝试强制刷新")
|
||||
self._force_uia_refresh(platform)
|
||||
elif stale == 10:
|
||||
logger.debug(f"[{platform}] 冻结 #{stale},重建窗口引用")
|
||||
self._cached_hwnd.pop(platform, None)
|
||||
self._cached_pid.pop(platform, None)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user