From b95c23d00b9cb69d1d8033427e92e7f8d8e412e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E6=B5=A9?= <971817787@qq.com> Date: Thu, 11 Dec 2025 23:17:51 +0800 Subject: [PATCH 1/8] =?UTF-8?q?feat:=20=E5=90=8E=E7=AB=AF=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0glaze=E5=8A=A0=E5=99=AA=E7=AE=97=E6=B3=95=E9=80=82?= =?UTF-8?q?=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/workers/perturbation_worker.py | 9 +++++++++ src/backend/config/algorithm_config.py | 19 +++++++++++++++++++ src/backend/init_db.py | 3 ++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/backend/app/workers/perturbation_worker.py b/src/backend/app/workers/perturbation_worker.py index ec345f0..bb3e399 100644 --- a/src/backend/app/workers/perturbation_worker.py +++ b/src/backend/app/workers/perturbation_worker.py @@ -196,6 +196,15 @@ def _run_real_algorithm(script_path, conda_env, algorithm_code, task_id, f"--output_dir={output_dir}", f"--eps={int(epsilon)}", ]) + elif algorithm_code == 'glaze': + # Glaze参数结构 + cmd_args.extend([ + f"--instance_data_dir={input_dir}", + f"--output_dir={output_dir}", + ]) + # 使用任务配置的epsilon覆盖默认值 + if epsilon is not None: + params['eps'] = float(epsilon) else: raise ValueError(f"Unsupported algorithm code: {algorithm_code}") diff --git a/src/backend/config/algorithm_config.py b/src/backend/config/algorithm_config.py index 22c0af6..17fb2f5 100644 --- a/src/backend/config/algorithm_config.py +++ b/src/backend/config/algorithm_config.py @@ -38,6 +38,7 @@ class AlgorithmConfig: 'simac': os.getenv('CONDA_ENV_SIMAC', 'simac'), 'caat': os.getenv('CONDA_ENV_CAAT', 'caat'), 'pid': os.getenv('CONDA_ENV_PID', 'pid'), + 'glaze': os.getenv('CONDA_ENV_GLAZE', 'pid'), 'dreambooth': os.getenv('CONDA_ENV_DREAMBOOTH', 'pid'), 'lora': os.getenv('CONDA_ENV_LORA', 'pid'), 'textual_inversion': os.getenv('CONDA_ENV_TI', 'pid'), @@ -126,6 +127,24 @@ class AlgorithmConfig: 'center_crop': True, 'attack_type': 'add-log' } + }, + 'glaze': { + 'real_script': os.path.join(ALGORITHMS_DIR, 'perturbation', 'glaze.py'), + 'virtual_script': os.path.join(ALGORITHMS_DIR, 'perturbation_engine.py'), + 'conda_env': CONDA_ENVS['glaze'], + 'default_params': { + 'pretrained_model_name_or_path': MODELS_DIR['model2'], + 'resolution': 512, + 'center_crop': True, + 'max_train_steps': 150, + 'eps': 0.05, + 'target_style': 'cubism painting by picasso', + 'style_strength': 0.75, + 'n_runs': 3, + 'style_transfer_iter': 15, + 'guidance_scale': 7.5, + 'seed': 42 + } } } diff --git a/src/backend/init_db.py b/src/backend/init_db.py index 0db5d42..fe7f475 100644 --- a/src/backend/init_db.py +++ b/src/backend/init_db.py @@ -60,7 +60,8 @@ def init_database(): {'perturbation_code': 'aspl', 'perturbation_name': 'ASPL算法', 'description': 'Advanced Semantic Protection Layer for Enhanced Privacy Defense'}, {'perturbation_code': 'simac', 'perturbation_name': 'SimAC算法', 'description': 'Simple Anti-Customization Method for Protecting Face Privacy'}, {'perturbation_code': 'caat', 'perturbation_name': 'CAAT算法', 'description': 'Perturbing Attention Gives You More Bang for the Buck'}, - {'perturbation_code': 'pid', 'perturbation_name': 'PID算法', 'description': 'Prompt-Independent Data Protection Against Latent Diffusion Models'} + {'perturbation_code': 'pid', 'perturbation_name': 'PID算法', 'description': 'Prompt-Independent Data Protection Against Latent Diffusion Models'}, + {'perturbation_code': 'glaze', 'perturbation_name': 'Glaze算法', 'description': 'Protecting Artists from Style Mimicry by Text-to-Image Models'} ] for config in perturbation_configs: -- 2.34.1 From 378d5fec324f5e39e893e9ed3603299348dbf38d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E6=B5=A9?= <971817787@qq.com> Date: Thu, 11 Dec 2025 23:44:52 +0800 Subject: [PATCH 2/8] =?UTF-8?q?feat:=20=E4=BF=AE=E6=94=B9=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E6=96=87=E4=BB=B6=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/app/workers/evaluate_worker.py | 24 +++++++++---------- src/backend/app/workers/finetune_worker.py | 22 ++++++++--------- src/backend/app/workers/heatmap_worker.py | 20 ++++++++-------- .../app/workers/perturbation_worker.py | 20 ++++++++-------- 4 files changed, 43 insertions(+), 43 deletions(-) diff --git a/src/backend/app/workers/evaluate_worker.py b/src/backend/app/workers/evaluate_worker.py index 4293cc5..5f203bc 100644 --- a/src/backend/app/workers/evaluate_worker.py +++ b/src/backend/app/workers/evaluate_worker.py @@ -69,10 +69,18 @@ def run_evaluate_task(task_id, clean_ref_dir, clean_output_dir, elif os.path.isdir(item_path): shutil.rmtree(item_path) + # 设置日志文件 + log_dir = AlgorithmConfig.LOGS_DIR + os.makedirs(log_dir, exist_ok=True) + log_file = os.path.join( + log_dir, + f'evaluate_task_{task_id}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log' + ) + # 运行真实评估算法 result = _run_real_evaluate( task_id, clean_ref_dir, clean_output_dir, - perturbed_output_dir, output_dir, image_size + perturbed_output_dir, output_dir, image_size, log_file ) # 保存评估结果文件路径到数据库 @@ -105,11 +113,11 @@ def run_evaluate_task(task_id, clean_ref_dir, clean_output_dir, def _run_real_evaluate(task_id, clean_ref_dir, clean_output_dir, - perturbed_output_dir, output_dir, image_size): - """运行真实数值评估算法""" + perturbed_output_dir, output_dir, image_size, log_file): + """运行真实评估算法""" from config.algorithm_config import AlgorithmConfig - logger.info(f"Running real evaluate generation") + logger.info(f"Running real evaluation") # 获取评估脚本配置 evaluate_config = AlgorithmConfig.EVALUATE_SCRIPTS.get('numbers', {}) @@ -143,14 +151,6 @@ def _run_real_evaluate(task_id, clean_ref_dir, clean_output_dir, env = os.environ.copy() env['HF_HUB_OFFLINE'] = '1' - # 设置日志文件 - log_dir = AlgorithmConfig.LOGS_DIR - os.makedirs(log_dir, exist_ok=True) - log_file = os.path.join( - log_dir, - f'evaluate_{task_id}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log' - ) - # 执行命令 with open(log_file, 'w') as f: process = subprocess.Popen( diff --git a/src/backend/app/workers/finetune_worker.py b/src/backend/app/workers/finetune_worker.py index 7bd8c8d..f39c065 100644 --- a/src/backend/app/workers/finetune_worker.py +++ b/src/backend/app/workers/finetune_worker.py @@ -99,11 +99,19 @@ def run_finetune_task(task_id, finetune_method, train_images_dir, coords_dir = os.path.dirname(coords_save_path) os.makedirs(coords_dir, exist_ok=True) + # 设置日志文件 + log_dir = AlgorithmConfig.LOGS_DIR + os.makedirs(log_dir, exist_ok=True) + log_file = os.path.join( + log_dir, + f'finetune_{finetune_method}_task_{task_id}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log' + ) + # 运行真实微调算法 result = _run_real_finetune( finetune_method, task_id, train_images_dir, output_model_dir, class_dir, coords_save_path, validation_output_dir, - instance_prompt, class_prompt, validation_prompt, is_perturbed, custom_params + instance_prompt, class_prompt, validation_prompt, is_perturbed, custom_params, log_file ) # 保存生成的验证图片到数据库 @@ -138,7 +146,7 @@ def run_finetune_task(task_id, finetune_method, train_images_dir, def _run_real_finetune(finetune_method, task_id, train_images_dir, output_model_dir, class_dir, coords_save_path, validation_output_dir, - instance_prompt, class_prompt, validation_prompt, is_perturbed, custom_params): + instance_prompt, class_prompt, validation_prompt, is_perturbed, custom_params, log_file): """ 运行真实微调算法(参考sh脚本配置) @@ -155,6 +163,7 @@ def _run_real_finetune(finetune_method, task_id, train_images_dir, output_model_ validation_prompt: 验证提示词 is_perturbed: 是否使用扰动图片 custom_params: 自定义参数 + log_file: 日志文件路径 """ from config.algorithm_config import AlgorithmConfig @@ -233,15 +242,6 @@ def _run_real_finetune(finetune_method, task_id, train_images_dir, output_model_ logger.info(f"Executing command: {' '.join(cmd)}") - # 设置日志文件 - log_dir = AlgorithmConfig.LOGS_DIR - os.makedirs(log_dir, exist_ok=True) - image_type = 'perturbed' if is_perturbed else 'original' - log_file = os.path.join( - log_dir, - f'finetune_{image_type}_{task_id}_{finetune_method}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log' - ) - # 执行命令 with open(log_file, 'w') as f: process = subprocess.Popen( diff --git a/src/backend/app/workers/heatmap_worker.py b/src/backend/app/workers/heatmap_worker.py index b92d28c..a02f402 100644 --- a/src/backend/app/workers/heatmap_worker.py +++ b/src/backend/app/workers/heatmap_worker.py @@ -93,10 +93,18 @@ def run_heatmap_task(task_id, original_image_path, perturbed_image_path, elif os.path.isdir(item_path): shutil.rmtree(item_path) + # 设置日志文件 + log_dir = AlgorithmConfig.LOGS_DIR + os.makedirs(log_dir, exist_ok=True) + log_file = os.path.join( + log_dir, + f'heatmap_task_{task_id}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log' + ) + # 运行真实热力图算法 result = _run_real_heatmap( task_id, original_image_path, perturbed_image_path, - prompt_text, target_word, output_dir + prompt_text, target_word, output_dir, log_file ) # 保存热力图文件到数据库 @@ -131,7 +139,7 @@ def run_heatmap_task(task_id, original_image_path, perturbed_image_path, def _run_real_heatmap(task_id, original_image_path, perturbed_image_path, - prompt_text, target_word, output_dir): + prompt_text, target_word, output_dir, log_file): """运行真实热力图算法""" from config.algorithm_config import AlgorithmConfig @@ -175,14 +183,6 @@ def _run_real_heatmap(task_id, original_image_path, perturbed_image_path, env = os.environ.copy() env['HF_HUB_OFFLINE'] = '1' - # 设置日志文件 - log_dir = AlgorithmConfig.LOGS_DIR - os.makedirs(log_dir, exist_ok=True) - log_file = os.path.join( - log_dir, - f'heatmap_{task_id}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log' - ) - # 执行命令 with open(log_file, 'w') as f: process = subprocess.Popen( diff --git a/src/backend/app/workers/perturbation_worker.py b/src/backend/app/workers/perturbation_worker.py index bb3e399..c486e28 100644 --- a/src/backend/app/workers/perturbation_worker.py +++ b/src/backend/app/workers/perturbation_worker.py @@ -85,10 +85,18 @@ def run_perturbation_task(task_id, algorithm_code, epsilon, input_dir, output_di elif os.path.isdir(item_path): shutil.rmtree(item_path) + # 设置日志文件 + log_dir = AlgorithmConfig.LOGS_DIR + os.makedirs(log_dir, exist_ok=True) + log_file = os.path.join( + log_dir, + f'perturbation_{algorithm_code}_task_{task_id}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log' + ) + # 运行真实算法 result = _run_real_algorithm( script_path, conda_env, algorithm_code, task_id, - epsilon, input_dir, output_dir, class_dir, custom_params + epsilon, input_dir, output_dir, class_dir, custom_params, log_file ) # 保存扰动图片到数据库 @@ -119,7 +127,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): + epsilon, input_dir, output_dir, class_dir, custom_params, log_file): """ 运行真实算法(参考sh脚本配置) @@ -228,14 +236,6 @@ def _run_real_algorithm(script_path, conda_env, algorithm_code, task_id, logger.info(f"Executing command: {' '.join(cmd)}") - # 设置日志文件 - log_dir = AlgorithmConfig.LOGS_DIR - os.makedirs(log_dir, exist_ok=True) - log_file = os.path.join( - log_dir, - f'task_{task_id}_{algorithm_code}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log' - ) - # 执行命令 with open(log_file, 'w') as f: process = subprocess.Popen( -- 2.34.1 From 16f64ed3b8eb257ce17ed0801e95bc5dc2956dfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E6=B5=A9?= <971817787@qq.com> Date: Thu, 11 Dec 2025 23:49:36 +0800 Subject: [PATCH 3/8] =?UTF-8?q?feat:=20=E5=BC=80=E5=A7=8B=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E5=89=8D=E5=88=A0=E9=99=A4=E4=B8=8A=E6=AC=A1=E7=9A=84?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/app/workers/evaluate_worker.py | 11 +++++++++++ src/backend/app/workers/finetune_worker.py | 10 ++++++++++ src/backend/app/workers/heatmap_worker.py | 11 +++++++++++ src/backend/app/workers/perturbation_worker.py | 10 ++++++++++ 4 files changed, 42 insertions(+) diff --git a/src/backend/app/workers/evaluate_worker.py b/src/backend/app/workers/evaluate_worker.py index 5f203bc..fb6b4cd 100644 --- a/src/backend/app/workers/evaluate_worker.py +++ b/src/backend/app/workers/evaluate_worker.py @@ -7,6 +7,7 @@ import os import subprocess import logging import shutil +import glob from datetime import datetime logging.basicConfig( @@ -72,6 +73,16 @@ def run_evaluate_task(task_id, clean_ref_dir, clean_output_dir, # 设置日志文件 log_dir = AlgorithmConfig.LOGS_DIR os.makedirs(log_dir, exist_ok=True) + + # 清除旧日志 + old_logs = glob.glob(os.path.join(log_dir, f'evaluate_task_{task_id}_*.log')) + for old_log in old_logs: + try: + os.remove(old_log) + logger.info(f"Removed old log file: {old_log}") + except Exception as e: + logger.warning(f"Failed to remove old log file {old_log}: {e}") + log_file = os.path.join( log_dir, f'evaluate_task_{task_id}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log' diff --git a/src/backend/app/workers/finetune_worker.py b/src/backend/app/workers/finetune_worker.py index f39c065..311a4fc 100644 --- a/src/backend/app/workers/finetune_worker.py +++ b/src/backend/app/workers/finetune_worker.py @@ -102,6 +102,16 @@ def run_finetune_task(task_id, finetune_method, train_images_dir, # 设置日志文件 log_dir = AlgorithmConfig.LOGS_DIR os.makedirs(log_dir, exist_ok=True) + + # 清除旧日志 + old_logs = glob.glob(os.path.join(log_dir, f'finetune_{finetune_method}_task_{task_id}_*.log')) + for old_log in old_logs: + try: + os.remove(old_log) + logger.info(f"Removed old log file: {old_log}") + except Exception as e: + logger.warning(f"Failed to remove old log file {old_log}: {e}") + log_file = os.path.join( log_dir, f'finetune_{finetune_method}_task_{task_id}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log' diff --git a/src/backend/app/workers/heatmap_worker.py b/src/backend/app/workers/heatmap_worker.py index a02f402..16a6fe7 100644 --- a/src/backend/app/workers/heatmap_worker.py +++ b/src/backend/app/workers/heatmap_worker.py @@ -8,6 +8,7 @@ import os import subprocess import logging import shutil +import glob from datetime import datetime logging.basicConfig( @@ -96,6 +97,16 @@ def run_heatmap_task(task_id, original_image_path, perturbed_image_path, # 设置日志文件 log_dir = AlgorithmConfig.LOGS_DIR os.makedirs(log_dir, exist_ok=True) + + # 清除旧日志 + old_logs = glob.glob(os.path.join(log_dir, f'heatmap_task_{task_id}_*.log')) + for old_log in old_logs: + try: + os.remove(old_log) + logger.info(f"Removed old log file: {old_log}") + except Exception as e: + logger.warning(f"Failed to remove old log file {old_log}: {e}") + log_file = os.path.join( log_dir, f'heatmap_task_{task_id}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log' diff --git a/src/backend/app/workers/perturbation_worker.py b/src/backend/app/workers/perturbation_worker.py index c486e28..1850920 100644 --- a/src/backend/app/workers/perturbation_worker.py +++ b/src/backend/app/workers/perturbation_worker.py @@ -88,6 +88,16 @@ def run_perturbation_task(task_id, algorithm_code, epsilon, input_dir, output_di # 设置日志文件 log_dir = AlgorithmConfig.LOGS_DIR os.makedirs(log_dir, exist_ok=True) + + # 清除旧日志 + old_logs = glob.glob(os.path.join(log_dir, f'perturbation_{algorithm_code}_task_{task_id}_*.log')) + for old_log in old_logs: + try: + os.remove(old_log) + logger.info(f"Removed old log file: {old_log}") + except Exception as e: + logger.warning(f"Failed to remove old log file {old_log}: {e}") + log_file = os.path.join( log_dir, f'perturbation_{algorithm_code}_task_{task_id}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log' -- 2.34.1 From 12d1f4eca066603184d18abe15a8f94dea022ade Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E6=B5=A9?= <971817787@qq.com> Date: Fri, 12 Dec 2025 00:24:24 +0800 Subject: [PATCH 4/8] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/controllers/task_controller.py | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/backend/app/controllers/task_controller.py b/src/backend/app/controllers/task_controller.py index 4741991..0a30e7e 100644 --- a/src/backend/app/controllers/task_controller.py +++ b/src/backend/app/controllers/task_controller.py @@ -15,6 +15,10 @@ from app.database import ( from app.services.task_service import TaskService from app.services.image_service import ImageService +import os +import glob +from config.algorithm_config import AlgorithmConfig + task_bp = Blueprint('task', __name__) @@ -65,6 +69,33 @@ def get_task_status(task_id, current_user_id): return jsonify(status), 200 +@task_bp.route('//logs', methods=['GET']) +@int_jwt_required +def get_task_logs(task_id, current_user_id): + """获取任务日志""" + task = Task.query.get(task_id) + if not TaskService.ensure_task_owner(task, current_user_id): + return TaskService.json_error('任务不存在或无权限', 404) + + log_dir = AlgorithmConfig.LOGS_DIR + # 匹配模式:*task_{task_id}_*.log + pattern = os.path.join(log_dir, f'*task_{task_id}_*.log') + log_files = glob.glob(pattern) + + if not log_files: + return jsonify({'logs': '暂无日志'}), 200 + + # 如果有多个,取修改时间最新的一个 + latest_log = max(log_files, key=os.path.getmtime) + + try: + with open(latest_log, 'r', encoding='utf-8') as f: + content = f.read() + return jsonify({'logs': content}), 200 + except Exception as e: + return TaskService.json_error(f'读取日志失败: {str(e)}', 500) + + @task_bp.route('//cancel', methods=['POST']) @int_jwt_required def cancel_task(task_id, current_user_id): -- 2.34.1 From 89450dc6ac190f6d287ff8418080c7df6369d943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E6=B5=A9?= <971817787@qq.com> Date: Fri, 12 Dec 2025 10:54:56 +0800 Subject: [PATCH 5/8] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E5=BA=8F=E5=88=97=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/app/database/__init__.py | 2 +- src/backend/init_db.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/app/database/__init__.py b/src/backend/app/database/__init__.py index 1ddd661..aedb9e8 100644 --- a/src/backend/app/database/__init__.py +++ b/src/backend/app/database/__init__.py @@ -60,7 +60,7 @@ class User(db.Model): 'user_id': self.user_id, 'username': self.username, 'email': self.email, - 'role': self.role.name, + 'role': self.role.role_code, 'is_active': self.is_active, 'created_at': self.created_at.isoformat(), 'updated_at': self.updated_at.isoformat() diff --git a/src/backend/init_db.py b/src/backend/init_db.py index fe7f475..eecfdc5 100644 --- a/src/backend/init_db.py +++ b/src/backend/init_db.py @@ -15,7 +15,7 @@ def init_database(): # 初始化角色数据 roles = [ - {'role_id': 1, 'role_code': 'admin', 'name': '管理员', 'max_concurrent_tasks': 15, 'description': '系统管理员,拥有最高权限'}, + {'role_id': 1, 'role_code': 'admin', 'name': '管理员', 'max_concurrent_tasks': 1000, 'description': '系统管理员,拥有最高权限'}, {'role_id': 2, 'role_code': 'vip', 'name': 'VIP用户', 'max_concurrent_tasks': 10, 'description': '付费用户,享有较高的资源使用权限'}, {'role_id': 3, 'role_code': 'normal', 'name': '普通用户', 'max_concurrent_tasks': 5, 'description': '免费用户,享有基本的资源使用权限'} ] -- 2.34.1 From 4b6eb76902ebbd506d3207a4c44e3b296e524909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E6=B5=A9?= <971817787@qq.com> Date: Fri, 12 Dec 2025 10:56:15 +0800 Subject: [PATCH 6/8] =?UTF-8?q?feat:=20=E5=8A=A0=E5=99=AA=E5=9B=BE?= =?UTF-8?q?=E7=9A=84=E6=97=A5=E5=BF=97=E5=86=99=E5=85=A5=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/app/workers/finetune_worker.py | 46 +++++++++++++++------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/src/backend/app/workers/finetune_worker.py b/src/backend/app/workers/finetune_worker.py index 311a4fc..57eef16 100644 --- a/src/backend/app/workers/finetune_worker.py +++ b/src/backend/app/workers/finetune_worker.py @@ -103,19 +103,33 @@ def run_finetune_task(task_id, finetune_method, train_images_dir, log_dir = AlgorithmConfig.LOGS_DIR os.makedirs(log_dir, exist_ok=True) - # 清除旧日志 - old_logs = glob.glob(os.path.join(log_dir, f'finetune_{finetune_method}_task_{task_id}_*.log')) - for old_log in old_logs: - try: - os.remove(old_log) - logger.info(f"Removed old log file: {old_log}") - except Exception as e: - logger.warning(f"Failed to remove old log file {old_log}: {e}") - - log_file = os.path.join( - log_dir, - f'finetune_{finetune_method}_task_{task_id}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log' - ) + if not is_perturbed: + # 原图微调:清除旧日志,创建新日志 + old_logs = glob.glob(os.path.join(log_dir, f'finetune_{finetune_method}_task_{task_id}_*.log')) + for old_log in old_logs: + try: + os.remove(old_log) + logger.info(f"Removed old log file: {old_log}") + except Exception as e: + logger.warning(f"Failed to remove old log file {old_log}: {e}") + + log_file = os.path.join( + log_dir, + f'finetune_{finetune_method}_task_{task_id}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log' + ) + else: + # 扰动图微调:尝试复用现有日志 + old_logs = glob.glob(os.path.join(log_dir, f'finetune_{finetune_method}_task_{task_id}_*.log')) + if old_logs: + # 找到最新的日志文件 + log_file = max(old_logs, key=os.path.getmtime) + logger.info(f"Appending to existing log file: {log_file}") + else: + # 没找到则创建新的 + log_file = os.path.join( + log_dir, + f'finetune_{finetune_method}_task_{task_id}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log' + ) # 运行真实微调算法 result = _run_real_finetune( @@ -253,7 +267,11 @@ def _run_real_finetune(finetune_method, task_id, train_images_dir, output_model_ logger.info(f"Executing command: {' '.join(cmd)}") # 执行命令 - with open(log_file, 'w') as f: + # 使用追加模式 'a',以便在同一日志文件中记录原图和扰动图的微调过程 + with open(log_file, 'a') as f: + if is_perturbed: + f.write(f"\n\n{'='*30}\nStarting Perturbed Finetune Task\n{'='*30}\n\n") + process = subprocess.Popen( cmd, stdout=subprocess.PIPE, -- 2.34.1 From afbcbb15f57546251ddf636d70d316bfa246b7a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E6=B5=A9?= <971817787@qq.com> Date: Fri, 12 Dec 2025 10:58:08 +0800 Subject: [PATCH 7/8] =?UTF-8?q?refactor:=20=E5=88=A0=E9=99=A4=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=E5=89=8D=E6=9C=9F=E6=B5=8B=E8=AF=95=E7=94=A8=E9=9D=99?= =?UTF-8?q?=E6=80=81=E7=BD=91=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/static/test.html | 565 ----------- src/backend/static/test0.html | 1644 --------------------------------- 2 files changed, 2209 deletions(-) delete mode 100644 src/backend/static/test.html delete mode 100644 src/backend/static/test0.html diff --git a/src/backend/static/test.html b/src/backend/static/test.html deleted file mode 100644 index b02d390..0000000 --- a/src/backend/static/test.html +++ /dev/null @@ -1,565 +0,0 @@ - - - - - 基于对抗性扰动的多风格图像生成防护系统 - 测试页面 - - - - - - -
- - - - - - - - - -
-
后端原始返回数据
-

