From 9dd6dbff447ff0693a2b0b4d069cca980068c941 Mon Sep 17 00:00:00 2001 From: jesxion Date: Mon, 13 Apr 2026 11:51:17 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=97=A5=E5=BF=97=E5=92=8C?= =?UTF-8?q?=E5=9B=9E=E5=A4=8D=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 改进 VLM prompt,明确说明微信左右消息布局判断 is_self - 添加详细调试日志,追踪回复判断过程 - 改进 should_reply 逻辑,添加 sender/content 日志 --- src/core/__pycache__/engine.cpython-311.pyc | Bin 0 -> 18960 bytes src/core/engine.py | 28 ++++++++++++++++---- src/vlm/__pycache__/qwen_vl.cpython-311.pyc | Bin 20335 -> 20701 bytes src/vlm/qwen_vl.py | 26 ++++++++++++------ 4 files changed, 41 insertions(+), 13 deletions(-) create mode 100644 src/core/__pycache__/engine.cpython-311.pyc diff --git a/src/core/__pycache__/engine.cpython-311.pyc b/src/core/__pycache__/engine.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b53542e2b25043e888ad8c2c3a48ee3641b227b3 GIT binary patch literal 18960 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 bool: """判断是否需要回复""" - if not chat_snapshot.has_new: - return False - - # 检查是否是自己的消息 + # 检查是否有消息 messages = chat_snapshot.messages if not messages: + logger.debug("没有消息,不回复") return False + # 检查最后一条消息 last_msg = messages[-1] - if last_msg.get("is_self"): + sender = last_msg.get("sender", "") + content = last_msg.get("content", "") + is_self = last_msg.get("is_self", False) + + logger.debug(f"最后一条消息: sender={sender}, is_self={is_self}, content={content[:30]}") + + # 如果是自己发的消息,不回复 + if is_self: + logger.debug("自己发的消息,不回复") + return False + + # 检查是否有新消息(未读标记) + if not chat_snapshot.has_new: + logger.debug("没有新消息,不回复") return False return True @@ -267,10 +279,16 @@ class WeChatAgent: # 判断是否需要回复 if self.processor.should_reply(snapshot): + logger.info(f"需要回复,生成回复内容...") reply = self.processor.generate_reply(snapshot) if reply: + logger.info(f"发送回复: {reply[:50]}...") result = self.send_reply(reply) self._emit("on_reply", result) + else: + logger.warning("生成回复为空") + else: + logger.debug("不需要回复(已读消息或自己发送)") except Exception as e: logger.error(f"轮询处理异常: {e}") diff --git a/src/vlm/__pycache__/qwen_vl.cpython-311.pyc b/src/vlm/__pycache__/qwen_vl.cpython-311.pyc index fa03f0a9715e520b63dd4b7d6142958c2378a07b..fe81d43fec5ed523bd185762a10c9f3ff679a1eb 100644 GIT binary patch delta 917 zcmZuvTTc@~6lRLWWEBh&Z_${|YES|c3ThN03Ydt*fQkA>QVTAZ1d6srpR|BLw}hs^ zVvE=iF14*CwBRT$rCc6-Fh-tCj1T&@Gu_6RV&V^Qc2{d3n1`9nch32~GvAryH26LX za(vm@R0dhN?OVsKs^y&KLeK;s7Jda;c=BD`x5R@3d9bOt8>oI{^4pqw777i*#6(aG z4Iyqp^bH{HMKU%;X*D$32nw6Cc!k4#A;b*{kthm#kpl`5kFen*Nuo7?!pq3*mp};_ zL7`RbT$PZpmmpLbVUc4B3!V%ym>Xk|V=U3z7oQqP#w;TpCY_1xY`ttY_OMhrDUeH3 z1%E03SELGB^_?b`Iwwg;bYkz|Srcox&l(F*bV3ZhB5G(bEUfcHNQeZ4XjHL)^eIH_ zBpToFAj_y7b55~u7%-yX0U4|;d;w&m*!VXTxruLTx8g3-@`_nmWL)KrcGJ0Q2sdl32pIyVQo!Ve=hpw z6V_qas9gkmj~p!JvUbYGFCB)*%0H{YUHJ22zY08p4=UX%&=0e#)Bt>ec~`VRTLaXm zmP|Vt(it&t)qcp^s*62U?z`-DD%gG1q5>{HS>pv`&{>-cfFJs=b?*T|c=SePCin#J c+{{;Lo7JFVCu8^hmyG{TkJj(w7aHFG0g_YdGXMYp delta 524 zcmcb+kn#OIM!w~|yj%=G@HF*K<_nvRd`a4jVVeuJZ!k_~9VG0^X5F8vHtnKB`+Gg-tXyov46_b+4F$hrxSW7s~PGj zK3lN!S?@ZalBW}vJ)6_{Y|g3|>vum}(EeiGhNm4%o=sajIo;5G@+Cv{dXRau_dV}y ze?DbJG=vrVV&RJCOLl?GUBC9_{LLU42n$JOdE3iH6TvcI7DDFPwDu>vw}E6JEVxXk zk`9*w5>P71%uSulYsAgHcKY)*%bx7m1hjFoxRILXvyN$Li8;loK(|4?Fk}6T_Ek@} zZ+zN6@nu8f^I0v=wskyfTtB(aNSEzt>$WGmr)}PDw3d;bS4gXa?StIrY?GI)jNY3= zt(uq^b2i_wnZv|bvANWqm67qn=4uB+Mr{jLOFpj9_K7`oMsl{0J8R Nf-GCcHCZy?2mrv4{Zaq` diff --git a/src/vlm/qwen_vl.py b/src/vlm/qwen_vl.py index 6021810..a34239a 100644 --- a/src/vlm/qwen_vl.py +++ b/src/vlm/qwen_vl.py @@ -283,7 +283,7 @@ class BailianVLMClient: - current_chat: 当前聊天对象名称 - has_new_message: 是否有新消息 - messages: 消息列表,每条消息包含: - - sender: 发送者 + - sender: 发送者昵称 - content: 消息内容 - time: 时间 - is_self: 是否是自己发送的 @@ -295,19 +295,29 @@ class BailianVLMClient: print(f"{msg['sender']}: {msg['content']}") """ prompt = """请分析这个微信聊天截图,返回严格的 JSON 格式,不要包含其他内容: + +关键识别规则: +1. 微信消息分为左右两侧:自己在右侧,对方在左侧 +2. 右侧消息是"我"发送的,is_self=true +3. 左侧消息是对方发送的,is_self=false +4. 发送者(sender)应该是具体的个人昵称,不是群名或聊天标题 +5. current_chat 是聊天窗口顶部的标题,如"Anna司梦 米果妈" +6. has_new_message 根据右上角是否有红色未读标记判断 + +返回 JSON: { - "current_chat": "当前聊天对象名称(如果是群聊,返回群名)", - "has_new_message": true或false(根据是否有未读标记判断), + "current_chat": "聊天窗口标题(顶部标题栏的文字)", + "has_new_message": true或false(右上角红色标记), "messages": [ { - "sender": "发送者昵称", - "content": "消息内容(图片用[图片]表示,语音用[语音]表示,视频用[视频]表示,文件用[文件]表示)", - "time": "时间字符串,如10:30", - "is_self": true或false(是否是自己发送的消息) + "sender": "发送者昵称(具体人名,不是聊天名)", + "content": "消息内容", + "time": "时间如10:30", + "is_self": true(右侧消息,我在右侧)或false(左侧消息,对方) } ] } -只返回 JSON,不要其他文字。""" +只返回 JSON,不要任何解释文字。""" result = self.analyze_image(screenshot_path, prompt)