- Fix window drag: install eventFilter on live2d_container, central, and _live2d_widget; fix super() call in dynamic class - Fix text input: remove WA_TransparentForMouseEvents from _chat_container - Force QT_QPA_PLATFORM=xcb on Linux (wayland has mouse event issues) - Add HealthTracker module, update AgentBrain with health integration - Update scheduler and memory modules - Add v5_modify documentation Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
6.1 KiB
EzVibe 架构评审 — 健康监测场景深度分析
评审日期:2026-05-18 评审者:e2hang
一、架构设计隐患与优化建议(技术层)
1. Qt 与 asyncio 的事件循环融合(高危隐患)
文档现状:
QTimer 每 20ms 调用 loop.run_until_complete(asyncio.sleep(0)),后台 asyncio.run()。
问题所在: 这是 PyQt/PySide 与 asyncio 结合时最容易出 Bug 的"土办法"。随着 LLM 推理(甚至网络波动)、OCR 截图的加入,这种粗暴的轮询极易导致:
- UI 线程卡顿(桌宠拖动掉帧)
- CPU 占用率异常升高
- 对于一个需要常驻后台的健康软件是致命的(会耗尽笔记本电池)
改进建议:
强烈建议引入 qasync 库。它实现了完美的 Qt 事件循环与 asyncio 的底层融合。主入口可以改写为原生的 async def main():,彻底告别由于跨线程/跨循环引发的死锁问题。
参考代码:
import qasync
from PySide6.QtWidgets import QApplication
async def main():
# 这里是真正的 asyncio 代码
window = create_pet_window(...)
window.show()
await qasync.EventLoopPolicy().mainloop()
if __name__ == "__main__":
qasync.run(main)
2. 感知层的性能消耗 (Battery Drain)
文档现状:
ScreenCapture 使用 mss 截图 + pytesseract OCR。
问题所在: OCR 是 CPU 密集型任务。如果每分钟都在后台跑 Tesseract,风扇会狂转。桌宠本来是辅助工具,不能成为系统负担。
改进建议:
- 降级策略:在"健康监测"场景下,**当前焦点窗口的名字(Window Title)**比全屏 OCR 更重要,也更轻量(Windows 用
pygetwindow/win32gui,Mac 用AppKit)。 - 按需触发:仅在发现用户持续活跃(
ActivityDetector > 0.8且持续 1 小时)时,才触发一次 OCR 看看他在干嘛(写代码/看视频),从而生成更精准的 LLM 提醒。
3. LLM 调用的延迟处理 (Latency)
文档现状:
主循环触发 decide_action(),依赖本地 Ollama 或 OpenAI API。
问题所在: 如果判断需要提醒喝水,但调用大模型生成文本花了 5 秒,这 5 秒内桌宠会"发呆",体验不佳。
改进建议: 解耦"动作触发"与"文案生成":
- 对于 P0 级健康提醒(如久坐),桌宠应立刻执行 UI 动作(如跳出来递水杯)
- LLM 文案可以异步加载
- 或者使用本地预存的 Fallback 文案缓存池
二、贴合"健康监测"场景的业务逻辑评审
1. "烦躁 (annoyed)" 状态屏蔽 P0 提醒的悖论
文档现状: 烦躁(annoyed)→ 禁止 P0/P1 所有打扰。
冲突分析:
真实场景中,用户连续工作 3 小时不休息,可能因为卡 Bug 导致键鼠敲击极重(此时通过 pynput 算出的活跃度极高,情绪很容易转为 focused 甚至 annoyed)。如果此时桌宠因为"怕打扰他"而屏蔽久坐提醒,就失去了健康监测的意义。
优化方案(柔性降级):
- 不要屏蔽 P0,而是改变 P0 的表现形式
- 正常状态:桌宠走到屏幕中间,大喊"喝水啦!"并强行弹窗
- 烦躁/极度专注状态:桌宠缩在角落,默默举起一个带有 💧 图标的小牌子(不播放音效,不挡视线)
- 这种"怂怂的但固执"的设定,反而能增加角色的情感厚度
设计变更:
为 Behavior 增加 display_mode 属性:
@dataclass
class Behavior:
display_mode: DisplayMode = DisplayMode.NORMAL # Normal | Quiet | Aggressive
2. 记忆系统 (RAG) 缺乏结构化健康数据
文档现状: 使用 RAG (VectorMemory) 记录事件,Cosine 检索。
冲突分析: RAG 擅长模糊语义检索(如:"我昨天提到喜欢喝什么奶茶?"),但不擅长精准的时序统计(如:"用户今天喝了几次水?"、"连续静坐了几个小时?")。
优化方案: 引入混合记忆架构:
- 语义记忆 (RAG):记录用户的习惯、喜好、甚至抱怨("别烦我,在赶 Due")
- 结构化健康数据库 (SQLite):记录
last_stand_time,daily_water_intake,screen_time
LLM 在 AgentBrain.think() 时,系统直接将这些精确数值注入 System Prompt 顶部,比让 LLM 自己去 RAG 里翻找要可靠得多。
3. 奖惩机制的闭环
文档现状:
user_healthy_action → happy +2.0
深入设计: 目前的互动是单向的(桌宠提醒 -> 用户去做)。如何判断用户真的做了?
优化方案:
- 微交互确认:当桌宠提醒喝水时,UI 上提供一个"吨吨吨(已喝)"和"等会儿"的按钮
- 基于感知的隐式确认:如果在提醒起立后,
ActivityDetector监测到键鼠长达 2 分钟完全无动作,且摄像头/麦克风无明显活动,系统自动判定用户去休息了,等用户回来时,桌宠状态变为happy并给出正向反馈
三、关键设计变更汇总
| 优先级 | 变更项 | 影响模块 | 预计工时 |
|---|---|---|---|
| P0 | qasync 替换 QTimer | main.py, ui/pet_window.py | 0.5 天 |
| P0 | HealthTracker 模块 | 新增 agent/health_tracker.py | 1 天 |
| P1 | 焦点窗口替代 OCR | perception/keyboard_mouse_monitor.py | 0.5 天 |
| P1 | DisplayMode 柔性降级 | agent/scheduler.py | 0.5 天 |
| P1 | LLM 文案异步加载 | agent/brain.py | 0.5 天 |
| P2 | 微交互确认 UI | ui/pet_window.py | 1 天 |
| P2 | 隐式确认反馈机制 | perception/keyboard_mouse_monitor.py | 1 天 |
四、架构优势总结
尽管存在上述改进空间,当前架构的优势在于:
- 分层清晰:感知 → 决策 → 记忆 → 表现,边界明确
- 技术栈务实:SQLite + 本地向量 + 本地 LLM,隐私优先
- 测试覆盖:128 个单元测试,底层基础牢固
- 策略模式:LLM 后端可替换,支持 Ollama/OpenAI/Dummy
- 延迟构造:PetWindow 动态构造,避免 Qt 导入冲突
接下来的重点:不需要再盲目堆砌 AI 能力,而是要把"健康数据采集"和"桌宠行为反馈"这两者结合得更自然、更不招人烦。