修复2个bug: 急停后OCR残留 + 知识库奖励配置匹配错误

Bug1 - 急停(ESC×2)后Windows OCR仍在运行输出日志:
  _emergency_stop设_running=False+杀EasyOCR子进程,但Windows OCR
  (RecognizeAsync)是同步阻塞调用,无法被中断。OCR完成后_poll继续
  处理文本→触发回复。
  修复:_poll中在_read_messages返回后+文本过滤后各增加self._running
  检查,OCR完成或文本处理中如已急停则立即return,不再触发回复。

Bug2 - 用户问寻宝奖励配置,bot返回指令参数表格(匹配度15.38):
  知识库sdf1_game.md中'## 寻宝玩法介绍'命令表含'寻宝'高频词,
  TF-IDF得分远高于'## 奖励配置:'段。heading bonus仅2.0/词,
  不足以翻转15分的TF-IDF差距。
  修复:heading bonus从2.0/词提升至5.0/词;新增heading连续短语
  匹配bonus(+8.0),如查询含'奖励配置'且heading含'奖励配置'则
  大幅boost,确保语义匹配的section排到最前。
This commit is contained in:
youpaishidifu
2026-07-30 13:49:58 +08:00
parent e9bccb688b
commit b55fff8cbb
2 changed files with 19 additions and 3 deletions
+9 -2
View File
@@ -413,9 +413,16 @@ class KnowledgeBase:
heading = doc.get("heading", "")
body = doc.get("body", doc.get("content", ""))
h_tokens = set(t for t in jieba.cut(heading) if len(t) >= 2)
# heading 包含查询关键词 → bonus
# heading 包含查询关键词 → bonus(5.0 每命中词,足够翻转 TF-IDF 差距)
heading_hits = len(query_tokens & h_tokens)
bonus = heading_hits * 2.0
bonus = heading_hits * 5.0
# heading 包含查询连续短语 → 额外 bonus(如查询含"奖励配置"且 heading 含"奖励配置")
for qlen in range(min(len(query_stripped), 8), 3, -1):
for start in range(len(query_stripped) - qlen + 1):
phrase = query_stripped[start:start+qlen]
if len(phrase) >= 4 and phrase in heading:
bonus += 8.0
break
# 文档头部惩罚:heading 是单层 # + 文档名(如 "# php管理员后端"),且无 body
if heading.startswith("# ") and (not body or len(body) < 50):
bonus -= 5.0
+10 -1
View File
@@ -3481,9 +3481,14 @@ class MessageMonitor:
else:
win = None # 惰性创建:OCR 失败后需要 fallback 时再建
# 3. 读消息
# 3. 读消息(Windows OCR 同步阻塞,可能耗时 2-5s)
texts = self._read_messages(win, platform)
# ⚠️ OCR 返回后立即检查急停标志:急停可能在 OCR 阻塞期间触发,
# Windows OCR 无法被中断,但后续文本处理可以立即跳过。
if not self._running:
return
if not texts:
# 截图未变→不计入空读,不触发清缓存
if self._ocr_unchanged.get(platform):
@@ -3691,6 +3696,10 @@ class MessageMonitor:
and not re.match(r'^\d{4}[/-]\d{1,2}', it.strip())
]
# ⚠️ 文本处理后再次检查急停:防止急停在过滤阶段触发后仍触发回复
if not self._running:
return
# 更新 last_texts 与签名
self._last_texts[platform] = list(texts)
self._last_sig[platform] = sig