Commit Graph
94 Commits
Author SHA1 Message Date
youpaishidifu 25073c35f1 requirements.txt: 添加 easyocr/torch/torchvision 依赖 2026-07-27 20:52:09 +08:00
youpaishidifu 79b739f59d md表格细胞值提取加固+replied子串包含过滤 CUDA Torch 安装 2>&1 2026-07-27 19:47:39 +08:00
youpaishidifu 17bfe35520 _poll: qq找窗去子线程,纯Win32直接跑在_run_loop线程 2026-07-27 19:27:22 +08:00
youpaishidifu e723ce582e OCR checkbox残片过滤 + EasyOCR GPU自动检测 2026-07-27 19:02:58 +08:00
youpaishidifu dc2e1f4105 EasyOCR:主线程预加载+torch.set_num_threads(1)防段错误 2026-07-27 18:52:31 +08:00
youpaishidifu 906c89f2f9 加faulthandler+OCR阶段心跳日志排查崩溃 2026-07-27 18:28:31 +08:00
youpaishidifu 5ecfa09017 窗口查找改纯PID+OCR垃圾过滤+md短标题修复 2026-07-27 18:18:36 +08:00
youpaishidifu a0e932276a 替换:文本指纹→截图像素签名(8x8感知hash),屏幕不变整轮跳过+跳过fallback+不计空读 2026-07-27 17:06:56 +08:00
youpaishidifu e90cea7343 修复:OCR环路五个靶点—①##中文(md检测)②位置0##不提取③跨轮指纹去重④引擎标签⑤回复标题去##追踪 2026-07-27 16:30:37 +08:00
youpaishidifu 24146f34d9 重大:新增微信OCR读取 + 提取_process_ocr_output共用方法 + 导航噪声过滤 + 垃圾计数改为dict 2026-07-27 15:55:55 +08:00
youpaishidifu ec06e48926 修复:KB同义词(权力→权利) + 微信"关闭"按钮过滤(NFKC标准化+行尾跳过) 2026-07-27 15:36:14 +08:00
youpaishidifu 12759cabfc 修复:OCR md片段中提取用户消息(_extract_user_text_from_md_fragment) 2026-07-27 14:50:47 +08:00
youpaishidifu 8894124b0a fix(kb): section级搜索+意图排序+分词级匹配修复短查询与跨section排序
1. knowledge_base.py:
   - 文档按 ## 标题切分为独立 section 后索引,每个 section 独立 TF-IDF
   - 分词级匹配(避免"定义"子串匹配"自定义"的假阳性)
   - 文档级优先排序:先按文档聚合,取最高 section 分决定最佳文档
   - 定义类查询(版号/版本号/定义):自动降权无定义类 section 的文档
   - 动作类查询(怎么/如何/用法):按优先级找"参数/指令/使用"→"方法"→"安装" heading
   - 预计算 heading/body 分词集合,避免每次搜索重复 jieba
   - 修复 SYNONYMS 重复 key

2. auto_reply.py:
   - 精简答案提取:section 级搜索后 doc['content'] 即最相关片段
   - 移除冗余的 _extract_relevant_snippet(重复 jieba 分词+section 切分)

3. monitor.py:
   - 增加微信/QQ UI 噪声过滤(通讯录、发现、朋友圈等)
2026-07-27 14:17:51 +08:00
youpaishidifu 1441278082 fix(kb): 混合评分策略修复短查询匹配失败
TF-IDF 余弦相似度单独使用对短中文查询过于严格(3-5 个词 vs 数百个词的长文档)。
改为混合评分:0.4×TF-IDF + 0.6×关键词命中率,让短查询只要命中关键词就能返回结果。

同时降低 auto_reply_min_score 从 0.35→0.30,适配混合评分的数值范围。
2026-07-27 12:30:31 +08:00
youpaishidifu 81419b82fd fix: QQ消息末尾O~/C~/0~状态标记清理更宽松正则
旧正则 \s*O~O~\s*$ 只匹配 O~O~,漏掉 O~、C~、0~ 等变体。
新正则 \s*(?:[A-Za-z0-9]~)+\s*$ 覆盖所有单/多字符+波浪线组合。

