[数智金融][14]金融桌面助手的设计和实现 金融桌面助手 —— 你的桌面 AI 陪伴 为什么需要桌面助手想象一下有一个 助理随时可见—— 一个小巧的悬浮球安静地待在你的桌面角落随时可聊—— 点一下就能对话不需要打开任何网页或 App能看懂你的屏幕—— 遇到报错让它帮你分析不用复制粘贴主动关心你—— 发现你长时间工作会提醒你休息这不只是一个工具而是一个虚拟助理。悬浮球的独特之处特点传统 AI 聊天桌面悬浮球存在感需要打开网页/App始终在桌面陪伴你交互方式主动去找它它就在那里点一下即可屏幕理解需要复制粘贴直接看懂你的屏幕主动性只会被动回答会主动关心你的状态情感连接冷冰冰的工具陪伴感✨ 核心功能 随时对话点击悬浮球打开对话窗口和你的 AI 伙伴聊天。你今天有点累... AI我注意到你已经连续工作了 3 个小时了呢要不要站起来活动一下 我可以帮你设置一个 10 分钟后的提醒 ☕沉浸式对话体验 完整 Markdown 渲染代码高亮、公式、表格️ 图片/文件拖拽发送 屏幕感知AI 能看到你屏幕上的内容帮你分析问题。你遇到一个代码报错 你帮我看看这个报错 AI我看到了这是一个 NullPointerException。 问题出在第 42 行userService 没有被正确初始化。 你可以在调用前加上空值检查或者检查依赖注入配置... 主动交互AI 会根据屏幕内容在合适的时机主动给你建议。你在浏览技术文章 AI这篇关于 Rust 异步编程的文章不错 需要我帮你总结一下关键点吗 你长时间盯着代码发呆 AI看起来遇到了难题要不要说说你的思路 我帮你梳理一下架构设计系统概述Desktop Assistant 是一个基于 PySide6 的跨平台桌面客户端采用悬浮球 对话窗口的交互模式与 AstrBot 服务端通过 WebSocket 进行实时通信。技术栈层次技术选型GUI 框架PySide6 (Qt6)异步框架asyncio qasyncHTTP 客户端httpx配置管理Pydantic屏幕截图mss PillowMarkdownmarkdown pygments设计原则模块化各模块职责单一便于测试和维护响应式采用 Qt 信号槽机制实现组件间通信异步优先使用 asyncio 处理 I/O 操作架构图整体架构┌─────────────────────────────────────────────────────────────────┐ │ Desktop Client │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ Presentation Layer │ │ │ │ ┌────────────┐ ┌────────────┐ ┌────────────────────┐ │ │ │ │ │ FloatingBall│ │ ChatWidgets│ │ SettingsWindow │ │ │ │ │ └────────────┘ └────────────┘ └────────────────────┘ │ │ │ │ ┌────────────┐ ┌────────────┐ ┌────────────────────┐ │ │ │ │ │ SystemTray │ │ Themes │ │ ScreenshotSelector │ │ │ │ │ └────────────┘ └────────────┘ └────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ Application Layer │ │ │ │ ┌────────────┐ ┌────────────┐ ┌────────────────────┐ │ │ │ │ │ App │ │ Controllers│ │ Handlers │ │ │ │ │ │ │ │ (Settings) │ │ (Msg/Screenshot/ │ │ │ │ │ │ │ │ │ │ Proactive/Media) │ │ │ │ │ └────────────┘ └────────────┘ └────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ Domain Layer │ │ │ │ ┌────────────┐ ┌────────────┐ ┌────────────────────┐ │ │ │ │ │ Bridge │ │ Services │ │ Platforms │ │ │ │ │ │ (Message) │ │ (Monitor/ │ │ │ │ │ │ │ │ │ │ Capture) │ │ │ │ │ │ │ └────────────┘ └────────────┘ └────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ Infrastructure Layer │ │ │ │ ┌────────────┐ ┌────────────┐ ┌────────────────────┐ │ │ │ │ │ API Client │ │ Config │ │ Storage │ │ │ │ │ │ (HTTP/WS) │ │ (Pydantic) │ │ (ChatHistory) │ │ │ │ │ └────────────┘ └────────────┘ └────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ WebSocket / HTTP ▼ ┌─────────────────────────────────────────────────────────────────┐ │ AstrBot Server │ │ ┌────────────────────────────────────────────────────────────┐ │ │ │ astrbot_plugin_desktop_assistant │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │ │ │ │ │ WSHandler │ │DesktopMonitor│ │ProactiveDialog │ │ │ │ │ └──────────────┘ └──────────────┘ └──────────────────┘ │ │ │ └────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘模块依赖图┌─────────────────┐ │ App │ │ (DesktopClient │ │ App) │ └────────┬────────┘ │ ┌─────────────────┼─────────────────┐ │ │ │ ▼ ▼ ▼ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ GUI │ │ Handlers │ │ Controllers │ │ Components │ │ │ │ │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ │ │ │ ┌────────────┴────────────┐ │ │ │ │ │ ▼ ▼ ▼ ▼ ┌──────────────┐ ┌──────────────┐ │ Bridge │◄───────────────│ Services │ │ (Message) │ │ │ └──────┬───────┘ └──────┬───────┘ │ │ ▼ ▼ ┌──────────────┐ ┌──────────────┐ │ API Client │ │ Platforms │ │ (HTTP/WS) │ │ (Adapters) │ └──────┬───────┘ └──────────────┘ │ ▼ ┌──────────────┐ │ Config │ └──────────────┘核心模块1. GUI 模块 (gui/)负责用户界面展示和交互。1.1 悬浮球 (floating_ball.py)classFloatingBallWindow(QWidget): 悬浮球主窗口 功能 - 拖拽移动与边缘吸附 - 单击切换输入框 - 双击触发主动对话 - 右键菜单 - 消息气泡显示 - 呼吸灯状态提示 信号 - clicked: 单击事件 - double_clicked: 双击事件 - message_sent: 消息发送 - image_sent: 图片发送 - screenshot_requested: 截图请求 - settings_requested: 设置请求 - quit_requested: 退出请求 1.2 聊天组件 (chat_widgets.py)classChatWidget(QWidget): 聊天界面组件 功能 - Markdown 渲染代码高亮、表格、公式 - 消息气泡展示 - 图片预览与缩放 - 消息输入与发送 1.3 主题系统 (themes.py)classThemeManager: 主题管理器单例 功能 - 亮色/暗色主题切换 - 自定义颜色配置 - 系统主题跟随 使用 from gui.themes import theme_manager theme_manager.set_theme(dark) colors theme_manager.get_colors() 2. Handler 模块 (handlers/)处理各类事件和消息。2.1 消息处理器 (message_handler.py)classMessageHandler(QObject): 消息处理器 职责 - 解析服务端响应消息 - 处理文本、图片、语音等消息类型 - 更新聊天历史 - 触发 UI 更新 信号 - message_processed: 消息处理完成 2.2 截图处理器 (screenshot_handler.py)classScreenshotHandler(QObject): 截图处理器 职责 - 全屏截图 - 区域截图 - 主动对话截图 - 截图编码与发送 信号 - screenshot_completed: 截图完成 - proactive_screenshot_completed: 主动截图完成 2.3 主动对话处理器 (proactive_handler.py)classProactiveHandler(QObject): 主动对话处理器 职责 - 处理主动对话触发事件 - 组装桌面状态信息 - 发送至服务端进行分析 2.4 媒体处理器 (media_handler.py)classMediaHandler(QObject): 媒体文件处理器 职责 - 下载图片/语音文件 - 文件存储管理 3. Service 模块 (services/)封装核心业务逻辑。3.1 桌面监控服务 (desktop_monitor.py)classDesktopMonitorService: 桌面状态监控服务 功能 - 定时捕获桌面状态 - 窗口变化检测 - 截图采集 - 状态上报 使用 monitor DesktopMonitorService( ... screen_capture_servicescreen_capture, ... report_interval60 ... ) await monitor.start() 3.2 屏幕捕获服务 (screen_capture.py)classScreenCaptureService: 屏幕捕获服务 功能 - 全屏截图 - 区域截图 - 图片压缩 - Base64 编码 3.3 主动对话服务 (proactive_dialog.py)classProactiveDialogService(QObject): 主动对话服务 功能 - 定时检查触发条件 - 概率触发主动对话 - 收集上下文信息 信号 - dialog_triggered: 对话触发 4. Bridge 模块 (bridge.py)消息桥接层统一管理消息收发。classMessageBridge(QObject): 消息桥接层 职责 - 封装 API Client - 统一消息格式 - 管理连接状态 - 信号分发 信号 - message_received: 收到消息 - connection_state_changed: 连接状态变化 使用 bridge MessageBridge(config) await bridge.connect_server() await bridge.send_input(InputMessage(...)) 5. API Client 模块 (api_client.py)底层通信客户端。classDesktopAPIClient: API 客户端 功能 - HTTP 请求登录、文件上传 - WebSocket 长连接 - SSE 流式响应 - 自动重连 支持的消息类型 - text: 文本消息 - image: 图片消息 - voice: 语音消息 - desktop_state: 桌面状态 设计模式1. Handler 链模式 (Chain of Responsibility)消息处理的职责链。消息进入 ──► MessageHandler ──► MediaHandler ──► ProactiveHandler │ │ │ ▼ ▼ ▼ 处理文本 处理媒体 处理主动对话特点每个 Handler 专注单一职责可灵活组合和扩展通过 Qt 信号槽实现解耦3. 观察者模式 (Observer Pattern)基于 Qt 信号槽实现组件间通信。# 定义信号classMessageBridge(QObject):message_receivedSignal(OutputMessage)connection_state_changedSignal(ConnectionState)# 连接信号到槽bridge.message_received.connect(message_handler.handle_output_message)bridge.connection_state_changed.connect(app.on_connection_state_changed)4. 单例模式 (Singleton Pattern)用于全局唯一的管理器。# themes.pyclassThemeManager:_instanceNonedef__new__(cls):ifcls._instanceisNone:cls._instancesuper().__new__(cls)returncls._instance# 全局访问theme_managerThemeManager()5. MVC 变体模式分离关注点。┌─────────────────────────────────────────────────────────┐ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────┐ │ │ │ View │◄───│ Controller │───►│ Model │ │ │ │ (GUI) │ │ (Handlers/ │ │ (Config/ │ │ │ │ │ │ Controllers)│ │ Bridge) │ │ │ └──────────────┘ └──────────────┘ └──────────┘ │ │ │ │ │ │ │ └───────────────────┴──────────────────┘ │ │ Qt Signals │ └─────────────────────────────────────────────────────────┘数据流1. 用户消息发送流程用户输入 │ ▼ ┌──────────────┐ │ FloatingBall │ message_sent 信号 └──────┬───────┘ │ ▼ ┌──────────────┐ │ App │ _on_message_sent() └──────┬───────┘ │ ▼ ┌──────────────┐ │ Bridge │ send_input(InputMessage) └──────┬───────┘ │ ▼ ┌──────────────┐ │ API Client │ WebSocket 发送 └──────┬───────┘ │ ▼ AstrBot Server2. 服务端消息接收流程AstrBot Server │ ▼ ┌──────────────┐ │ API Client │ WebSocket 接收 └──────┬───────┘ │ ▼ ┌──────────────┐ │ Bridge │ message_received 信号 └──────┬───────┘ │ ▼ ┌──────────────┐ │MessageHandler│ handle_output_message() └──────┬───────┘ │ ├─── 文本消息 ──► 更新聊天界面 │ ├─── 图片消息 ──► MediaHandler 下载 ──► 显示图片 │ └─── 语音消息 ──► MediaHandler 下载 ──► 自动播放3. 主动对话触发流程┌────────────────────┐ │ProactiveDialogSvc │ 定时检查 └─────────┬──────────┘ │ ▼ 触发条件满足 │ ▼ Yes ┌────────────────────┐ │ ScreenshotHandler │ 捕获截图 └─────────┬──────────┘ │ ▼ ┌────────────────────┐ │ProactiveHandler │ 组装状态 └─────────┬──────────┘ │ ▼ ┌────────────────────┐ │ Bridge │ 发送 desktop_state └─────────┬──────────┘ │ ▼ AstrBot Server │ ▼ AI 分析并响应通信协议WebSocket 消息格式1. 客户端 → 服务端文本消息{type:text,content:你好,session_id:user_12345}图片消息{type:image,content:/path/to/image.png,session_id:user_12345,metadata:{text:这是什么}}桌面状态{type:desktop_state,data:{timestamp:2024-01-01T12:00:00,active_window_title:Visual Studio Code,active_window_process:Code.exe,active_window_pid:12345,screenshot_base64:iVBORw0KGgo...,screenshot_width:800,screenshot_height:600,running_apps:[{pid:12345,name:Code.exe},{pid:67890,name:chrome.exe}],window_changed:true,previous_window_title:Chrome}}2. 服务端 → 客户端文本响应{type:text,content:你好有什么可以帮助你的吗}图片响应{type:image,url:https://server/images/response.png}