update nunchaku installer

Signed-off-by: vladmandic <mandic00@live.com>
This commit is contained in:
vladmandic
2026-03-28 08:57:23 +01:00
parent 274aeef65e
commit 611dfe4301
3 changed files with 65 additions and 53 deletions
+4 -3
View File
@@ -1,8 +1,8 @@
# Change Log for SD.Next
## Update for 2026-03-27
## Update for 2026-03-28
### Highlights for 2026-03-27
### Highlights for 2026-03-28
This release brings massive code refactoring to modernize codebase and removal of some obsolete features. Leaner & Faster!
And since its a bit quieter period when it comes to new models, notable additions would be : *FireRed-Image-Edit*, *SkyWorks-UniPic-3* and new versions of *Anima-Preview*, *Flux-Klein-KV*
@@ -20,7 +20,7 @@ Just how big? Some stats: *~530 commits over 880 files*
[ReadMe](https://github.com/vladmandic/automatic/blob/master/README.md) | [ChangeLog](https://github.com/vladmandic/automatic/blob/master/CHANGELOG.md) | [Docs](https://vladmandic.github.io/sdnext-docs/) | [WiKi](https://github.com/vladmandic/automatic/wiki) | [Discord](https://discord.com/invite/sd-next-federal-batch-inspectors-1101998836328697867) | [Sponsor](https://github.com/sponsors/vladmandic)
### Details for 2026-03-27
### Details for 2026-03-28
- **Models**
- [Google Flash 3.1 Image](https://ai.google.dev/gemini-api/docs/models/gemini-3-flash-preview) a.k.a. *Nano Banana 2*
@@ -77,6 +77,7 @@ Just how big? Some stats: *~530 commits over 880 files*
- *note* **Cuda** `torch==2.10` removed support for `rtx1000` series and older GPUs
use following before first startup to force installation of `torch==2.9.1` with `cuda==12.6`:
> `set TORCH_COMMAND='torch==2.9.1 torchvision==0.24.1 torchaudio==2.9.1 --index-url https://download.pytorch.org/whl/cu126'`
- update installer and support `nunchaku==1.2.1`
- **UI**
- legacy panels **T2I** and **I2I** are disabled by default
you can re-enable them in *settings -> ui -> hide legacy tabs*
+8 -7
View File
@@ -197,14 +197,15 @@ def installed(package, friendly: str | None = None, quiet = False): # pylint: di
def uninstall(package, quiet = False):
t_start = time.time()
packages = package if isinstance(package, list) else [package]
res = ''
txt = ''
for p in packages:
if installed(p, p, quiet=True):
if not quiet:
log.warning(f'Package: {p} uninstall')
res += pip(f"uninstall {p} --yes --quiet", ignore=True, quiet=True, uv=False)
_result, _txt = pip(f"uninstall {p} --yes --quiet", ignore=True, quiet=True, uv=False)
txt += _txt
ts('uninstall', t_start)
return res
return txt
def run(cmd: str, *nargs: str, **kwargs):
@@ -259,20 +260,20 @@ def pip(arg: str, ignore: bool = False, quiet: bool = True, uv = True):
all_args = f'{pip_log}{arg} {env_args}'.strip()
if not quiet:
log.debug(f'Running: {pipCmd}="{all_args}"')
result, txt = run(sys.executable, "-m", pipCmd, all_args)
result, output = run(sys.executable, "-m", pipCmd, all_args)
if len(result.stderr) > 0:
if uv and result.returncode != 0:
log.warning(f'Install: cmd="{pipCmd}" args="{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}: {txt}')
debug(f'Install {pipCmd}: {output}')
if result.returncode != 0 and not ignore:
errors.append(f'pip: {package}')
log.error(f'Install: {pipCmd}: {arg}')
log.debug(f'Install: pip output {txt}')
log.debug(f'Install: pip code={result.returncode} stdout={result.stdout} stderr={result.stderr} output={output}')
ts('pip', t_start)
return txt
return result, output
# install package using pip if not already installed
+53 -43
View File
@@ -2,43 +2,20 @@
from installer import pip
from modules.logger import log
from modules import devices
nunchaku_versions = {
'2.5': '1.0.1',
'2.6': '1.0.1',
'2.7': '1.1.0',
'2.8': '1.1.0',
'2.9': '1.1.0',
'2.10': '1.0.2',
'2.11': '1.1.0',
}
ok = False
def _expected_ver():
try:
import torch
torch_ver = '.'.join(torch.__version__.split('+')[0].split('.')[:2])
return nunchaku_versions.get(torch_ver)
except Exception:
return None
def check():
global ok # pylint: disable=global-statement
if ok:
return True
try:
import nunchaku
import nunchaku.utils
from nunchaku import __version__
expected = _expected_ver()
import nunchaku.utils # pylint: disable=no-name-in-module, no-member
from nunchaku import __version__ # pylint: disable=no-name-in-module
log.info(f'Nunchaku: path={nunchaku.__path__} version={__version__.__version__} precision={nunchaku.utils.get_precision()}')
if expected is not None and __version__.__version__ != expected:
ok = False
return False
ok = True
return True
except Exception as e:
@@ -47,14 +24,15 @@ def check():
return False
def install_nunchaku():
if devices.backend is None:
return False # too early
def install_nunchaku(force=False):
if not force:
from modules import devices
if devices.backend is None:
return False # too early
if not check():
import os
import sys
import platform
import torch
python_ver = f'{sys.version_info.major}{sys.version_info.minor}'
if python_ver not in ['311', '312', '313']:
log.error(f'Nunchaku: python={sys.version_info} unsupported')
@@ -63,24 +41,56 @@ def install_nunchaku():
if arch not in ['linux', 'windows']:
log.error(f'Nunchaku: platform={arch} unsupported')
return False
if devices.backend not in ['cuda']:
if not force and devices.backend not in ['cuda']:
log.error(f'Nunchaku: backend={devices.backend} unsupported')
return False
torch_ver = '.'.join(torch.__version__.split('+')[0].split('.')[:2])
nunchaku_ver = nunchaku_versions.get(torch_ver)
if nunchaku_ver is None:
log.error(f'Nunchaku: torch={torch.__version__} unsupported')
return False
suffix = 'x86_64' if arch == 'linux' else 'win_amd64'
url = os.environ.get('NUNCHAKU_COMMAND', None)
if url is None:
arch = f'{arch}_' if arch == 'linux' else ''
url = f'https://huggingface.co/nunchaku-ai/nunchaku/resolve/main/nunchaku-{nunchaku_ver}'
url += f'+torch{torch_ver}-cp{python_ver}-cp{python_ver}-{arch}{suffix}.whl'
cmd = f'install --upgrade {url}'
log.debug(f'Nunchaku: install="{url}"')
pip(cmd, ignore=False, uv=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)
return result.returncode == 0
else:
import torch
torch_ver = '.'.join(torch.__version__.split('+')[0].split('.')[:2])
cuda_ver = torch.__version__.split('+')[1]if '+' in torch.__version__ else None
cuda_ver = cuda_ver[:4] + '.' + cuda_ver[-1] if cuda_ver and len(cuda_ver) >= 4 else None
suffix = 'linux_x86_64' if arch == 'linux' else 'win_amd64'
if cuda_ver is None:
log.error(f'Nunchaku: torch={torch.__version__} cuda="unknown"')
return False
if cuda_ver.startswith('cu13'):
nunchaku_versions = ['1.2.1', '1.2.0', '1.1.0', '1.0.2', '1.0.1']
else:
nunchaku_versions = ['1.2.1', '1.0.2', '1.0.1'] # 1.2.0 and 1.1.0 imply cu13 but do not specify it
for v in nunchaku_versions:
url = f'https://github.com/nunchaku-ai/nunchaku/releases/download/v{v}/'
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)
if force:
log.debug(f'Nunchaku: url="{fn}" code={result.returncode} stdout={result.stdout} stderr={result.stderr} output={_output}')
if result.returncode == 0:
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)
if force:
log.debug(f'Nunchaku: url="{fn}" code={result.returncode} stdout={result.stdout} stderr={result.stderr} output={_output}')
if result.returncode == 0:
log.info(f'Nunchaku: install version={v} url="{url+fn}"')
return True
log.error(f'Nunchaku install failed: torch={torch.__version__} cuda={cuda_ver} python={python_ver} platform={arch}')
return False
if not check():
log.error('Nunchaku: install failed')
return False
return True
if __name__ == '__main__':
from modules.logger import setup_logging
setup_logging()
log.info('Nunchaku: manual install')
install_nunchaku(force=True)