三处同步更新归一化函数:
1. _normalize_ocr_text (全局字符清理)
2. OCR原始行分割前 (split前整行清理)
3. 剪贴板行过滤 (clipboard路径清理)
4. 时间戳分割后逐片段清理 (关键修复:之前只清了分割前行,分割后片段漏了)
2026-07-27 11:38:59 +08:00
youpaishidifu 135da38760 fix: 清理 QQ 消息末尾 O~O~ 状态标记 + md 检测移到分割后
1. 剪贴板/OCR 行末尾 '0~O~' 状态标记污染 KB 匹配 → 用正则清理
2. md 文档检测从分割前移到分割后逐片段执行,避免 bot md 片段误杀同条 OCR 行里的用户消息
3. easyocr 导入移到 COM 模块之前,避免 c10.dll 初始化冲突
2026-07-27 10:33:29 +08:00
youpaishidifu 0d375ab230 chore: gitignore 屏蔽 nul 文件(Shell 重定向产物) 2026-07-26 23:26:11 +08:00
youpaishidifu d6b2f21dcd fix: easyocr 导入 OSError 改为捕获降级 2026-07-26 23:25:04 +08:00
youpaishidifu 948af558ea 新增: 双 OCR 引擎(Windows OCR + EasyOCR 备用)+ 对比选择机制
Windows OCR 保持主力,EasyOCR 作为备用对比引擎:
1. 条件导入:easyocr/numpy 可选,缺省时优雅降级到纯 Windows OCR
2. 引擎对比:_score_ocr_text 打分(CJK 量、垃圾字符、空格率、时间戳)
   _pick_ocr_text 选高分者,日志记录引擎胜负统计
3. 每轮 OCR 两张多跑一次 EasyOCR(CPU 模式),结果对比后选优
4. _pick_ocr_text 引入后,日志格式变化:
   [ocr] 引擎对比: win=xx.x vs easy=xx.x → 选 XX (胜率XX%, N轮)
2026-07-26 22:19:04 +08:00
youpaishidifu 20cdeeb15c 修复: OCR 图像预处理 2x 放大+锐化+对比度 + 增强 normalize 纠错
1. 图像预处理(截图保存后、OCR 前):
   - 2x LANCZOS 放大:Windows OCR 对高 DPI 输入识别更好
   - 锐化 1.8x + 对比度 1.4x:字符边缘更清晰,减少 CJK 空格/字符混淆
   预期:减少《→<错误、减少 CJK 间空格残留、减少字符分裂(什→亻牛)

2. 增强 _normalize_ocr_text:
   - 《》→ <> 修复:Minecraft 聊天 <player> 被 OCR 误读为中文书名号
   - l→| 管道分隔符修复:|quiz| 误读为 lquizl,使用 (?<=\s)l(...)l(?=\s) 模式
   - .→ . 全角点→半角数字小数点(0.45 → 0.45)
   这些修复只在非 md 文本上运行(md 被 pre-split check 提前过滤)
2026-07-26 21:55:55 +08:00
youpaishidifu 5d0cedcab4 修复: OCR cap_top 跳过群名头栏 + 行级群名头栏过滤
1. cap_top 从 max(40, 4%)→max(80, 6%):跳过 TIM 聊天面板
   顶部群名+角色标签头栏(~70px),之前只跳过了 Windows 标题栏
2. 行级内容过滤:行首匹配 '名称(角色〕' / 【名称】等 header 模式
   (闭合括号为 〕」】 等非日常聊天用符号)—— cap_top 残余的二次防御
3. 防止 OCR 将群名头栏+消息预览混成一条无时间戳的乱码”新消息
2026-07-26 20:46:31 +08:00
youpaishidifu 643619453d chore: gitignore 屏蔽 ocr_debug_*.png 并移除跟踪 2026-07-26 20:17:03 +08:00
youpaishidifu 953f1da797 修复: OCR 右裁剪边界 95%→78% 排除群成员侧栏 + 内容过滤二次防御
1. cap_right 从 win_w*0.95 收窄到 win_w*0.78,排除右栏群成员列表(~80%+ 区域)
   防止群成员列表混入聊天消息 OCR 导致"新消息"乱码触发 bot 回复
