fix: 修复两个OCR问题

1. 修复_clean_ocr_prefix误删登录关键词导致答非所问
   - 噪声前缀后必须跟标点/空格或字符串结束,不能紧跟中文字符
   - 登录插件,哪里可以下载到?不再被清理为插件,哪里可以下载到?

2. 修复EasyOCR静默原生崩溃检测
   - 父进程:空stderr+空crash log也计入CUDA崩溃计数,2次后强制CPU
   - Worker:添加CUDA驱动DLL预检,加载失败时强制CPU模式
This commit is contained in:
youpaishidifu
2026-08-07 14:50:29 +08:00
parent 5627a2b88a
commit 5c4a17043a
2 changed files with 24 additions and 4 deletions
+15
View File
@@ -137,6 +137,21 @@ try:
os.environ.setdefault("OMP_NUM_THREADS", "1")
os.environ.setdefault("MKL_NUM_THREADS", "1")
# ── CUDA 驱动预检:在 import torch 之前探测 CUDA 驱动是否可用 ──
# 防止 CUDA 驱动损坏导致 import torch 时原生崩溃(crash log 为空的静默崩溃)
if os.environ.get("EASYOCR_FORCE_CPU") != "1":
try:
import ctypes
ctypes.windll.nvcuda # 尝试加载 CUDA 驱动 DLL
sys.stderr.write("[easyocr_worker] CUDA 驱动 DLL 加载成功\n")
sys.stderr.flush()
except Exception as _cuda_drv_err:
os.environ["EASYOCR_FORCE_CPU"] = "1"
os.environ["CUDA_VISIBLE_DEVICES"] = ""
sys.stderr.write(f"[easyocr_worker] ⚠️ CUDA 驱动加载失败({_cuda_drv_err}),强制 CPU 模式\n")
sys.stderr.flush()
_write_crash_log(f"{datetime.now()} [easyocr_worker] CUDA 驱动预检失败: {_cuda_drv_err}")
# ── 预检:物理内存+虚拟内存是否足够加载 CUDA 库 ──
_vm = _get_virtual_memory_info()
# ⭐ 统一使用 GlobalMemoryStatusEx(与 monitor.py / Task Manager 一致)
+9 -4
View File
@@ -1856,10 +1856,13 @@ class MessageMonitor:
if crash:
detail = (detail + "\n[ocr] worker 崩溃日志(easyocr_crash.log):\n" + crash).strip()
logger.error(f"[ocr] EasyOCR worker 启动即崩溃: {detail}")
# ⭐ 检测 CUDA 相关崩溃(access violation / torch 错误)→ 增加 OOM 计数,下次强制 CPU
if crash and ("access violation" in crash.lower() or "torch" in crash.lower()):
# ⭐ 检测 CUDA 相关崩溃(access violation / torch 错误 / 静默原生崩溃)→ 增加 OOM 计数,下次强制 CPU
_is_cuda_crash = (crash and ("access violation" in crash.lower() or "torch" in crash.lower()))
_is_silent_native_crash = (not err.strip() and not crash.strip()) # 无stderr无crash log = 原生层崩溃
if _is_cuda_crash or _is_silent_native_crash:
self._easyocr_cuda_oom_count += 1
logger.warning(f"[ocr] 检测到 CUDA 崩溃,累计{self._easyocr_cuda_oom_count}次,下次可能强制 CPU")
logger.warning(f"[ocr] 检测到{'CUDA崩溃' if _is_cuda_crash else '静默原生崩溃(无日志)'}, "
f"累计{self._easyocr_cuda_oom_count}次,下次可能强制 CPU")
# ⭐ 检测页面文件不足(WinError 1455)→ 长期冷却,不反复重试
_is_pagefile_error = "页面文件" in str(detail) or "1455" in str(detail)
if _is_pagefile_error:
@@ -4810,6 +4813,8 @@ class MessageMonitor:
# ⭐ OCR噪声前缀清理:去除UI按钮标签等OCR误识别的前缀
# 如"必选,运营方有哪些权利和义务?" → "运营方有哪些权利和义务?"
# 注意:前缀后必须跟标点/空格或字符串结束,不能紧跟中文字符
# 否则会误删"登录插件"中的"登录"
_OCR_NOISE_PREFIXES = re.compile(
r'^(?:必选|必填|可选|请输入|搜索|查找|查询|发送|取消|确认|确定|提交|保存|删除|编辑| '
r'|添加|新建|创建|设置|修改|返回|关闭|展开|收起|更多|选项|操作|'
@@ -4817,7 +4822,7 @@ class MessageMonitor:
r'同意|拒绝|同意并|下一步|上一步|完成|跳过|继续|登录|注册|退出|'
r'开启|关闭|启用|禁用|暂停|恢复|开始|停止|运行|'
r'是|否|有|无|对|错|真|假|好|坏|新|旧|已|未)'
r'[,,::\s]*'
r'[,,::\s]+|$'
)
@staticmethod