修订时间戳新鲜度评分逻辑:≥5分直接放行,<5分查DB决定是否补分到5
This commit is contained in:
+81
-10
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user