用Python打造AI监督桌宠:开源项目my_ai_town实战指南

📅 2026/8/21 20:29:02
用Python打造AI监督桌宠:开源项目my_ai_town实战指南
你是不是也经常这样打开电脑准备写代码结果刷了半小时手机计划今天完成一个功能模块结果在调试环境上耗了一下午明明想学习新技术却总被各种琐事打断。自律这件事对开发者来说有时候比解决一个技术难题还难。今天要聊的就是一个用“魔法”打败“魔法”的解决方案——一个开源的桌面宠物桌宠。但它不是普通的卖萌小猫而是一条会“监督”你工作的“蓝色大肥鱼”。这个项目在 GitHub 上叫my_ai_town它把 AI 智能体Agent的概念从云端搬到了你的桌面上变成了一个具象化的、有互动的“工作伙伴”。这篇文章要解决的远不止“如何运行一个桌宠程序”。我们真正要探讨的是如何利用开源技术和 AI 能力为自己构建一个低成本、高趣味性的“外部监督系统”。对于独立开发者、远程工作者、自由职业者或者任何需要对抗拖延症的程序员来说这或许是一个将技术用于自我提升的绝佳实践。我们将从这条“蓝色大肥鱼”出发拆解一个开源桌宠项目的完整实现包括环境搭建、核心原理、代码解读并最终让你能定制属于自己的“数字监工”。你会发现它背后串联起了 Python 桌面应用开发、跨平台 GUI、简单的 AI 交互逻辑以及最重要的——如何将个人需求转化为一个有趣的 Side Project。1. 核心痛点我们为什么需要一个“桌宠监工”在深入代码之前我们先明确需求。传统的待办事项Todo List或番茄钟Pomodoro应用是“被动”的它们安静地躺在那里等你主动去看、去操作。而“监工桌宠”的设计理念是“主动”的它通过视觉存在感和随机互动创造一种轻微的“被注视”压力从而提升你的专注度。这解决了几个具体问题视觉提醒一个始终在桌面角落活动的角色比系统通知栏的一个图标更具提醒效力。情感化交互将枯燥的“工作时间到”提示转化为“小鱼盯着你催你干活”的趣味场景降低心理抵触。低侵入性监督它不会像某些强制锁屏软件一样粗暴地打断你而是通过存在感进行温和的督促更适合需要创造性思考的编程工作。技术人的浪漫自己动手用代码创造一个独一无二的“伙伴”这个过程本身就有极大的成就感和驱动力。my_ai_town项目提供的正是一个可高度自定义的基座。你得到的不仅是一条鱼更是一个能够理解简单指令、做出反馈的智能体框架。2. 项目概览与技术栈选择根据项目信息my_ai_town是一个开源项目其核心是创建一个具有简单 AI 行为的桌面宠物。从“桌宠开发 Python”等热词可以推断其技术栈很可能以 Python 为主。一个典型的桌面宠物项目会涉及以下技术层面GUI 框架用于创建无边框、可拖动、始终置顶的窗口。常见选择有PyQt5/PySide6、Tkinter、Kivy或者更轻量的pywebview HTML/JS。图形渲染显示宠物动画。可以是Pygame适合2D精灵动画或是直接使用 GUI 框架的QLabel加载 GIF/APNG 序列帧。行为逻辑控制宠物何时移动、做什么动作、如何响应事件如点击、拖拽。这部分是“大脑”。AI 集成可选进阶为宠物注入更智能的交互能力。例如集成一个轻量级本地 LLM大语言模型或调用云端 AI API让宠物能进行简单的对话或根据你的活动如键盘鼠标静止时长做出提醒。my_ai_town项目名中的 “AI Town” 暗示了其可能包含多智能体模拟或更复杂的 AI 行为树但作为桌宠我们可以先聚焦于其最核心的桌面交互部分。3. 环境准备与项目初始化在开始之前请确保你的开发环境已经就绪。我们将以最通用的 Python 环境为例进行说明。3.1 基础环境操作系统Windows 10/11, macOS, 或 Linux本文以 Windows 为例其他系统类似。Python 版本建议使用 Python 3.8 及以上版本。你可以通过命令行检查python --version # 或 python3 --version包管理工具pip应已随 Python 安装。3.2 获取项目代码访问项目 GitHub 仓库假设地址为https://github.com/mewamew/my_ai_town根据输入材料使用git克隆到本地git clone https://github.com/mewamew/my_ai_town.git cd my_ai_town如果未安装git也可以直接下载项目的 ZIP 包并解压。3.3 创建虚拟环境强烈推荐为避免依赖冲突为项目创建独立的 Python 虚拟环境。# 在项目根目录下 python -m venv venv激活虚拟环境Windows (CMD/PowerShell):.\venv\Scripts\activatemacOS/Linux:source venv/bin/activate激活后命令行提示符前通常会显示(venv)。3.4 安装依赖查看项目根目录下是否存在requirements.txt或pyproject.toml文件。这是安装依赖的关键。# 如果存在 requirements.txt pip install -r requirements.txt # 或者如果使用 poetry 等工具请参照项目 README注意如果项目没有提供明确的依赖文件你需要根据其代码中import的库来手动安装。一个典型的桌宠项目可能依赖pip install PyQt5 pygame pillow numpy具体依赖需以项目实际代码为准。4. 项目结构与核心原理拆解在运行项目前我们先剖析一下它的目录结构这能帮助我们理解其设计思路。一个组织良好的桌宠项目可能包含以下部分my_ai_town/ ├── assets/ # 资源文件夹 │ ├── sprites/ # 宠物精灵图PNG序列或GIF │ │ └── blue_fat_fish/ # “蓝色大肥鱼”的所有动画帧 │ ├── sounds/ # 音效文件 │ └── config/ # 配置文件 ├── src/ # 源代码 │ ├── pet_engine.py # 宠物行为引擎核心类 │ ├── ui_window.py # 主窗口和GUI逻辑 │ ├── ai_agent.py # AI交互逻辑如果存在 │ └── utils.py # 工具函数 ├── main.py # 程序入口点 ├── requirements.txt # Python依赖列表 └── README.md # 项目说明文档4.1 核心原理一个桌宠是如何工作的一个基本的桌宠程序其运行循环可以概括为以下几步创建透明置顶窗口使用 GUI 库创建一个没有标题栏、边框的窗口并设置为“始终在最前面”。加载与显示动画将宠物的图片资源通常是带透明通道的 PNG 序列加载到内存并在窗口中按一定帧率循环播放形成动画效果。实现交互逻辑拖动监听鼠标事件当鼠标在宠物图像上按下并移动时更新窗口位置。点击反馈监听点击事件触发特定的动画如跳跃、生气或播放音效。随机行为通过一个定时器让宠物在一定时间间隔后自动执行一些动作如走动、睡觉、切换表情。集成“监督”逻辑本项目重点这是区别于普通桌宠的关键。程序需要监控用户的活动状态例如通过监听全局键盘鼠标事件或检测特定应用窗口是否活跃并根据规则触发宠物的“监督”行为。例如当检测到用户超过30分钟未活动可能在看视频宠物就播放一个“催促工作”的动画和音效。5. 核心代码实现与解读让我们基于通用模式构建一个简化版的“监督桌宠”核心代码。即使my_ai_town的具体实现不同以下代码也能帮助你理解其骨架。5.1 主窗口与宠物显示使用 PyQt5我们选择PyQt5作为 GUI 框架因为它功能强大、跨平台且能轻松实现透明窗口和图形渲染。文件main.pyimport sys import random from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel from PyQt5.QtCore import Qt, QTimer, QPoint, pyqtSignal from PyQt5.QtGui import QMovie, QPixmap import ctypes import time class DesktopPet(QMainWindow): # 定义一个信号用于触发监督行为 urge_to_work pyqtSignal() def __init__(self): super().__init__() self.initUI() self.initPetBehavior() self.initMonitorTimer() def initUI(self): # 设置窗口属性无边框、透明、置顶 self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Tool) self.setAttribute(Qt.WA_TranslucentBackground) # 创建一个标签用于显示宠物动画GIF self.pet_label QLabel(self) self.movie QMovie(‘assets/sprites/blue_fat_fish/idle.gif‘) # 假设有 idle 动画 self.pet_label.setMovie(self.movie) self.movie.start() # 设置窗口大小匹配动画大小 self.resize(self.movie.frameRect().size()) self.setFixedSize(self.size()) # 固定大小 # 初始位置放在屏幕右下角 screen_geometry QApplication.desktop().screenGeometry() self.move(screen_geometry.width() - self.width() - 50, screen_geometry.height() - self.height() - 50) self.show() def initPetBehavior(self): 初始化宠物的随机行为定时器 self.behavior_timer QTimer(self) self.behavior_timer.timeout.connect(self.randomAction) self.behavior_timer.start(10000) # 每10秒触发一次随机行为 # 连接监督信号到具体的反馈动作 self.urge_to_work.connect(self.onUrgeToWork) def initMonitorTimer(self): 初始化用户活动监控定时器 self.monitor_timer QTimer(self) self.monitor_timer.timeout.connect(self.checkUserActivity) self.monitor_timer.start(60000) # 每60秒检查一次 self.last_activity_time time.time() self.idle_threshold 30 * 60 # 30分钟无活动视为闲置 def mousePressEvent(self, event): 鼠标按下事件用于拖动窗口 if event.button() Qt.LeftButton: self.drag_position event.globalPos() - self.frameGeometry().topLeft() event.accept() def mouseMoveEvent(self, event): 鼠标移动事件实现拖动 if event.buttons() Qt.LeftButton and hasattr(self, ‘drag_position‘): self.move(event.globalPos() - self.drag_position) event.accept() def randomAction(self): 宠物随机执行的动作如眨眼、走动、跳跃 actions [‘blink‘, ‘move_slightly‘, ‘change_expression‘] action random.choice(actions) # 这里可以切换不同的动画GIF if action ‘blink‘: self.movie.stop() self.movie QMovie(‘assets/sprites/blue_fat_fish/blink.gif‘) self.pet_label.setMovie(self.movie) self.movie.start() QTimer.singleShot(500, self.restoreIdle) # 0.5秒后恢复待机 def restoreIdle(self): 恢复待机动画 self.movie.stop() self.movie QMovie(‘assets/sprites/blue_fat_fish/idle.gif‘) self.pet_label.setMovie(self.movie) self.movie.start() def checkUserActivity(self): 检查用户是否在闲置简化版仅检查时间间隔 # 注意实际项目中获取系统空闲时间需要调用系统API以下为Windows示例 try: class LASTINPUTINFO(ctypes.Structure): _fields_ [(“cbSize“, ctypes.c_uint), (“dwTime“, ctypes.c_uint)] lastInputInfo LASTINPUTINFO() lastInputInfo.cbSize ctypes.sizeof(lastInputInfo) ctypes.windll.user32.GetLastInputInfo(ctypes.byref(lastInputInfo)) idle_time (ctypes.windll.kernel32.GetTickCount() - lastInputInfo.dwTime) // 1000 # 转换为秒 except Exception: # 跨平台或备用方案使用简单的时长判断不精确 current_time time.time() idle_time current_time - self.last_activity_time # 这里可以添加更精确的全局事件监听但复杂度较高 if idle_time self.idle_threshold: print(f“[监督触发] 用户已闲置 {idle_time//60} 分钟小鱼要发话了“) self.urge_to_work.emit() # 发出监督信号 # 重置活动时间避免连续触发 self.last_activity_time time.time() def onUrgeToWork(self): 当需要督促工作时触发的动作 # 切换为“生气”或“催促”的动画 self.movie.stop() self.movie QMovie(‘assets/sprites/blue_fat_fish/angry.gif‘) self.pet_label.setMovie(self.movie) self.movie.start() # 可以在这里播放一段音效 # QSound.play(‘assets/sounds/urge.wav‘) # 显示一个气泡对话框需要额外UI组件 print(“蓝色大肥鱼我允许你偷懒了吗快回去工作“) QTimer.singleShot(3000, self.restoreIdle) # 3秒后恢复 if __name__ ‘__main__‘: app QApplication(sys.argv) pet DesktopPet() sys.exit(app.exec_())代码解读DesktopPet类继承自QMainWindow创建了一个无边框透明窗口。initUI方法初始化界面加载宠物的待机动画GIF格式并将窗口置于屏幕右下角。initPetBehavior和initMonitorTimer分别设置了两个QTimerbehavior_timer: 控制宠物自主的随机动作增加生动性。monitor_timer: 核心的“监督”逻辑定期检查用户空闲时间。checkUserActivity方法尝试获取系统空闲时间Windows API示例。当空闲时间超过阈值30分钟就发射urge_to_work信号。onUrgeToWork是信号对应的槽函数会切换为生气动画并在控制台输出督促语句。这是“监督”功能的核心体现。鼠标事件处理实现了窗口的拖动功能。5.2 资源文件组织项目需要一个清晰的资源目录。你需要准备宠物的动画帧。方案A推荐使用 GIF 动画。准备多个 GIF 文件如idle.gif待机、blink.gif眨眼、angry.gif生气、walk.gif走动。GIF 支持透明且QMovie能直接播放。方案B使用 PNG 序列帧。需要自己编写代码控制帧切换灵活性更高但更复杂。一个简单的assets目录结构如下assets/ ├── sprites/ │ └── blue_fat_fish/ │ ├── idle.gif │ ├── blink.gif │ ├── angry.gif │ └── walk.gif └── sounds/ └── urge.wav5.3 进阶集成简单 AI 对话可选如果想让你的桌宠更“智能”可以集成一个轻量级的本地 LLM 或调用云端 API。这里以调用 OpenAI 格式的本地模型如通过ollama运行的模型为例进行概念性展示。文件ai_chat.py(简化示例)import requests import json class PetAI: def __init__(self, base_url“http://localhost:11434/api/generate“): self.base_url base_url self.personality “你是一只蓝色的大肥鱼是用户的桌面宠物兼工作监督员。你的语气要严厉又带点可爱当用户偷懒时你要用幽默但坚定的方式督促他回去工作。回答要简短不超过两句话。“ def generate_response(self, user_input): 生成AI回复 prompt f“{self.personality}\n用户说{user_input}\n小鱼回复” payload { “model“: “qwen:7b“, # 替换为你本地运行的模型名 “prompt“: prompt, “stream“: False } try: response requests.post(self.base_url, jsonpayload, timeout10) if response.status_code 200: result response.json() return result.get(‘response‘, ‘小鱼今天不想说话~‘).strip() else: return “网络好像不太对劲...“ except Exception as e: print(f“AI调用失败: {e}“) return “小鱼思考中但没想出来“ # 在主窗口中集成 # 可以添加一个右键菜单点击后弹出输入框将用户输入传给 PetAI并在桌面显示气泡回复。注意这需要你在本地部署兼容 OpenAI API 的模型服务如ollama。对于纯桌宠项目这不是必须的但能极大增强趣味性。6. 运行与效果验证确保环境与依赖在虚拟环境中确认已安装PyQt5(pip install PyQt5)。准备资源按照上述结构至少准备一个idle.gif和angry.gif放在对应的assets目录下。可以从开源游戏素材网站寻找或自己绘制。运行主程序python main.py预期效果屏幕右下角会出现一个无边框的动画窗口你的蓝色大肥鱼。你可以用鼠标拖动它到任何位置。每隔10秒左右宠物会随机做一个动作如眨眼。当你长时间示例为30分钟不操作电脑或根据代码逻辑宠物会切换成生气动画并在控制台打印督促语句。验证监督功能为了快速测试你可以将checkUserActivity方法中的idle_threshold暂时改为1010秒然后停止操作电脑观察10秒后宠物是否会触发督促行为。7. 常见问题与排查思路问题现象可能原因排查方式解决方案运行后无窗口显示1. 资源路径错误。2. PyQt5 未正确安装。3. 代码存在语法错误。1. 检查控制台是否有FileNotFoundError。2. 运行python -c “import PyQt5.QtWidgets; print(‘ok‘)“。3. 仔细查看运行时的错误信息。1. 使用绝对路径或确保相对路径正确。2. 重新安装pip install PyQt5。3. 根据错误信息修正代码。窗口有黑色背景不透明setAttribute(Qt.WA_TranslucentBackground)未生效或图片背景不透明。1. 检查窗口标志设置顺序。2. 确认使用的 GIF/PNG 图片背景是否为透明通道。1. 确保在setWindowFlags之后调用setAttribute。2. 使用图像处理软件确保素材背景透明。宠物动画不播放1. GIF 文件损坏或格式不支持。2.QMovie未启动。1. 尝试用其他软件打开 GIF。2. 检查是否调用了movie.start()。1. 转换或重新制作 GIF。2. 确保start()在setMovie()之后调用。无法拖动窗口鼠标事件未被正确捕获或处理。检查mousePressEvent和mouseMoveEvent方法是否被重写以及事件是否被accept()。确保事件处理函数中调用了event.accept()。监督功能永不触发1. 活动检测逻辑错误。2. 定时器未工作。3. 阈值设置过大。1. 在checkUserActivity中打印idle_time值。2. 检查monitor_timer是否正常启动。3. 临时将阈值调小测试。1. 修正获取系统空闲时间的代码或换用更可靠的库如pyautogui检测鼠标位置变化。2. 确保定时器信号正确连接。CPU 占用率过高动画刷新率过快或循环逻辑有误。1. 检查 GIF 帧率。2. 检查定时器间隔是否太短。1. 优化 GIF减少帧数和尺寸。2. 将行为定时器间隔调整到合理值如5-10秒。8. 最佳实践与进阶开发建议一个玩具项目和生产级 Side Project 之间差的就是这些细节。8.1 工程化建议配置文件将宠物的行为参数如各种定时器间隔、动画路径、空闲阈值抽离到config.ini或config.yaml文件中方便非开发者调整。日志系统使用 Python 的logging模块替代print记录宠物的行为、错误和用户交互便于调试。状态管理为宠物设计一个清晰的状态机如IDLE,MOVING,SLEEPING,URGING使行为逻辑更清晰。跨平台兼容获取系统空闲时间的 API 在 Windows、macOS、Linux 上各不相同。可以使用pyautogui来近似检测检查最近一段时间内鼠标像素位置是否变化或者使用平台特定的库如win32apifor Windows,Quartzfor macOS。8.2 功能增强方向更精准的“工作”检测不仅仅是全局空闲可以结合psutil库检测特定进程如chrome.exe,steam.exe是否在前台运行过久实现更精准的“摸鱼检测”。丰富的交互方式除了点击可以支持双击喂食、右键菜单设置、语音输入集成speech_recognition等。数据统计与可视化记录每日“被督促”次数、专注时长并生成简单的统计图表形成正向反馈。插件化系统设计插件接口允许通过编写 Python 脚本为宠物添加新技能、新动画或新的监督规则。8.3 性能与体验优化资源懒加载动画图片较多时不要一次性全部加载进内存使用时再加载。动画平滑移动宠物时使用缓动函数而不是直接设置坐标让移动更自然。多显示器支持计算窗口位置时考虑多显示器的情况。系统托盘图标添加托盘图标实现最小化到托盘、退出、暂停监督等功能。9. 总结从“玩具”到“工具”的思考通过这个“蓝色大肥鱼”桌宠项目我们完成了一次从创意到代码的完整实践。它起点是一个有趣的 Side Project但其内核涉及了 GUI 编程、事件驱动、多线程定时器、系统交互甚至可选的 AI 集成是一个非常好的全栈练手项目。更重要的是它代表了一种思路用技术解决自身的非技术痛点。作为开发者我们擅长构建工具去解决别人的问题却常常忽视用同样的能力来优化自己的工作流和生活习惯。这个桌宠就是一个将外部监督内化为趣味化数字存在的尝试。你可以完全按照本文的代码骨架从零开始打造你的专属桌宠。也可以深入研究my_ai_town这类开源项目学习它们更复杂的 AI 行为树和多智能体模拟是如何实现的。无论是为了对抗拖延症还是单纯享受创造的乐趣动手实现它你会收获的远不止一个桌面宠物。下一步你可以克隆并运行my_ai_town项目看看原作者实现了哪些更酷的功能。替换资源将蓝色大肥鱼换成你喜欢的任何角色形象。修改规则将“30分钟闲置”的监督规则改为“检测到代码编辑器失去焦点超过10分钟”等更贴合程序员工作的规则。分享你的版本将你的修改发布到 GitHub或写成一篇属于自己的 CSDN 博客。技术最有魅力的地方在于它能将想象变为现实。现在就让这条或你创造的数字伙伴开始它的监督工作吧。