修订时间戳新鲜度评分逻辑:≥5分直接放行,<5分查DB决定是否补分到5

This commit is contained in:
youpaishidifu
2026-08-28 20:10:16 +08:00
parent cb48663d87
commit c34ed371eb
+81 -10
View File
@@ -595,6 +595,20 @@ class MessageHistory:
finally: finally:
conn.close() conn.close()
def has_ocr_message_record(self, platform: str, content: str) -> bool:
"""检查OCR暂存表中是否已存在该消息的记录(用于时间戳新鲜度评分逻辑)"""
content_hash = hashlib.md5(content.strip().encode('utf-8')).hexdigest()
conn = self._get_conn()
try:
cursor = conn.execute(
"SELECT COUNT(*) FROM ocr_staging WHERE platform=? AND content_hash=?",
(platform, content_hash)
)
count = cursor.fetchone()[0]
return count > 0
finally:
conn.close()
class MessageMonitor: class MessageMonitor:
"""多线程消息监控器""" """多线程消息监控器"""
@@ -6747,6 +6761,45 @@ class MessageMonitor:
diff = (now - parsed).total_seconds() diff = (now - parsed).total_seconds()
return max(diff, 0) return max(diff, 0)
def _timestamp_freshness_score(self, text: str) -> float:
"""计算消息的时间戳新鲜度分数。
以系统当前时间为基准,根据时间戳与当前时间的接近程度给分:
- 5分钟内(300秒):+5分
- 10分钟内(600秒):+4分
- 30分钟内(1800秒):+3分
- 1小时内(3600秒):+2分
- 2小时内(7200秒):+1分
- 超过2小时或无时间戳:+0分
所有有时间戳的消息都至少+1分(2小时内),确保时间戳新鲜度作为加分项。
"""
# 从文本中提取时间戳
timestamps = re.findall(r'\d{1,2}:\d{1,2}(?::\d{1,2})?', text)
if not timestamps:
return 0.0
# 取最后一个时间戳(通常是最新消息的时间戳)
ts_str = timestamps[-1]
age_seconds = self._timestamp_age_seconds(ts_str)
if age_seconds is None:
return 0.0
# 根据时间差给分(越接近得分越高)
if age_seconds <= 300: # 5分钟内
return 5.0
elif age_seconds <= 600: # 10分钟内
return 4.0
elif age_seconds <= 1800: # 30分钟内
return 3.0
elif age_seconds <= 3600: # 1小时内
return 2.0
elif age_seconds <= 7200: # 2小时内
return 1.0
else:
return 0.0
@staticmethod @staticmethod
def _is_system_message(text: str) -> bool: def _is_system_message(text: str) -> bool:
"""过滤机器人/系统消息,不作为用户消息处理。""" """过滤机器人/系统消息,不作为用户消息处理。"""
@@ -9022,10 +9075,16 @@ class MessageMonitor:
except Exception as e: except Exception as e:
logger.error(f"[{platform}] 获取近5分钟回复失败: {e}") logger.error(f"[{platform}] 获取近5分钟回复失败: {e}")
new_items = [] new_items = []
# ⭐ 时间戳新鲜度评分:在关键词打分和查重之前计算,作为加分项
freshness_scores = {} # 存储每条消息的时间戳新鲜度分数
for t in texts: for t in texts:
ts = t.strip() ts = t.strip()
if not ts: if not ts:
continue continue
# 计算时间戳新鲜度分数(作为后续综合得分的加分项)
freshness_score = self._timestamp_freshness_score(ts)
# 存储原始文本和新鲜度分数
freshness_scores[ts] = freshness_score
# === URL-only 兜底:无中文且含 URL → 碎片 === # === URL-only 兜底:无中文且含 URL → 碎片 ===
if not re.search(r'[\u4e00-\u9fff]', ts) and re.search(r'https?\S', ts, re.IGNORECASE): if not re.search(r'[\u4e00-\u9fff]', ts) and re.search(r'https?\S', ts, re.IGNORECASE):
logger.debug(f"[{platform}] Poll过滤: URL-only碎片 ts={ts!r}") logger.debug(f"[{platform}] Poll过滤: URL-only碎片 ts={ts!r}")
@@ -9658,8 +9717,25 @@ class MessageMonitor:
continue continue
# ⭐ 添加到候选列表(含质量分) # ⭐ 添加到候选列表(含质量分)
score = self._score_message_quality(cleaned_item) score = self._score_message_quality(cleaned_item)
# ⭐ Task #1609: 时间戳新鲜度奖励——优先处理最新消息 # ⭐ 时间戳新鲜度奖励:使用预先计算的freshness_score
# 从原始文本中提取时间戳,计算与当前时间的差值 # 从freshness_scores字典中获取当前消息的时间戳新鲜度分数
freshness_score = freshness_scores.get(item, 0.0)
# 修订逻辑:≥5分直接放行,<5分查DB决定是否补分到5
if freshness_score >= 5:
# ≥5分:直接放行,加上5分
score += 5.0
if freshness_score > 0:
logger.info(f"[{platform}] 时间戳新鲜度≥5直接放行(+5): {item[:50]}")
else:
# <5分:查DB
if self._msg_history and self._msg_history.has_ocr_message_record(platform, cleaned_item):
# DB有记录:不加分
logger.info(f"[{platform}] 时间戳新鲜度<5且DB有记录,不加分: {item[:50]}")
else:
# DB无记录:补分到5
score += 5.0
logger.info(f"[{platform}] 时间戳新鲜度<5且DB无记录,补分到5: {item[:50]}")
# 保留原有时间戳差值计算(用于排序)
_ts_match = re.search(r'(\d{1,2}):(\d{1,2})(?::(\d{1,2}))?', item) _ts_match = re.search(r'(\d{1,2}):(\d{1,2})(?::(\d{1,2}))?', item)
if _ts_match: if _ts_match:
_h, _m = int(_ts_match.group(1)), int(_ts_match.group(2)) _h, _m = int(_ts_match.group(1)), int(_ts_match.group(2))
@@ -9671,14 +9747,9 @@ class MessageMonitor:
# 如果差值为负,说明时间戳跨天(如23:59 vs 00:01),视为很旧 # 如果差值为负,说明时间戳跨天(如23:59 vs 00:01),视为很旧
if _diff < 0: if _diff < 0:
_diff += 86400 _diff += 86400
# 新鲜度奖励:≤300秒+5分,≤600秒+3分,≤1800秒+1分 else:
if _diff <= 300: _diff = 86400 # 无时间戳,视为很旧
score += 5.0 _candidates.append((score, item, cleaned_item, _diff))
elif _diff <= 600:
score += 3.0
elif _diff <= 1800:
score += 1.0
_candidates.append((score, item, cleaned_item, _diff if _ts_match else 86400))
# ⭐ 同轮择优:只选质量分最高的那条消息触发回复 # ⭐ 同轮择优:只选质量分最高的那条消息触发回复
if _candidates: if _candidates: