Files
EzVibe/docs/v2_design/ARCHITECTURE.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

13 KiB
Raw Permalink Blame History

EzVibe v2 架构设计文档

本文档描述 EzVibe 系统当前v1.x的整体架构设计。


1. 系统概览

EzVibe 是一个运行在用户桌面上的 AI 桌宠系统,核心目标是健康监测与提醒(久坐提醒、喝水提醒)。

技术栈

  • Python 3.10+
  • PySide6 / PyQt6Qt 图形界面)
  • SQLite + NumPy本地持久化 + 向量检索)
  • Ollama / OpenAILLM 推理)
  • pynput全局键鼠监听

运行模式

  • 完整 GUI 模式(python main.py
  • Headless Dummy 模式(python main.py --dummy
  • API Server 模式(python main.py --server

2. 分层架构

┌─────────────────────────────────────────────┐
│              表现层 (UI)                     │
│         ui/pet_window.py                    │
│    - PetWindow / DummyPetWindow             │
│    - 情绪动画渲染、右键菜单、托盘            │
└────────────────────┬────────────────────────┘
                     │
┌────────────────────▼────────────────────────┐
│              智能层 (Agent)                  │
│                                             │
│  ┌─────────┐ ┌─────────┐ ┌──────────────┐  │
│  │ brain   │ │ emotion │ │   scheduler  │  │
│  │ .py     │ │ .py     │ │   .py        │  │
│  │ LLM决策 │ │ 状态机  │ │   行为调度    │  │
│  └────┬────┘ └────┬────┘ └──────┬───────┘  │
│       └───────┬──┴────────────┘          │
│        ┌──────▼──────┐                   │
│        │   memory    │                   │
│        │   .py       │                   │
│        │ RAG向量记忆  │                   │
│        └─────────────┘                   │
└────────────────────┬────────────────────────┘
                     │
┌────────────────────▼────────────────────────┐
│              感知层 (Perception)              │
│     perception/keyboard_mouse_monitor.py   │
│    - 键鼠事件监听、活跃度检测               │
│    - ScreenCapture截图+OCR              │
└─────────────────────────────────────────────┘

3. 模块职责

3.1 表现层 — ui/pet_window.py

职责

  • 渲染桌宠窗口(无边框、置顶、透明背景)
  • 情绪状态驱动动画idle/happy/focused/annoyed/sleepy
  • 提醒通知弹窗(健康喝水/伸展提醒)
  • 拖拽移动、右键菜单、最小化到托盘

关键类

  • PetWindowPySide6/PyQt6 实现,延迟构造避免导入冲突
  • DummyPetWindowheadless 测试替代,不依赖 Qt

图像资源

assets/pet/
├── idle/
├── happy/
├── focused/
├── annoyed/
└── sleepy/

每个情绪目录下存放 16 帧 PNG 动画180×180px。无图像时回退到 emoji 显示。

设计亮点

  • _make_pet_window_class() 使用 type() 动态构造类,避免模块级导入 QtWidgets
  • create_pet_window() 工厂函数,支持 force_dummy 强制降级

3.2 智能层 — agent/

3.2.1 brain.py — AgentBrainLLM 推理引擎)

职责

  • 整合记忆上下文 + 情绪状态 + 用户输入
  • 调用 LLMOllama/OpenAI/Dummy生成回复
  • 决策是否触发主动行为
  • 管理会话历史(短期上下文窗口)

LLM 后端适配器(策略模式)

LLMBackend (基类)
├── OllamaBackend    — http://localhost:11434
├── OpenAIBackend    — OpenAI API / 兼容第三方
└── DummyLLMBackend  — 测试用固定回复

核心方法

  • think(user_input):接收用户输入,返回 {"text", "emotion_state", "action"}
  • decide_action():异步决策是否触发主动行为
  • _parse_action():从 LLM 回复中解析 [ACTION: type:description] 标签

System Prompt 模板

DEFAULT_SYSTEM_PROMPT = """你是「EzVibe」一个运行在用户桌面上的 AI 桌宠。
【当前情绪状态】{emotion_display}
【性格设定】友善、活泼,偶尔会犯懒或闹小脾气...
【主动行为能力】可以提醒喝水/休息,或做出可爱小动作。
请用自然对话风格回复。如果想触发主动行为,在回复末尾加上:
[ACTION: <action_type>:<description>]
"""

3.2.2 emotion.py — EmotionEngine情绪状态机

状态集合S = {idle, happy, focused, annoyed, sleepy}

核心机制

  • 5×5 状态转移矩阵 P
  • 上下文调制因子(事件驱动增益)
  • 蒙特卡洛随机采样
  • 最小驻留时间限制(防止抖动)

状态转移矩阵(行=当前状态,列=目标状态):

          → idle   happy  focused annoyed sleepy
  idle   │ 0.4    0.2    0.2     0.1    0.1
  happy  │ 0.2    0.5    0.1     0.1    0.1
 focused │ 0.1    0.2    0.5     0.1    0.1
 annoyed │ 0.1    0.1    0.1     0.6    0.1
 sleepy  │ 0.2    0.1    0.1     0.1    0.5

事件增益ContextBoost.EVENT_BOOSTS

"long_work_session"   sleepy +2.0, focused +0.8
"user_focused"         focused +2.5
"reminder_ignored"     annoyed +3.0
"user_praise"          happy +3.0
"user_healthy_action"  happy +2.0

关键方法

  • update(event):根据事件触发状态转移
  • tick():时钟推进,触发 time_passes 事件
  • force_state(state):强制设置状态(测试用)

3.2.3 scheduler.py — BehaviorScheduler行为调度器

行为优先级定义

  • PRIORITY_HIGHEST = 0:健康/高危提醒(打断所有)
  • PRIORITY_USER_INPUT = 1:用户主动输入响应
  • PRIORITY_PROACTIVE = 2:系统主动闲聊/行为
  • PRIORITY_LLM_TRIGGER = 3LLM 自触发

内置行为

行为 优先级 冷却 说明
remind_water 0 1800s 喝水提醒
remind_stretch 0 3600s 久坐伸展提醒
idle_nudge 2 300s 空闲闲聊触发
happy_nudge 2 600s 开心时主动搭话

核心逻辑

  • 活跃度限制极度专注activity < 0.15)时禁止 P2/P3 打扰
  • 情绪调制focused 状态概率×0.2sleepy 状态概率×0.3
  • 提醒队列:Reminder 延迟执行任务

3.2.4 memory.py — VectorMemory向量记忆系统

数据模型

@dataclass
class MemoryEntry:
    text: str           # 记忆文本
    embedding: list[float]  # 向量嵌入
    tags: list[str]     # 标签
    metadata: dict      # 元数据
    created_at: float   # 时间戳
    id: str | None      # UUID

存储层SQLite + MemoryStore

CREATE TABLE memories (
    id         TEXT PRIMARY KEY,
    text       TEXT NOT NULL,
    embedding  BLOB NOT NULL,  -- numpy 序列化
    tags       TEXT NOT NULL DEFAULT '[]',
    metadata   TEXT NOT NULL DEFAULT '{}',
    created_at REAL NOT NULL
);

嵌入适配器

make_embedder(backend)
├── OllamaEmbedder   — nomic-embed-text
├── OpenAIEmbedder  — text-embedding-3-small
└── DummyEmbedder   — TF-IDF开发/测试用)