2. 加 "群成员"/"索群成员"/"搜索成员" 行级内容过滤,裁剪残余的二次防御
2026-07-26 20:16:06 +08:00
youpaishidifu fd077e343c 修复: OCR md文档预检 + 日志显示完整文本
1. 分割前 md 预检:在时间戳分割前用 _is_markdown_document 检查整行,
   避免分割打断 md 链接/标题语法导致碎片漏过_BqDgv_过滤
2. 强化 _is_markdown_document:新增 .md) 文件引用模式
   (如 gin.md) 分割后残缺链接)+ 内联 # # 标题标记
3. 调试日志不再截断:normalize/clean 显示前120字符+长度,
   split parts 显示前60字符,定位问题不靠猜
2026-07-26 20:04:54 +08:00
youpaishidifu 2ccb677abf OCR截屏前点击消息面板设焦点(TIM默认焦点在会话列表,VK_END只滚滚会话列表)+加详细OCR处理日志(stage normalize/clean/split) 2026-07-26 19:35:54 +08:00
youpaishidifu 54d474a6c5 裁剪退回c9acd7e版: cap_left=0.25, cap_top=0.04, cap_bottom=0.10. 42%+45%只截到bot自身消息右侧, 对方消息被切; md过滤+滚底保留负责拦截md内容和避旧堆 2026-07-26 19:24:44 +08:00
youpaishidifu 59e3657684 加_is_markdown_document过滤: bot回复是md格式(%23标题、[链接](url)、-列表、反引号代码、|表格), 用户聊天框不用md语法, 借此区分bot旧回复vs用户新消息 2026-07-26 19:19:37 +08:00
youpaishidifu 3602ad6ef3 OCR裁剪cap_top 62%->45%放宽避免切消息+PostMessage VK_END兜底滚底(怕keybd_event被TIM忽略) 2026-07-26 19:12:53 +08:00
youpaishidifu 8c71412600 OCR截屏前Ctrl+End滚底+cap_top改为底部38%: 避免历史堆积+bot旧回复混入OCR, 只截最新消息区域 2026-07-26 19:01:24 +08:00
youpaishidifu 4307d5743f TIM裁剪左边界从25%调到42%: 25%截到会话列表的文档预览(混入OCR), 42%从消息面板左边缘开始, 避免文档预览混入, 保留对方消息 2026-07-26 18:54:26 +08:00
youpaishidifu 621d4c45b6 EnumWindows简化: _enum_callback已只加QQ/TIM相关窗口(for+TXGuiFoundation+Chrome+title), for循环直接取第一个可见+尺寸正常的, 不要求标题含QQ/TIM 2026-07-26 18:49:23 +08:00
youpaishidifu efdc8b0a4c QQ NT Electron主窗口标题是群名/昵称而非固定"QQ": Chrome_WidgetWin_1类名+可见+尺寸>200x100即可接受,不要求标题含QQ/TIM 2026-07-26 18:45:05 +08:00
youpaishidifu 3047a3ee82 OCR去重加强: _replied_texts加模糊匹配(0.85阈值)拦截OCR噪声版长回复; 超长文本(>200字符)跳过避免堆积历史冒充新消息触发回环 2026-07-26 18:38:27 +08:00
youpaishidifu ff6b72d5f2 EnumWindows加IsWindowVisible检查+debug log看候选窗口: 之前不可见TXGuiFoundation辅助窗口被缓存, title空top=592874, 真实主窗口一直不被使用 2026-07-26 18:28:11 +08:00
youpaishidifu 8626130f0c Fix QQ_FindWindow误缓存不可见托盘辅助窗口: TXGuiFoundation有不可见托盘辅助窗口(空标题IsWindowVisible=False), FindWindow返回它并缓存→_poll里IsWindowVisible检查静默跳过全轮。加IsWindowVisible检查后才缓存,不可见则fall through到EnumWindows找Chrome_WidgetWin_1可见主窗口 2026-07-26 18:23:57 +08:00
youpaishidifu 7aa3c9398e 修微信[S-A]读到侧栏文件列表而非聊天消息: _read_message_list加位置过滤>窗口45%右半侧才接受; 修QQ NT(Electron)新类名查找失败: EnumWindows加Chrome类名+标题含QQ搜索; config.py默认qq_enabled=True 2026-07-26 18:15:50 +08:00
youpaishidifu 0775ceaea7 QQ托盘隐藏时跳过poll不尝试恢复窗口: 任何ShowWindow(SW_SHOWNORMAL)在隐藏QQ NT窗口上都会触发托盘预览弹窗而非恢复主窗口 2026-07-26 17:57:15 +08:00
youpaishidifu 6bc8885eae 降级_validate_qq_window回c9acd7e版: 不做自动恢复->OCR空读->剪贴板兜底_ensure_foreground负责恢复主窗口 2026-07-26 17:46:55 +08:00
youpaishidifu 86686d0e22 修复Q窗口托盘恢复用SW_SHOWNORMAL替代SW_SHOWNA: SW_SHOWNA触发托盘预览弹窗而非主窗口 2026-07-26 17:38:11 +08:00
youpaishidifu 8f9433983f QQ托盘隐藏时用SW_SHOWNA恢复窗口(不触发托盘弹窗)+poll结束后自动SW_HIDE缩回托盘+验证不通过不再直接报窗口不可用 2026-07-26 17:21:09 +08:00
youpaishidifu e7f3adaa73 QQ窗口定位用Win32 FindWindow/EnumWindows替代UIA枚举,避免root.GetChildren()挂死 2026-07-26 16:59:03 +08:00
youpaishidifu 039b34179a 裁剪左边界退回25%(c9acd7e版),48%只截到自身消息右半边对方消息完全不可见 2026-07-26 16:54:23 +08:00
youpaishidifu 8963a34b6a 修复OCR乱码+KB全文返回: 裁剪48%+&提前清理+全角:转换+纯时间戳过滤+KB回复限200字
1. cap_left 38%→48%(完全避开会话列表~30-55%)
   38%仍捕获到左侧KB预览文字(问题1/2…)混入OCR
   48%只捕获消息面板正文,KB预览不再出现

