# -*- coding: utf-8 -*- """ Entry for Fooocus API. Use for starting Fooocus API. python main.py --help for more usage @file: main.py @author: Konie @update: 2024-03-22 """ import argparse import os import re import sys from threading import Thread from fooocusapi.utils.logger import logger from fooocusapi.utils.tools import run_pip, check_torch_cuda, requirements_check from fooocus_api_version import version script_path = os.path.dirname(os.path.realpath(__file__)) module_path = os.path.join(script_path, "repositories/Fooocus") sys.path.append(script_path) sys.path.append(module_path) logger.std_info("[System ARGV] " + str(sys.argv)) try: index = sys.argv.index('--gpu-device-id') os.environ["CUDA_VISIBLE_DEVICES"] = str(sys.argv[index+1]) logger.std_info(f"[Fooocus] Set device to: {str(sys.argv[index+1])}") except ValueError: pass os.environ["PYTORCH_ENABLE_MPS_FALLBACK"] = "1" os.environ["PYTORCH_MPS_HIGH_WATERMARK_RATIO"] = "0.0" python = sys.executable default_command_live = True index_url = os.environ.get("INDEX_URL", "") re_requirement = re.compile(r"\s*([-_a-zA-Z0-9]+)\s*(?:==\s*([-+_.a-zA-Z0-9]+))?\s*") def install_dependents(skip: bool = False): """ Check and install dependencies Args: skip: skip pip install """ if skip: return torch_index_url = os.environ.get("TORCH_INDEX_URL", "https://download.pytorch.org/whl/cu121") logger.std_info(f"[Fooocus-API] Using torch index URL: {torch_index_url}") # Check if you need pip install if not requirements_check(): logger.std_info("[Fooocus-API] Installing requirements.txt...") run_pip("install -r requirements.txt", "requirements") if not check_torch_cuda(): logger.std_info("[Fooocus-API] Installing PyTorch with CUDA support...") run_pip( f"install torch==2.1.0 torchvision==0.16.0 --extra-index-url {torch_index_url}", desc="torch", ) else: logger.std_info("[Fooocus-API] PyTorch with CUDA already installed") def preload_pipeline(): """Preload pipeline with detailed error handling""" logger.std_info("[Fooocus-API] Preloading pipeline ...") try: import torch logger.std_info(f"[Fooocus-API] PyTorch version: {torch.__version__}, CUDA available: {torch.cuda.is_available()}") if torch.cuda.is_available(): logger.std_info(f"[Fooocus-API] CUDA device: {torch.cuda.current_device()}, {torch.cuda.get_device_name(0)}") import modules.default_pipeline as pipeline logger.std_info("[Fooocus-API] Pipeline module imported successfully") # Add more granular steps here if needed to isolate crash except Exception as e: logger.std_error(f"[Fooocus-API] Pipeline preload failed: {str(e)}") raise def prepare_environments(args) -> bool: """ Prepare environments Args: args: command line arguments """ if args.base_url is None or len(args.base_url.strip()) == 0: host = args.host if host == "0.0.0.0": host = "127.0.0.1" # For base_url display args.base_url = f"http://{host}:{args.port}" sys.argv = [sys.argv[0]] # Define preset folder paths but avoid runtime file operations origin_preset_folder = os.path.abspath(os.path.join(module_path, "presets")) preset_folder = os.path.abspath(os.path.join(script_path, "presets")) logger.std_info(f"[Fooocus-API] Origin preset folder: {origin_preset_folder}") logger.std_info(f"[Fooocus-API] Local preset folder: {preset_folder}") # Comment out file operations to avoid permission issues on Hugging Face Spaces # if os.path.exists(preset_folder): # shutil.rmtree(preset_folder) # shutil.copytree(origin_preset_folder, preset_folder) from modules import config from fooocusapi.configs import default from fooocusapi.utils.model_loader import download_models default.default_inpaint_engine_version = config.default_inpaint_engine_version default.default_styles = config.default_styles default.default_base_model_name = config.default_base_model_name default.default_refiner_model_name = config.default_refiner_model_name default.default_refiner_switch = config.default_refiner_switch default.default_loras = config.default_loras default.default_cfg_scale = config.default_cfg_scale default.default_prompt_negative = config.default_prompt_negative default.default_aspect_ratio = default.get_aspect_ratio_value(config.default_aspect_ratio) default.available_aspect_ratios = [default.get_aspect_ratio_value(a) for a in config.available_aspect_ratios] if not args.disable_preset_download: logger.std_info("[Fooocus-API] Downloading models...") download_models() logger.std_info("[Fooocus-API] Model download completed") # Init task queue from fooocusapi import worker from fooocusapi.task_queue import TaskQueue worker.worker_queue = TaskQueue( queue_size=args.queue_size, history_size=args.queue_history, webhook_url=args.webhook_url, persistent=args.persistent, ) logger.std_info(f"[Fooocus-API] Task queue size: {args.queue_size}") logger.std_info(f"[Fooocus-API] Queue history size: {args.queue_history}") logger.std_info(f"[Fooocus-API] Webhook url: {args.webhook_url}") logger.std_info(f"[Fooocus-API] Base URL: {args.base_url}") return True def pre_setup(): """ Pre setup, for replicate or Hugging Face Spaces """ class Args(object): """ Arguments object """ host = "127.0.0.1" port = 7860 base_url = None sync_repo = "skip" disable_image_log = True skip_pip = True preload_pipeline = True queue_size = 100 queue_history = 0 preset = "default" webhook_url = None persistent = False always_gpu = False all_in_fp16 = False gpu_device_id = None apikey = None logger.std_info("[Pre Setup] Preparing environments") arguments = Args() sys.argv = [sys.argv[0]] sys.argv.append("--disable-image-log") install_dependents(arguments.skip_pip) prepare_environments(arguments) from fooocusapi.worker import task_schedule_loop task_thread = Thread(target=task_schedule_loop, daemon=True) task_thread.start() logger.std_info("[Pre Setup] Finished") if __name__ == "__main__": logger.std_info(f"[Fooocus API] Python {sys.version}") logger.std_info(f"[Fooocus API] Fooocus API version: {version}") from fooocusapi.base_args import add_base_args parser = argparse.ArgumentParser() add_base_args(parser, True) parser.set_defaults(host="0.0.0.0") # Default to 0.0.0.0 for broader access args, _ = parser.parse_known_args() install_dependents(skip=args.skip_pip) from fooocusapi.args import args if prepare_environments(args): sys.argv = [sys.argv[0]] # Load pipeline in new thread with error handling preload_pipeline_thread = Thread(target=preload_pipeline, daemon=True) preload_pipeline_thread.start() # Start task schedule thread from fooocusapi.worker import task_schedule_loop task_schedule_thread = Thread(target=task_schedule_loop, daemon=True) task_schedule_thread.start() # Start API server using original Fooocus API call from fooocusapi.api import start_app try: logger.std_info("[Fooocus-API] Starting API server...") start_app(args) except Exception as e: logger.std_error(f"[Fooocus-API] Failed to start API server: {str(e)}") raise