mirror of
https://github.com/vladmandic/automatic
synced 2026-09-20 01:31:13 +02:00
@@ -51,6 +51,8 @@ Plus continued work on modernization of codebase: UI is now fully TypeScript bas
|
||||
see *settings -> huggingface -> download method* for options
|
||||
- **Nunchaku** consider *DEV* builds when auto-installing
|
||||
- **Gallery** add clear cache button to folder menu
|
||||
- **UV** much updated `--uv` support for fast installs
|
||||
now also supports global `uv` if present in the system
|
||||
- **Changes**
|
||||
- all **Guidance** params are now set to *-1* by default to allow using model defaults and avoid confusion with different model behaviour
|
||||
log will print default values used by model if not set by user
|
||||
|
||||
+63
-14
@@ -208,6 +208,37 @@ def uninstall(package, quiet = False):
|
||||
return txt
|
||||
|
||||
|
||||
def uv_info():
|
||||
uv_version = None
|
||||
uv_cache_dir = None
|
||||
uv_cache_active = False
|
||||
uv_local = os.path.join(sys.prefix, "bin", "uv") # Prefer uv inside the venv
|
||||
if os.path.exists(uv_local):
|
||||
uv_version = subprocess.check_output([uv_local, "--version"], text=True).strip()
|
||||
uv_cache_dir = subprocess.check_output([uv_local, "cache", "dir"], text=True).strip()
|
||||
uv_global = shutil.which("uv") # Fallback: system uv
|
||||
if uv_global:
|
||||
uv_version = subprocess.check_output([uv_global, "--version"], text=True).strip()
|
||||
uv_cache_dir = subprocess.check_output([uv_global, "cache", "dir"], text=True).strip()
|
||||
uv_cache_disabled = os.environ.get("UV_NO_CACHE") == "1"
|
||||
site = next(p for p in sys.path if p.endswith("site-packages"))
|
||||
if uv_cache_dir and not uv_cache_disabled:
|
||||
for root, _dirs, files in os.walk(site):
|
||||
for f in files:
|
||||
full = os.path.join(root, f)
|
||||
try:
|
||||
st = os.stat(full)
|
||||
except FileNotFoundError:
|
||||
continue
|
||||
if st.st_nlink > 1: # Hardlink count > 1 means deduped
|
||||
uv_cache_active = True
|
||||
cache_path = os.path.join(uv_cache_dir, f) # Or check if inode matches something in cache
|
||||
if os.path.exists(cache_path):
|
||||
if os.stat(cache_path).st_ino == st.st_ino:
|
||||
uv_cache_active = True
|
||||
log.debug(f'Package manager: app=uv version="{uv_version}" folder="{uv_cache_dir}" dedup={uv_cache_active}')
|
||||
|
||||
|
||||
def run(cmd: str, *nargs: str, **kwargs):
|
||||
options = {
|
||||
"check": False,
|
||||
@@ -253,7 +284,8 @@ def pip(arg: str, ignore: bool = False, quiet: bool = True, *, uv = True, constr
|
||||
log.warning('Offline mode enabled')
|
||||
return None, 'offline'
|
||||
package = arg.replace("install", "").replace("--upgrade", "").replace("--no-deps", "").replace("--force-reinstall", "").strip()
|
||||
uv = uv and args.uv and not package.startswith('git+')
|
||||
# uv = uv and args.uv and not package.startswith('git+')
|
||||
uv = uv and args.uv
|
||||
pipCmd = "uv pip" if uv else "pip"
|
||||
if not quiet and '-r ' not in arg:
|
||||
log.info(f'Install: package="{package}" mode={"uv" if uv else "pip"}')
|
||||
@@ -264,20 +296,26 @@ def pip(arg: str, ignore: bool = False, quiet: bool = True, *, uv = True, constr
|
||||
all_args.append(arg)
|
||||
if env_args:
|
||||
all_args.append(env_args)
|
||||
if constraints and "-c " not in env_args:
|
||||
if constraints and "-c " not in env_args and arg.startswith("install"):
|
||||
all_args.append("-c constraints.txt")
|
||||
if not quiet:
|
||||
log.debug(f'Running: {pipCmd}="{" ".join(all_args)}"')
|
||||
|
||||
result, output = run(sys.executable, "-m", pipCmd, *all_args)
|
||||
if uv:
|
||||
result, output = run("uv", "pip", *all_args)
|
||||
else:
|
||||
result, output = run(sys.executable, "-m", pipCmd, *all_args)
|
||||
|
||||
if len(result.stderr) > 0:
|
||||
if uv and result.returncode != 0:
|
||||
print('HERE1', result)
|
||||
print('HERE2', output)
|
||||
log.warning(f'Install: cmd="{pipCmd}" args="{" ".join(all_args)}" cannot use uv, fallback to pip')
|
||||
debug(f'Install: uv pip error: {result.stderr}')
|
||||
cleanup_broken_packages()
|
||||
return pip(originalArg, ignore, quiet, uv=False)
|
||||
debug(f'Install {pipCmd}: {output}')
|
||||
if os.environ.get('SD_INSTALL_DEBUG', None) is not None:
|
||||
log.debug(f'PIP cmd="{pipCmd}": {output}')
|
||||
if result.returncode != 0 and not ignore:
|
||||
errors.append(f'pip: {package}')
|
||||
log.error(f'Install: {pipCmd}: {arg}')
|
||||
@@ -294,7 +332,7 @@ def install(package, friendly: str | None = None, ignore: bool = False, reinstal
|
||||
if args.reinstall or args.upgrade:
|
||||
global quick_allowed # pylint: disable=global-statement
|
||||
quick_allowed = False
|
||||
if (args.reinstall) or (reinstall) or (not installed(package, friendly, quiet=quiet)):
|
||||
if args.reinstall or reinstall or not installed(package, friendly, quiet=quiet):
|
||||
deps = '' if not no_deps else '--no-deps '
|
||||
isolation = '' if not no_build_isolation else '--no-build-isolation '
|
||||
cmd = f"install{' --upgrade' if not args.uv else ''}{' --force-reinstall' if force else ''} {deps}{isolation}{package}"
|
||||
@@ -432,6 +470,8 @@ def get_platform():
|
||||
'locale': locale.getlocale(),
|
||||
'setuptools': package_version('setuptools'),
|
||||
'docker': os.environ.get('SD_DOCKER', None) is not None,
|
||||
'pip': package_version('pip'),
|
||||
'uv': package_version('uv'),
|
||||
# 'host': platform.node(),
|
||||
# 'version': platform.version(),
|
||||
}
|
||||
@@ -539,9 +579,9 @@ def check_transformers():
|
||||
log.info(f'Install: package="transformers" version={target_transformers}')
|
||||
else:
|
||||
log.info(f'Update: package="transformers" current={pkg_transformers.version} target={target_transformers}')
|
||||
pip('uninstall --yes transformers', ignore=True, quiet=True, uv=False)
|
||||
pip(f'install --upgrade tokenizers=={target_tokenizers}', ignore=False, quiet=True, uv=False)
|
||||
pip(f'install --upgrade transformers=={target_transformers}', ignore=False, quiet=True, uv=False)
|
||||
pip('uninstall --yes transformers', ignore=True, quiet=True)
|
||||
pip(f'install --upgrade tokenizers=={target_tokenizers}', ignore=False, quiet=True)
|
||||
pip(f'install --upgrade transformers=={target_transformers}', ignore=False, quiet=True)
|
||||
else:
|
||||
# Git commit-pinned version
|
||||
current = opts.get('transformers_version', '')
|
||||
@@ -550,9 +590,9 @@ def check_transformers():
|
||||
log.info(f'Install: package="transformers" commit={target_commit}')
|
||||
else:
|
||||
log.info(f'Update: package="transformers" current={pkg_transformers.version} hash={current} target={target_commit}')
|
||||
pip('uninstall --yes transformers', ignore=True, quiet=True, uv=False)
|
||||
pip(f'install --upgrade tokenizers=={target_tokenizers}', ignore=False, quiet=True, uv=False)
|
||||
pip(f'install --upgrade git+https://github.com/huggingface/transformers@{target_commit}', ignore=False, quiet=True, uv=False)
|
||||
pip('uninstall --yes transformers', ignore=True, quiet=True)
|
||||
pip(f'install --upgrade tokenizers=={target_tokenizers}', ignore=False, quiet=True)
|
||||
pip(f'install --upgrade git+https://github.com/huggingface/transformers@{target_commit}', ignore=False, quiet=True)
|
||||
global transformers_commit # pylint: disable=global-statement
|
||||
transformers_commit = target_commit
|
||||
ts('transformers', t_start)
|
||||
@@ -1490,6 +1530,8 @@ def check_venv():
|
||||
import site
|
||||
pkg_path = [try_relpath(p) for p in site.getsitepackages() if os.path.exists(p)]
|
||||
log.debug(f'Packages: prefix={try_relpath(sys.prefix)} site={pkg_path}')
|
||||
if args.uv:
|
||||
uv_info()
|
||||
for p in pkg_path:
|
||||
invalid = []
|
||||
for f in os.listdir(p):
|
||||
@@ -1791,12 +1833,18 @@ def read_options():
|
||||
def ensure_base_requirements():
|
||||
t_start = time.time()
|
||||
setuptools_version = '69.5.1'
|
||||
if (args.uv or '--uv' in sys.argv) and (shutil.which('uv') is not None): # early enable uv
|
||||
args.uv = True # pylint: disable=attribute-defined-outside-init
|
||||
uv_info()
|
||||
|
||||
def update_setuptools():
|
||||
local_log = logging.getLogger('sdnext.installer')
|
||||
global setuptools, distutils # pylint: disable=global-statement
|
||||
# python may ship with incompatible setuptools
|
||||
subprocess.run(f'"{sys.executable}" -m pip install setuptools=={setuptools_version}', shell=True, check=False, env=os.environ, capture_output=True)
|
||||
if args.uv:
|
||||
subprocess.run(f'uv pip install setuptools=={setuptools_version} wheel', shell=True, check=False, env=os.environ, capture_output=True)
|
||||
else:
|
||||
subprocess.run(f'"{sys.executable}" -m pip install setuptools=={setuptools_version} wheel', shell=True, check=False, env=os.environ, capture_output=True)
|
||||
# need to delete all references to modules to be able to reload them otherwise python will use cached version
|
||||
modules = [m for m in sys.modules if m.startswith('setuptools') or m.startswith('distutils')]
|
||||
for m in modules:
|
||||
@@ -1825,6 +1873,7 @@ def ensure_base_requirements():
|
||||
|
||||
try:
|
||||
global setuptools # pylint: disable=global-statement
|
||||
import wheel # pylint: disable=unused-import
|
||||
import setuptools # pylint: disable=redefined-outer-name
|
||||
if setuptools.__version__ != setuptools_version:
|
||||
update_setuptools()
|
||||
@@ -1832,13 +1881,13 @@ def ensure_base_requirements():
|
||||
update_setuptools()
|
||||
|
||||
# used by installler itself so must be installed before requirements
|
||||
install('rich==14.1.0', 'rich', quiet=True)
|
||||
install('rich==15.0.0', 'rich', quiet=True)
|
||||
install('psutil', 'psutil', quiet=True)
|
||||
install('requests==2.32.3', 'requests', quiet=True)
|
||||
ts('base', t_start)
|
||||
|
||||
# startup
|
||||
|
||||
# startup
|
||||
ensure_base_requirements()
|
||||
from modules.logger import setup_logging # must be loaded after ensure_base_requirements
|
||||
from modules.logger import log as log_instance
|
||||
|
||||
@@ -5,6 +5,7 @@ import os
|
||||
import sys
|
||||
import time
|
||||
import shlex
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
import installer
|
||||
@@ -255,7 +256,7 @@ def main():
|
||||
log.info(f'Args: {sys.argv[1:]}')
|
||||
if not args.skip_env and not args.skip_all:
|
||||
installer.set_environment()
|
||||
if args.uv:
|
||||
if args.uv and shutil.which('uv') is None:
|
||||
installer.install('uv', 'uv')
|
||||
installer.install_gradio()
|
||||
installer.check_torch()
|
||||
|
||||
@@ -53,7 +53,7 @@ def install_nunchaku(force=False):
|
||||
if url is not None:
|
||||
cmd = f'install --upgrade {url}'
|
||||
log.debug(f'Nunchaku: install="{url}"')
|
||||
result, _output = pip(cmd, uv=False, ignore=not force, quiet=not force)
|
||||
result, _output = pip(cmd, ignore=not force, quiet=not force)
|
||||
return result.returncode == 0
|
||||
else:
|
||||
import torch
|
||||
@@ -75,7 +75,7 @@ def install_nunchaku(force=False):
|
||||
fn = f'nunchaku-{v}+{cuda_ver}torch{torch_ver}-cp{python_ver}-cp{python_ver}-{suffix}.whl'
|
||||
else:
|
||||
fn = f'nunchaku-{v}+{cuda_ver}torch{torch_ver}-cp{python_ver}-cp{python_ver}-{suffix}.whl'
|
||||
result, _output = pip(f'install --upgrade {url+fn}', uv=False, ignore=True, quiet=True)
|
||||
result, _output = pip(f'install --upgrade {url+fn}', ignore=True, quiet=True)
|
||||
if (result is None) or (_output == 'offline'):
|
||||
log.error(f'Nunchaku: install url="{url+fn}" offline mode')
|
||||
return False
|
||||
@@ -85,7 +85,7 @@ def install_nunchaku(force=False):
|
||||
log.info(f'Nunchaku: install url="{url}"')
|
||||
return True
|
||||
fn = f'nunchaku-{v}+torch{torch_ver}-cp{python_ver}-cp{python_ver}-{suffix}.whl'
|
||||
result, _output = pip(f'install --upgrade {url+fn}', uv=False, ignore=True, quiet=True)
|
||||
result, _output = pip(f'install --upgrade {url+fn}', ignore=True, quiet=True)
|
||||
if (result is None) or (_output == 'offline'):
|
||||
log.error(f'Nunchaku: install url="{url+fn}" offline mode')
|
||||
return False
|
||||
|
||||
+4
-4
@@ -22,7 +22,7 @@ ftfy
|
||||
|
||||
# versioned
|
||||
fastapi==0.124.4
|
||||
rich==14.1.0
|
||||
rich==15.0.0
|
||||
safetensors==0.8.0rc0
|
||||
peft==0.19.1
|
||||
httpx==0.28.1
|
||||
@@ -30,12 +30,12 @@ requests==2.32.3
|
||||
tqdm==4.67.3
|
||||
accelerate==1.13.0
|
||||
einops==0.8.1
|
||||
huggingface_hub==1.15.0
|
||||
huggingface_hub==1.16.4
|
||||
hf_xet==1.5.0
|
||||
numpy==2.1.2
|
||||
pandas==2.3.1
|
||||
protobuf==6.33.5
|
||||
pytorch_lightning==2.6.1
|
||||
protobuf==7.35.0
|
||||
pytorch_lightning==2.6.5
|
||||
urllib3==1.26.19
|
||||
Pillow==12.2.0
|
||||
timm==1.0.24
|
||||
|
||||
@@ -16,24 +16,44 @@ goto :show_stdout_stderr
|
||||
|
||||
:check_pip
|
||||
%PYTHON% -mpip --help >tmp/stdout.txt 2>tmp/stderr.txt
|
||||
if %ERRORLEVEL% == 0 goto :start_venv
|
||||
if %ERRORLEVEL% == 0 goto :check_uv_flag
|
||||
if "%PIP_INSTALLER_LOCATION%" == "" goto :show_stdout_stderr
|
||||
%PYTHON% "%PIP_INSTALLER_LOCATION%" >tmp/stdout.txt 2>tmp/stderr.txt
|
||||
if %ERRORLEVEL% == 0 goto :start_venv
|
||||
if %ERRORLEVEL% == 0 goto :check_uv_flag
|
||||
echo Cannot install pip
|
||||
goto :show_stdout_stderr
|
||||
|
||||
:check_uv_flag
|
||||
set use_uv=0
|
||||
for %%i in (%*) do (
|
||||
if /I "%%i"=="--uv" set use_uv=1
|
||||
)
|
||||
|
||||
goto :start_venv
|
||||
|
||||
:start_venv
|
||||
if ["%VENV_DIR%"] == ["-"] goto :skip_venv
|
||||
if ["%SKIP_VENV%"] == ["1"] goto :skip_venv
|
||||
if "%use_uv%" == "1" (
|
||||
where uv >nul 2>&1
|
||||
if %ERRORLEVEL% neq 0 (
|
||||
echo Warning: uv is not installed, falling back to python venv
|
||||
set use_uv=0
|
||||
)
|
||||
)
|
||||
|
||||
dir "%VENV_DIR%\Scripts\Python.exe" >tmp/stdout.txt 2>tmp/stderr.txt
|
||||
if %ERRORLEVEL% == 0 goto :activate_venv
|
||||
|
||||
for /f "delims=" %%i in ('CALL %PYTHON% -c "import sys; print(sys.executable)"') do set PYTHON_FULLNAME="%%i"
|
||||
echo Using python: %PYTHON_FULLNAME%
|
||||
echo Creating VENV: %VENV_DIR%
|
||||
%PYTHON_FULLNAME% -m venv "%VENV_DIR%" >tmp/stdout.txt 2>tmp/stderr.txt
|
||||
if "%use_uv%" == "1" (
|
||||
echo Creating VENV: UV
|
||||
uv venv "%VENV_DIR%" >tmp/stdout.txt 2>tmp/stderr.txt
|
||||
) else (
|
||||
echo Creating VENV: VENV
|
||||
%PYTHON_FULLNAME% -m venv "%VENV_DIR%" >tmp/stdout.txt 2>tmp/stderr.txt
|
||||
)
|
||||
if %ERRORLEVEL% == 0 goto :activate_venv
|
||||
echo Failed creating VENV: "%VENV_DIR%"
|
||||
goto :show_stdout_stderr
|
||||
|
||||
@@ -22,6 +22,14 @@ function ShowStdOutStdErr {
|
||||
$PYTHON = if ($env:PYTHON) { $env:PYTHON } else { 'python' }
|
||||
$VENV_DIR = if ($env:VENV_DIR) { $env:VENV_DIR } else { Join-Path $PSScriptRoot 'venv' }
|
||||
|
||||
$use_uv = $false
|
||||
foreach ($arg in $args) {
|
||||
if ($arg -eq '--uv') {
|
||||
$use_uv = $true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
New-Item -Path 'tmp' -ItemType Directory -ErrorAction SilentlyContinue
|
||||
|
||||
try {
|
||||
@@ -58,9 +66,21 @@ if ($VENV_DIR -ne '-' -and $env:SKIP_VENV -ne '1') {
|
||||
$PYTHON_FULLNAME = & $PYTHON -c 'import sys; print(sys.executable)'
|
||||
|
||||
Write-Output "Using python: $PYTHON_FULLNAME"
|
||||
Write-Output "Creating VENV: $VENV_DIR"
|
||||
|
||||
& $PYTHON_FULLNAME -m venv $VENV_DIR 2>tmp\stderr.txt | Out-File tmp\stdout.txt
|
||||
if ($use_uv) {
|
||||
if (-not (Get-Command uv -ErrorAction SilentlyContinue)) {
|
||||
Write-Output 'Warning: uv is not installed, falling back to python venv'
|
||||
$use_uv = $false
|
||||
}
|
||||
}
|
||||
|
||||
if ($use_uv) {
|
||||
Write-Output "Creating VENV: UV"
|
||||
& uv venv $VENV_DIR 2>tmp\stderr.txt | Out-File tmp\stdout.txt
|
||||
} else {
|
||||
Write-Output "Creating VENV: VENV"
|
||||
& $PYTHON_FULLNAME -m venv $VENV_DIR 2>tmp\stderr.txt | Out-File tmp\stdout.txt
|
||||
}
|
||||
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
$PYTHON = Join-Path $VENV_DIR 'Scripts\Python.exe'
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
cd -- "$(dirname -- "$0")"
|
||||
|
||||
can_run_as_root=0
|
||||
use_uv=0
|
||||
export ERROR_REPORTING=FALSE
|
||||
export PIP_IGNORE_INSTALLED=0
|
||||
|
||||
@@ -34,6 +35,15 @@ then
|
||||
venv_dir="venv"
|
||||
fi
|
||||
|
||||
for arg in "$@"
|
||||
do
|
||||
if [[ "$arg" == "--uv" ]]
|
||||
then
|
||||
use_uv=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# read any command line flags to the webui.sh script
|
||||
while getopts "f" flag > /dev/null 2>&1
|
||||
do
|
||||
@@ -59,16 +69,34 @@ do
|
||||
fi
|
||||
done
|
||||
|
||||
if ! "${PYTHON}" -c "import venv" &>/dev/null
|
||||
if [[ "${use_uv}" -eq 1 ]]
|
||||
then
|
||||
echo "Error: python3-venv is not installed"
|
||||
exit 1
|
||||
if ! hash "uv" &>/dev/null
|
||||
then
|
||||
echo "Warning: uv is not installed globally"
|
||||
use_uv=0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "${use_uv}" -eq 0 ]]
|
||||
then
|
||||
if ! "${PYTHON}" -c "import venv" &>/dev/null
|
||||
then
|
||||
echo "Error: python3-venv is not installed"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ! -d "${venv_dir}" ]]
|
||||
then
|
||||
echo "Create python venv"
|
||||
"${PYTHON}" -m venv "${venv_dir}"
|
||||
if [[ "${use_uv}" -eq 1 ]]
|
||||
then
|
||||
echo "Create VENV: UV"
|
||||
uv venv "${venv_dir}"
|
||||
else
|
||||
echo "Create VENV: VENV"
|
||||
"${PYTHON}" -m venv "${venv_dir}"
|
||||
fi
|
||||
first_launch=1
|
||||
fi
|
||||
|
||||
|
||||
Reference in New Issue
Block a user