2. &清理移到时间戳分割前+全角:→半角:
   原来&在分割后才清理,"13:5&07"无法被时间戳正则捕获
   分割前清理→"13:5 07"可匹配时间戳→分割出独立段
   全角:统一半角,后续正则只匹配半角

3. 时间戳段用\d{1,2}(允许单数字分钟)
   分割后"07""15"等纯数字段被^[\d:\s]+$过滤
   之前"13:5  07 14:2  15"整段因含空格,^\d{1,2}[::]\d{2}不匹配

4. auto_reply非Q&A文档回复限200字(之前500仍过多)
   子串匹配触发的全文返回只回复前200字符

5. KB行级预览过滤移除(与用户消息混行时误杀)
   段级别^问题\d+过滤器已足够,配合新裁剪基本不会触发
2026-07-26 16:37:41 +08:00
youpaishidifu 0e02a4a44c 修复OCR文字乱码:裁剪38-97%+KB预览过滤+&碎片清理
1. cap_left 25%→38%(避开会话列表KB预览文字)
   25%捕获联系人+会话列表双面板文字,KB预览"问题1:你叫什么名字"
   及小字OCR误读"届亻牛"(插件)→混合乱码
   38%从会话列表偏右开始,主要捕获消息面板大字号正文

2. cap_right 95%→97%(减少右侧时间戳裁剪)
   95%裁到时间戳右边缘→"13:57:07"变"13:5&07"
   97%多给2%宽度,大幅减少&碎片