RAG 工作流

  1. Query → Embedding
  2. 向量检索 Top-k
  3. 格式化上下文
  4. 注入 System Prompt

3.3 感知层 — perception/

3.3.1 keyboard_mouse_monitor.py — KeyboardMouseMonitor

职责:全局键盘/鼠标监听,使用 pynput 全局钩子。

核心组件

  • ActivityDetector:滑动窗口活跃度统计
  • KeyboardMouseMonitorpynput listener + queue
  • ScreenCapturemss 截图 + pytesseract OCR

活跃度计算

baseline = window_seconds / 60.0 * 30.0  # 30 events/min = normal
activity = min(raw / baseline, 1.0)

阈值定义

  • activity < 0.15:极度专注(可能深度工作/游戏)
  • activity < 0.3:比较专注
  • 0.3 ≤ activity < 0.7:适度活跃
  • activity ≥ 0.7:非常活跃

全局单例

_global_monitor: KeyboardMouseMonitor | None = None

def get_global_monitor(...)  KeyboardMouseMonitor
def stop_global_monitor()  None

4. 主入口 — main.py

4.1 EzVibeApp 初始化流程

def _init_components(self):
    1. EmotionEngine()
    2. VectorMemory(embedder_backend="dummy")  # 避免依赖 Ollama
    3. AgentBrain(llm_backend=...)
    4. KeyboardMouseMonitor + ScreenCapture
    5. BehaviorScheduler(emotion_engine, activity_detector)
    6. PetWindow延迟到 QApplication 之后

