# 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():`,彻底告别由于跨线程/跨循环引发的死锁问题。 **参考代码**: ```python 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` 属性: ```python @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 天 | --- ## 四、架构优势总结 尽管存在上述改进空间,当前架构的优势在于: 1. **分层清晰**:感知 → 决策 → 记忆 → 表现,边界明确 2. **技术栈务实**:SQLite + 本地向量 + 本地 LLM,隐私优先 3. **测试覆盖**:128 个单元测试,底层基础牢固 4. **策略模式**:LLM 后端可替换,支持 Ollama/OpenAI/Dummy 5. **延迟构造**:PetWindow 动态构造,避免 Qt 导入冲突 接下来的重点:**不需要再盲目堆砌 AI 能力,而是要把"健康数据采集"和"桌宠行为反馈"这两者结合得更自然、更不招人烦。**