add offline mode

Signed-off-by: Vladimir Mandic <mandic00@live.com>
This commit is contained in:
Vladimir Mandic
2025-10-19 09:33:49 -04:00
parent 9d4cf3db94
commit 281db94625
6 changed files with 52 additions and 10 deletions
+13
View File
@@ -1,5 +1,18 @@
# Change Log for SD.Next
## Update for 2025-10-19
- **Features**
- **offline mode**: enable in *settings -> hugginface*
enables fully offline mode where previously downloaded models are used as-is
- **Backend**
- switch to `torch==2.9` for *ipex, rocm and openvino*
- switch to `rocm==7.0` for nightlies
- **Quantization**
- improved SDNQ SVD and low-bit matmul performance
- **Fixes**
- startup error with `--profile` enabled if using `--skip`
## Update for 2025-10-18
- **Models**
+8 -3
View File
@@ -1496,12 +1496,17 @@ def check_venv():
# check version of the main repo and optionally upgrade it
def check_version(offline=False, reset=True): # pylint: disable=unused-argument
def check_version(reset=True): # pylint: disable=unused-argument
if opts.get('offline_mode', False):
log.warning('Offline mode enabled')
args.skip_git = True # pylint: disable=attribute-defined-outside-init
args.skip_all = True # pylint: disable=attribute-defined-outside-init
return
t_start = time.time()
if args.skip_all:
return
if not os.path.exists('.git'):
log.warning('Not a git repository, all git operations are disabled')
log.warning('Not a git repository')
args.skip_git = True # pylint: disable=attribute-defined-outside-init
ver = get_version()
log.info(f'Version: {print_dict(ver)}')
@@ -1538,7 +1543,7 @@ def check_version(offline=False, reset=True): # pylint: disable=unused-argument
else:
log.warning('Repository: retrying upgrade...')
git_reset()
check_version(offline=offline, reset=False)
check_version(reset=False)
else:
dt = commits["commit"]["commit"]["author"]["date"]
commit = commits["commit"]["sha"][:8]
+4 -1
View File
@@ -20,6 +20,8 @@ pbar = None
def hf_login(token=None):
if shared.opts.offline_mode:
return False
global loggedin # pylint: disable=global-statement
token = token or shared.opts.huggingface_token
token = token.replace("\n", "").replace("\r", "").strip() if token is not None else None
@@ -38,7 +40,8 @@ def hf_login(token=None):
if loggedin != token:
stdout = io.StringIO()
try:
hf.logout()
with contextlib.redirect_stdout(stdout):
hf.logout()
except Exception:
pass
with contextlib.redirect_stdout(stdout):
+15 -5
View File
@@ -657,6 +657,15 @@ def load_diffuser(checkpoint_info=None, op='model', revision=None): # pylint: di
unload_model_weights(op=op)
return
# handle offline mode
if shared.opts.offline_mode:
shared.log.info(f'Load {op}: offline=True')
diffusers_load_config["local_files_only"] = True
os.environ['HF_HUB_OFFLINE'] = '1'
else:
os.environ.pop('HF_HUB_OFFLINE', None)
os.unsetenv('HF_HUB_OFFLINE')
# detect pipeline
pipeline, model_type = sd_detect.detect_pipeline(checkpoint_info.path, op)
set_huggingface_options()
@@ -1247,14 +1256,15 @@ def unload_model_weights(op='model'):
def hf_auth_check(checkpoint_info, force:bool=False):
if shared.opts.offline_mode:
shared.log.info('Offline mode: skipping auth check')
return False
login = None
if not force:
try:
# skip check for single-file safetensors models
if (checkpoint_info.path.endswith('.safetensors') and os.path.isfile(checkpoint_info.path)):
if (checkpoint_info.path.endswith('.safetensors') and os.path.isfile(checkpoint_info.path)): # skip check for single-file safetensors models
return True
# skip check for local diffusers folders
if (os.path.exists(checkpoint_info.path) and os.path.isdir(checkpoint_info.path) and os.path.isfile(os.path.join(checkpoint_info.path, 'model_index.json'))):
if (os.path.exists(checkpoint_info.path) and os.path.isdir(checkpoint_info.path) and os.path.isfile(os.path.join(checkpoint_info.path, 'model_index.json'))): # skip check for local diffusers folders
return True
except Exception:
pass
@@ -1263,7 +1273,7 @@ def hf_auth_check(checkpoint_info, force:bool=False):
login = modelloader.hf_login()
return hf.auth_check(repo_id)
except Exception as e:
shared.log.error(f'Load model: repo="{repo_id}" login={login} {e}')
shared.log.error(f'Auth: repo="{repo_id}" login={login} {e}')
return False
+1
View File
@@ -689,6 +689,7 @@ options_templates.update(options_section(('huggingface', "Huggingface"), {
"huggingface_token": OptionInfo('', 'HuggingFace token', gr.Textbox, {"lines": 2}),
"hf_transfer_mode": OptionInfo("rust", "HuggingFace download method", gr.Radio, {"choices": ['requests', 'rust', 'xet']}),
"huggingface_mirror": OptionInfo('', 'HuggingFace mirror', gr.Textbox),
"offline_mode": OptionInfo(False, 'Force offline mode', gr.Checkbox),
"diffusers_model_load_variant": OptionInfo("default", "Preferred Model variant", gr.Radio, {"choices": ['default', 'fp32', 'fp16']}),
"diffusers_vae_load_variant": OptionInfo("default", "Preferred VAE variant", gr.Radio, {"choices": ['default', 'fp32', 'fp16']}),
+11 -1
View File
@@ -37,12 +37,15 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage):
if not shared.opts.sd_checkpoint_autodownload or not shared.opts.extra_network_reference_enable:
return []
count = { 'total': 0, 'ready': 0, 'hidden': 0, 'experimental': 0 }
for k, v in shared.reference_models.items():
count['total'] += 1
url = v['path']
experimental = v.get('experimental', False)
if experimental:
if shared.cmd_opts.experimental:
shared.log.debug(f'Networks: experimental model="{k}"')
count['experimental'] += 1
else:
continue
preview = v.get('preview', v['path'])
@@ -61,6 +64,12 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage):
path = f'{v.get("path", "")}+{v.get("subfolder", "")}'
else:
path = f'{v.get("path", "")}'
ready = reference_downloaded(url)
if not ready and shared.opts.offline_mode:
count['hidden'] += 1
continue
if ready:
count['ready'] += 1
yield {
"type": 'Model',
"name": name,
@@ -75,8 +84,9 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage):
"info": {},
"metadata": {},
"description": v.get('desc', ''),
"version": "ready" if reference_downloaded(url) else "download",
"version": "ready" if ready else "download",
}
shared.log.debug(f'Networks: type="reference" items={count["total"]} ready={count["ready"]} hidden={count["hidden"]} experimental={count["experimental"]}')
def create_item(self, name):
record = None