diff --git a/UV-req-lock.txt b/UV-req-lock.txt new file mode 100644 index 000000000..8cf3abeb0 --- /dev/null +++ b/UV-req-lock.txt @@ -0,0 +1,2 @@ +pip==24.0 +setuptools==65.5.0 diff --git a/clean_venv.py b/clean_venv.py new file mode 100755 index 000000000..e6e89ab1f --- /dev/null +++ b/clean_venv.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +""" +ComfyUI Virtual Environment Cleanup Script +Created: May 2, 2025 +""" + +import argparse +import os +import shutil +import sys +import platform +from pathlib import Path + +def deactivate_venv(): + """Attempt to deactivate any active virtual environment.""" + if "VIRTUAL_ENV" in os.environ: + print(f"Active virtual environment detected: {os.environ['VIRTUAL_ENV']}") + print("Attempting to deactivate...") + + # This won't actually deactivate within this process since Python can't modify + # its parent environment, but it will provide instructions to the user + print("\nTo properly deactivate your virtual environment, please run:") + if platform.system() == "Windows": + print(" deactivate") + else: + print(" deactivate") + + print("\nAfter deactivating, run this script again.") + return True + return False + +def remove_venv(venv_path, force=False): + """Remove a virtual environment directory if it exists.""" + path = Path(venv_path).expanduser().resolve() + + if not path.exists(): + print(f"Virtual environment not found at: {path}") + return False + + # Safety check - make sure it looks like a venv + is_venv = False + if platform.system() == "Windows": + is_venv = (path / "Scripts" / "python.exe").exists() + else: + is_venv = (path / "bin" / "python").exists() + + if not is_venv and not force: + print(f"Warning: {path} doesn't appear to be a virtual environment.") + print("Use --force to remove it anyway.") + return False + + try: + print(f"Removing virtual environment at: {path}") + shutil.rmtree(path) + print("āœ… Virtual environment removed successfully.") + return True + except Exception as e: + print(f"āŒ Error removing virtual environment: {e}") + if platform.system() == "Windows": + print("\nTry running this script with administrator privileges or closing any") + print("applications that might be using files in the virtual environment.") + else: + print("\nTry running this script with sudo if you have permission issues:") + print(f" sudo rm -rf {path}") + return False + +def main(): + parser = argparse.ArgumentParser(description="Remove ComfyUI virtual environments") + parser.add_argument("--all", action="store_true", help="Remove all known virtual environment locations") + parser.add_argument("--force", action="store_true", help="Force removal even if directory doesn't look like a venv") + parser.add_argument("--venv-path", type=str, help="Path to custom virtual environment to remove") + args = parser.parse_args() + + # Don't proceed if a virtual environment is active + if deactivate_venv(): + return + + # Common venv locations + venv_locations = [ + ".venv", # Default UV venv name + "venv", # Common alternative name + Path.home() / ".venvs" / "comfyui", # User-level venvs + ] + + if args.venv_path: + # Just remove the specified venv + remove_venv(args.venv_path, args.force) + elif args.all: + # Remove all common venv locations + removed_any = False + for venv_loc in venv_locations: + if remove_venv(venv_loc, args.force): + removed_any = True + + if not removed_any: + print("No virtual environments were found in common locations.") + else: + # Default: just remove .venv + if not remove_venv(".venv", args.force): + print("\nTo remove other virtual environment locations, use:") + print(" python clean_venv.py --all") + print(" python clean_venv.py --venv-path /path/to/venv") + + print("\nšŸš€ Ready to create a new UV-based environment!") + print("Run the following commands to set up with UV:") + print(" ./uv_setup.sh") + print(" source .venv/bin/activate # On Linux/macOS") + print(" ./update_dependencies_uv.py --advanced --cuda --lock") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 97420defc..5361562a0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,4 +34,26 @@ lint.select = [ exclude = ["*.ipynb"] [tool.uv] -# Add any uv-specific configurations here +# UV-specific configurations (updated May 2025) +python = "3.11" +system = false +verbosity = 1 +threads = "auto" +no-binary = [] +only-binary = [] + +[tool.uv.dependencies] +# Core dependencies with modern 2025 versions +torch = { version = ">=2.3.0", source = "pytorch" } +torchvision = { version = ">=0.18.0", source = "pytorch" } +numpy = ">=2.0.0" +pillow = ">=10.0.0" +aiohttp = ">=3.9.0" +rich = ">=13.6.0" +tqdm = ">=4.66.0" +transformers = ">=4.38.0" +diffusers = ">=0.25.0" +safetensors = ">=0.4.0" + +[tool.uv.sources] +pytorch = { url = "https://download.pytorch.org/whl/cu121" } diff --git a/requirements.txt b/requirements.txt index 74a4ceb02..bec554918 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,6 +17,18 @@ Pillow scipy tqdm psutil +opencv-python>=4.8.0 +flash-attn>=2.3.0 +nvidia-cuda-runtime-cu12>=12.0.0 +nvidia-cuda-nvrtc-cu12>=12.0.0 +nvidia-cudnn-cu12>=8.9.0 +nvidia-cublas-cu12>=12.0.0 +nvidia-cufft-cu12>=11.0.0 +nvidia-curand-cu12>=10.3.0 +nvidia-cusolver-cu12>=11.4.0 +nvidia-cusparse-cu12>=12.1.0 +nvidia-nccl-cu12>=2.18.0 +nvidia-nvtx-cu12>=12.0.0 #non essential dependencies: kornia>=0.7.1 diff --git a/update_dependencies_uv.py b/update_dependencies_uv.py new file mode 100755 index 000000000..d488bc66b --- /dev/null +++ b/update_dependencies_uv.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 +""" +ComfyUI Dependency Update Script using UV +Created: May 2, 2025 +""" + +import argparse +import os +import platform +import subprocess +import sys + +def check_uv_installed(): + """Check if UV is installed and install if missing.""" + try: + subprocess.run(["uv", "--version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True) + print("āœ… UV is installed") + return True + except (subprocess.CalledProcessError, FileNotFoundError): + print("āš ļø UV not found. Installing...") + + if platform.system() == "Windows": + subprocess.run( + ["powershell", "-Command", "Invoke-WebRequest -Uri https://astral.sh/uv/install.ps1 -OutFile install.ps1; ./install.ps1"], + check=True + ) + else: + subprocess.run( + ["bash", "-c", "curl -LsSf https://astral.sh/uv/install.sh | sh"], + check=True + ) + + print("āœ… UV installed successfully") + return True + +def update_dependencies(args): + """Update dependencies using UV.""" + # Ensure we're in a virtual environment + if not os.environ.get("VIRTUAL_ENV") and not args.no_venv_check: + print("āš ļø Not running in a virtual environment. Activate one before updating dependencies.") + print("šŸ’” Run: uv venv && source .venv/bin/activate (or .venv\\Scripts\\activate on Windows)") + if not args.force: + return False + + print("šŸ“¦ Updating dependencies using UV...") + + # Update base requirements + subprocess.run(["uv", "pip", "install", "--upgrade", "-r", "requirements.txt"], check=True) + print("āœ… Base dependencies updated") + + # Update advanced requirements if requested + if args.advanced: + subprocess.run(["uv", "pip", "install", "--upgrade", "-r", "requirements_advanced.txt"], check=True) + print("āœ… Advanced dependencies updated") + + # Update PyTorch with CUDA if requested + if args.cuda: + torch_version = "2.4.0" if args.latest else "2.3.0" + cuda_version = "12.1" if args.latest else "11.8" + + print(f"šŸ”„ Installing PyTorch {torch_version} with CUDA {cuda_version}...") + subprocess.run([ + "uv", "pip", "install", "--upgrade", + f"torch=={torch_version}", + f"torchvision>={torch_version}", + f"torchaudio>={torch_version}", + "--index-url", f"https://download.pytorch.org/whl/cu{cuda_version.replace('.', '')}" + ], check=True) + print("āœ… PyTorch updated with CUDA support") + + # Generate lockfile for reproducibility + if args.lock: + print("šŸ”’ Generating lockfile...") + subprocess.run(["uv", "pip", "freeze", ">", "UV-req-lock.txt"], shell=True, check=True) + print("āœ… Lockfile generated: UV-req-lock.txt") + + return True + +def main(): + parser = argparse.ArgumentParser(description="Update ComfyUI dependencies using UV") + parser.add_argument("--advanced", action="store_true", help="Update advanced dependencies") + parser.add_argument("--cuda", action="store_true", help="Update PyTorch with CUDA support") + parser.add_argument("--latest", action="store_true", help="Use latest versions (may be less stable)") + parser.add_argument("--lock", action="store_true", help="Generate lockfile after update") + parser.add_argument("--force", action="store_true", help="Force update even if not in venv") + parser.add_argument("--no-venv-check", action="store_true", help="Skip virtual environment check") + + args = parser.parse_args() + + print("ComfyUI Dependency Update") + print("========================") + + if not check_uv_installed(): + sys.exit(1) + + if update_dependencies(args): + print("\n✨ Dependencies updated successfully!") + print("\nšŸ’” To start ComfyUI, run: python main.py") + else: + print("\nāŒ Dependency update failed or was skipped") + sys.exit(1) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/uv_setup.sh b/uv_setup.sh new file mode 100755 index 000000000..193d45044 --- /dev/null +++ b/uv_setup.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# ComfyUI UV Environment Setup Script +# Created: May 2, 2025 + +# Set UV environment variables for better performance +export UV_CACHE_DIR="${HOME}/.cache/uv" +export UV_SYSTEM_PYTHON=false +export UV_DEFAULT_PYTHON=3.11 +export UV_THREADS=auto +export UV_VERBOSITY=1 + +# Create directory structure if needed +mkdir -p "${UV_CACHE_DIR}" + +echo "UV environment variables set:" +echo " UV_CACHE_DIR: ${UV_CACHE_DIR}" +echo " UV_DEFAULT_PYTHON: ${UV_DEFAULT_PYTHON}" +echo " UV_THREADS: ${UV_THREADS}" + +# Check if UV is installed +if ! command -v uv >/dev/null 2>&1; then + echo "UV not found. Installing..." + curl -LsSf https://astral.sh/uv/install.sh | sh + + # Add to PATH for this session + source $HOME/.local/bin/env +fi + +# Check for ComfyUI virtual environment +if [ ! -d ".venv" ]; then + echo "Creating virtual environment..." + uv venv + echo "Virtual environment created at .venv" +fi + +echo "" +echo "To activate the virtual environment, run:" +echo " source .venv/bin/activate # On Linux/macOS" +echo " .venv\\Scripts\\activate.bat # On Windows" +echo "" +echo "To install/update dependencies:" +echo " ./update_dependencies_uv.py --advanced --cuda --lock" +echo "" +echo "To start ComfyUI:" +echo " python main.py" \ No newline at end of file