修:OCR全角括号md碎片导致KB死循环

问题:OCR将英文括号识别为全角(()形式,[官方下载](?https...
此类碎片漏过 _is_markdown_document 检测,进入KB匹配触发回复。

修复:
1. _is_markdown_document: 新增 ]( 和 [text]( 检测(全角括号md链接)
2. OCR行级过滤: 新增 ]( 碎片丢弃
3. _extract_user_text_from_md_fragment: 新增全角括号md标记分割
4. KB scoring: 短查询(≤3分词)降权,防碎片得分反超真实消息
This commit is contained in:
youpaishidifu
2026-07-27 21:48:44 +08:00
parent 8d5e9b7e17
commit 3a7a05f973
2 changed files with 24 additions and 1 deletions
+8
View File
@@ -269,6 +269,14 @@ class KnowledgeBase:
combined_scores = 0.7 * tfidf_scores + 0.3 * keyword_scores
# 短查询惩罚:分词数 ≤2 的短查询(如图标残片/短词)得分大幅降权
# 防止 OCR 碎片中的高 IDF 词(如"下载")获得超过真实用户消息的分数
n_tokens = len(tokens)
if n_tokens <= 2:
combined_scores *= 0.3
elif n_tokens <= 3:
combined_scores *= 0.6
# 按文档聚合:取各文档下的最高 section 分作为文档分
# 同时统计匹配 section 数量,用于后续排序(section 多的文档更可能是主文档)
doc_best = {}
+16 -1
View File
@@ -1073,6 +1073,10 @@ class MessageMonitor:
if len(re.findall(r'\[\s*[VXvx√✗]\s*\]', line)) >= 2:
logger.debug(f"[{platform}] OCR 过滤: 多checkbox碎片 line={line!r}")
continue
# 全角括号 md 链接碎片:`[text](url` 或 `](` — md 链接 OCR 全角退化
if re.search(r'\](', line):
logger.debug(f"[{platform}] OCR 过滤: 全角括号碎片 line={line!r}")
continue
if re.match(r'^\d{1,2}[::\s]\d{1,2}', line):
continue
if re.match(r'^\d{4}[/-]\d{1,2}', line):
@@ -1431,6 +1435,11 @@ class MessageMonitor:
# # 行首标题:短文本也检测(OCR 把 ##协议修 切成 5 字符片段)
if re.match(r'^#{1,6}(?:\s|\[|[\u4e00-\u9fff])', text):
return True
# 全角括号退化 md 链接:短文本也检测
if re.search(r'\](', text):
return True
if re.search(r'\[.+?\](', text):
return True
if len(text) < 10:
return False
# ##直接跟汉字(OCR 丢失 ##后空格时常见:##文档导航)
@@ -1475,6 +1484,9 @@ class MessageMonitor:
# ── 整段以 ## 开头 → 无用户文本(无空格 ##中文 也捕获)──
if re.match(r'^#{1,6}(?:\s|\[|[\u4e00-\u9fff])', text):
return []
# 整段以 [text]( 开头 → 全角括号 md 链接碎片,无用户文本
if re.match(r'^\[.+?\](', text):
return []
# ── 找第一个 markdown 起始标记的位置 ──
# 标记:## 标题、[text](url)、.md)、| 表格分隔、``` 代码块
@@ -1485,8 +1497,11 @@ class MessageMonitor:
if m and m.start() < md_start:
md_start = m.start()
# [text](url) 链接
# [text](url) 链接(含全角括号退化 [text](url))
m = re.search(r'(?<=\S)\s*\[.+?\]\(.+?\)', text)
if m and m.start() < md_start:
md_start = m.start()
m = re.search(r'(?<=\S)\s*\[.+?\](.+?)', text)
if m and m.start() < md_start:
md_start = m.start()