4.2 运行模式

Dummy 模式headless 测试):

def _run_dummy(self):
    # 初始化后直接打印状态摘要,模拟行为触发

Qt 模式

def _run_qt(self):
    app = QtWidgets.QApplication(sys.argv)
    self._window = create_pet_window(...)  # QApplication 之后才能创建
    # QTimer 20ms 驱动 asyncio 轮询(临时方案,待改进)
    timer.timeout.connect(lambda: self._loop.run_until_complete(asyncio.sleep(0)))
    app.exec()

5. API 服务器 — api/server.py

FastAPI 服务器,提供 REST/WebSocket 接口:

端点 方法 说明
/status GET 返回系统状态
/emotion GET/POST 获取/设置情绪状态
/remind POST 添加提醒
/memory/search POST RAG 检索
/memory/add POST 添加记忆
/ws WebSocket 实时事件流

6. 数据流

6.1 用户交互流程

用户输入文本
    ↓
AgentBrain.think()
    ↓
┌─ 注入情绪状态到 System Prompt
├─ RAG 检索相关记忆VectorMemory.search
├─ 追加对话历史
└─ 调用 LLMOllama/OpenAI/Dummy
    ↓
解析 [ACTION: ...] 标签
    ↓
返回 {"text": "...", "action": {...}, "emotion_state": "..."}
    ↓
PetWindow 显示回复 + 动画

6.2 健康监测流程

定时调度(每 10s
    ↓
BehaviorScheduler.check_and_trigger()
    ↓
┌─ 冷却时间检查
├─ 活跃度限制检查(极度专注时禁止打扰)
├─ 概率触发(结合情绪调制)
└─ 执行 action_fn()
    ↓
show_reminder() → 气泡通知
    ↓
记录到记忆VectorMemory.add

6.3 感知数据流

pynput 全局钩子(独立线程)
    ↓
queue.Queue 传递事件
    ↓
_worker_loop 消费队列
    ↓
ActivityDetector.record() 记录到滑动窗口
    ↓
get_activity() → 0.0~1.0 活跃度

7. 文件结构

EzVibe/
├── main.py                 # 主入口EzVibeApp
├── requirements.txt        # 依赖列表
├── setup_project.py        # 项目初始化脚本
│
├── agent/
│   ├── __init__.py
│   ├── brain.py           # AgentBrain + LLM后端
│   ├── emotion.py         # EmotionEngine 状态机
│   ├── scheduler.py       # BehaviorScheduler + ActivityDetector
│   ├── memory.py          # VectorMemory + MemoryStore + VectorEngine
│   └── test_*.py          # 单元测试
│
├── perception/
│   ├── __init__.py
│   ├── keyboard_mouse_monitor.py  # KeyboardMouseMonitor + ActivityDetector
│   └── test_perception.py
│
├── ui/
│   ├── __init__.py
│   ├── pet_window.py      # PetWindow + DummyPetWindow
│   └── test_pet_window.py
│
├── api/
│   ├── __init__.py
│   └── server.py          # FastAPI 服务器
│
├── data/                  # SQLite 数据库目录
├── assets/                # 桌宠图像资源
│
└── docs/
    ├── v2_design/
    │   ├── ARCHITECTURE.md         # 本文档
    │   ├── ARCHITECTURE_REVIEW.md  # 架构评审
    │   ├── EVOLUTION_ROADMAP.md    # 演进路线
    │   ├── HEALTH_TRACKER_SPEC.md  # HealthTracker 规格
    │   └── DESIGN_DECISIONS.md     # 设计决策
    └── *.md               # 其他文档

8. 已知限制与改进方向

问题 现状 改进方向
Qt + asyncio 融合 QTimer 轮询(不稳定) 引入 qasync
OCR 性能消耗 mss + pytesseract 每分钟执行 轻量级焦点窗口提取
LLM 延迟 同步等待 5 秒 解耦动作与文案Fallback 缓存
annoyed 状态屏蔽 P0 完全禁止打扰 柔性降级(安静模式)
健康数据缺乏结构化 RAG 模糊检索 HealthTracker 结构化数据库
奖惩机制无闭环 单向提醒 隐式确认 + 正向反馈

详见 ARCHITECTURE_REVIEW.md