diff --git a/src/backend/README.md b/src/backend/README.md index 09cb774..7a3e5d6 100644 --- a/src/backend/README.md +++ b/src/backend/README.md @@ -1,378 +1,703 @@ -# MuseGuard 后端框架 +# MuseGuard 后端服务 -基于对抗性扰动的多风格图像生成防护系统 - 后端API服务 +MuseGuard 是一个基于对抗性扰动的多风格图像生成防护系统,旨在保护艺术家的作品不被 AI 模型恶意学习和模仿。本项目为 MuseGuard 的后端服务,基于 Flask 框架开发,提供 RESTful API 接口,支持异步任务处理、用户管理、图像处理等功能。 +## 目录 -## Linux 环境配置(MySQL、Redis、Python等) +- [项目简介](#项目简介) +- [技术架构](#技术架构) +- [项目结构](#项目结构) +- [环境配置](#环境配置) +- [部署流程](#部署流程) +- [数据库设计](#数据库设计) +- [API 接口](#api-接口) +- [前后端连接](#前后端连接) -### 1. 安装系统依赖 +## 项目简介 + +MuseGuard 后端服务主要负责处理前端请求、管理用户数据、调度图像处理任务以及与底层算法模块交互。核心功能包括: + +- **用户认证与权限管理**:基于 JWT 的身份验证,支持普通用户、VIP 用户和管理员三种角色。 +- **图像加噪防护**:集成多种对抗性扰动算法(ASPL, SimAC, CAAT, PID, Glaze 等),支持针对不同场景(人脸、风格迁移等)的防护。 +- **异步任务调度**:使用 Redis + RQ 实现耗时算法任务的异步处理,支持任务状态追踪和日志查看。 +- **效果评估**:提供微调训练、图像质量评估(FID, LPIPS, SSIM, PSNR)和热力图分析功能。 +- **资源管理**:管理用户上传的图片、生成的防护图片以及训练模型等资源。 + +## 🏗 技术架构 + +- **Web 框架**: Flask 3.0 +- **数据库**: MySQL 8.0 (数据存储) + Redis 6.0 (缓存与消息队列) +- **ORM**: SQLAlchemy +- **任务队列**: RQ (Redis Queue) +- **环境管理**: Conda +- **部署环境**: Linux (AutoDL) + +## 项目结构 -```bash -sudo apt update -sudo apt install -y build-essential python3 python3-venv python3-pip git ``` +src/backend/ +├── app/ +│ ├── algorithms/ # 算法相关代码 +│ │ ├── evaluate/ # 评估算法模块 +│ │ ├── finetune/ # 微调算法模块 +│ │ ├── perturbation/ # 加噪算法模块 +│ │ └── processor/ # 图像预处理模块 +│ ├── controllers/ # 控制器层 (API 接口实现) +│ │ ├── admin_controller.py # 管理员相关接口 +│ │ ├── auth_controller.py # 用户认证接口 +│ │ ├── image_controller.py # 图像管理接口 +│ │ ├── task_controller.py # 任务管理接口 +│ │ └── user_controller.py # 用户信息接口 +│ ├── database/ # 数据库模型定义 +│ │ └── __init__.py # 数据库模型初始化 +│ ├── repositories/ # 数据访问层 (DAO) +│ │ ├── base_repository.py # 基础仓储类 +│ │ ├── config_repository.py # 配置信息仓储 +│ │ ├── image_repository.py # 图像数据仓储 +│ │ ├── task_repository.py # 任务数据仓储 +│ │ └── user_repository.py # 用户数据仓储 +│ ├── scripts/ # 算法执行脚本 (Shell) +│ │ ├── attack_*.sh # 各种攻击算法执行脚本 +│ │ ├── eva_*.sh # 评估任务执行脚本 +│ │ └── finetune_*.sh # 微调任务执行脚本 +│ ├── services/ # 业务逻辑层 +│ │ ├── image_service.py # 图像处理业务逻辑 +│ │ ├── task_service.py # 任务管理业务逻辑 +│ │ ├── user_service.py # 用户管理业务逻辑 +│ │ └── ... +│ ├── utils/ # 工具函数 +│ │ ├── file_utils.py # 文件操作工具 +│ │ └── jwt_utils.py # JWT 认证工具 +│ └── workers/ # RQ Worker 任务处理逻辑 +│ ├── evaluate_worker.py # 评估任务处理器 +│ ├── finetune_worker.py # 微调任务处理器 +│ ├── heatmap_worker.py # 热力图任务处理器 +│ └── perturbation_worker.py # 加噪任务处理器 +├── config/ # 配置文件 +│ ├── algorithm_config.py # 算法参数配置 +│ ├── settings.py # 应用全局配置 +│ └── settings.env # 环境变量配置 (需自行创建) +├── static/ # 静态资源 (图片存储) +├── app.py # 应用工厂函数入口 +├── init_db.py # 数据库初始化脚本 +├── run.py # 开发环境启动脚本 +├── worker.py # RQ Worker 启动脚本 +├── start.sh # 一键启动脚本 +├── stop.sh # 一键停止脚本 +├── status.sh # 状态检查脚本 +└── requirements.txt # Python 依赖列表 +``` + +## 环境配置 -### 2. 安装 MySQL +本项目使用 Conda 进行环境管理。 + +### 1. 创建 Conda 环境 -老版使用 ```bash -# 启动 Redis -sudo service mysqld start -# 停止 Redis -sudo service mysqld stop -# 重启 Redis -sudo service mysqld restart -# 查看 Redis 状态 -sudo service mysqld status +# 创建名为 flask 的环境,指定 python 版本 +conda create -n flask python=3.10 + +# 激活环境 +conda activate flask ``` +### 2. 安装依赖 ```bash -sudo apt install -y mysql-server -sudo systemctl enable mysql -sudo systemctl start mysql - -# 安全初始化(可选,建议设置root密码) -sudo mysql_secure_installation +# 安装项目依赖 +pip install -r requirements.txt -# 登录MySQL创建数据库和用户 -mysql -u root -p +# 安装 PyTorch (根据 CUDA 版本选择) +# 示例: CUDA 11.8 +pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 ``` -在MySQL命令行中执行: -```sql -CREATE DATABASE museguard DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -# CREATE USER 'museguard'@'localhost' IDENTIFIED BY 'yourpassword'; -# GRANT ALL PRIVILEGES ON museguard.* TO 'museguard'@'localhost'; -# FLUSH PRIVILEGES; -EXIT; + +### 3. 配置环境变量 + +在 `src/backend/config/` 目录下创建 `settings.env` 文件: + +```ini +# 数据库配置 +DB_HOST=localhost +DB_PORT=3306 +DB_USER=root +DB_PASSWORD=your_password +DB_NAME=museguard_schema + +# Redis 配置 +REDIS_URL=redis://localhost:6379/0 + +# JWT 配置 +JWT_SECRET_KEY=your-secret-key +SECRET_KEY=your-app-secret-key + +# 邮件配置 (可选) +MAIL_SERVER=smtp.example.com +MAIL_PORT=465 +MAIL_USERNAME=your_email@example.com +MAIL_PASSWORD=your_email_password ``` -### 3. 安装 Redis +## 部署流程 + +### 1. 基础环境准备 + +确保服务器已安装以下基础软件: + +- **Miniconda/Anaconda**: 用于 Python 环境管理 +- **MySQL 8.0+**: 数据库服务 +- **Redis 6.0+**: 缓存与消息队列服务 +- **CUDA Toolkit**: (可选) 如果需要 GPU 加速 + +### 2. 启动基础服务 + +确保 MySQL 和 Redis 服务已启动。 -老版使用service命令 ```bash +# 启动 MySQL (根据系统不同命令可能不同) +service mysql start +# 或者 +systemctl start mysql + # 启动 Redis -sudo service redis-server start -# 停止 Redis -sudo service redis-server stop -# 重启 Redis -sudo service redis-server restart -# 查看 Redis 状态 -sudo service redis-server status +redis-server --daemonize yes ``` -```bash -sudo apt install -y redis-server -sudo systemctl enable redis-server -sudo systemctl start redis-server +### 3. 初始化数据库 -# 测试 -redis-cli ping -# 返回PONG表示正常 -``` +#### 3.1 创建数据库和用户 + +首次部署需要手动创建 MySQL 数据库和用户。 -### 4. Python 虚拟环境与依赖 +**步骤 1:登录 MySQL** -在Linux换成conda管理 ```bash -cd /path/to/your/project/src/backend -python3 -m venv venv -source venv/bin/activate -python -m pip install --upgrade pip -pip install -r requirements.txt +# 使用 root 用户登录 MySQL +mysql -u root -p +# 输入 root 密码 ``` -### 5. 配置数据库连接 +**步骤 2:创建数据库** -编辑 `config/settings.py` 或 `setting.env` 文件,设置如下内容: -```python -DROP DATABASE IF EXISTS muse_guard; -CREATE DATABASE muse_guard DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -EXIT; +```sql +-- 创建数据库(使用 UTF-8 字符集) +CREATE DATABASE museguard_schema CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://museguard:yourpassword@localhost:3306/museguard?charset=utf8mb4' -REDIS_URL = 'redis://localhost:6379/0' +-- 查看数据库是否创建成功 +SHOW DATABASES; ``` -### 6. 初始化数据库 +**步骤 3:创建数据库用户并授权** + +```sql +-- 创建用户(请修改密码为安全密码) +CREATE USER 'museguard_user'@'localhost' IDENTIFIED BY 'your_secure_password'; + +-- 授予该用户对数据库的所有权限 +GRANT ALL PRIVILEGES ON museguard_schema.* TO 'museguard_user'@'localhost'; + +-- 刷新权限 +FLUSH PRIVILEGES; + +-- 查看用户权限 +SHOW GRANTS FOR 'museguard_user'@'localhost'; + +-- 退出 MySQL +EXIT; +``` + +**步骤 4:测试数据库连接** ```bash -python init_db.py +# 使用新创建的用户登录,验证权限 +mysql -u museguard_user -p museguard_schema +# 输入刚才设置的密码 + +# 登录成功后,查看当前数据库 +SELECT DATABASE(); +# 应该显示: museguard_schema + +# 退出 +EXIT; ``` -### 7. 启动服务 +#### 3.2 配置数据库连接 + +在 `src/backend/config/` 目录下创建或编辑 `settings.env` 文件,填入数据库连接信息: + +```ini +# ==================== 数据库配置 ==================== +# MySQL 连接配置(必填) +DB_HOST=localhost # 数据库主机地址 +DB_PORT=3306 # 数据库端口 +DB_USER=museguard_user # 步骤 3 创建的数据库用户名 +DB_PASSWORD=your_secure_password # 步骤 3 设置的密码 +DB_NAME=museguard_schema # 步骤 2 创建的数据库名 + +# ==================== Redis 配置 ==================== +# Redis 连接配置(必填) +REDIS_URL=redis://localhost:6379/0 + +# ==================== JWT 配置 ==================== +# JWT 密钥(请修改为随机字符串) +JWT_SECRET_KEY=your-random-jwt-secret-key-change-this-in-production +SECRET_KEY=your-random-flask-secret-key-change-this-in-production + +# ==================== 邮件配置(可选)==================== +# 用于发送验证码等功能,如不需要可暂时不配置 +MAIL_SERVER=smtp.example.com +MAIL_PORT=465 +MAIL_USE_SSL=True +MAIL_USERNAME=your_email@example.com +MAIL_PASSWORD=your_email_password +MAIL_DEFAULT_SENDER=your_email@example.com + +# ==================== 算法配置(可选)==================== +# 是否启用真实算法(默认 false) +USE_REAL_ALGORITHMS=true + +# RQ 队列配置 +RQ_QUEUE_NAME=perturbation_tasks +TASK_TIMEOUT=3600 +``` + +**注意事项:** +- `DB_USER` 和 `DB_PASSWORD` 必须与步骤 3 中创建的用户信息一致 +- `DB_NAME` 必须与步骤 2 中创建的数据库名一致 +- `JWT_SECRET_KEY` 和 `SECRET_KEY` 请务必修改为随机字符串,可使用以下命令生成: + ```bash + python -c "import secrets; print(secrets.token_hex(32))" + ``` + +#### 3.3 运行数据库初始化脚本 + +配置文件填写完成后,运行初始化脚本创建数据表和基础数据。 ```bash -# 启动Flask后端 -python run.py +# 1. 确保已激活 flask 环境 +conda activate flask -# 启动RQ Worker(另开终端) -source venv/bin/activate -cd /path/to/your/project/src/backend -rq worker museguard +# 2. 进入后端根目录 +cd src/backend + +# 3. 运行初始化脚本 +python init_db.py ``` ---- +**初始化脚本会自动完成以下操作:** -## 项目结构 +1. **创建所有数据表**(如 users, tasks, images, perturbation, finetune 等) +2. **初始化角色数据**(admin, vip, normal 三种角色) +3. **初始化任务状态数据**(waiting, processing, completed, failed, cancelled) +4. **初始化图片类型数据**(original, perturbed, heatmap 等) +5. **初始化加噪算法配置**(ASPL, SimAC, CAAT, PID, Glaze, Quick 等 10 种算法) +6. **初始化微调方式配置**(DreamBooth, LoRA, Textual Inversion) +7. **初始化数据集类型**(人脸、艺术品) +8. **初始化任务类型**(perturbation, finetune, heatmap, evaluate) +9. **创建测试用户**(可选,包含 admin_test, vip_test, normal_test 三个测试账号) + +**初始化成功提示:** ``` -backend/ -├── app/ # 主应用目录 -│ ├── algorithms/ # 算法实现 -│ │ ├── perturbation_engine.py # 对抗性扰动引擎 -│ │ └── evaluation_engine.py # 评估引擎 -│ ├── controllers/ # 控制器(路由处理) -│ │ ├── auth_controller.py # 认证控制器 -│ │ ├── user_controller.py # 用户配置控制器 -│ │ ├── task_controller.py # 任务控制器 -| | ├── demo_controller.py # 首页示例控制器 -│ │ ├── image_controller.py # 图像控制器 -│ │ └── admin_controller.py # 管理员控制器 -│ ├── models/ # 数据模型 -│ │ └── __init__.py # SQLAlchemy模型定义 -│ ├── services/ # 业务逻辑服务 -│ │ ├── auth_service.py # 认证服务 -│ │ ├── task_service.py # 任务处理服务 -│ │ └── image_service.py # 图像处理服务 -│ └── utils/ # 工具类 -│ └── file_utils.py # 文件处理工具 -├── config/ # 配置文件 -│ └── settings.py # 应用配置 -├── uploads/ # 文件上传目录 -├── static/ # 静态文件 -│ ├── originals/ # 重命名后的原始图片 -│ ├── perturbed/ # 加噪后的图片 -│ ├── model_outputs/ # 模型生成的图片 -│ │ ├── clean/ # 原图的模型生成结果 -│ │ └── perturbed/ # 加噪图的模型生成结果 -│ ├── heatmaps/ # 热力图 -│ └── demo/ # 演示图片 -│ ├── original/ # 演示原始图片 -│ ├── perturbed/ # 演示加噪图片 -│ └── comparisons/ # 演示对比图 -├── app.py # Flask应用工厂 -├── run.py # 启动脚本 -├── init_db.py # 数据库初始化脚本 -└── requirements.txt # Python依赖 +数据库初始化完成! ``` -## 功能特性 - -### 用户功能 -- ✅ 用户注册(邮箱验证,同一邮箱只能注册一次) -- ✅ 用户登录/登出 -- ✅ 密码修改 -- ✅ 任务创建和管理 -- ✅ 图片上传(单张/压缩包批量) -- ✅ 加噪处理(4种算法:SimAC、CAAT、PID、ASPL) -- ✅ 扰动强度自定义 -- ✅ 防净化版本选择 -- ✅ 智能配置记忆:自动保存用户上次选择的配置 -- ✅ 处理结果下载 -- ✅ 图片质量对比查看(FID、LPIPS、SSIM、PSNR、热力图) -- ✅ 模型生成对比分析 -- ✅ 预设演示图片浏览 - -### 管理员功能 -- ✅ 用户管理(增删改查) -- ✅ 系统统计信息查看 - -### 算法实现 -- ✅ ASPL算法虚拟实现(原始版本 + 防净化版本) -- ✅ SimAC算法虚拟实现(原始版本 + 防净化版本) -- ✅ CAAT算法虚拟实现(原始版本 + 防净化版本) -- ✅ PID算法虚拟实现(原始版本 + 防净化版本) -- ✅ 图像质量评估指标计算 -- ✅ 模型生成效果对比 -- ✅ 热力图生成 - -## 安装和运行 - -### 1. 环境准备 - -#### 使用虚拟环境(推荐) - -**为什么需要虚拟环境?** -- ✅ **避免依赖冲突**:不同项目使用不同版本的包 -- ✅ **环境隔离**:不污染系统Python环境 -- ✅ **版本一致性**:确保团队环境统一 -- ✅ **易于管理**:可以随时删除重建 +**测试用户账号:** + +| 用户名 | 密码 | 角色 | 邮箱 | +|--------|------|------|------| +| admin_test | Admin123__ | 管理员 | admin@test.com | +| vip_test | Vip123__ | VIP用户 | vip@test.com | +| normal_test | Normal123__ | 普通用户 | normal@test.com | + +**验证初始化结果:** ```bash -# 创建虚拟环境 -python -m venv venv +# 登录 MySQL 查看表结构 +mysql -u museguard_user -p museguard_schema -# 激活虚拟环境 -# Windows: -venv\\Scripts\\activate -# Linux/Mac: -source venv/bin/activate +# 查看所有表 +SHOW TABLES; -# 更新pip(推荐) -python -m pip install --upgrade pip +# 查看某个表的数据(例如查看角色表) +SELECT * FROM role; -# 安装依赖 -pip install -r requirements.txt +# 查看用户表 +SELECT user_id, username, email, role_id, is_active FROM users; + +# 查看加噪算法配置 +SELECT perturbation_configs_id, perturbation_code, perturbation_name FROM perturbation_configs; + +# 退出 +EXIT; ``` -### 2. 数据库配置 +**常见问题排查:** -确保已安装MySQL数据库并创建数据库。 +1. **连接失败**:检查 `settings.env` 中的数据库配置是否正确 +2. **权限错误**:确认数据库用户是否有足够的权限(重新执行步骤 3 的授权命令) +3. **表已存在**:如需重新初始化,先手动删除所有表或删除数据库后重新创建 + ```sql + DROP DATABASE museguard_schema; + CREATE DATABASE museguard_schema CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + ``` -修改 `config/.env` 中的数据库连接配置: +### 4. 启动服务 -### 3. 初始化数据库 +使用提供的脚本一键启动 Web 服务和 Worker 服务。 ```bash -# 运行数据库初始化脚本 -python init_db.py +# 1. 赋予脚本执行权限 +chmod +x start.sh stop.sh status.sh + +# 2. 启动服务 +./start.sh ``` -### 4. 启动应用 +脚本会自动: + +1. 激活 `flask` conda 环境 +2. 检查 MySQL 和 Redis 状态 +3. 启动 Flask Web 服务 (默认端口 6006) +4. 启动 RQ Worker 服务 (用于处理后台任务) + +### 5. 验证服务 ```bash -# 开发模式启动 -python run.py +# 查看服务状态 +./status.sh -# 或者使用Flask命令 -flask run +# 或者查看日志 +tail -f nohup.out ``` -应用将在 `http://localhost:5000` 启动 +### 6. 停止服务 -### 5. 系统测试 +```bash +./stop.sh +``` -访问 `http://localhost:5000/static/test.html` 进入功能测试页面: +## 数据库设计 -## API接口文档 +主要数据表包括: -### 认证接口 (`/api/auth`) +- **users**: 用户信息表 +- **role**: 角色表 (admin, vip, normal) +- **tasks**: 任务主表,记录任务状态、类型等 +- **perturbation**: 加噪任务详情表 +- **finetune**: 微调任务详情表 +- **evaluate**: 评估任务详情表 +- **heatmap**: 热力图任务详情表 +- **images**: 图片资源表 +- **configs**: 各类配置表 (perturbation_configs, finetune_configs 等) -- `POST /register` - 用户注册 -- `POST /login` - 用户登录 -- `POST /change-password` - 修改密码 -- `GET /profile` - 获取用户信息 -- `POST /logout` - 用户登出 +## API 接口 -### 任务管理 (`/api/task`) +> 详细的 API 接口文档请参考:[`doc/project/02-设计文档/backend-api.md`](../../doc/project/02-设计文档/backend-api.md) -- `POST /create` - 创建任务(使用默认配置) -- `POST /upload/` - 上传图片到指定任务 -- `GET //config` - 获取任务配置(显示用户上次选择) -- `PUT //config` - 更新任务配置(自动保存为用户偏好) -- `GET /load-config` - 加载用户上次配置 -- `POST /save-config` - 保存用户配置偏好 -- `POST /start/` - 开始处理任务 -- `GET /list` - 获取任务列表 -- `GET /` - 获取任务详情 -- `GET //status` - 获取处理状态 +API 基础路径: `/api` -### 图片管理 (`/api/image`) +### 认证模块 (`/api/auth`) -- `GET /file/` - 查看图片 -- `GET /download/` - 下载图片 -- `GET /batch//download` - 批量下载 -- `GET //evaluations` - 获取评估结果 -- `POST /compare` - 对比图片 -- `GET /heatmap/` - 获取热力图 -- `DELETE /delete/` - 删除图片 +- `POST /auth/register` - 用户注册(需邮箱验证码) +- `POST /auth/login` - 用户登录 +- `POST /auth/code` - 发送邮箱验证码 +- `POST /auth/change-password` - 修改密码(需登录) +- `POST /auth/change-email` - 修改邮箱(需验证码) +- `POST /auth/change-username` - 修改用户名(需登录) +- `POST /auth/forgot-password` - 忘记密码(需验证码) +- `GET /auth/profile` - 获取当前用户信息 +- `POST /auth/logout` - 退出登录 -### 用户设置 (`/api/user`) +### 用户模块 (`/api/user`) -- `GET /config` - 获取用户配置(已弃用,配置集成到任务流程中) -- `PUT /config` - 更新用户配置(已弃用,通过任务配置自动保存) -- `GET /algorithms` - 获取可用算法(动态从数据库加载) -- `GET /stats` - 获取用户统计 +- `GET /user/config` - 获取用户配置 +- `PUT /user/config` - 更新用户配置 -### 管理员功能 (`/api/admin`) +### 任务模块 (`/api/task`) -- `GET /users` - 用户列表 -- `GET /users/` - 用户详情 -- `POST /users` - 创建用户 -- `PUT /users/` - 更新用户 -- `DELETE /users/` - 删除用户 -- `GET /stats` - 系统统计 +#### 通用任务接口 -### 演示功能 (`/api/demo`) +- `GET /task` - 获取任务列表(支持筛选) +- `GET /task/` - 获取任务详情 +- `GET /task//status` - 查询任务状态 +- `POST /task//cancel` - 取消任务 +- `GET /task//logs` - 获取任务日志 +- `GET /task/quota` - 查看任务配额 -- `GET /images` - 获取演示图片列表 -- `GET /image/original/` - 获取演示原始图片 -- `GET /image/perturbed/` - 获取演示加噪图片 -- `GET /image/comparison/` - 获取演示对比图片 -- `GET /algorithms` - 获取算法演示信息 -- `GET /stats` - 获取演示统计数据 +#### 加噪任务接口 -## 默认账户 +- `GET /task/perturbation/configs` - 获取可用的加噪算法列表 +- `GET /task/perturbation/style-presets` - 获取风格迁移预设风格 +- `POST /task/perturbation` - 创建加噪任务(支持上传图片) +- `PATCH /task/perturbation/` - 更新加噪任务参数 +- `POST /task/perturbation//start` - 启动加噪任务 +- `GET /task/perturbation` - 获取所有加噪任务 +- `GET /task/perturbation/` - 获取加噪任务详情 -系统初始化后会创建3个管理员账户: +#### 微调任务接口 -- 用户名:`admin1`, `admin2`, `admin3` -- 默认密码:`admin123` -- 邮箱:`admin1@museguard.com` 等 +- `GET /task/finetune/configs` - 获取微调方式列表 +- `POST /task/finetune/from-perturbation` - 基于加噪结果创建微调任务 +- `POST /task/finetune/from-upload` - 基于上传图片创建微调任务(VIP) +- `POST /task/finetune//start` - 启动微调任务 +- `GET /task/finetune` - 获取所有微调任务 +- `GET /task/finetune/` - 获取微调任务详情 +- `GET /task/finetune//coords` - 获取3D可视化坐标数据 -## 技术栈 +#### 热力图任务接口 -- **Web框架**: Flask 2.3.3 -- **数据库ORM**: SQLAlchemy 3.0.5 -- **数据库**: MySQL(通过PyMySQL连接) -- **认证**: JWT (Flask-JWT-Extended) -- **跨域**: Flask-CORS -- **图像处理**: Pillow + NumPy -- **数学计算**: NumPy +- `POST /task/heatmap` - 创建热力图任务 +- `POST /task/heatmap//start` - 启动热力图任务 +- `GET /task/heatmap` - 获取所有热力图任务 +- `GET /task/heatmap/` - 获取热力图任务详情 -## 开发说明 +#### 评估任务接口 -### 虚拟实现说明 +- `POST /task/evaluate` - 创建评估任务 +- `POST /task/evaluate//start` - 启动评估任务 +- `GET /task/evaluate` - 获取所有评估任务 +- `GET /task/evaluate/` - 获取评估任务详情 -当前所有算法都是**虚拟实现**,用于框架搭建和测试: +### 图像模块 (`/api/image`) -1. **对抗性扰动算法**: 使用随机噪声模拟真实算法效果 -2. **评估指标**: 基于像素差异的简化计算 -3. **模型生成**: 通过图像变换模拟DreamBooth/LoRA效果 +#### 图像上传与获取 -### 扩展指南 +- `POST /image/original` - 上传原始图片 +- `GET /image/file/` - 获取单张图片文件 +- `GET /image/task/` - 获取任务的所有图片(base64) -要集成真实算法: +#### 图像预览接口 -1. 替换 `app/algorithms/perturbation_engine.py` 中的虚拟实现 -2. 替换 `app/algorithms/evaluation_engine.py` 中的评估计算 -3. 根据需要调整配置参数 +- `GET /image/preview/flow/` - 获取工作流所有图片预览 +- `GET /image/preview/task/` - 获取单个任务图片预览 +- `GET /image/preview/compare/` - 获取对比预览图片 -### 目录权限 +#### 按任务类型获取图片 -确保以下目录有写入权限: +- `GET /image/perturbation/` - 获取加噪结果图片(base64) +- `GET /image/heatmap/` - 获取热力图(base64) +- `GET /image/finetune/` - 获取微调生成图片(base64) +- `GET /image/evaluate/` - 获取评估报告图片(base64) -- `uploads/` - 用户上传文件 -- `static/originals/` - 重命名后的原始图片 -- `static/perturbed/` - 加噪后的图片 -- `static/model_outputs/` - 模型生成的图片 -- `static/heatmaps/` - 热力图文件 -- `static/demo/` - 演示图片(需要手动添加演示文件) +#### 图像下载接口 -## 许可证 +- `GET /image/perturbation//download` - 下载加噪结果压缩包 +- `GET /image/heatmap//download` - 下载热力图压缩包 +- `GET /image/finetune//download` - 下载微调结果压缩包 +- `GET /image/evaluate//download` - 下载评估报告压缩包 -本项目仅用于学习和研究目的。 +#### 图像管理 +- `DELETE /image/` - 删除单张图片 -https://docs.pingcode.com/baike/2645380 +### 管理员模块 (`/api/admin`) +- `GET /admin/users` - 获取用户列表(分页) +- `GET /admin/users/` - 获取用户详情 +- `POST /admin/users` - 创建用户 +- `PUT /admin/users/` - 更新用户信息 +- `DELETE /admin/users/` - 删除用户 +- `GET /admin/stats` - 获取系统统计信息 +### 支持的加噪算法 -功能流程正确(本地) -- 测试网页 -- 配置正确加载 -- 微调算法执行时机 -云端正常调用算法 -算法正常执行 -云端部署,本地可直接访问 -api规范 -前端对接 +| ID | 算法代码 | 算法名称 | 适用场景 | +|----|---------|---------|---------| +| 1 | aspl | ASPL算法 | 通用防护 | +| 2 | simac | SimAC算法 | 人脸防护 | +| 3 | caat | CAAT算法 | 通用防护 | +| 4 | caat_pro | CAAT Pro算法 | 通用防护(增强版) | +| 5 | pid | PID算法 | 通用防护 | +| 6 | glaze | Glaze算法 | 艺术风格防护 | +| 7 | anti_customize | 防定制生成 | 人脸防护(专用) | +| 8 | anti_face_edit | 防人脸编辑 | 人脸防护(专用) | +| 9 | style_protection | 风格迁移防护 | 艺术品防护(需指定风格) | +| 10 | quick | 快速防护算法 | 快速测试(基于PID) | +### 认证说明 -conda activate flask -pip install accelerate -或 -conda install -c conda-forge accelerate +- 除 `/auth/register`、`/auth/login`、`/auth/code` 外,所有接口均需要 JWT 认证 +- 请在请求头中添加:`Authorization: Bearer ` +- 管理员接口需要管理员角色权限 + +## 前后端连接 (AutoDL 自定义服务) + +本项目部署在 AutoDL 算力云平台上,通过 **SSH 端口转发**功能暴露后端接口给前端访问。 + +### 为什么使用 SSH 端口转发? + +使用 SSH 端口转发(SSH Tunneling)相比直接公网暴露服务具有以下优势: + +#### 安全优势 + +1. **加密传输**:所有数据通过 SSH 加密隧道传输,防止中间人攻击和数据窃听 +2. **无需公网 IP**:不需要 AutoDL 实例具有公网 IP 地址,降低被攻击风险 +3. **防火墙保护**:后端服务仅监听 `127.0.0.1`(本地回环),外部无法直接访问 +4. **访问控制**:只有持有 SSH 密钥/密码的用户才能建立端口转发,天然的身份验证 + +#### 成本优势 + +1. **节省流量费用**:AutoDL 公网流量通常需要额外付费,SSH 端口转发可节省成本 +2. **无需额外配置**:不需要购买域名、配置 SSL 证书等额外服务 +3. **灵活计费**:开发调试时可随时断开连接,按需使用 + +#### 开发便利性 + +1. **本地开发体验**:前端可以像访问本地服务一样访问远程后端(`localhost:6006`) +2. **无需修改代码**:前后端代码无需区分开发/生产环境的 API 地址 +3. **热重载友好**:配合前端热重载,开发体验接近本地全栈开发 +4. **多环境隔离**:可同时转发多个 AutoDL 实例到不同本地端口,轻松切换环境 + +#### 运维优势 + +1. **简单稳定**:SSH 是成熟的协议,稳定性高,断线自动重连(使用 `autossh`) +2. **易于调试**:可直接在本地浏览器查看网络请求,使用开发者工具调试 +3. **日志集中**:所有请求日志在 AutoDL 服务器端,便于排查问题 +4. **版本管理**:本地可使用 Git 管理代码,推送到服务器后立即生效 + +### 1. AutoDL 端口配置 + +后端服务默认监听 `6006` 端口(Flask Web 服务)。 + +### 2. 设置 SSH 端口转发 + +#### 查看 AutoDL 实例的 SSH 连接信息 + +1. 登录 AutoDL 控制台 +2. 进入你的容器实例页面 +3. 找到 **"SSH 连接"** 或 **"自定义服务"** 部分 +4. 复制提供的 SSH 端口转发命令,格式类似: + ```bash + ssh -CNg -L 6006:127.0.0.1:6006 root@connect.xxx.seetacloud.com -p + ``` + +**命令说明:** +- `-C`: 压缩数据传输 +- `-N`: 不执行远程命令,仅用于端口转发 +- `-g`: 允许远程主机连接本地转发端口 +- `-L 6006:127.0.0.1:6006`: 将本地 6006 端口转发到远程服务器的 6006 端口 +- `root@connect.cqa1.seetacloud.com`: AutoDL 服务器地址 +- `-p 30588`: SSH 连接端口(每个实例不同,请在 AutoDL 控制台查看) + +**注意事项:** +1. `connect.cqa1.seetacloud.com` 和端口 `30588` 是示例,请根据你的 AutoDL 实例信息修改 +2. 在 AutoDL 控制台的 **"容器实例"** -> **"SSH 连接"** 中可以找到你的连接信息 +3. 执行命令后需要输入 AutoDL 实例的 root 密码 +4. 命令执行后会保持运行状态(不要关闭终端),此时端口转发已建立 + +### 3. 验证端口转发 + +端口转发建立后,在本地浏览器访问: + +``` +http://localhost:6006 +``` + +如果能看到后端 API 响应(可能是 404 或欢迎页面),说明转发成功。 + +### 4. 前端配置 + +#### 本地开发环境配置 + +在前端项目的配置文件中,将后端 API 地址设置为本地转发地址。 + +**方式 1:使用环境变量(推荐)** + +在前端项目根目录创建 `.env.development` 文件: + +```ini +# 开发环境配置 +VITE_API_BASE_URL=http://localhost:6006/api +``` + +**方式 2:使用 Vite 代理配置** + +编辑 `vite.config.js`: + +```javascript +export default defineConfig({ + server: { + proxy: { + '/api': { + target: 'http://localhost:6006', // 本地转发地址 + changeOrigin: true, + rewrite: (path) => path // 保持 /api 前缀 + } + } + } +}) +``` +#### 生产环境配置 + +如果需要部署到生产环境,可以: + +1. **使用 AutoDL 公网地址**(如果开通了公网访问) +2. **使用内网穿透工具**(如 ngrok, frp) +3. **部署到云服务器**(如阿里云、腾讯云) + +### 5. 完整使用流程 + +**本地开发完整步骤:** + +1. **启动 AutoDL 后端服务** + ```bash + # SSH 登录到 AutoDL 实例 + ssh root@connect.cqa1.seetacloud.com -p 30588 + + # 启动后端服务 + cd /root/autodl-tmp/MuseGuard/src/backend + ./start.sh + ``` + +2. **在本地建立 SSH 端口转发**(新开一个本地终端) + ```bash + ssh -CNg -L 6006:127.0.0.1:6006 root@connect.cqa1.seetacloud.com -p 30588 + # 输入密码后保持运行 + ``` + +3. **启动前端服务**(本地) + ```bash + cd /path/to/frontend + npm run dev + ``` + +4. **访问前端应用** + ``` + http://localhost:5173 # Vite 默认端口 + ``` + +### 6. 常见问题 + +**Q1: 端口转发命令执行后立即退出?** +- 检查 SSH 连接信息是否正确 +- 确认 AutoDL 实例是否正在运行 +- 检查密码是否输入正确 + +**Q2: 本地无法访问 localhost:6006?** +- 确认端口转发命令仍在运行 +- 检查 AutoDL 后端服务是否已启动(`./status.sh`) +- 尝试使用 `127.0.0.1:6006` 代替 `localhost:6006` + +**Q3: 前端请求后端接口 CORS 错误?** +- 后端已配置 `Flask-CORS`,应该不会出现跨域问题 +- 检查前端请求的 URL 是否正确 +- 查看后端日志确认请求是否到达 + +**Q4: SSH 连接断开后端口转发失效?** +- 使用 `autossh` 实现自动重连: + ```bash + autossh -M 0 -CNg -L 6006:127.0.0.1:6006 root@connect.cqa1.seetacloud.com -p 30588 + ``` +- 或者在 `~/.ssh/config` 中配置 `ServerAliveInterval` 保持连接 + +### 注意事项 + +- **端口转发保活**:SSH 端口转发需要保持终端运行,建议使用 `tmux` 或 `screen` 在后台运行 +- **安全性**:端口转发仅在本地有效,外部无法访问,相对安全 +- **性能**:所有请求都通过 SSH 加密传输,可能会有轻微延迟 +- **多实例**:如果有多个 AutoDL 实例,注意区分不同的 SSH 端口和转发端口 +- **服务保活**:建议使用 `tmux` 或 `nohup` 保持后端服务在后台运行,防止 SSH 断开后服务停止。`start.sh` 脚本已包含后台运行逻辑 diff --git a/src/backend/app/controllers/admin_controller.py b/src/backend/app/controllers/admin_controller.py index 1683845..1fdb46f 100644 --- a/src/backend/app/controllers/admin_controller.py +++ b/src/backend/app/controllers/admin_controller.py @@ -183,7 +183,7 @@ def delete_user(user_id): current_user_id = get_jwt_identity() # 不能删除自己 - if user_id == current_user_id: + if user_id == int(get_jwt_identity()): return jsonify({'error': '不能删除自己的账户'}), 400 user = User.query.get(user_id) diff --git a/src/backend/app/controllers/task_controller.py b/src/backend/app/controllers/task_controller.py index 456694b..957d433 100644 --- a/src/backend/app/controllers/task_controller.py +++ b/src/backend/app/controllers/task_controller.py @@ -1,6 +1,5 @@ """ 任务管理控制器 -适配新数据库结构,提供加噪、微调、热力图、数值评估等任务相关接口 """ from flask import Blueprint, request, jsonify diff --git a/src/backend/app/services/task_service.py b/src/backend/app/services/task_service.py index e681e4e..669a711 100644 --- a/src/backend/app/services/task_service.py +++ b/src/backend/app/services/task_service.py @@ -1,5 +1,5 @@ """ -任务处理服务(适配新数据库结构和路径配置) +任务处理服务 处理加噪、微调、热力图、评估等核心业务逻辑 使用Redis Queue进行异步任务处理 diff --git a/src/backend/app/workers/evaluate_worker.py b/src/backend/app/workers/evaluate_worker.py index fb6b4cd..0a3dd2e 100644 --- a/src/backend/app/workers/evaluate_worker.py +++ b/src/backend/app/workers/evaluate_worker.py @@ -1,5 +1,5 @@ """ -RQ Worker 数值评估任务处理器(仅使用真实算法) +RQ Worker 数值评估任务处理器 生成原始图与扰动图微调后的模型生成效果对比报告 """ @@ -20,7 +20,7 @@ logger = logging.getLogger(__name__) def run_evaluate_task(task_id, clean_ref_dir, clean_output_dir, perturbed_output_dir, output_dir, image_size=512): """ - 执行数值评估任务(仅使用真实算法) + 执行数值评估任务 Args: task_id: 任务ID diff --git a/src/backend/app/workers/finetune_worker.py b/src/backend/app/workers/finetune_worker.py index a0458ad..8d66f8e 100644 --- a/src/backend/app/workers/finetune_worker.py +++ b/src/backend/app/workers/finetune_worker.py @@ -1,6 +1,5 @@ """ -RQ Worker 微调任务处理器 - 适配新数据库结构 -仅支持真实算法,移除虚拟算法调用 +RQ Worker 微调任务处理器 """ import os @@ -22,7 +21,7 @@ def run_finetune_task(task_id, finetune_method, train_images_dir, output_model_dir, class_dir, coords_save_path, validation_output_dir, finetune_type, custom_params=None): """ - 执行微调任务(仅使用真实算法) + 执行微调任务 Args: task_id: 任务ID @@ -95,7 +94,7 @@ def run_finetune_task(task_id, finetune_method, train_images_dir, # DreamBooth/LoRA: 直接使用模板 instance_prompt_prefix = instance_prompt - # 处理 Validation Prompt (拼接后缀) + # 处理 Validation Prompt prompt_suffix = finetune.custom_prompt.strip() if finetune.custom_prompt else "" if prompt_suffix: @@ -207,7 +206,7 @@ def _run_real_finetune(finetune_method, task_id, train_images_dir, output_model_ class_dir, coords_save_path, validation_output_dir, instance_prompt, class_prompt, validation_prompt, finetune_type, custom_params, log_file): """ - 运行真实微调算法(参考sh脚本配置) + 运行真实微调算法 Args: finetune_method: 微调方法 @@ -240,7 +239,7 @@ def _run_real_finetune(finetune_method, task_id, train_images_dir, output_model_ if not script_path: raise ValueError(f"Finetune method {finetune_method} not configured") - # 覆盖提示词参数(从数据库读取) + # 覆盖提示词参数 if 'instance_prompt' in default_params: default_params['instance_prompt'] = instance_prompt if 'class_prompt' in default_params: @@ -273,7 +272,7 @@ def _run_real_finetune(finetune_method, task_id, train_images_dir, output_model_ ]) elif finetune_method == 'textual_inversion': - # Textual Inversion 特有参数 (不需要 class_data_dir) + # Textual Inversion 特有参数 cmd_args.extend([ f"--coords_save_path={coords_save_path}", ]) @@ -354,30 +353,6 @@ def _run_real_finetune(finetune_method, task_id, train_images_dir, output_model_ os.makedirs(output_model_dir) logger.info(f"Cleanup completed. Only validation images and coords.json are kept.") - - - - # # 清理class_dir(参考sh脚本) - # if finetune_method in ['dreambooth', 'lora']: - # logger.info(f"Cleaning class directory: {class_dir}") - # if os.path.exists(class_dir): - # shutil.rmtree(class_dir) - # os.makedirs(class_dir) - - # # 清理output_model_dir中的非图片文件 - # logger.info(f"Cleaning non-image files in output directory: {output_model_dir}") - # if os.path.exists(output_model_dir): - # image_extensions = {'.jpg', '.jpeg', '.png', '.bmp', '.gif', '.webp', '.tiff'} - # for item in os.listdir(output_model_dir): - # item_path = os.path.join(output_model_dir, item) - # if os.path.isfile(item_path): - # _, ext = os.path.splitext(item) - # if ext.lower() not in image_extensions: - # try: - # os.remove(item_path) - # logger.info(f"Removed non-image file: {item}") - # except Exception as e: - # logger.warning(f"Failed to remove {item}: {str(e)}") return { 'status': 'success', @@ -388,7 +363,7 @@ def _run_real_finetune(finetune_method, task_id, train_images_dir, output_model_ def _save_generated_images(task_id, output_dir, finetune_type): """ - 保存微调生成的验证图片到数据库(适配新数据库结构) + 保存微调生成的验证图片到数据库 新数据库结构: - Task表:tasks_id (主键), flow_id, tasks_type_id diff --git a/src/backend/app/workers/heatmap_worker.py b/src/backend/app/workers/heatmap_worker.py index 672122c..f5081e0 100644 --- a/src/backend/app/workers/heatmap_worker.py +++ b/src/backend/app/workers/heatmap_worker.py @@ -1,7 +1,6 @@ """ -RQ Worker 热力图任务处理器 - 适配新数据库结构 +RQ Worker 热力图任务处理器 生成原始图与扰动图的注意力差异热力图 -仅支持真实算法,移除虚拟算法调用 """ import os @@ -21,14 +20,14 @@ logger = logging.getLogger(__name__) def run_heatmap_task(task_id, original_image_path, perturbed_image_path, output_dir, perturbed_image_id=None): """ - 执行热力图生成任务(仅使用真实算法) + 执行热力图生成任务 Args: task_id: 任务ID original_image_path: 原始图片路径 perturbed_image_path: 扰动图片路径 output_dir: 输出目录 - perturbed_image_id: 扰动图片ID(用于建立father关系) + perturbed_image_id: 扰动图片ID Returns: 任务执行结果 @@ -228,7 +227,7 @@ def _save_heatmap_image(task_id, heatmap_file_path, father_image_id=None): Args: task_id: 任务ID heatmap_file_path: 热力图文件完整路径 - father_image_id: 父图片ID(原始图片ID) + father_image_id: 父图片ID """ from app import db from app.database import Image, ImageType diff --git a/src/backend/app/workers/perturbation_worker.py b/src/backend/app/workers/perturbation_worker.py index 6a92364..792d685 100644 --- a/src/backend/app/workers/perturbation_worker.py +++ b/src/backend/app/workers/perturbation_worker.py @@ -1,7 +1,5 @@ """ RQ Worker任务处理器 - 加噪任务 -适配新数据库结构: Task + Perturbation + Images -仅支持真实算法,移除虚拟算法调用 """ import os @@ -24,7 +22,7 @@ logger = logging.getLogger(__name__) def run_perturbation_task(task_id, algorithm_code, epsilon, input_dir, output_dir, class_dir, custom_params=None): """ - 执行对抗性扰动任务(仅使用真实算法) + 执行对抗性扰动任务 Args: task_id: 任务ID(对应 tasks 表的 tasks_id) @@ -139,7 +137,7 @@ def run_perturbation_task(task_id, algorithm_code, epsilon, input_dir, output_di def _run_real_algorithm(script_path, conda_env, algorithm_code, task_id, epsilon, input_dir, output_dir, class_dir, custom_params, log_file): """ - 运行真实算法(参考sh脚本配置) + 运行真实算法 Args: script_path: 算法脚本路径 @@ -307,7 +305,7 @@ def _run_real_algorithm(script_path, conda_env, algorithm_code, task_id, def _save_perturbed_images(task_id, output_dir): """ - 保存扰动图片到数据库(适配新数据库结构) + 保存扰动图片到数据库 新数据库结构: - Task表:tasks_id (主键), flow_id, tasks_type_id diff --git a/src/backend/config/settings.py b/src/backend/config/settings.py index c38028d..338a677 100644 --- a/src/backend/config/settings.py +++ b/src/backend/config/settings.py @@ -67,39 +67,14 @@ class Config: MODEL_ORIGINAL_FOLDER = os.path.join(MODEL_OUTPUTS_FOLDER, 'original') # 原图的模型生成结果 MODEL_PERTURBED_FOLDER = os.path.join(MODEL_OUTPUTS_FOLDER, 'perturbed') # 加噪图的模型生成结果 # 微调训练相关配置 - CLASS_DATA_FOLDER = os.path.join(STATIC_ROOT, 'class') # 类别数据目录(用于 prior preservation) - MODEL_DATA_FOLDER = os.path.join(STATIC_ROOT, 'model_data') # 模型数据目录(用于微调训练数据存储) + CLASS_DATA_FOLDER = os.path.join(STATIC_ROOT, 'class') # 类别数据目录 + MODEL_DATA_FOLDER = os.path.join(STATIC_ROOT, 'model_data') # 模型数据目录 # 可视化与分析配置 EVA_RES_FOLDER = os.path.join(STATIC_ROOT, 'eva_res') # 评估结果根目录 - COORDS_SAVE_FOLDER = os.path.join(EVA_RES_FOLDER, 'position') # 3D坐标可视化数据(用于训练轨迹) - POSITIONS_SAVE_FOLDER = os.path.join(EVA_RES_FOLDER, 'position') # 位置数据(与coords相同,LoRA使用)未使用 + COORDS_SAVE_FOLDER = os.path.join(EVA_RES_FOLDER, 'position') # 3D坐标可视化数据 + POSITIONS_SAVE_FOLDER = os.path.join(EVA_RES_FOLDER, 'position') # 位置数据 HEATDIF_SAVE_FOLDER = os.path.join(EVA_RES_FOLDER, 'heatdif') # 热力图差异数据 NUMBERS_SAVE_FOLDER = os.path.join(EVA_RES_FOLDER, 'numbers') # 数值结果数据 - - # 预设演示图像配置 - DEMO_IMAGES_FOLDER = os.path.join(STATIC_ROOT, 'demo') # 演示图片根目录 - DEMO_ORIGINAL_FOLDER = os.path.join(DEMO_IMAGES_FOLDER, 'original') # 演示原始图片 - DEMO_PERTURBED_FOLDER = os.path.join(DEMO_IMAGES_FOLDER, 'perturbed') # 演示加噪图片 - DEMO_COMPARISONS_FOLDER = os.path.join(DEMO_IMAGES_FOLDER, 'comparisons') # 演示对比图 - - # 算法配置 - ALGORITHMS = { - 'simac': { - 'name': 'SimAC算法', - 'description': 'Simple Anti-Customization Method for Protecting Face Privacy', - 'default_epsilon': 8.0 - }, - 'caat': { - 'name': 'CAAT算法', - 'description': 'Perturbing Attention Gives You More Bang for the Buck', - 'default_epsilon': 16.0 - }, - 'pid': { - 'name': 'PID算法', - 'description': 'Prompt-Independent Data Protection Against Latent Diffusion Models', - 'default_epsilon': 4.0 - } - } class DevelopmentConfig(Config): """开发环境配置""" diff --git a/src/backend/status.sh b/src/backend/status.sh index 2c128bb..519bce7 100755 --- a/src/backend/status.sh +++ b/src/backend/status.sh @@ -11,56 +11,56 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd "$SCRIPT_DIR" # 检查Flask应用 -echo "📌 Flask 应用:" +echo "Flask 应用:" if [ -f logs/flask.pid ]; then FLASK_PID=$(cat logs/flask.pid) if ps -p $FLASK_PID > /dev/null 2>&1; then - echo " ✅ 运行中 (PID: $FLASK_PID)" - echo " 📍 URL: http://127.0.0.1:6006" - echo " 📍 测试: http://127.0.0.1:6006/static/test.html" + echo " 运行中 (PID: $FLASK_PID)" + echo " URL: http://127.0.0.1:6006" + echo " 测试: http://127.0.0.1:6006/static/test.html" else - echo " ❌ 未运行 (PID文件存在但进程不存在)" + echo " 未运行 (PID文件存在但进程不存在)" fi else if pgrep -f "python run.py" > /dev/null 2>&1; then FLASK_PID=$(pgrep -f "python run.py") - echo " ⚠️ 运行中但无PID文件 (PID: $FLASK_PID)" + echo " 运行中但无PID文件 (PID: $FLASK_PID)" else - echo " ❌ 未运行" + echo " 未运行" fi fi echo "" # 检查Worker -echo "📌 RQ Worker:" +echo "RQ Worker:" if [ -f logs/worker.pid ]; then WORKER_PID=$(cat logs/worker.pid) if ps -p $WORKER_PID > /dev/null 2>&1; then - echo " ✅ 运行中 (PID: $WORKER_PID)" + echo " 运行中 (PID: $WORKER_PID)" else - echo " ❌ 未运行 (PID文件存在但进程不存在)" + echo " 未运行 (PID文件存在但进程不存在)" fi else if pgrep -f "python worker.py" > /dev/null 2>&1; then WORKER_PID=$(pgrep -f "python worker.py") - echo " ⚠️ 运行中但无PID文件 (PID: $WORKER_PID)" + echo " 运行中但无PID文件 (PID: $WORKER_PID)" else - echo " ❌ 未运行" + echo " 未运行" fi fi echo "" # 检查Redis -echo "📌 Redis:" +echo "Redis:" if redis-cli ping > /dev/null 2>&1; then - echo " ✅ 运行中" + echo " 运行中" else - echo " ❌ 未运行" + echo " 未运行" fi echo "" # 检查日志文件 -echo "📌 日志文件:" +echo "日志文件:" if [ -f logs/flask.log ]; then FLASK_LOG_SIZE=$(du -h logs/flask.log | cut -f1) echo " Flask: logs/flask.log ($FLASK_LOG_SIZE)" diff --git a/src/backend/worker.py b/src/backend/worker.py index 2c4d77c..4932c02 100644 --- a/src/backend/worker.py +++ b/src/backend/worker.py @@ -29,11 +29,11 @@ def main(): # 创建worker worker = Worker([queue], connection=redis_conn) - print(f"🚀 RQ Worker启动成功!") - print(f"📡 Redis: {AlgorithmConfig.REDIS_URL}") - print(f"📋 Queue: {AlgorithmConfig.RQ_QUEUE_NAME}") - print(f"🔄 使用{'真实' if AlgorithmConfig.USE_REAL_ALGORITHMS else '虚拟'}算法") - print(f"⏳ 等待任务...") + print(f"RQ Worker启动成功!") + print(f"Redis: {AlgorithmConfig.REDIS_URL}") + print(f"Queue: {AlgorithmConfig.RQ_QUEUE_NAME}") + print(f"使用{'真实' if AlgorithmConfig.USE_REAL_ALGORITHMS else '虚拟'}算法") + print(f"等待任务...") # 启动worker worker.work()