model metadata handle invalid keys

Signed-off-by: Vladimir Mandic <mandic00@live.com>
This commit is contained in:
Vladimir Mandic
2026-06-29 11:23:29 +02:00
parent 825b714753
commit 7c228892cf
6 changed files with 54 additions and 29 deletions
+18 -17
View File
@@ -34,23 +34,24 @@ Plus new **Krea 2** model and **SDNQ** improvements: now with *NPU* support and
- **Internal**
- delay init of video models
- **Fixes**
- `sdnq` warn instead of error for triton
- `insightface` missing dependencies
- `pulid` import paths
- `processors` init code and multiple fixes
- `live preview` configurable pause when not in focus, thanks @Artheriax
- `mps` install `torchsde` as requirement
- `vae` scale factor improved detection
- `ui` networks details scrollbars
- `onnxruntime` handle invalid version
- `onnxruntime` mark all import paths as non-critical
- `measure` handle current kanvas stage
- `caption` button in standard-ui
- `python` experimental/ignore version checks
- `hipBLASLt` improved detection, thanks @0xDELUXA
- `embeddings` handle textual-inversion with new transformers
- `options` handle compatibility options
- `log` strip ansi sequences from ring buffer and client side logging
- sdnq: warn instead of error for triton
- insightface: missing dependencies
- pulid: import paths
- processors: init code and multiple fixes
- live preview: configurable pause when not in focus, thanks @Artheriax
- mps: install `torchsde` as requirement
- vae: scale factor improved detection
- ui: networks details scrollbars
- onnxruntime: handle invalid version
- onnxruntime: mark all import paths as non-critical
- measure: handle current kanvas stage
- caption: button in standard-ui
- python: experimental/ignore version checks
- hipBLASLt: improved detection, thanks @0xDELUXA
- embeddings: handle textual-inversion with new transformers
- options: handle compatibility options
- log: strip ansi sequences from ring buffer and client side logging
- model metadata: handle invalid metadata and strip workflows
## Update for 2026-06-16
+2 -2
View File
@@ -538,7 +538,7 @@ def check_diffusers():
t_start = time.time()
if args.skip_all:
return
target_commit = "9d52996c4dd46a1a075d2a8fa32432857a6705e5" # diffusers commit hash == 0.39.0.dev0 == 06-15-2026
target_commit = "ea802951f5fb235b6af8fe9247f56187d49748b2" # diffusers commit hash == 0.39.0.dev0 == 06-29-2026
# if args.use_rocm or args.use_zluda or args.use_directml:
# sha = '043ab2520f6a19fce78e6e060a68dbc947edb9f9' # lock diffusers versions for now
pkg = package_spec('diffusers')
@@ -568,7 +568,7 @@ def check_transformers():
pkg_tokenizers = package_spec('tokenizers')
# target_commit = '753d61104116eefc8ffc977327b441ee0c8d599f' # transformers commit hash == 4.57.6
# target_commit = "380e3cc5d59912a48508cb6d4959a31cd460e12e" # transformers commit hash == 5.5.0.dev-0409
target_commit = "d242bb790bcbbe6c9a20e46cf9d70648739a90bf" # transformers commit hash == 5.13.0.dev0 == 06-15-2026
target_commit = "d9e7791b129797be80ca7b3b0bf2a53cda0d4b8c" # transformers commit hash == 5.13.0.dev0 == 06-29-2026
if args.use_directml:
target_transformers = '4.52.4'
target_tokenizers = '0.21.4'
+12 -2
View File
@@ -39,6 +39,8 @@ def readfile(filename: str | os.PathLike[str], silent: bool = False, lock: bool
t0 = time.time()
with open(filename, "rb") as file:
b = file.read()
if len(b) == 0:
return {} if as_type == "dict" else []
data = orjson.loads(b) # pylint: disable=no-member
# if type(data) is str:
# data = json.loads(data)
@@ -78,9 +80,10 @@ def readfile(filename: str | os.PathLike[str], silent: bool = False, lock: bool
def writefile(obj: dict | list, filename: str | os.PathLike[str], mode="w", silent=False, atomic=False):
import copy
import tempfile
global locking_available # pylint: disable=global-statement
global locking_available # pylint: disable=global-statement
lock_file = None
locked = False
@@ -90,7 +93,14 @@ def writefile(obj: dict | list, filename: str | os.PathLike[str], mode="w", sile
try:
t0 = time.time()
data = obj.copy() # Ensure keys/items aren't added/deleted during json.dumps
data = copy.deepcopy(obj) # ensure keys/items aren't added/deleted during json.dumps
for k, v in obj.items() if isinstance(obj, dict) else []: # validate each key-by-key to avoid global exceptions
try:
_tmp = json.dumps(v, indent=2, default=default, allow_nan=False, ensure_ascii=False)
except Exception as err:
if not silent:
log.error(f'Save: file="{filename}" key="{k}" value="{v}" {err}')
del data[k]
output = json.dumps(data, indent=2, default=default)
except Exception as err:
log.error(f'Save failed: file="{filename}" {err}')
+18 -5
View File
@@ -383,7 +383,8 @@ def read_metadata_from_safetensors(filename: str):
return res
json_data = json_start + file.read(metadata_len-2)
json_obj = json.loads(json_data)
for k, v in json_obj.get("__metadata__", {}).items():
json_dct = json_obj.get("__metadata__", {})
for k, v in json_dct.items():
if k == 'modelspec.thumbnail' and v.startswith("data:"):
extract_thumbnail(filename, v)
if v.startswith("data:"):
@@ -391,7 +392,12 @@ def read_metadata_from_safetensors(filename: str):
if k == 'format' and v == 'pt':
continue
large = True if len(v) > 2048 else False
if large and k in ['ss_datasets', 'workflow', 'prompt', 'ss_bucket_info', 'sd_metadata_file']:
if large and k in ['ss_datasets', 'prompt', 'ss_bucket_info', 'sd_metadata_file']:
continue
if k in ['workflow']:
res[k] = 'workflow'
continue
if str(v) == 'NaN':
continue
if v[0:1] == '{':
try:
@@ -402,7 +408,14 @@ def read_metadata_from_safetensors(filename: str):
scrub_dict(v, ['sd_merge_recipe'])
except Exception:
pass
res[k] = v
if isinstance(v, dict):
try:
_tmp = json.dumps(v, indent=2, default=str, allow_nan=False, ensure_ascii=False)
except Exception:
# log.warning(f'Model metadata: file="{filename}" key="{k}" value="{v}" not serializable')
continue
if v is not None:
res[k] = v
except Exception as e:
log.error(f'Model metadata: file="{filename}" {e}')
from modules import errors
@@ -434,6 +447,6 @@ def write_metadata():
if sd_metadata_pending == 0:
log.debug(f'Model metadata: file="{sd_metadata_file}" no changes')
return
writefile(sd_metadata, sd_metadata_file)
log.info(f'Model metadata saved: file="{sd_metadata_file}" items={sd_metadata_pending} time={sd_metadata_timer:.2f}')
writefile(sd_metadata, sd_metadata_file, silent=True)
log.info(f'Model metadata: file="{sd_metadata_file}" added={sd_metadata_pending} time={sd_metadata_timer:.2f}')
sd_metadata_pending = 0
+1 -1
View File
@@ -27,7 +27,7 @@ safetensors==0.8.0
peft==0.19.1
httpx==0.28.1
requests==2.34.2
tqdm==4.68.2
tqdm==4.68.3
accelerate==1.14.0
einops==0.8.2
huggingface_hub==1.21.0
+3 -2
View File
@@ -92,8 +92,6 @@ def initialize():
def _scan_models():
modules.modelloader.cleanup_models()
modules.sd_checkpoint.setup_model()
from modules.sd_checkpoint import write_metadata
write_metadata()
def _scan_lora():
from modules.lora import lora_load
lora_load.list_available_networks()
@@ -109,6 +107,9 @@ def initialize():
future.result()
except Exception as e:
log.error(f'Scan error: {name} {e}')
from modules.sd_checkpoint import write_metadata
write_metadata()
timer.startup.record("scans")
shared.prompt_styles.reload()