- 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>
152 lines
6.1 KiB
Markdown
152 lines
6.1 KiB
Markdown
# 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 能力,而是要把"健康数据采集"和"桌宠行为反馈"这两者结合得更自然、更不招人烦。** |