-
- - - - diff --git a/src/backend/static/test0.html b/src/backend/static/test0.html deleted file mode 100644 index 719ec40..0000000 --- a/src/backend/static/test0.html +++ /dev/null @@ -1,1644 +0,0 @@ - - - - - - MuseGuard API 全功能测试页面 - - - -
-

🧪 MuseGuard API 测试页面

- - -
-

🌐 服务器连通性测试

- - -
- - -
-

🎨 Demo Controller - 演示模块

-
-
-

演示图片

- - -
- -
-

算法信息

- -
- - -
-
- - -
-

🧑‍💻 Auth Controller - 认证模块

-
-
-

用户注册

-
- - -
-
- - -
-
- - -
- -
- -
-

用户登录

-
- - -
-
- - -
- - - -

修改密码

-
- - -
-
- - -
-
- - -
- - - - -
- -
-
- - -
-

🔄 Task Controller - 任务管理模块

-
-
-

1. 创建任务(第一步)

-
- - -
- -
- -
-

我的批次列表

-
-

正在加载批次...

-
- -
- -
-

2. 文件上传(第二步)

-
- - -
-
- -
- -

点击或拖放图片文件到此处

-
-
- -
- -
-

3. 配置任务(第三步)

-

配置已自动加载上次使用的设置,您可以根据需要调整

