Files
EzVibe/docs/v2_design/ARCHITECTURE_REVIEW.md
e2hang 96cb28fe08 feat: multi-layer eventFilter for window drag + text input fix + Qt platform xcb
- 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>
2026-05-19 23:36:58 +08:00

152 lines
6.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 能力,而是要把"健康数据采集"和"桌宠行为反馈"这两者结合得更自然、更不招人烦。**