3. KB预览行直接过滤:^问题\d+[::]
4. 循环中去掉&字符:line.replace('&', '')
2026-07-26 15:52:43 +08:00
youpaishidifu 7bdc7ad637 修复2问题: KB误匹配+返回全文 / Ctrl+C无法停止
1. KB匹配与返回全文
   - _poll中过滤纯时间/日期格式文本(OCR时间戳分割残留)->不入KB搜索
   - knowledge_base.py子串fallback要求query>=4字符,避免"19:15"等短时间戳误匹配
   - auto_reply._get_answer: 非Q&A文档只返回content前500字符,不返回整篇文件
   - 时间戳文本不进入KB + 短query不子串匹配 + 非Q&A截取 = 三层兜底

2. Ctrl+C无法停止
   - ThreadPoolExecutor创建非daemon线程->进程无法退出->必须杀CMD
     改用daemon thread + Event.wait(timeout): daemon线程不阻塞进程退出
   - main.py注册signal.signal(SIGINT) handler: 收到Ctrl+C后stop监控+quit窗口
   - 移除from concurrent.futures导入,替换为import signal
2026-07-26 15:30:55 +08:00
youpaishidifu 6d0974ea8f 修复_ensure_hwnd UIA挂死导致整条while循环卡住\n\n1. _ensure_hwnd 调用包装 ThreadPoolExecutor + 12s 超时\n 防止 QQ TXGuiFoundation 枚举或微信窗口检测无限阻塞\n 超时后日志警告 + 跳过本轮,while 循环继续跑\n\n2. _run_loop 首轮加 '进入 while 循环' 日志\n 快速确认循环启动\n\n3. 新增 concurrent.futures 导入\n\n根因:UIA COM 调用可挂死不返回(如遍历所有顶层窗口时\n某进程无响应),整个 _poll 卡住 → while 循环停转\n→ 无心跳 → 无任何输出 2026-07-26 15:13:09 +08:00
youpaishidifu 5492cdf81b QQ OCR按时间戳分割恢复独立消息
- QQ NT OCR 输出所有可见消息合并为一段无换行文本
- 用re.split捕获组按时间戳(HH:MM或HH:MM:SS)切割
- 每段时间戳之间的文本作为独立消息处理
- 避免"7你好我叫12314:2&15你好我叫12314:42:45SDFI届亻牛有中文吗?"
  整坨变成一条新消息
2026-07-26 14:54:21 +08:00
youpaishidifu 62f6277cf3 修复 stale UnboundLocalError:初始化stal变量在不同路径
- stale 变量仅在 signature-early-return 分支定义
- 正常路径(新消息处理)用到 stale 时报 UnboundLocalError
- 修复:在 signature 检查前初始化 stale=0,两个路径都能访问
2026-07-26 14:46:39 +08:00
youpaishidifu f4c6243944 修复重复处理+新消息不处理:全签名跳过+_seen_messages上限+模糊阈值0.80
1. 全文本签名提前跳过(关键)
   OCR输出与上轮完全一样→立即return,不跑去重循环
   99%场景OCR内容不变,之前却每次都跑模糊匹配→噪声导致漏网

2. _seen_messages上限500条,超了裁到300
   无限增长→新消息模糊匹配时被历史噪声误杀("新消息没处理")
   上限后新消息只和最近300条比,大幅降低误杀率

3. 模糊匹配阈值0.72→0.80
   短文本0.72太松,"你好"vs"你好啊"75%相似就被当成重复
   0.80要求80%重复才跳过,放行真新消息
2026-07-26 14:11:37 +08:00
youpaishidifu e9d9551e3d 修复2个问题:退回裁剪+知识库只回复匹配句\n\n1. 裁剪退回c9acd7e版(cap_left=0.25)\n 0.35只截到时间戳,用户消息被切;0.25覆盖消息文字区域\n\n2. 知识库返回全文→只返回匹配问答段\n 原问题:名字.txt含2个Q&A,TF-IDF整文件匹配后返回全文\n 该方案:knowledge_base._parse_qa_segments解析文件为独立问答段\n 每段作为独立doc,auto_reply._get_answer优先返回doc.answer\n 用户问一句话,只回复对应答句,不塞全部内容 2026-07-26 13:38:04 +08:00