- -
- - -
-
- - - 推荐范围: 1.0 - 16.0 -
-
- - -
-
- - 强防护模式可提高安全性,但会增加处理时间 -
- - -
- -
-

4. 任务管理(第四步)

- - - - -
- -
-
- - - - -
-

🖼️ Image Controller - 图像处理模块

-
-
-

图像查看和下载

-
- - -
- - - -
- -
-

图像评估和对比

-
- - -
-
- - -
- - -
- -
-

其他功能

- - -
- - -
-
- - -
-

👨‍💼 Admin Controller - 管理员模块

-
-
-

用户管理

-
-
- - -
-
- - -
-
- - -
- - -
- -
- -
-

用户创建和编辑

-
- - -
-
- - -
-
- - -
- - - -
- -
-

系统统计

- -
- -
-
-
- - - - \ No newline at end of file -- 2.34.1 From 38877c006c5936f684cea3afdea17b5c7daba6c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E6=B5=A9?= <971817787@qq.com> Date: Fri, 12 Dec 2025 11:16:20 +0800 Subject: [PATCH 8/8] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0=E5=85=B3?= =?UTF-8?q?=E4=BA=8E=E5=90=8E=E7=AB=AF=E6=97=A5=E5=BF=97=E7=9A=84=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/project/02-设计文档/backend-api.md | 28 ++++++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/doc/project/02-设计文档/backend-api.md b/doc/project/02-设计文档/backend-api.md index c0ffcbb..423dbc2 100644 --- a/doc/project/02-设计文档/backend-api.md +++ b/doc/project/02-设计文档/backend-api.md @@ -1437,12 +1437,12 @@ Authorization: Bearer **不同任务类型返回的图片** -| 任务类型 | 返回图片类型 | -| ------------ | ------------------------------------------------------------ | -| perturbation | original, perturbed | +| 任务类型 | 返回图片类型 | +| ------------ | ------------------------------------------------------------------ | +| perturbation | original, perturbed | | finetune | original, original_generate, perturbed_generate, uploaded_generate | -| heatmap | heatmap | -| evaluate | original_generate, perturbed_generate, report | +| heatmap | heatmap | +| evaluate | original_generate, perturbed_generate, report | 失败 (404): @@ -1547,3 +1547,21 @@ Authorization: Bearer | 403 | 无权限访问 | | 404 | 资源不存在 | | 500 | 服务器内部错误 | + +--- + +## 五、任务日志相关 + +### GET `/api/task//logs` +**功能**:获取指定任务的运行日志。 +**认证**:是 +**成功响应** `200 OK`: +```json +{ + "logs": "2025-12-12 10:00:00 - INFO - Starting task...\n2025-12-12 10:00:01 - INFO - Processing..." +} +``` +**错误响应**: +- `401 {"error": "无效的用户身份标识"}` +- `404 {"error": "任务不存在或无权限"}` +- `500 {"error": "读取日志失败: ..."}` -- 2.34.1