mirror of
https://github.com/vladmandic/automatic
synced 2026-09-20 01:31:13 +02:00
Merge branch 'dev' into feat/ltx-tab-unification
This commit is contained in:
@@ -21,6 +21,7 @@ log_cost = {
|
||||
"/sdapi/v1/browser/thumb": -1,
|
||||
"/sdapi/v1/network/thumb": -1,
|
||||
"/run/predict": -1,
|
||||
"/queue/join": -1,
|
||||
"/internal/progress": -1,
|
||||
"/sdapi/v1/version": -1,
|
||||
"/sdapi/v1/log": -1,
|
||||
|
||||
+2
-1
@@ -1,7 +1,7 @@
|
||||
from modules.image.metadata import image_data, read_info_from_image
|
||||
from modules.image.save import save_image, sanitize_filename_part
|
||||
from modules.image.resize import resize_image
|
||||
from modules.image.namegen import FilenameGenerator
|
||||
from modules.image.namegen import FilenameGenerator, get_next_sequence_number
|
||||
from modules.image.grid import Grid, image_grid, check_grid_size, get_grid_size, draw_grid_annotations, draw_prompt_matrix, combine_grid, get_font
|
||||
|
||||
__all__ = [
|
||||
@@ -19,4 +19,5 @@ __all__ = [
|
||||
'sanitize_filename_part',
|
||||
'save_image',
|
||||
'get_font',
|
||||
'get_next_sequence_number',
|
||||
]
|
||||
|
||||
+21
-26
@@ -7,8 +7,7 @@ import fasteners
|
||||
import orjson
|
||||
from modules.logger import log
|
||||
|
||||
|
||||
locking_available = True # used by file read/write locking
|
||||
locking_available = True # used by file read/write locking
|
||||
|
||||
|
||||
@overload
|
||||
@@ -18,39 +17,42 @@ def readfile(filename: str, silent: bool = False, lock: bool = False, *, as_type
|
||||
@overload
|
||||
def readfile(filename: str, silent: bool = False, lock: bool = False) -> dict | list: ...
|
||||
def readfile(filename: str, silent: bool = False, lock: bool = False, *, as_type="") -> dict | list:
|
||||
global locking_available # pylint: disable=global-statement
|
||||
global locking_available # pylint: disable=global-statement
|
||||
data = {} if as_type == "dict" else []
|
||||
lock_file = None
|
||||
locked = False
|
||||
|
||||
if lock and locking_available:
|
||||
try:
|
||||
lock_file = fasteners.InterProcessReaderWriterLock(f"{filename}.lock")
|
||||
lock_file.logger.disabled = True # type: ignore - False positive. Bad typing in Fasteners.
|
||||
lock_file.logger.disabled = True # type: ignore - False positive. Bad typing in Fasteners.
|
||||
locked = lock_file.acquire_read_lock(blocking=True, timeout=3)
|
||||
except Exception as err:
|
||||
lock_file = None
|
||||
locking_available = False
|
||||
log.error(f'File read lock: file="{filename}" {err}')
|
||||
locked = False
|
||||
|
||||
try:
|
||||
# if not os.path.exists(filename):
|
||||
# return {}
|
||||
t0 = time.time()
|
||||
with open(filename, "rb") as file:
|
||||
b = file.read()
|
||||
data = orjson.loads(b) # pylint: disable=no-member
|
||||
data = orjson.loads(b) # pylint: disable=no-member
|
||||
# if type(data) is str:
|
||||
# data = json.loads(data)
|
||||
t1 = time.time()
|
||||
if not silent:
|
||||
fn = f'{sys._getframe(2).f_code.co_name}:{sys._getframe(1).f_code.co_name}' # pylint: disable=protected-access
|
||||
log.debug(f'Read: file="{filename}" json={len(data)} bytes={os.path.getsize(filename)} time={t1-t0:.3f} fn={fn}')
|
||||
fn = f"{sys._getframe(2).f_code.co_name}:{sys._getframe(1).f_code.co_name}" # pylint: disable=protected-access
|
||||
log.debug(f'Read: file="{filename}" json={len(data)} bytes={os.path.getsize(filename)} time={t1 - t0:.3f} fn={fn}')
|
||||
except FileNotFoundError as err:
|
||||
if not silent:
|
||||
log.debug(f'Read failed: file="{filename}" {err}')
|
||||
except Exception as err:
|
||||
if not silent:
|
||||
log.error(f'Read failed: file="{filename}" {err}')
|
||||
|
||||
try:
|
||||
if locking_available and lock_file is not None:
|
||||
lock_file.release_read_lock()
|
||||
@@ -58,6 +60,7 @@ def readfile(filename: str, silent: bool = False, lock: bool = False, *, as_type
|
||||
os.remove(f"{filename}.lock")
|
||||
except Exception:
|
||||
locking_available = False
|
||||
|
||||
if isinstance(data, list) and as_type == "dict":
|
||||
if not data:
|
||||
return {}
|
||||
@@ -74,9 +77,10 @@ def readfile(filename: str, silent: bool = False, lock: bool = False, *, as_type
|
||||
return data
|
||||
|
||||
|
||||
def writefile(obj, filename, mode='w', silent=False, atomic=False):
|
||||
def writefile(obj: dict | list, filename, mode="w", silent=False, atomic=False):
|
||||
import tempfile
|
||||
global locking_available # pylint: disable=global-statement
|
||||
|
||||
global locking_available # pylint: disable=global-statement
|
||||
lock_file = None
|
||||
locked = False
|
||||
|
||||
@@ -86,33 +90,23 @@ def writefile(obj, filename, mode='w', silent=False, atomic=False):
|
||||
|
||||
try:
|
||||
t0 = time.time()
|
||||
data = obj.copy()
|
||||
# skipkeys=True, ensure_ascii=True, check_circular=True, allow_nan=True
|
||||
if type(data) == dict:
|
||||
output = json.dumps(data, indent=2, default=default)
|
||||
elif type(data) == list:
|
||||
output = json.dumps(data, indent=2, default=default)
|
||||
elif isinstance(data, object):
|
||||
simple = {}
|
||||
for k in data.__dict__:
|
||||
if data.__dict__[k] is not None:
|
||||
simple[k] = data.__dict__[k]
|
||||
output = json.dumps(simple, indent=2, default=default)
|
||||
else:
|
||||
raise ValueError('not a valid object')
|
||||
data = obj.copy() # Ensure keys/items aren't added/deleted during json.dumps
|
||||
output = json.dumps(data, indent=2, default=default)
|
||||
except Exception as err:
|
||||
log.error(f'Save failed: file="{filename}" {err}')
|
||||
return
|
||||
|
||||
try:
|
||||
if locking_available:
|
||||
lock_file = fasteners.InterProcessReaderWriterLock(f"{filename}.lock") if locking_available else None
|
||||
lock_file.logger.disabled = True # type: ignore - False positive. Bad typing in Fasteners.
|
||||
lock_file.logger.disabled = True # type: ignore - False positive. Bad typing in Fasteners.
|
||||
locked = lock_file.acquire_write_lock(blocking=True, timeout=3) if lock_file is not None else False
|
||||
except Exception as err:
|
||||
locking_available = False
|
||||
lock_file = None
|
||||
log.error(f'File write lock: file="{filename}" {err}')
|
||||
locked = False
|
||||
|
||||
try:
|
||||
if atomic:
|
||||
with tempfile.NamedTemporaryFile(mode=mode, encoding="utf8", delete=False, dir=os.path.dirname(filename)) as f:
|
||||
@@ -125,10 +119,11 @@ def writefile(obj, filename, mode='w', silent=False, atomic=False):
|
||||
file.write(output)
|
||||
t1 = time.time()
|
||||
if not silent:
|
||||
datalength = len(data) if isinstance(data, (dict, list)) else (len(data.__dict__))
|
||||
log.debug(f'Save: file="{filename}" json={datalength} bytes={len(output)} time={t1-t0:.3f}')
|
||||
datalength = len(data)
|
||||
log.debug(f'Save: file="{filename}" json={datalength} bytes={len(output)} time={t1 - t0:.3f}')
|
||||
except Exception as err:
|
||||
log.error(f'Save failed: file="{filename}" {err}')
|
||||
|
||||
try:
|
||||
if locking_available and lock_file is not None:
|
||||
lock_file.release_write_lock()
|
||||
|
||||
@@ -4,6 +4,7 @@ import sys
|
||||
import time
|
||||
import gradio as gr
|
||||
import numpy as np
|
||||
import torch
|
||||
import cv2
|
||||
from PIL import Image, ImageFilter, ImageOps
|
||||
from transformers import SamModel, SamImageProcessor, MaskGenerationPipeline
|
||||
@@ -236,6 +237,8 @@ def run_segment(input_image: gr.Image, input_mask: np.ndarray):
|
||||
input_mask_size = np.count_nonzero(input_mask)
|
||||
debug(f'Segment SAM: {vars(opts)}')
|
||||
for mask, score in zip(outputs['masks'], outputs['scores'], strict=False):
|
||||
if isinstance(mask, torch.Tensor):
|
||||
mask = mask.cpu().numpy()
|
||||
mask = mask.astype('uint8')
|
||||
mask_size = np.count_nonzero(mask)
|
||||
if mask_size == 0:
|
||||
@@ -259,6 +262,9 @@ def run_segment(input_image: gr.Image, input_mask: np.ndarray):
|
||||
|
||||
def run_rembg(input_image: Image.Image, input_mask: np.ndarray):
|
||||
try:
|
||||
from installer import install
|
||||
for pkg in ["dctorch==0.1.2", "pymatting", "pooch", "rembg"]:
|
||||
install(pkg, no_deps=True, ignore=False)
|
||||
import rembg
|
||||
except Exception as e:
|
||||
log.error(f'Mask Rembg load failed: {e}')
|
||||
|
||||
+13
-5
@@ -18,6 +18,7 @@ def hf_init():
|
||||
os.environ.setdefault('HF_HUB_ETAG_TIMEOUT', '10')
|
||||
os.environ.setdefault('HF_ENABLE_PARALLEL_LOADING', 'true' if opts.sd_parallel_load else 'false')
|
||||
os.environ.setdefault('HF_HUB_CACHE', opts.hfcache_dir)
|
||||
os.environ.setdefault('HF_XET_CACHE', opts.xetcache_dir)
|
||||
if opts.hf_transfer_mode == 'requests':
|
||||
os.environ.setdefault('HF_XET_HIGH_PERFORMANCE', 'false')
|
||||
os.environ.setdefault('HF_HUB_ENABLE_HF_TRANSFER', 'false')
|
||||
@@ -42,14 +43,21 @@ def hf_init():
|
||||
|
||||
|
||||
def hf_check_cache():
|
||||
prev_default = os.environ.get("SD_HFCACHEDIR", None) or os.path.join(os.path.expanduser('~'), '.cache', 'huggingface', 'hub')
|
||||
from modules.modelstats import stat
|
||||
prev_default = os.environ.get("SD_HFCACHEDIR", None) or os.path.join(os.path.expanduser('~'), '.cache', 'huggingface', 'hub')
|
||||
if opts.hfcache_dir != prev_default:
|
||||
size, _mtime = stat(prev_default)
|
||||
if size//1024//1024 > 16:
|
||||
log.warning(f'Cache location changed: previous="{prev_default}" size={size//1024//1024} MB')
|
||||
size, _mtime = stat(opts.hfcache_dir)
|
||||
log.debug(f'Huggingface: cache="{opts.hfcache_dir}" size={size//1024//1024} MB')
|
||||
if size//1024//1024 > 32:
|
||||
log.warning(f'Huggingface cache changed: type=huggingface unused="{prev_default}" size={size//1024//1024} MB')
|
||||
prev_default = os.path.join(os.path.expanduser('~'), '.cache', 'huggingface', 'xet')
|
||||
if opts.xetcache_dir != prev_default:
|
||||
size, _mtime = stat(prev_default)
|
||||
if size//1024//1024 > 32:
|
||||
log.warning(f'Huggingface cache changed: type=xet unused="{prev_default}" size={size//1024//1024} MB')
|
||||
|
||||
hf_size, _mtime = stat(opts.hfcache_dir)
|
||||
xet_size, _mtime = stat(opts.xetcache_dir)
|
||||
log.debug(f'Huggingface: cache="{opts.hfcache_dir}" size={hf_size//1024//1024} MB xet="{opts.xetcache_dir}" size={xet_size//1024//1024} MB')
|
||||
|
||||
|
||||
def hf_search(keyword):
|
||||
|
||||
@@ -107,6 +107,7 @@ def create_paths(opts):
|
||||
create_path(fix_path('ckpt_dir'))
|
||||
create_path(fix_path('diffusers_dir'))
|
||||
create_path(fix_path('hfcache_dir'))
|
||||
create_path(fix_path('xetcache_dir'))
|
||||
create_path(fix_path('vae_dir'))
|
||||
create_path(fix_path('unet_dir'))
|
||||
create_path(fix_path('te_dir'))
|
||||
|
||||
@@ -12,16 +12,31 @@ import torch
|
||||
import triton
|
||||
import triton.language as tl
|
||||
|
||||
try:
|
||||
from .common import is_rdna2_and_older
|
||||
except Exception:
|
||||
is_rdna2_and_older = False
|
||||
|
||||
matmul_configs = [
|
||||
triton.Config({'BLOCK_SIZE_M': BM, 'BLOCK_SIZE_N': BN, "BLOCK_SIZE_K": BK, "GROUP_SIZE_M": GM}, num_warps=w, num_stages=s)
|
||||
for BM in [32, 64, 128, 256]
|
||||
for BN in [32, 64, 128, 256]
|
||||
for BK in [32, 64, 128]
|
||||
for GM in [4, 8]
|
||||
for w in [4, 8]
|
||||
for s in [2]
|
||||
]
|
||||
if is_rdna2_and_older:
|
||||
matmul_configs = [
|
||||
triton.Config({'BLOCK_SIZE_M': BM, 'BLOCK_SIZE_N': BN, "BLOCK_SIZE_K": BK, "GROUP_SIZE_M": GM}, num_warps=w, num_stages=s)
|
||||
for BM in [64, 128]
|
||||
for BN in [64, 128]
|
||||
for BK in [64]
|
||||
for GM in [2, 4]
|
||||
for w in [2, 4]
|
||||
for s in [2]
|
||||
]
|
||||
else:
|
||||
matmul_configs = [
|
||||
triton.Config({'BLOCK_SIZE_M': BM, 'BLOCK_SIZE_N': BN, "BLOCK_SIZE_K": BK, "GROUP_SIZE_M": GM}, num_warps=w, num_stages=s)
|
||||
for BM in [32, 64, 128, 256]
|
||||
for BN in [32, 64, 128, 256]
|
||||
for BK in [32, 64, 128]
|
||||
for GM in [4, 8]
|
||||
for w in [4, 8]
|
||||
for s in [2]
|
||||
]
|
||||
|
||||
|
||||
@triton.autotune(configs=matmul_configs, key=["M", "N", "K", "stride_bk", "ACCUMULATOR_DTYPE"], cache_results=True)
|
||||
|
||||
@@ -64,6 +64,7 @@ def create_settings(cmd_opts):
|
||||
|
||||
default_hfcache_dir = os.environ.get("SD_HFCACHEDIR", None) or os.path.join(paths.models_path, 'huggingface')
|
||||
default_checkpoint = list_checkpoint_titles()[0] if len(list_checkpoint_titles()) > 0 else "model.safetensors"
|
||||
default_xetcache_dir = os.environ.get("HF_XET_CACHE ", None) or os.path.join(paths.models_path, 'xet')
|
||||
|
||||
hide_dirs = {"visible": not cmd_opts.hide_ui_dir_config}
|
||||
|
||||
@@ -384,6 +385,7 @@ def create_settings(cmd_opts):
|
||||
"ckpt_dir": OptionInfo(os.path.join(paths.models_path, 'Stable-diffusion'), "Folder with stable diffusion models", folder=True),
|
||||
"diffusers_dir": OptionInfo(os.path.join(paths.models_path, 'Diffusers'), "Folder with Huggingface models", folder=True),
|
||||
"hfcache_dir": OptionInfo(default_hfcache_dir, "Folder for Huggingface cache", folder=True),
|
||||
"xetcache_dir": OptionInfo(default_xetcache_dir, "Folder for XET cache", folder=True),
|
||||
"tunable_dir": OptionInfo(os.path.join(paths.models_path, 'tunable'), "Folder for Tunable ops cache", folder=True),
|
||||
"vae_dir": OptionInfo(os.path.join(paths.models_path, 'VAE'), "Folder with VAE files", folder=True),
|
||||
"unet_dir": OptionInfo(os.path.join(paths.models_path, 'UNET'), "Folder with UNET files", folder=True),
|
||||
@@ -524,6 +526,23 @@ def create_settings(cmd_opts):
|
||||
"compact_view": OptionInfo(False, "Compact view"),
|
||||
"ui_columns": OptionInfo(4, "Gallery view columns", gr.Slider, {"minimum": 1, "maximum": 8, "step": 1}),
|
||||
|
||||
'uiux_separator_appearance': OptionInfo("<h2>Appearance</h2>", "", gr.HTML),
|
||||
"uiux_grid_image_size": OptionInfo(150, "Grid image size", gr.Slider, {"minimum": 64, "maximum": 1024, "step": 1}),
|
||||
"uiux_panel_min_width": OptionInfo(35, "Panel minimum width", gr.Number),
|
||||
"uiux_hide_legacy": OptionInfo(True, "Hide legacy tabs"),
|
||||
"uiux_persist_layout": OptionInfo(True, "Persist UI layout"),
|
||||
"uiux_no_slider_layout": OptionInfo(False, "Hide input range sliders"),
|
||||
"uiux_show_labels_aside": OptionInfo(False, "Show labels for aside tabs"),
|
||||
"uiux_show_labels_main": OptionInfo(False, "Show labels for main tabs"),
|
||||
"uiux_show_labels_tabs": OptionInfo(True, "Show labels for page tabs"),
|
||||
"uiux_show_input_range_ticks": OptionInfo(True, "Show ticks for input range slider", gr.Checkbox, {"visible": False}),
|
||||
"uiux_no_headers_params": OptionInfo(False, "Hide params headers", gr.Checkbox, {"visible": False}),
|
||||
"uiux_show_outline_params": OptionInfo(True, "Show parameter outline", gr.Checkbox, {"visible": False}),
|
||||
|
||||
'uiux_separator_mobile': OptionInfo("<h2>Mobile</h2>", "", gr.HTML),
|
||||
"uiux_default_layout": OptionInfo("Auto", "Layout", gr.Radio, {"choices": ["Auto","Desktop", "Mobile"]}),
|
||||
"uiux_mobile_scale": OptionInfo(0.7, "Mobile scale", gr.Slider, {"minimum": 0.5, "maximum": 1, "step": 0.05}),
|
||||
|
||||
"images_sep_log": OptionInfo("<h2>Log Display</h2>", "", gr.HTML),
|
||||
"logmonitor_show": OptionInfo(True, "Show log view"),
|
||||
"logmonitor_refresh_period": OptionInfo(5000, "Log view update period", gr.Slider, {"minimum": 0, "maximum": 30000, "step": 25}),
|
||||
|
||||
@@ -395,7 +395,7 @@ def create_html(search_text, sort_column):
|
||||
ext['status'] = 0
|
||||
style = "style='cursor: help;width: 1rem;margin: 0.2em;'"
|
||||
if ext['url'] is None or ext['url'] == '':
|
||||
status = f"<div title='Local'>{ui_symbols.svg_bullet.style('#00C0FD')}</div>"
|
||||
status = f"<div {style} title='Local'>{ui_symbols.svg_bullet.style('#00C0FD')}</div>"
|
||||
elif ext['status'] > 0:
|
||||
if ext['status'] == 1:
|
||||
status = f"<div {style} title='Verified'>{ui_symbols.svg_bullet.style('#00FD9C')}</div>"
|
||||
|
||||
@@ -8,7 +8,6 @@ import html
|
||||
import base64
|
||||
import urllib.parse
|
||||
import threading
|
||||
from typing import TYPE_CHECKING
|
||||
from types import SimpleNamespace
|
||||
from pathlib import Path
|
||||
from html.parser import HTMLParser
|
||||
@@ -134,7 +133,7 @@ class DateTimeEncoder(json.JSONEncoder):
|
||||
|
||||
|
||||
class ExtraNetworksPage:
|
||||
def __init__(self, title):
|
||||
def __init__(self, title: str):
|
||||
self.title = title
|
||||
self.name = title.lower()
|
||||
self.allow_negative_prompt = False
|
||||
@@ -198,7 +197,7 @@ class ExtraNetworksPage:
|
||||
errors.display(e, 'Network version')
|
||||
return all_versions[0]
|
||||
|
||||
def link_preview(self, filename):
|
||||
def link_preview(self, filename: str):
|
||||
quoted_filename = urllib.parse.quote(filename.replace('\\', '/'))
|
||||
mtime = os.path.getmtime(filename) if os.path.exists(filename) else 0
|
||||
preview = f"{shared.opts.subpath}/sdapi/v1/network/thumb?filename={quoted_filename}&mtime={mtime}"
|
||||
@@ -256,7 +255,7 @@ class ExtraNetworksPage:
|
||||
log.info(f'Network thumbnails: type={self.name} created={created}')
|
||||
self.missing_thumbs.clear()
|
||||
|
||||
def create_items(self, tabname):
|
||||
def create_items(self, tabname: str):
|
||||
if self.refresh_time is not None and self.refresh_time > refresh_time: # cached results
|
||||
return
|
||||
t0 = time.time()
|
||||
@@ -276,7 +275,7 @@ class ExtraNetworksPage:
|
||||
debug(f'EN create-items: page={self.name} items={len(self.items)} time={t1-t0:.2f}')
|
||||
self.list_time += t1-t0
|
||||
|
||||
def create_page(self, tabname, skip = False):
|
||||
def create_page(self, tabname: str, skip = False):
|
||||
debug(f'EN create-page: {self.name}')
|
||||
if self.page_time > refresh_time and len(self.html) > 0: # cached page
|
||||
return self.patch(self.html, tabname)
|
||||
@@ -388,7 +387,7 @@ class ExtraNetworksPage:
|
||||
def allowed_directories_for_previews(self):
|
||||
return []
|
||||
|
||||
def create_html(self, item, tabname):
|
||||
def create_html(self, item, tabname: str):
|
||||
def random_bright_color():
|
||||
r = random.randint(100, 255)
|
||||
g = random.randint(100, 255)
|
||||
@@ -429,7 +428,7 @@ class ExtraNetworksPage:
|
||||
errors.display(e, 'Networks')
|
||||
return ""
|
||||
|
||||
def find_preview_file(self, path):
|
||||
def find_preview_file(self, path: str | None):
|
||||
if path is None:
|
||||
return 'html/missing.png'
|
||||
if os.path.join('models', 'Reference') in path:
|
||||
@@ -450,7 +449,7 @@ class ExtraNetworksPage:
|
||||
return file
|
||||
return 'html/missing.png'
|
||||
|
||||
def find_preview(self, filename):
|
||||
def find_preview(self, filename: str):
|
||||
t0 = time.time()
|
||||
preview_file = self.find_preview_file(filename)
|
||||
self.preview_time += time.time() - t0
|
||||
@@ -503,7 +502,7 @@ class ExtraNetworksPage:
|
||||
debug(f'EN missing-preview: {item["name"]}')
|
||||
self.preview_time += time.time() - t0
|
||||
|
||||
def find_description(self, path, info=None):
|
||||
def find_description(self, path: str | None, info=None):
|
||||
t0 = time.time()
|
||||
class HTMLFilter(HTMLParser):
|
||||
text = ""
|
||||
@@ -535,7 +534,7 @@ class ExtraNetworksPage:
|
||||
self.desc_time += t1-t0
|
||||
return f.text
|
||||
|
||||
def find_info(self, path):
|
||||
def find_info(self, path: str | None):
|
||||
data = {}
|
||||
if shared.cmd_opts.no_metadata:
|
||||
return data
|
||||
@@ -594,7 +593,7 @@ def register_pages():
|
||||
register_page(ExtraNetworksPageTextualInversion())
|
||||
|
||||
|
||||
def get_pages(title=None):
|
||||
def get_pages(title: str | None = None):
|
||||
visible = shared.opts.extra_networks
|
||||
pages: list[ExtraNetworksPage] = []
|
||||
if 'All' in visible or visible == []: # default en sort order
|
||||
@@ -646,7 +645,7 @@ class ExtraNetworksUi:
|
||||
self.state: gr.State = None
|
||||
|
||||
|
||||
def create_ui(container, button_parent, tabname, skip_indexing = False):
|
||||
def create_ui(container, button_parent: gr.Button, tabname: str, skip_indexing = False):
|
||||
if 'networks' in shared.opts.ui_disabled:
|
||||
return None
|
||||
debug(f'EN create-ui: {tabname}')
|
||||
@@ -881,25 +880,19 @@ def create_ui(container, button_parent, tabname, skip_indexing = False):
|
||||
from modules import images
|
||||
page, item = get_item(state, params)
|
||||
is_style = (page is not None) and (page.title == 'Style')
|
||||
is_valid = (item is not None) and hasattr(item, 'name') and hasattr(item, 'filename')
|
||||
is_valid = False
|
||||
|
||||
if is_valid:
|
||||
if TYPE_CHECKING:
|
||||
assert item is not None # Part of the definition of "is_valid"
|
||||
if (item is not None) and hasattr(item, 'name') and hasattr(item, 'filename'):
|
||||
is_valid = True
|
||||
stat_size, stat_mtime = modelstats.stat(item.filename)
|
||||
if hasattr(item, 'size') and item.size > 0:
|
||||
stat_size = item.size
|
||||
if hasattr(item, 'mtime') and item.mtime is not None:
|
||||
stat_mtime = item.mtime
|
||||
desc = item.description
|
||||
fullinfo = shared.readfile(os.path.splitext(item.filename)[0] + '.json', silent=True, as_type="dict")
|
||||
if 'modelVersions' in fullinfo: # sanitize massive objects
|
||||
fullinfo['modelVersions'] = []
|
||||
info = fullinfo
|
||||
if isinstance(info, list):
|
||||
item.filename = None
|
||||
log.warning('Network: show details not supported for compound item')
|
||||
info = None
|
||||
info = shared.readfile(os.path.splitext(item.filename)[0] + '.json', silent=True, as_type="dict")
|
||||
if 'modelVersions' in info: # sanitize massive objects
|
||||
info['modelVersions'] = []
|
||||
if prompt is not None and len(prompt) > 0:
|
||||
item.prompt = prompt
|
||||
if negative is not None and len(negative) > 0:
|
||||
@@ -974,10 +967,12 @@ def create_ui(container, button_parent, tabname, skip_indexing = False):
|
||||
'''
|
||||
if item.name.startswith('Diffusers'):
|
||||
url = item.name.replace('Diffusers/', '')
|
||||
url = f'<a href="https://huggingface.co/{url}" target="_blank">https://huggingface.co/models/{url}</a>' if url is not None else 'N/A'
|
||||
url = f'<a href="https://huggingface.co/{url}" target="_blank">https://huggingface.co/models/{url}</a>'
|
||||
else:
|
||||
url = info.get('id', None) if info is not None else None
|
||||
url = f'<a href="https://civitai.com/models/{url}" target="_blank">civitai.com/models/{url}</a>' if url is not None else 'N/A'
|
||||
info_id = info.get('id', None)
|
||||
nsfw = info.get('nsfw', False) if info_id is not None else False
|
||||
tld = "red" if nsfw else "com"
|
||||
url = f'<a href="https://civitai.{tld}/models/{info_id}" target="_blank">civitai.{tld}/models/{info_id}</a>' if info_id is not None else 'N/A'
|
||||
text = f'''
|
||||
<h2 style="border-bottom: 1px solid var(--button-primary-border-color); margin: 0em 0px 1em 0 !important">{item.name}</h2>
|
||||
<table style="width: 100%; line-height: 1.5em;"><tbody>
|
||||
|
||||
Reference in New Issue
Block a user