diff --git a/CHANGELOG.md b/CHANGELOG.md index b813f4591..89bb9c62e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,7 @@ TBD - refactor: switch from deprecated `pkg_resources` to `importlib` - refactor: modernize typing and type annotations - refactor: improve `pydantic==2.x` compatibility + - refactor: entire logging into separate `modules/logger` - update `lint` rules, thanks @awsr - remove requirements: `clip`, `open-clip` - update `requirements` diff --git a/installer.py b/installer.py index e8e2fbe72..aa82b6ead 100644 --- a/installer.py +++ b/installer.py @@ -13,6 +13,7 @@ import cProfile import importlib import importlib.util import importlib.metadata +from modules.logger import setup_logging, get_console, get_log, install_traceback, log, console class Dot(dict): # dot notation access to dictionary attributes @@ -30,8 +31,6 @@ version = { } setuptools, distutils = None, None # defined via ensure_base_requirements current_branch = None -log = logging.getLogger("sd") -console = None debug = log.debug if os.environ.get('SD_INSTALL_DEBUG', None) is not None else lambda *args, **kwargs: None pip_log = '--log pip.log ' if os.environ.get('SD_PIP_DEBUG', None) is not None else '' log_file = os.path.join(os.path.dirname(__file__), 'sdnext.log') @@ -86,232 +85,7 @@ except Exception: elapsed = lambda *args, **kwargs: None # pylint: disable=unnecessary-lambda-assignment -def get_console(): - return console - - -def get_log(): - return log - - -@overload -def str_to_bool(val: str | bool) -> bool: ... -@overload -def str_to_bool(val: None) -> None: ... -def str_to_bool(val: str | bool | None) -> bool | None: - if isinstance(val, str): - if val.strip() and val.strip().lower() in ("1", "true"): - return True - return False - return val - - -def install_traceback(suppress: list = None): - from rich.traceback import install as traceback_install - from rich.pretty import install as pretty_install - - if suppress is None: - suppress = [] - width = os.environ.get("SD_TRACEWIDTH", console.width if console else None) - if width is not None: - width = int(width) - log.excepthook = traceback_install( - console=console, - extra_lines=int(os.environ.get("SD_TRACELINES", 1)), - max_frames=int(os.environ.get("SD_TRACEFRAMES", 16)), - width=width, - word_wrap=str_to_bool(os.environ.get("SD_TRACEWRAP", False)), - indent_guides=str_to_bool(os.environ.get("SD_TRACEINDENT", False)), - show_locals=str_to_bool(os.environ.get("SD_TRACELOCALS", False)), - locals_hide_dunder=str_to_bool(os.environ.get("SD_TRACEDUNDER", True)), - locals_hide_sunder=str_to_bool(os.environ.get("SD_TRACESUNDER", None)), - suppress=suppress, - ) - pretty_install(console=console) - - -# setup console and file logging -def setup_logging(): - from functools import partial, partialmethod - from logging.handlers import RotatingFileHandler - try: - pass # pylint: disable=unused-import - except Exception: - log.error('Please restart SD.Next so changes take effect') - sys.exit(1) - from rich.theme import Theme - from rich.logging import RichHandler - from rich.console import Console - from rich.padding import Padding - from rich.segment import Segment - from rich import box - from rich import print as rprint - from rich.pretty import install as pretty_install - - class RingBuffer(logging.StreamHandler): - def __init__(self, capacity): - super().__init__() - self.capacity = capacity - self.buffer = [] - self.formatter = logging.Formatter('{ "asctime":"%(asctime)s", "created":%(created)f, "facility":"%(name)s", "pid":%(process)d, "tid":%(thread)d, "level":"%(levelname)s", "module":"%(module)s", "func":"%(funcName)s", "msg":"%(message)s" }') - - def emit(self, record): - if record.msg is not None and not isinstance(record.msg, str): - record.msg = str(record.msg) - try: - record.msg = record.msg.replace('"', "'") - except Exception: - pass - msg = self.format(record) - # self.buffer.append(json.loads(msg)) - self.buffer.append(msg) - if len(self.buffer) > self.capacity: - self.buffer.pop(0) - - def get(self): - return self.buffer - - class LogFilter(logging.Filter): - def __init__(self): - super().__init__() - - def filter(self, record): - return len(record.getMessage()) > 2 - - def override_padding(self, console, options): # pylint: disable=redefined-outer-name - style = console.get_style(self.style) - width = options.max_width - self.left = 0 - render_options = options.update_width(width - self.left - self.right) - if render_options.height is not None: - render_options = render_options.update_height(height=render_options.height - self.top - self.bottom) - lines = console.render_lines(self.renderable, render_options, style=style, pad=False) - _Segment = Segment - left = _Segment(" " * self.left, style) if self.left else None - right = [_Segment.line()] - blank_line: list[Segment] | None = None - if self.top: - blank_line = [_Segment(f'{" " * width}\n', style)] - yield from blank_line * self.top - if left: - for line in lines: - yield left - yield from line - yield from right - else: - for line in lines: - yield from line - yield from right - if self.bottom: - blank_line = blank_line or [_Segment(f'{" " * width}\n', style)] - yield from blank_line * self.bottom - - t_start = time.time() - - if args.log: - global log_file # pylint: disable=global-statement - log_file = args.log - - logging.TRACE = 25 - logging.addLevelName(logging.TRACE, 'TRACE') - logging.Logger.trace = partialmethod(logging.Logger.log, logging.TRACE) - logging.trace = partial(logging.log, logging.TRACE) - - def exception_hook(e: Exception, suppress=None): - from rich.traceback import Traceback - if suppress is None: - suppress = [] - tb = Traceback.from_exception(type(e), e, e.__traceback__, show_locals=False, max_frames=16, extra_lines=1, suppress=suppress, theme="ansi_dark", word_wrap=False, width=console.width) - # print-to-console, does not get printed-to-file - exc_type, exc_value, exc_traceback = sys.exc_info() - log.excepthook(exc_type, exc_value, exc_traceback) - # print-to-file, temporarily disable-console-handler - for handler in log.handlers.copy(): - if isinstance(handler, RichHandler): - log.removeHandler(handler) - with console.capture() as capture: - console.print(tb) - log.critical(capture.get()) - log.addHandler(rh) - - log.traceback = exception_hook - - level = logging.DEBUG if (args.debug or args.trace) else logging.INFO - log.setLevel(logging.DEBUG) # log to file is always at level debug for facility `sd` - log.print = rprint - global console # pylint: disable=global-statement - theme = Theme({ - "traceback.border": "black", - "inspect.value.border": "black", - "traceback.border.syntax_error": "dark_red", - "logging.level.info": "blue_violet", - "logging.level.debug": "purple4", - "logging.level.trace": "dark_blue", - }) - - Padding.__rich_console__ = override_padding - box.ROUNDED = box.SIMPLE - console = Console( - log_time=True, - log_time_format='%H:%M:%S-%f', - tab_size=4, - soft_wrap=True, - safe_box=True, - theme=theme, - ) - - logging.basicConfig(level=logging.ERROR, format='%(asctime)s | %(name)s | %(levelname)s | %(module)s | %(message)s', handlers=[logging.NullHandler()]) # redirect default logger to null - - pretty_install(console=console) - install_traceback() - - while log.hasHandlers() and len(log.handlers) > 0: - log.removeHandler(log.handlers[0]) - - log_filter = LogFilter() - # handlers - rh = RichHandler(show_time=True, omit_repeated_times=False, show_level=True, show_path=False, markup=False, rich_tracebacks=True, log_time_format='%H:%M:%S-%f', level=level, console=console) - if args.trace: - rh.formatter = logging.Formatter('[%(module)s][%(pathname)s:%(lineno)d] %(message)s') - rh.addFilter(log_filter) - rh.setLevel(level) - log.addHandler(rh) - - fh = RotatingFileHandler(log_file, maxBytes=32*1024*1024, backupCount=9, encoding='utf-8', delay=True) # 10MB default for log rotation - if args.trace: - fh.formatter = logging.Formatter(f'%(asctime)s | {hostname} | %(name)s | %(levelname)s | %(module)s | | %(pathname)s:%(lineno)d | %(message)s') - else: - fh.formatter = logging.Formatter(f'%(asctime)s | {hostname} | %(name)s | %(levelname)s | %(module)s | %(message)s') - fh.addFilter(log_filter) - fh.setLevel(logging.DEBUG) - log.addHandler(fh) - global log_rolled # pylint: disable=global-statement - if not log_rolled and args.debug and not args.log: - try: - fh.doRollover() - except Exception: - pass - log_rolled = True - - rb = RingBuffer(100) # 100 entries default in log ring buffer - rb.addFilter(log_filter) - rb.setLevel(level) - log.addHandler(rb) - log.buffer = rb.buffer - - def quiet_log(quiet: bool=False, *args, **kwargs): # pylint: disable=redefined-outer-name,keyword-arg-before-vararg - if not quiet: - log.debug(*args, **kwargs) - log.quiet = quiet_log - - # overrides - logging.getLogger("urllib3").setLevel(logging.ERROR) - logging.getLogger("httpx").setLevel(logging.ERROR) - logging.getLogger("diffusers").setLevel(logging.ERROR) - logging.getLogger("torch").setLevel(logging.ERROR) - logging.getLogger("ControlNet").handlers = log.handlers - logging.getLogger("lycoris").handlers = log.handlers - ts('log', t_start) +# setup console and file logging is imported from modules.logger def get_logfile(): diff --git a/launch.py b/launch.py index 3ba43ef5b..997a68021 100755 --- a/launch.py +++ b/launch.py @@ -1,5 +1,6 @@ #!/usr/bin/env python +from modules import logger import os import sys import time @@ -9,7 +10,7 @@ from functools import lru_cache import installer -debug_install = installer.log.debug if os.environ.get('SD_INSTALL_DEBUG', None) is not None else lambda *args, **kwargs: None +debug_install = logger.log.debug if os.environ.get('SD_INSTALL_DEBUG', None) is not None else lambda *args, **kwargs: None commandline_args = os.environ.get('COMMANDLINE_ARGS', "") sys.argv += shlex.split(commandline_args) args = None @@ -58,17 +59,17 @@ def get_custom_args(): current = getattr(args, arg) if current != default: custom[arg] = getattr(args, arg) - installer.log.info(f'Command line args: {sys.argv[1:]} {installer.print_dict(custom)}') + logger.log.info(f'Command line args: {sys.argv[1:]} {installer.print_dict(custom)}') if os.environ.get('SD_ENV_DEBUG', None) is not None: env = os.environ.copy() if 'PATH' in env: del env['PATH'] if 'PS1' in env: del env['PS1'] - installer.log.trace(f'Environment: {installer.print_dict(env)}') + logger.log.trace(f'Environment: {installer.print_dict(env)}') env = [f'{k}={v}' for k, v in os.environ.items() if k.startswith('SD_')] ld = [f'{k}={v}' for k, v in os.environ.items() if k.startswith('LD_')] - installer.log.debug(f'Flags: sd={env} ld={ld}') + logger.log.debug(f'Flags: sd={env} ld={ld}') rec('args') @@ -88,7 +89,7 @@ def commit_hash(): # compatbility function @lru_cache def run(command, desc=None, errdesc=None, custom_env=None, live=False): # compatbility function if desc is not None: - installer.log.info(desc) + logger.log.info(desc) if live: result = subprocess.run(command, check=False, shell=True, env=os.environ if custom_env is None else custom_env) if result.returncode != 0: @@ -183,9 +184,9 @@ def clean_server(): modules_sorted = {} for module_key in modules_keys: modules_sorted[module_key] = len([m for m in modules_cleaned if m.startswith(module_key)]) - installer.log.trace(f'Server modules: {modules_sorted}') + logger.log.trace(f'Server modules: {modules_sorted}') t1 = time.time() - installer.log.trace(f'Server modules: total={len(modules_loaded)} unloaded={len(removed_removed)} remaining={len(modules_cleaned)} gc={collected} time={t1-t0:.2f}') + logger.log.trace(f'Server modules: total={len(modules_loaded)} unloaded={len(removed_removed)} remaining={len(modules_cleaned)} gc={collected} time={t1-t0:.2f}') def start_server(immediate=True, server=None): @@ -202,20 +203,20 @@ def start_server(immediate=True, server=None): if not immediate: time.sleep(3) if collected > 0: - installer.log.debug(f'Memory: {get_memory_stats()} collected={collected}') + logger.log.debug(f'Memory: {get_memory_stats()} collected={collected}') module_spec = importlib.util.spec_from_file_location('webui', 'webui.py') server = importlib.util.module_from_spec(module_spec) - installer.log.debug(f'Starting module: {server}') + logger.log.debug(f'Starting module: {server}') module_spec.loader.exec_module(server) uvicorn = None if args.test: - installer.log.info("Test only") - installer.log.critical('Logging: level=critical') - installer.log.error('Logging: level=error') - installer.log.warning('Logging: level=warning') - installer.log.info('Logging: level=info') - installer.log.debug('Logging: level=debug') - installer.log.trace('Logging: level=trace') + logger.log.info("Test only") + logger.log.critical('Logging: level=critical') + logger.log.error('Logging: level=error') + logger.log.warning('Logging: level=warning') + logger.log.info('Logging: level=info') + logger.log.debug('Logging: level=debug') + logger.log.trace('Logging: level=trace') server.wants_restart = False else: uvicorn = server.webui(restart=not immediate) @@ -231,8 +232,8 @@ def main(): installer.ensure_base_requirements() init_args() # setup argparser and default folders installer.args = args - installer.setup_logging() - installer.log.info('Starting SD.Next') + installer.setup_logging(debug=args.debug, trace=args.trace, log_filename=args.log) + logger.log.info('Starting SD.Next') installer.get_logfile() try: sys.excepthook = installer.custom_excepthook @@ -245,10 +246,10 @@ def main(): if args.reset: installer.git_reset() if args.skip_git or args.skip_all: - installer.log.info('Skipping GIT operations') - installer.log.info(f'Platform: {installer.print_dict(installer.get_platform())}') + logger.log.info('Skipping GIT operations') + logger.log.info(f'Platform: {installer.print_dict(installer.get_platform())}') installer.check_venv() - installer.log.info(f'Args: {sys.argv[1:]}') + logger.log.info(f'Args: {sys.argv[1:]}') if not args.skip_env or args.skip_all: installer.set_environment() if args.uv: @@ -259,42 +260,42 @@ def main(): installer.check_transformers() installer.check_diffusers() if args.test: - installer.log.info('Startup: test mode') + logger.log.info('Startup: test mode') installer.quick_allowed = False if args.reinstall: - installer.log.info('Startup: force reinstall of all packages') + logger.log.info('Startup: force reinstall of all packages') installer.quick_allowed = False if args.skip_all: - installer.log.info('Startup: skip all') + logger.log.info('Startup: skip all') installer.quick_allowed = True init_paths() else: installer.install_requirements() if installer.check_timestamp(): - installer.log.info('Startup: quick launch') + logger.log.info('Startup: quick launch') init_paths() installer.check_extensions() else: - installer.log.info('Startup: standard') + logger.log.info('Startup: standard') installer.install_submodules() init_paths() installer.install_extensions() installer.install_requirements() # redo requirements since extensions may change them if len(installer.errors) == 0: - installer.log.debug(f'Setup complete without errors: {round(time.time())}') + logger.log.debug(f'Setup complete without errors: {round(time.time())}') else: - installer.log.warning(f'Setup complete with errors: {installer.errors}') - installer.log.warning(f'See log file for more details: {installer.log_file}') + logger.log.warning(f'Setup complete with errors: {installer.errors}') + logger.log.warning(f'See log file for more details: {logger.log_file}') installer.extensions_preload(parser) # adds additional args from extensions args = installer.parse_args(parser) - installer.log.info(f'Installer time: {init_summary()}') + logger.log.info(f'Installer time: {init_summary()}') get_custom_args() import threading threading.Thread(target=installer.run_deferred_tasks, daemon=True).start() uv, instance = start_server(immediate=True, server=None) if installer.restart_required: - installer.log.warning('Restart is recommended due to packages updates...') + logger.log.warning('Restart is recommended due to packages updates...') t_server = time.time() t_monitor = time.time() while True: @@ -308,19 +309,19 @@ def main(): if float(args.status) > 0 and (t_current - t_server) > float(args.status): s = instance.state.status() if (s.timestamp is None) or (s.step == 0): # dont spam during active job - installer.log.trace(f'Server: alive={alive} requests={requests} memory={get_memory_stats()} {s}') + logger.log.trace(f'Server: alive={alive} requests={requests} memory={get_memory_stats()} {s}') t_server = t_current if float(args.monitor) > 0 and t_current - t_monitor > float(args.monitor): - installer.log.trace(f'Monitor: {get_memory_stats(detailed=True)}') + logger.log.trace(f'Monitor: {get_memory_stats(detailed=True)}') t_monitor = t_current if not alive: if uv is not None and uv.wants_restart: clean_server() - installer.log.info('Server restarting...') + logger.log.info('Server restarting...') # uv, instance = start_server(immediate=False, server=instance) os.execv(sys.executable, ['python'] + sys.argv) else: - installer.log.info('Exiting...') + logger.log.info('Exiting...') break time.sleep(1.0) diff --git a/modules/api/api.py b/modules/api/api.py index 669362d7d..cbc7fa5ca 100644 --- a/modules/api/api.py +++ b/modules/api/api.py @@ -4,6 +4,7 @@ from fastapi import FastAPI, APIRouter, Depends, Request from fastapi.security import HTTPBasic, HTTPBasicCredentials from fastapi.exceptions import HTTPException from modules import errors, shared +from modules import logger from modules.api import models, endpoints, script, helpers, server, generate, process, control, docs, gpu @@ -142,13 +143,13 @@ class Api: if hasattr(self.app, 'tokens') and (self.app.tokens is not None): if credentials.password in self.app.tokens.keys(): return True - shared.log.error(f'API authentication: user="{credentials.username}"') + logger.log.error(f'API authentication: user="{credentials.username}"') raise HTTPException(status_code=401, detail="Unauthorized", headers={"WWW-Authenticate": "Basic"}) def get_session_start(self, req: Request, agent: str | None = None): token = req.cookies.get("access-token") or req.cookies.get("access-token-unsecure") user = self.app.tokens.get(token) if hasattr(self.app, 'tokens') else None - shared.log.info(f'Browser session: user={user} client={req.client.host} agent={agent}') + logger.log.info(f'Browser session: user={user} client={req.client.host} agent={agent}') return {} def launch(self): @@ -165,7 +166,7 @@ class Api: # from modules.server import HypercornServer # server = HypercornServer(self.app, **config) http_server.start() - shared.log.info(f'API server: Uvicorn options={config}') + logger.log.info(f'API server: Uvicorn options={config}') return http_server diff --git a/modules/api/control.py b/modules/api/control.py index 5f5882e04..8219d06df 100644 --- a/modules/api/control.py +++ b/modules/api/control.py @@ -2,6 +2,7 @@ from typing import Optional from threading import Lock from pydantic import BaseModel, Field # pylint: disable=no-name-in-module from modules import errors, shared, processing_helpers +from modules import logger from modules.api import models, helpers from modules.control import run @@ -156,7 +157,7 @@ class APIControl: if req.unit_type is None: req.unit_type = 'controlnet' if req.unit_type not in unit_types: - shared.log.error(f'Control uknown unit type: type={req.unit_type} available={unit_types}') + logger.log.error(f'Control uknown unit type: type={req.unit_type} available={unit_types}') return for i in range(len(req.control)): u = req.control[i] diff --git a/modules/api/endpoints.py b/modules/api/endpoints.py index 543756906..8d5dc8a66 100644 --- a/modules/api/endpoints.py +++ b/modules/api/endpoints.py @@ -1,3 +1,4 @@ +from modules import logger from modules import shared from modules.api import models, helpers @@ -90,7 +91,7 @@ def get_schedulers(): from modules.sd_samplers import list_samplers all_schedulers = list_samplers() for s in all_schedulers: - shared.log.critical(s) + logger.log.critical(s) return all_schedulers def post_unload_checkpoint(): diff --git a/modules/api/gallery.py b/modules/api/gallery.py index ac6cf93e1..407a3d39b 100644 --- a/modules/api/gallery.py +++ b/modules/api/gallery.py @@ -9,10 +9,11 @@ from starlette.websockets import WebSocket, WebSocketState from pydantic import BaseModel, Field # pylint: disable=no-name-in-module from PIL import Image from modules import shared, images, files_cache, modelstats +from modules import logger from modules.paths import resolve_output_path -debug = shared.log.debug if os.environ.get('SD_BROWSER_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.debug if os.environ.get('SD_BROWSER_DEBUG', None) is not None else lambda *args, **kwargs: None OPTS_FOLDERS = [ @@ -96,7 +97,7 @@ def register_api(app: FastAPI): # register api } return content except Exception as e: - shared.log.error(f'Gallery video: file="{filepath}" {e}') + logger.log.error(f'Gallery video: file="{filepath}" {e}') return {} def get_image_thumbnail(filepath): @@ -123,7 +124,7 @@ def register_api(app: FastAPI): # register api } return content except Exception as e: - shared.log.error(f'Gallery image: file="{filepath}" {e}') + logger.log.error(f'Gallery image: file="{filepath}" {e}') return {} # @app.get('/sdapi/v1/browser/folders', response_model=List[str]) @@ -183,7 +184,7 @@ def register_api(app: FastAPI): # register api else: return JSONResponse(content=get_image_thumbnail(decoded)) except Exception as e: - shared.log.error(f'Gallery: {file} {e}') + logger.log.error(f'Gallery: {file} {e}') content = { 'error': str(e) } return JSONResponse(content=content) @@ -199,10 +200,10 @@ def register_api(app: FastAPI): # register api msg = msg[:1] + ":" + msg[4:] if msg[1:4] == "%3A" else msg lines.append(msg) t1 = time.time() - shared.log.debug(f'Gallery: type=ht folder="{folder}" files={len(lines)} time={t1-t0:.3f}') + logger.log.debug(f'Gallery: type=ht folder="{folder}" files={len(lines)} time={t1-t0:.3f}') return lines except Exception as e: - shared.log.error(f'Gallery: {folder} {e}') + logger.log.error(f'Gallery: {folder} {e}') return [] shared.api.add_api_route("/sdapi/v1/browser/folders", get_folders, methods=["GET"], response_model=list[str]) @@ -228,7 +229,7 @@ def register_api(app: FastAPI): # register api await manager.send(ws, msg) await manager.send(ws, '#END#') t1 = time.time() - shared.log.debug(f'Gallery: type=ws folder="{folder}" files={numFiles} time={t1-t0:.3f}') + logger.log.debug(f'Gallery: type=ws folder="{folder}" files={numFiles} time={t1-t0:.3f}') except Exception as e: debug(f'Browser WS error: {e}') manager.disconnect(ws) diff --git a/modules/api/gpu.py b/modules/api/gpu.py index e5290d96e..299fa0f46 100644 --- a/modules/api/gpu.py +++ b/modules/api/gpu.py @@ -1,5 +1,5 @@ import torch -from installer import log +from modules.logger import log device = None diff --git a/modules/api/helpers.py b/modules/api/helpers.py index a686e6bec..ae80a0426 100644 --- a/modules/api/helpers.py +++ b/modules/api/helpers.py @@ -5,6 +5,7 @@ import piexif import piexif.helper from fastapi.exceptions import HTTPException from modules import shared, sd_samplers +from modules import logger def validate_sampler_name(name): @@ -25,7 +26,7 @@ def decode_base64_to_image(encoding, quiet=False): image = Image.open(data) return image except Exception as e: - shared.log.warning(f'API cannot decode image: {e}') + logger.log.warning(f'API cannot decode image: {e}') # from modules import errors # errors.display(e, 'API cannot decode image') if not quiet: @@ -41,7 +42,7 @@ def encode_pil_to_base64(image): return base64.b64encode(bytes_data) """ if not isinstance(image, Image.Image): - shared.log.error('API cannot encode image: not a PIL image') + logger.log.error('API cannot encode image: not a PIL image') return '' buffered = io.BytesIO() save_image(image, fn=buffered, ext=shared.opts.samples_format) @@ -66,7 +67,7 @@ def save_image(image, fn, ext): image.save(fn, format=image_format, quality=shared.opts.jpeg_quality, pnginfo=pnginfo_data) elif image_format == 'JPEG': if image.mode == 'RGBA': - shared.log.warning('Save: RGBA image as JPEG - removed alpha channel') + logger.log.warning('Save: RGBA image as JPEG - removed alpha channel') image = image.convert("RGB") elif image.mode == 'I;16': image = image.point(lambda p: p * 0.0038910505836576).convert("L") @@ -87,5 +88,5 @@ def save_image(image, fn, ext): exif_bytes = piexif.dump({ "Exif": { piexif.ExifIFD.UserComment: piexif.helper.UserComment.dump(parameters or "", encoding="unicode") } }) image.save(fn, format=image_format, quality=shared.opts.jpeg_quality, lossless=shared.opts.webp_lossless, exif=exif_bytes) else: - # shared.log.warning(f'Unrecognized image format: {extension} attempting save as {image_format}') + # logger.log.warning(f'Unrecognized image format: {extension} attempting save as {image_format}') image.save(fn, format=image_format, quality=shared.opts.jpeg_quality) diff --git a/modules/api/middleware.py b/modules/api/middleware.py index 8dc10e31e..874200171 100644 --- a/modules/api/middleware.py +++ b/modules/api/middleware.py @@ -10,7 +10,7 @@ from starlette.responses import JSONResponse from fastapi import FastAPI, Request, Response from fastapi.exceptions import HTTPException from fastapi.encoders import jsonable_encoder -from installer import log +from modules.logger import log import modules.errors as errors diff --git a/modules/api/nvml.py b/modules/api/nvml.py index f800b9424..0dec562be 100644 --- a/modules/api/nvml.py +++ b/modules/api/nvml.py @@ -1,5 +1,6 @@ try: - from installer import install, log + from installer import install + from modules.logger import log except Exception: def install(*args, **kwargs): # pylint: disable=unused-argument pass diff --git a/modules/api/rocm_smi.py b/modules/api/rocm_smi.py index bbf7f1ba7..e7b9a2f74 100644 --- a/modules/api/rocm_smi.py +++ b/modules/api/rocm_smi.py @@ -5,7 +5,7 @@ from enum import IntFlag try: - from installer import log + from modules.logger import log except Exception: import logging log = logging.getLogger(__name__) diff --git a/modules/api/server.py b/modules/api/server.py index 69de6d18d..fc07415b2 100644 --- a/modules/api/server.py +++ b/modules/api/server.py @@ -5,11 +5,12 @@ from fastapi import Request, Depends from fastapi.exceptions import HTTPException from fastapi.responses import FileResponse from modules import shared +from modules import logger from modules.api import models, helpers def post_shutdown(): - shared.log.info('Shutdown request received') + logger.log.info('Shutdown request received') import sys sys.exit(0) @@ -21,7 +22,7 @@ def get_js(request: Request): if ext not in ['js', 'css', 'map', 'html', 'wasm', 'ttf', 'mjs', 'json']: raise HTTPException(status_code=400, detail=f"invalid file extension: {ext}") if not os.path.exists(file): - shared.log.error(f"API: file not found: {file}") + logger.log.error(f"API: file not found: {file}") raise HTTPException(status_code=404, detail=f"file not found: {file}") if ext in ['js', 'mjs']: media_type = 'application/javascript' @@ -50,12 +51,12 @@ def get_motd(): res = requests.get('https://vladmandic.github.io/sdnext/motd', timeout=3) if res.status_code == 200: msg = (res.text or '').strip() - shared.log.info(f'MOTD: {msg if len(msg) > 0 else "N/A"}') + logger.log.info(f'MOTD: {msg if len(msg) > 0 else "N/A"}') motd += res.text else: - shared.log.error(f'MOTD: {res.status_code}') + logger.log.error(f'MOTD: {res.status_code}') except Exception as err: - shared.log.error(f'MOTD: {err}') + logger.log.error(f'MOTD: {err}') return motd def get_version(): @@ -67,18 +68,18 @@ def get_platform(): return { **installer_get_platform(), **loader_get_packages() } def get_log(req: models.ReqGetLog = Depends()): - lines = shared.log.buffer[:req.lines] if req.lines > 0 else shared.log.buffer.copy() + lines = logger.log.buffer[:req.lines] if req.lines > 0 else logger.log.buffer.copy() if req.clear: - shared.log.buffer.clear() + logger.log.buffer.clear() return lines def post_log(req: models.ReqPostLog): if req.message is not None: - shared.log.info(f'UI: {req.message}') + logger.log.info(f'UI: {req.message}') if req.debug is not None: - shared.log.debug(f'UI: {req.debug}') + logger.log.debug(f'UI: {req.debug}') if req.error is not None: - shared.log.error(f'UI: {req.error}') + logger.log.error(f'UI: {req.error}') return {} @@ -132,8 +133,8 @@ def get_progress(req: models.ReqProgress = Depends()): progress = min((current / total) if current > 0 and total > 0 else 0, 1) time_since_start = time.time() - shared.state.time_start eta_relative = (time_since_start / progress) - time_since_start if progress > 0 else 0 - # shared.log.critical(f'get_progress: batch {batch_x}/{batch_y} step {step_x}/{step_y} current {current}/{total} time={time_since_start} eta={eta_relative}') - # shared.log.critical(shared.state) + # logger.log.critical(f'get_progress: batch {batch_x}/{batch_y} step {step_x}/{step_y} current {current}/{total} time={time_since_start} eta={eta_relative}') + # logger.log.critical(shared.state) res = models.ResProgress(id=shared.state.id, progress=round(progress, 2), eta_relative=round(eta_relative, 2), current_image=current_image, textinfo=shared.state.textinfo, state=shared.state.dict(), ) return res diff --git a/modules/api/xpu_smi.py b/modules/api/xpu_smi.py index 742393456..70401b84d 100644 --- a/modules/api/xpu_smi.py +++ b/modules/api/xpu_smi.py @@ -1,5 +1,5 @@ try: - from installer import log + from modules.logger import log except Exception: import logging log = logging.getLogger(__name__) diff --git a/modules/attention.py b/modules/attention.py index 6490f6abb..b69f71595 100644 --- a/modules/attention.py +++ b/modules/attention.py @@ -1,6 +1,7 @@ from functools import wraps import torch from modules import rocm +from modules import logger from modules.errors import log from installer import install, installed @@ -194,7 +195,7 @@ def set_diffusers_attention(pipe, quiet:bool=False): if 'Nunchaku' in pipe.unet.__class__.__name__: pass else: - shared.log.error(f'Torch attention: type="{name}" cls={attention.__class__.__name__} pipe={pipe.__class__.__name__} {e}') + logger.log.error(f'Torch attention: type="{name}" cls={attention.__class__.__name__} pipe={pipe.__class__.__name__} {e}') """ # each transformer typically has its own attention processor if getattr(pipe, "transformer", None) is not None and hasattr(pipe.transformer, "set_attn_processor"): try: @@ -203,10 +204,10 @@ def set_diffusers_attention(pipe, quiet:bool=False): if 'Nunchaku' in pipe.transformer.__class__.__name__: pass else: - shared.log.error(f'Torch attention: type="{name}" cls={attention.__class__.__name__} pipe={pipe.__class__.__name__} {e}') + logger.log.error(f'Torch attention: type="{name}" cls={attention.__class__.__name__} pipe={pipe.__class__.__name__} {e}') """ - shared.log.quiet(quiet, f'Setting model: attention="{shared.opts.cross_attention_optimization}"') + logger.log.quiet(quiet, f'Setting model: attention="{shared.opts.cross_attention_optimization}"') if shared.opts.cross_attention_optimization == "Disabled": pass # do nothing elif shared.opts.cross_attention_optimization == "Scaled-Dot-Product": # The default set by Diffusers @@ -216,7 +217,7 @@ def set_diffusers_attention(pipe, quiet:bool=False): if hasattr(pipe, 'enable_xformers_memory_efficient_attention'): pipe.enable_xformers_memory_efficient_attention() else: - shared.log.warning(f"Attention: xFormers is not compatible with {pipe.__class__.__name__}") + logger.log.warning(f"Attention: xFormers is not compatible with {pipe.__class__.__name__}") elif shared.opts.cross_attention_optimization == "Batch matrix-matrix": set_attn(pipe, p.AttnProcessor(), name="Batch matrix-matrix") elif shared.opts.cross_attention_optimization == "Dynamic Attention BMM": @@ -228,6 +229,6 @@ def set_diffusers_attention(pipe, quiet:bool=False): pipe.enable_attention_slicing() else: pipe.disable_attention_slicing() - shared.log.debug(f"Torch attention: slicing={shared.opts.attention_slicing}") + logger.log.debug(f"Torch attention: slicing={shared.opts.attention_slicing}") pipe.current_attn_name = shared.opts.cross_attention_optimization diff --git a/modules/cachedit.py b/modules/cachedit.py index 057b23804..af68b81c7 100644 --- a/modules/cachedit.py +++ b/modules/cachedit.py @@ -1,6 +1,7 @@ import os from installer import install from modules import shared +from modules import logger def apply_cache_dit(pipe): @@ -11,12 +12,12 @@ def apply_cache_dit(pipe): try: import cache_dit except Exception as e: - shared.log.error(f'Cache-DIT: {e}') + logger.log.error(f'Cache-DIT: {e}') return _, supported = cache_dit.supported_pipelines() supported = [s.replace('*', '') for s in supported] if not any(pipe.__class__.__name__.startswith(s) for s in supported): - shared.log.error(f'Cache-DiT: pipeline={pipe.__class__.__name__} unsupported') + logger.log.error(f'Cache-DiT: pipeline={pipe.__class__.__name__} unsupported') return if getattr(pipe, 'has_cache_dit', False): @@ -38,7 +39,7 @@ def apply_cache_dit(pipe): calibrator_config = cache_dit.FoCaCalibratorConfig() else: calibrator_config = None - shared.log.info(f'Apply Cache-DiT: config="{cache_config.strify()}" calibrator="{calibrator_config.strify() if calibrator_config else "None"}"') + logger.log.info(f'Apply Cache-DiT: config="{cache_config.strify()}" calibrator="{calibrator_config.strify() if calibrator_config else "None"}"') try: cache_dit.enable_cache( pipe, @@ -47,7 +48,7 @@ def apply_cache_dit(pipe): ) shared.sd_model.has_cache_dit = True except Exception as e: - shared.log.error(f'Cache-DiT: {e}') + logger.log.error(f'Cache-DiT: {e}') return @@ -57,7 +58,7 @@ def unapply_cache_dir(pipe): try: import cache_dit # stats = cache_dit.summary(pipe) - # shared.log.critical(f'Unapply Cache-DiT: {stats}') + # logger.log.critical(f'Unapply Cache-DiT: {stats}') cache_dit.disable_cache(pipe) pipe.has_cache_dit = False except Exception: diff --git a/modules/call_queue.py b/modules/call_queue.py index ebfe58f0f..f3b0fb360 100644 --- a/modules/call_queue.py +++ b/modules/call_queue.py @@ -5,6 +5,7 @@ import threading import time import cProfile from modules import shared, progress, errors, timer +from modules import logger queue_lock = threading.Lock() @@ -14,7 +15,7 @@ debug = os.environ.get('SD_QUEUE_DEBUG', None) is not None def get_lock(): if debug: fn = f'{sys._getframe(3).f_code.co_name}:{sys._getframe(2).f_code.co_name}:{sys._getframe(1).f_code.co_name}' # pylint: disable=protected-access - errors.log.debug(f'Queue: fn={fn} lock={queue_lock.locked()}') + logger.log.debug(f'Queue: fn={fn} lock={queue_lock.locked()}') return queue_lock @@ -41,8 +42,8 @@ def wrap_gradio_gpu_call(func, extra_outputs=None, name=None): res = func(*args, **kwargs) progress.record_results(id_task, res) except Exception as e: - shared.log.error(f"Exception: {e}") - shared.log.error(f"Arguments: args={str(args)[:10240]} kwargs={str(kwargs)[:10240]}") + logger.log.error(f"Exception: {e}") + logger.log.error(f"Arguments: args={str(args)[:10240]} kwargs={str(kwargs)[:10240]}") errors.display(e, 'gradio call') res = extra_outputs or [] res.append(f"
{html.escape(str(e))}
") @@ -69,7 +70,7 @@ def wrap_gradio_call(func, extra_outputs=None, add_stats=False, name=None): res = func(*args, **kwargs) if res is None: msg = "No result returned from function" - shared.log.warning(msg) + logger.log.warning(msg) res = extra_outputs_array or [] res.append(f"
{html.escape(msg)}
") else: diff --git a/modules/caption/caption.py b/modules/caption/caption.py index 78e33d667..6f38c4ed6 100644 --- a/modules/caption/caption.py +++ b/modules/caption/caption.py @@ -1,6 +1,7 @@ import time from PIL import Image from modules import shared +from modules import logger def caption(image): @@ -9,21 +10,21 @@ def caption(image): if isinstance(image, dict) and 'name' in image: image = Image.open(image['name']) if image is None: - shared.log.error('Caption: no image provided') + logger.log.error('Caption: no image provided') return '' t0 = time.time() if shared.opts.caption_default_type == 'OpenCLiP': - shared.log.info(f'Caption: type={shared.opts.caption_default_type} clip="{shared.opts.caption_openclip_model}" blip="{shared.opts.caption_openclip_blip_model}" mode="{shared.opts.caption_openclip_mode}"') + logger.log.info(f'Caption: type={shared.opts.caption_default_type} clip="{shared.opts.caption_openclip_model}" blip="{shared.opts.caption_openclip_blip_model}" mode="{shared.opts.caption_openclip_mode}"') from modules.caption import openclip openclip.load_captioner(clip_model=shared.opts.caption_openclip_model, blip_model=shared.opts.caption_openclip_blip_model) openclip.update_caption_params() prompt = openclip.caption(image, mode=shared.opts.caption_openclip_mode) if shared.opts.caption_offload: openclip.unload_clip_model() - shared.log.debug(f'Caption: time={time.time()-t0:.2f} answer="{prompt}"') + logger.log.debug(f'Caption: time={time.time()-t0:.2f} answer="{prompt}"') return prompt elif shared.opts.caption_default_type == 'Tagger': - shared.log.info(f'Caption: type={shared.opts.caption_default_type} model="{shared.opts.waifudiffusion_model}"') + logger.log.info(f'Caption: type={shared.opts.caption_default_type} model="{shared.opts.waifudiffusion_model}"') from modules.caption import tagger prompt = tagger.tag( image=image, @@ -37,14 +38,14 @@ def caption(image): use_spaces=shared.opts.tagger_use_spaces, escape_brackets=shared.opts.tagger_escape_brackets, ) - shared.log.debug(f'Caption: time={time.time()-t0:.2f} answer="{prompt}"') + logger.log.debug(f'Caption: time={time.time()-t0:.2f} answer="{prompt}"') return prompt elif shared.opts.caption_default_type == 'VLM': - shared.log.info(f'Caption: type={shared.opts.caption_default_type} vlm="{shared.opts.caption_vlm_model}" prompt="{shared.opts.caption_vlm_prompt}"') + logger.log.info(f'Caption: type={shared.opts.caption_default_type} vlm="{shared.opts.caption_vlm_model}" prompt="{shared.opts.caption_vlm_prompt}"') from modules.caption import vqa prompt = vqa.caption(image=image, model_name=shared.opts.caption_vlm_model, question=shared.opts.caption_vlm_prompt, prompt=None, system_prompt=shared.opts.caption_vlm_system) - shared.log.debug(f'Caption: time={time.time()-t0:.2f} answer="{prompt}"') + logger.log.debug(f'Caption: time={time.time()-t0:.2f} answer="{prompt}"') return prompt else: - shared.log.error(f'Caption: type="{shared.opts.caption_default_type}" unknown') + logger.log.error(f'Caption: type="{shared.opts.caption_default_type}" unknown') return '' diff --git a/modules/caption/deepbooru.py b/modules/caption/deepbooru.py index 5162a0dc8..b20afb52d 100644 --- a/modules/caption/deepbooru.py +++ b/modules/caption/deepbooru.py @@ -5,6 +5,7 @@ import torch import numpy as np from PIL import Image from modules import modelloader, devices, shared, paths +from modules import logger re_special = re.compile(r'([\\()])') load_lock = threading.Lock() @@ -19,7 +20,7 @@ class DeepDanbooru: if self.model is not None: return model_path = os.path.join(paths.models_path, "DeepDanbooru") - shared.log.debug(f'Caption load: module=DeepDanbooru folder="{model_path}"') + logger.log.debug(f'Caption load: module=DeepDanbooru folder="{model_path}"') files = modelloader.load_models( model_path=model_path, model_url='https://github.com/AUTOMATIC1111/TorchDeepDanbooru/releases/download/v1/model-resnet_custom_v3.pt', @@ -139,14 +140,14 @@ def load_model(model_name: str = None) -> bool: # pylint: disable=unused-argumen model.load() return model.model is not None except Exception as e: - shared.log.error(f'DeepBooru load: {e}') + logger.log.error(f'DeepBooru load: {e}') return False def unload_model(): """Unload the DeepBooru model and free memory.""" if model.model is not None: - shared.log.debug('DeepBooru unload') + logger.log.debug('DeepBooru unload') model.model.to(devices.cpu) model.model = None devices.torch_gc(force=True) @@ -166,14 +167,14 @@ def tag(image, **kwargs) -> str: import time t0 = time.time() jobid = shared.state.begin('DeepBooru Tag') - shared.log.info(f'DeepBooru: image_size={image.size if image else None}') + logger.log.info(f'DeepBooru: image_size={image.size if image else None}') try: result = model.tag(image, **kwargs) - shared.log.debug(f'DeepBooru: complete time={time.time()-t0:.2f} tags={len(result.split(", ")) if result else 0}') + logger.log.debug(f'DeepBooru: complete time={time.time()-t0:.2f} tags={len(result.split(", ")) if result else 0}') except Exception as e: result = f"Exception {type(e)}" - shared.log.error(f'DeepBooru: {e}') + logger.log.error(f'DeepBooru: {e}') shared.state.end(jobid) return result @@ -264,18 +265,18 @@ def batch( image_files = unique_files if not image_files: - shared.log.warning('DeepBooru batch: no images found') + logger.log.warning('DeepBooru batch: no images found') return '' t0 = time.time() jobid = shared.state.begin('DeepBooru Batch') - shared.log.info(f'DeepBooru batch: images={len(image_files)} write={save_output} append={save_append} recursive={recursive}') + logger.log.info(f'DeepBooru batch: images={len(image_files)} write={save_output} append={save_append} recursive={recursive}') results = [] model.start() # Progress bar - pbar = rp.Progress(rp.TextColumn('[cyan]DeepBooru:'), rp.BarColumn(), rp.MofNCompleteColumn(), rp.TaskProgressColumn(), rp.TimeRemainingColumn(), rp.TimeElapsedColumn(), rp.TextColumn('[cyan]{task.description}'), console=shared.console) + pbar = rp.Progress(rp.TextColumn('[cyan]DeepBooru:'), rp.BarColumn(), rp.MofNCompleteColumn(), rp.TaskProgressColumn(), rp.TimeRemainingColumn(), rp.TimeElapsedColumn(), rp.TextColumn('[cyan]{task.description}'), console=logger.console) with pbar: task = pbar.add_task(total=len(image_files), description='starting...') @@ -283,7 +284,7 @@ def batch( pbar.update(task, advance=1, description=str(img_path.name)) try: if shared.state.interrupted: - shared.log.info('DeepBooru batch: interrupted') + logger.log.info('DeepBooru batch: interrupted') break image = Image.open(img_path) @@ -296,12 +297,12 @@ def batch( results.append(f'{img_path.name}: {tags_str[:100]}...' if len(tags_str) > 100 else f'{img_path.name}: {tags_str}') except Exception as e: - shared.log.error(f'DeepBooru batch: file="{img_path}" error={e}') + logger.log.error(f'DeepBooru batch: file="{img_path}" error={e}') results.append(f'{img_path.name}: ERROR - {e}') model.stop() elapsed = time.time() - t0 - shared.log.info(f'DeepBooru batch: complete images={len(results)} time={elapsed:.1f}s') + logger.log.info(f'DeepBooru batch: complete images={len(results)} time={elapsed:.1f}s') shared.state.end(jobid) return '\n'.join(results) diff --git a/modules/caption/deepseek.py b/modules/caption/deepseek.py index 44bff3fb6..a25e38e3d 100644 --- a/modules/caption/deepseek.py +++ b/modules/caption/deepseek.py @@ -13,6 +13,7 @@ import sys import importlib from transformers import AutoModelForCausalLM from modules import shared, devices, paths, sd_models +from modules import logger # model_path = "deepseek-ai/deepseek-vl2-small" @@ -32,11 +33,11 @@ def load(repo: str): """Load DeepSeek VL2 model (experimental).""" global vl_gpt, vl_chat_processor, loaded_repo # pylint: disable=global-statement if not shared.cmd_opts.experimental: - shared.log.error(f'Caption: type=vlm model="DeepSeek VL2" repo="{repo}" is experimental-only') + logger.log.error(f'Caption: type=vlm model="DeepSeek VL2" repo="{repo}" is experimental-only') return False folder = os.path.join(paths.script_path, 'repositories', 'deepseek-vl2') if not os.path.exists(folder): - shared.log.error(f'Caption: type=vlm model="DeepSeek VL2" repo="{repo}" deepseek-vl2 repo not found') + logger.log.error(f'Caption: type=vlm model="DeepSeek VL2" repo="{repo}" deepseek-vl2 repo not found') return False if vl_gpt is None or loaded_repo != repo: # GLOBAL PATCHES (not reverted): DeepSeek VL2 requires attrdict and uses LlamaFlashAttention2 @@ -58,7 +59,7 @@ def load(repo: str): vl_gpt.eval() # required: trust_remote_code model loaded_repo = repo devices.torch_gc() - shared.log.info(f'Caption: type=vlm model="DeepSeek VL2" repo="{repo}"') + logger.log.info(f'Caption: type=vlm model="DeepSeek VL2" repo="{repo}"') sd_models.move_model(vl_gpt, devices.device) return True @@ -67,14 +68,14 @@ def unload(): """Release DeepSeek VL2 model from GPU/memory.""" global vl_gpt, vl_chat_processor, loaded_repo # pylint: disable=global-statement if vl_gpt is not None: - shared.log.debug(f'DeepSeek unload: model="{loaded_repo}"') + logger.log.debug(f'DeepSeek unload: model="{loaded_repo}"') sd_models.move_model(vl_gpt, devices.cpu, force=True) vl_gpt = None vl_chat_processor = None loaded_repo = None devices.torch_gc(force=True) else: - shared.log.debug('DeepSeek unload: no model loaded') + logger.log.debug('DeepSeek unload: no model loaded') def predict(question, image, repo): diff --git a/modules/caption/joycaption.py b/modules/caption/joycaption.py index 99f4ef677..507b280ab 100644 --- a/modules/caption/joycaption.py +++ b/modules/caption/joycaption.py @@ -3,6 +3,7 @@ from dataclasses import dataclass from transformers import AutoProcessor, LlavaForConditionalGeneration from modules import shared, devices, sd_models, model_quant +from modules import logger """ @@ -63,7 +64,7 @@ def load(repo: str = None): if llava_model is None or opts.repo != repo: opts.repo = repo llava_model = None - shared.log.info(f'Caption: type=vlm model="JoyCaption" {str(opts)}') + logger.log.info(f'Caption: type=vlm model="JoyCaption" {str(opts)}') processor = AutoProcessor.from_pretrained(repo, max_pixels=1024*1024, cache_dir=shared.opts.hfcache_dir) quant_args = model_quant.create_config(module='LLM') llava_model = LlavaForConditionalGeneration.from_pretrained( @@ -80,13 +81,13 @@ def unload(): """Release JoyCaption model from GPU/memory.""" global llava_model, processor # pylint: disable=global-statement if llava_model is not None: - shared.log.debug(f'JoyCaption unload: model="{opts.repo}"') + logger.log.debug(f'JoyCaption unload: model="{opts.repo}"') sd_models.move_model(llava_model, devices.cpu, force=True) llava_model = None processor = None devices.torch_gc(force=True) else: - shared.log.debug('JoyCaption unload: no model loaded') + logger.log.debug('JoyCaption unload: no model loaded') def predict(question: str, image, vqa_model: str = None) -> str: diff --git a/modules/caption/joytag.py b/modules/caption/joytag.py index 042f87529..afdc1fafe 100644 --- a/modules/caption/joytag.py +++ b/modules/caption/joytag.py @@ -17,6 +17,7 @@ import einops from einops.layers.torch import Rearrange import huggingface_hub from modules import shared, devices, sd_models +from modules import logger from modules.image import convert @@ -1049,7 +1050,7 @@ def load(): model.eval() # required: custom loader, not from_pretrained with open(os.path.join(folder, 'top_tags.txt'), encoding='utf8') as f: tags = [line.strip() for line in f.readlines() if line.strip()] - shared.log.info(f'Caption: type=vlm model="JoyTag" repo="{MODEL_REPO}" tags={len(tags)}') + logger.log.info(f'Caption: type=vlm model="JoyTag" repo="{MODEL_REPO}" tags={len(tags)}') sd_models.move_model(model, devices.device) @@ -1057,13 +1058,13 @@ def unload(): """Release JoyTag model from GPU/memory.""" global model, tags # pylint: disable=global-statement if model is not None: - shared.log.debug('JoyTag unload') + logger.log.debug('JoyTag unload') sd_models.move_model(model, devices.cpu, force=True) model = None tags = None devices.torch_gc(force=True) else: - shared.log.debug('JoyTag unload: no model loaded') + logger.log.debug('JoyTag unload: no model loaded') def predict(image: Image.Image): diff --git a/modules/caption/moondream3.py b/modules/caption/moondream3.py index 12c28b1b6..d108b4b34 100644 --- a/modules/caption/moondream3.py +++ b/modules/caption/moondream3.py @@ -9,6 +9,7 @@ import collections import transformers from PIL import Image from modules import shared, devices, sd_models +from modules import logger from modules.caption import vqa_detection @@ -17,7 +18,7 @@ debug_enabled = os.environ.get('SD_CAPTION_DEBUG', None) is not None def debug(*args, **kwargs): if debug_enabled: - shared.log.trace(*args, **kwargs) + logger.log.trace(*args, **kwargs) # Global state @@ -47,7 +48,7 @@ def load_model(repo: str): global moondream3_model, loaded # pylint: disable=global-statement if moondream3_model is None or loaded != repo: - shared.log.debug(f'Caption load: vlm="{repo}"') + logger.log.debug(f'Caption load: vlm="{repo}"') moondream3_model = None moondream3_model = transformers.AutoModelForCausalLM.from_pretrained( @@ -410,18 +411,18 @@ def clear_cache(): cache_size = len(image_cache) image_cache.clear() debug(f'VQA caption: handler=moondream3 cleared image cache cache_size_was={cache_size}') - shared.log.debug(f'Moondream3: Cleared image cache ({cache_size} entries)') + logger.log.debug(f'Moondream3: Cleared image cache ({cache_size} entries)') def unload(): """Release Moondream 3 model from GPU/memory.""" global moondream3_model, loaded # pylint: disable=global-statement if moondream3_model is not None: - shared.log.debug(f'Moondream3 unload: model="{loaded}"') + logger.log.debug(f'Moondream3 unload: model="{loaded}"') sd_models.move_model(moondream3_model, devices.cpu, force=True) moondream3_model = None loaded = None clear_cache() devices.torch_gc(force=True) else: - shared.log.debug('Moondream3 unload: no model loaded') + logger.log.debug('Moondream3 unload: no model loaded') diff --git a/modules/caption/openclip.py b/modules/caption/openclip.py index b43229a93..de48b67e8 100644 --- a/modules/caption/openclip.py +++ b/modules/caption/openclip.py @@ -6,10 +6,11 @@ import re import gradio as gr from PIL import Image from modules import devices, shared, errors +from modules import logger debug_enabled = os.environ.get('SD_CAPTION_DEBUG', None) is not None -debug_log = shared.log.trace if debug_enabled else lambda *args, **kwargs: None +debug_log = logger.log.trace if debug_enabled else lambda *args, **kwargs: None # Per-request overrides for API calls _clip_overrides = None @@ -107,7 +108,7 @@ def refresh_clip_models(): global clip_models # pylint: disable=global-statement import open_clip models = sorted(open_clip.list_pretrained()) - shared.log.debug(f'Caption: pkg=openclip version={open_clip.__version__} models={len(models)}') + logger.log.debug(f'Caption: pkg=openclip version={open_clip.__version__} models={len(models)}') clip_models = ['/'.join(x) for x in models] return clip_models @@ -141,7 +142,7 @@ def load_captioner(clip_model, blip_model): t0 = time.time() device = devices.get_optimal_device() cache_path = shared.opts.clip_models_path - shared.log.info(f'CLIP load: clip="{clip_model}" blip="{blip_model}" device={device}') + logger.log.info(f'CLIP load: clip="{clip_model}" blip="{blip_model}" device={device}') debug_log(f'CLIP load: cache_path="{cache_path}" max_length={shared.opts.caption_openclip_max_length} chunk_size={shared.opts.caption_openclip_chunk_size} flavor_count={shared.opts.caption_openclip_flavor_count} offload={shared.opts.caption_offload}') caption_model, caption_processor = _load_blip_model(blip_model, device) captioner_config = clip_interrogator.Config( @@ -163,18 +164,18 @@ def load_captioner(clip_model, blip_model): if blip_model.startswith('blip2-'): _apply_blip2_fix(ci.caption_model, ci.caption_processor) - shared.log.debug(f'CLIP load: time={time.time()-t0:.2f}') + logger.log.debug(f'CLIP load: time={time.time()-t0:.2f}') elif clip_model != ci.config.clip_model_name or blip_model != ci.config.caption_model_name: t0 = time.time() if clip_model != ci.config.clip_model_name: - shared.log.info(f'CLIP load: clip="{clip_model}" reloading') + logger.log.info(f'CLIP load: clip="{clip_model}" reloading') debug_log(f'CLIP load: previous clip="{ci.config.clip_model_name}"') ci.config.clip_model_name = clip_model ci.config.clip_model = None ci.load_clip_model() ci.clip_offloaded = True # Reset flag so _prepare_clip() will move model to device if blip_model != ci.config.caption_model_name: - shared.log.info(f'CLIP load: blip="{blip_model}" reloading') + logger.log.info(f'CLIP load: blip="{blip_model}" reloading') debug_log(f'CLIP load: previous blip="{ci.config.caption_model_name}"') ci.config.caption_model_name = blip_model caption_model, caption_processor = _load_blip_model(blip_model, ci.device) @@ -183,14 +184,14 @@ def load_captioner(clip_model, blip_model): ci.caption_offloaded = True # Reset flag so _prepare_caption() will move model to device if blip_model.startswith('blip2-'): _apply_blip2_fix(ci.caption_model, ci.caption_processor) - shared.log.debug(f'CLIP load: time={time.time()-t0:.2f}') + logger.log.debug(f'CLIP load: time={time.time()-t0:.2f}') else: debug_log(f'CLIP: models already loaded clip="{clip_model}" blip="{blip_model}"') def unload_clip_model(): if ci is not None and shared.opts.caption_offload: - shared.log.debug('CLIP unload: offloading models to CPU') + logger.log.debug('CLIP unload: offloading models to CPU') # Direct .to() instead of sd_models.move_model — models are from clip_interrogator, not transformers if ci.caption_model is not None and hasattr(ci.caption_model, 'to'): ci.caption_model.to(devices.cpu) @@ -237,7 +238,7 @@ def caption_image(image, clip_model, blip_model, mode, overrides=None): global _clip_overrides # pylint: disable=global-statement jobid = shared.state.begin('Caption CLiP') t0 = time.time() - shared.log.info(f'CLIP: mode="{mode}" clip="{clip_model}" blip="{blip_model}" image_size={image.size if image else None}') + logger.log.info(f'CLIP: mode="{mode}" clip="{clip_model}" blip="{blip_model}" image_size={image.size if image else None}') if overrides: debug_log(f'CLIP: overrides={overrides}') try: @@ -255,10 +256,10 @@ def caption_image(image, clip_model, blip_model, mode, overrides=None): if shared.opts.caption_offload: unload_clip_model() devices.torch_gc() - shared.log.debug(f'CLIP: complete time={time.time()-t0:.2f}') + logger.log.debug(f'CLIP: complete time={time.time()-t0:.2f}') except Exception as e: prompt = f"Exception {type(e)}" - shared.log.error(f'CLIP: {e}') + logger.log.error(f'CLIP: {e}') errors.display(e, 'Caption') finally: # Clear per-request overrides @@ -278,10 +279,10 @@ def caption_batch(batch_files, batch_folder, batch_str, clip_model, blip_model, from modules.files_cache import list_files files += list(list_files(batch_str, ext_filter=['.png', '.jpg', '.jpeg', '.webp', '.jxl'], recursive=recursive)) if len(files) == 0: - shared.log.warning('CLIP batch: no images found') + logger.log.warning('CLIP batch: no images found') return '' t0 = time.time() - shared.log.info(f'CLIP batch: mode="{mode}" images={len(files)} clip="{clip_model}" blip="{blip_model}" write={write} append={append}') + logger.log.info(f'CLIP batch: mode="{mode}" images={len(files)} clip="{clip_model}" blip="{blip_model}" write={write} append={append}') debug_log(f'CLIP batch: recursive={recursive} files={files[:5]}{"..." if len(files) > 5 else ""}') jobid = shared.state.begin('Caption batch') prompts = [] @@ -292,14 +293,14 @@ def caption_batch(batch_files, batch_folder, batch_str, clip_model, blip_model, writer = BatchWriter(os.path.dirname(files[0]), mode=file_mode) debug_log(f'CLIP batch: writing to "{os.path.dirname(files[0])}" mode="{file_mode}"') import rich.progress as rp - pbar = rp.Progress(rp.TextColumn('[cyan]Caption:'), rp.BarColumn(), rp.MofNCompleteColumn(), rp.TaskProgressColumn(), rp.TimeRemainingColumn(), rp.TimeElapsedColumn(), rp.TextColumn('[cyan]{task.description}'), console=shared.console) + pbar = rp.Progress(rp.TextColumn('[cyan]Caption:'), rp.BarColumn(), rp.MofNCompleteColumn(), rp.TaskProgressColumn(), rp.TimeRemainingColumn(), rp.TimeElapsedColumn(), rp.TextColumn('[cyan]{task.description}'), console=logger.console) with pbar: task = pbar.add_task(total=len(files), description='starting...') for file in files: pbar.update(task, advance=1, description=file) try: if shared.state.interrupted: - shared.log.info('CLIP batch: interrupted') + logger.log.info('CLIP batch: interrupted') break image = Image.open(file).convert('RGB') prompt = caption(image, mode) @@ -307,20 +308,20 @@ def caption_batch(batch_files, batch_folder, batch_str, clip_model, blip_model, if write: writer.add(file, prompt) except OSError as e: - shared.log.error(f'CLIP batch: file="{file}" error={e}') + logger.log.error(f'CLIP batch: file="{file}" error={e}') if write: writer.close() ci.config.quiet = False unload_clip_model() shared.state.end(jobid) - shared.log.info(f'CLIP batch: complete images={len(prompts)} time={time.time()-t0:.2f}') + logger.log.info(f'CLIP batch: complete images={len(prompts)} time={time.time()-t0:.2f}') return '\n\n'.join(prompts) def analyze_image(image, clip_model, blip_model): t0 = time.time() - shared.log.info(f'CLIP analyze: clip="{clip_model}" blip="{blip_model}" image_size={image.size if image else None}') + logger.log.info(f'CLIP analyze: clip="{clip_model}" blip="{blip_model}" image_size={image.size if image else None}') load_captioner(clip_model, blip_model) image = image.convert('RGB') image_features = ci.image_to_features(image) @@ -335,7 +336,7 @@ def analyze_image(image, clip_model, blip_model): movement_ranks = dict(sorted(zip(top_movements, ci.similarities(image_features, top_movements), strict=False), key=lambda x: x[1], reverse=True)) trending_ranks = dict(sorted(zip(top_trendings, ci.similarities(image_features, top_trendings), strict=False), key=lambda x: x[1], reverse=True)) flavor_ranks = dict(sorted(zip(top_flavors, ci.similarities(image_features, top_flavors), strict=False), key=lambda x: x[1], reverse=True)) - shared.log.debug(f'CLIP analyze: complete time={time.time()-t0:.2f}') + logger.log.debug(f'CLIP analyze: complete time={time.time()-t0:.2f}') # Format labels as text def format_category(name, ranks): diff --git a/modules/caption/tagger.py b/modules/caption/tagger.py index e0d3b37d8..94d6e532d 100644 --- a/modules/caption/tagger.py +++ b/modules/caption/tagger.py @@ -2,6 +2,7 @@ # Provides a common interface for the Booru Tags tab from modules import shared +from modules import logger DEEPBOORU_MODEL = "DeepBooru" @@ -27,7 +28,7 @@ def save_tags_to_file(img_path, tags_str: str, save_append: bool) -> bool: f.write(tags_str) return True except Exception as e: - shared.log.error(f'Tagger batch: failed to save file="{img_path}" error={e}') + logger.log.error(f'Tagger batch: failed to save file="{img_path}" error={e}') return False diff --git a/modules/caption/vqa.py b/modules/caption/vqa.py index 9c358145f..5a141f943 100644 --- a/modules/caption/vqa.py +++ b/modules/caption/vqa.py @@ -9,6 +9,7 @@ import transformers import transformers.dynamic_module_utils from PIL import Image from modules import shared, devices, errors, model_quant, sd_models, sd_models_compile, ui_symbols +from modules import logger from modules.caption import vqa_detection @@ -17,7 +18,7 @@ debug_enabled = os.environ.get('SD_CAPTION_DEBUG', None) is not None def debug(*args, **kwargs): if debug_enabled: - shared.log.trace(*args, **kwargs) + logger.log.trace(*args, **kwargs) vlm_default = "Alibaba Qwen 2.5 VL 3B" vlm_models = { @@ -455,15 +456,15 @@ class VQA: """Release VLM model from GPU/memory, including external handlers.""" if self.model is not None: model_name = self.loaded - shared.log.debug(f'VQA unload: unloading model="{model_name}"') + logger.log.debug(f'VQA unload: unloading model="{model_name}"') sd_models.move_model(self.model, devices.cpu, force=True) self.model = None self.processor = None self.loaded = None devices.torch_gc(force=True, reason='vqa unload') - shared.log.debug(f'VQA unload: model="{model_name}" unloaded') + logger.log.debug(f'VQA unload: model="{model_name}" unloaded') else: - shared.log.debug('VQA unload: no internal model loaded') + logger.log.debug('VQA unload: no internal model loaded') # External handlers manage their own module-level globals and are not covered by self.model from modules.caption import moondream3, joycaption, joytag, deepseek moondream3.unload() @@ -475,14 +476,14 @@ class VQA: """Load VLM model into memory for the specified model name.""" model_name = model_name or shared.opts.caption_vlm_model if not model_name: - shared.log.warning('VQA load: no model specified') + logger.log.warning('VQA load: no model specified') return repo = vlm_models.get(model_name) if repo is None: - shared.log.error(f'VQA load: unknown model="{model_name}"') + logger.log.error(f'VQA load: unknown model="{model_name}"') return - shared.log.debug(f'VQA load: pre-loading model="{model_name}" repo="{repo}"') + logger.log.debug(f'VQA load: pre-loading model="{model_name}" repo="{repo}"') # Dispatch to appropriate loader (same logic as caption) repo_lower = repo.lower() @@ -515,34 +516,34 @@ class VQA: elif 'moondream3' in repo_lower: from modules.caption import moondream3 moondream3.load_model(repo) - shared.log.info(f'VQA load: model="{model_name}" loaded (external handler)') + logger.log.info(f'VQA load: model="{model_name}" loaded (external handler)') return elif 'joytag' in repo_lower: from modules.caption import joytag joytag.load() - shared.log.info(f'VQA load: model="{model_name}" loaded (external handler)') + logger.log.info(f'VQA load: model="{model_name}" loaded (external handler)') return elif 'joycaption' in repo_lower: from modules.caption import joycaption joycaption.load(repo) - shared.log.info(f'VQA load: model="{model_name}" loaded (external handler)') + logger.log.info(f'VQA load: model="{model_name}" loaded (external handler)') return elif 'deepseek' in repo_lower: from modules.caption import deepseek deepseek.load(repo) - shared.log.info(f'VQA load: model="{model_name}" loaded (external handler)') + logger.log.info(f'VQA load: model="{model_name}" loaded (external handler)') return else: - shared.log.warning(f'VQA load: no pre-loader for model="{model_name}"') + logger.log.warning(f'VQA load: no pre-loader for model="{model_name}"') return sd_models.move_model(self.model, devices.device) - shared.log.info(f'VQA load: model="{model_name}" loaded') + logger.log.info(f'VQA load: model="{model_name}" loaded') def _load_fastvlm(self, repo: str): """Load FastVLM model and tokenizer.""" if self.model is None or self.loaded != repo: - shared.log.debug(f'Caption load: vlm="{repo}"') + logger.log.debug(f'Caption load: vlm="{repo}"') quant_args = model_quant.create_config(module='LLM') self.model = None self.processor = transformers.AutoTokenizer.from_pretrained(repo, trust_remote_code=True, cache_dir=shared.opts.hfcache_dir) @@ -596,7 +597,7 @@ class VQA: def _load_qwen(self, repo: str): """Load Qwen VL model and processor.""" if self.model is None or self.loaded != repo: - shared.log.debug(f'Caption load: vlm="{repo}"') + logger.log.debug(f'Caption load: vlm="{repo}"') self.model = None if 'Qwen3-VL' in repo or 'Qwen3VL' in repo: cls_name = transformers.Qwen3VLForConditionalGeneration @@ -720,7 +721,7 @@ class VQA: def _load_gemma(self, repo: str): """Load Gemma 3 model and processor.""" if self.model is None or self.loaded != repo: - shared.log.debug(f'Caption load: vlm="{repo}"') + logger.log.debug(f'Caption load: vlm="{repo}"') self.model = None if '3n' in repo: cls = transformers.Gemma3nForConditionalGeneration # pylint: disable=no-member @@ -834,7 +835,7 @@ class VQA: def _load_paligemma(self, repo: str): """Load PaliGemma model and processor.""" if self.model is None or self.loaded != repo: - shared.log.debug(f'Caption load: vlm="{repo}"') + logger.log.debug(f'Caption load: vlm="{repo}"') self.processor = transformers.PaliGemmaProcessor.from_pretrained(repo, cache_dir=shared.opts.hfcache_dir) self.model = None self.model = transformers.PaliGemmaForConditionalGeneration.from_pretrained( @@ -864,7 +865,7 @@ class VQA: def _load_ovis(self, repo: str): """Load Ovis model (requires flash-attn).""" if self.model is None or self.loaded != repo: - shared.log.debug(f'Caption load: vlm="{repo}"') + logger.log.debug(f'Caption load: vlm="{repo}"') self.model = None # Ovis remote code calls AutoConfig.register("aimv2", ...) at module scope # without exist_ok=True, which fails on reload or when the type is already @@ -889,7 +890,7 @@ class VQA: try: pass # pylint: disable=unused-import except Exception: - shared.log.error(f'Caption: vlm="{repo}" flash-attn is not available') + logger.log.error(f'Caption: vlm="{repo}" flash-attn is not available') return '' self._load_ovis(repo) sd_models.move_model(self.model, devices.device) @@ -921,7 +922,7 @@ class VQA: def _load_smol(self, repo: str): """Load SmolVLM model and processor.""" if self.model is None or self.loaded != repo: - shared.log.debug(f'Caption load: vlm="{repo}"') + logger.log.debug(f'Caption load: vlm="{repo}"') self.model = None quant_args = model_quant.create_config(module='LLM') self.model = transformers.AutoModelForVision2Seq.from_pretrained( @@ -1016,7 +1017,7 @@ class VQA: def _load_git(self, repo: str): """Load Microsoft GIT model and processor.""" if self.model is None or self.loaded != repo: - shared.log.debug(f'Caption load: vlm="{repo}"') + logger.log.debug(f'Caption load: vlm="{repo}"') self.model = None self.model = transformers.GitForCausalLM.from_pretrained( repo, @@ -1047,7 +1048,7 @@ class VQA: def _load_blip(self, repo: str): """Load Salesforce BLIP model and processor.""" if self.model is None or self.loaded != repo: - shared.log.debug(f'Caption load: vlm="{repo}"') + logger.log.debug(f'Caption load: vlm="{repo}"') self.model = None self.model = transformers.BlipForQuestionAnswering.from_pretrained( repo, @@ -1072,7 +1073,7 @@ class VQA: def _load_vilt(self, repo: str): """Load ViLT model and processor.""" if self.model is None or self.loaded != repo: - shared.log.debug(f'Caption load: vlm="{repo}"') + logger.log.debug(f'Caption load: vlm="{repo}"') self.model = None self.model = transformers.ViltForQuestionAnswering.from_pretrained( repo, @@ -1099,7 +1100,7 @@ class VQA: def _load_pix(self, repo: str): """Load Pix2Struct model and processor.""" if self.model is None or self.loaded != repo: - shared.log.debug(f'Caption load: vlm="{repo}"') + logger.log.debug(f'Caption load: vlm="{repo}"') self.model = None self.model = transformers.Pix2StructForConditionalGeneration.from_pretrained( repo, @@ -1127,7 +1128,7 @@ class VQA: def _load_moondream(self, repo: str): """Load Moondream 2 model and tokenizer.""" if self.model is None or self.loaded != repo: - shared.log.debug(f'Caption load: vlm="{repo}"') + logger.log.debug(f'Caption load: vlm="{repo}"') self.model = None self.model = transformers.AutoModelForCausalLM.from_pretrained( repo, @@ -1225,7 +1226,7 @@ class VQA: effective_revision = revision_from_repo if self.model is None or self.loaded != cache_key: - shared.log.debug(f'Caption load: vlm="{repo_name}" revision="{effective_revision}" path="{shared.opts.hfcache_dir}"') + logger.log.debug(f'Caption load: vlm="{repo_name}" revision="{effective_revision}" path="{shared.opts.hfcache_dir}"') transformers.dynamic_module_utils.get_imports = get_imports self.model = None quant_args = model_quant.create_config(module='LLM') @@ -1354,7 +1355,7 @@ class VQA: if image.mode != 'RGB': image = image.convert('RGB') if image is None: - shared.log.error(f'VQA caption: model="{model_name}" error="No input image provided"') + logger.log.error(f'VQA caption: model="{model_name}" error="No input image provided"') self._generation_overrides = None shared.state.end(jobid) return 'Error: No input image provided. Please upload or select an image.' @@ -1363,7 +1364,7 @@ class VQA: if question == "Use Prompt": # Use content from Prompt field directly - requires user input if not prompt or len(prompt.strip()) < 2: - shared.log.error(f'VQA caption: model="{model_name}" error="Please enter a prompt"') + logger.log.error(f'VQA caption: model="{model_name}" error="Please enter a prompt"') self._generation_overrides = None shared.state.end(jobid) return 'Error: Please enter a question or instruction in the Prompt field.' @@ -1374,7 +1375,7 @@ class VQA: if raw_mapping in ("POINT_MODE", "DETECT_MODE"): # These modes require user input in the prompt field if not prompt or len(prompt.strip()) < 2: - shared.log.error(f'VQA caption: model="{model_name}" error="Please specify what to find in the prompt field"') + logger.log.error(f'VQA caption: model="{model_name}" error="Please specify what to find in the prompt field"') self._generation_overrides = None shared.state.end(jobid) return 'Error: Please specify what to find in the prompt field (e.g., "the red car" or "faces").' @@ -1387,12 +1388,12 @@ class VQA: try: if model_name is None: - shared.log.error(f'Caption: type=vlm model="{model_name}" no model selected') + logger.log.error(f'Caption: type=vlm model="{model_name}" no model selected') shared.state.end(jobid) return '' vqa_model = vlm_models.get(model_name, None) if vqa_model is None: - shared.log.error(f'Caption: type=vlm model="{model_name}" unknown') + logger.log.error(f'Caption: type=vlm model="{model_name}" unknown') shared.state.end(jobid) return '' @@ -1484,7 +1485,7 @@ class VQA: debug(f'VQA caption: handler={handler} response_after_clean="{answer}" has_annotation={self.last_annotated_image is not None}') t1 = time.time() if not quiet: - shared.log.debug(f'Caption: type=vlm model="{model_name}" repo="{vqa_model}" args={get_kwargs()} time={t1-t0:.2f}') + logger.log.debug(f'Caption: type=vlm model="{model_name}" repo="{vqa_model}" args={get_kwargs()} time={t1-t0:.2f}') self._generation_overrides = None # Clear per-request overrides shared.state.end(jobid) return answer @@ -1518,7 +1519,7 @@ class VQA: from modules.files_cache import list_files files += list(list_files(batch_str, ext_filter=['.png', '.jpg', '.jpeg', '.webp', '.jxl'], recursive=recursive)) if len(files) == 0: - shared.log.warning('Caption batch: type=vlm no images') + logger.log.warning('Caption batch: type=vlm no images') return '' jobid = shared.state.begin('Caption batch') prompts = [] @@ -1529,7 +1530,7 @@ class VQA: shared.opts.caption_offload = False try: import rich.progress as rp - pbar = rp.Progress(rp.TextColumn('[cyan]Caption:'), rp.BarColumn(), rp.MofNCompleteColumn(), rp.TaskProgressColumn(), rp.TimeRemainingColumn(), rp.TimeElapsedColumn(), rp.TextColumn('[cyan]{task.description}'), console=shared.console) + pbar = rp.Progress(rp.TextColumn('[cyan]Caption:'), rp.BarColumn(), rp.MofNCompleteColumn(), rp.TaskProgressColumn(), rp.TimeRemainingColumn(), rp.TimeElapsedColumn(), rp.TextColumn('[cyan]{task.description}'), console=logger.console) with pbar: task = pbar.add_task(total=len(files), description='starting...') for file in files: @@ -1547,7 +1548,7 @@ class VQA: if write: writer.add(file, result) except Exception as e: - shared.log.error(f'Caption batch: {e}') + logger.log.error(f'Caption batch: {e}') if write: writer.close() finally: diff --git a/modules/caption/waifudiffusion.py b/modules/caption/waifudiffusion.py index 416a9b1bd..a1e679b57 100644 --- a/modules/caption/waifudiffusion.py +++ b/modules/caption/waifudiffusion.py @@ -8,11 +8,12 @@ import threading import numpy as np from PIL import Image from modules import shared, devices, errors +from modules import logger # Debug logging - enable with SD_CAPTION_DEBUG environment variable debug_enabled = os.environ.get('SD_CAPTION_DEBUG', None) is not None -debug_log = shared.log.trace if debug_enabled else lambda *args, **kwargs: None +debug_log = logger.log.trace if debug_enabled else lambda *args, **kwargs: None re_special = re.compile(r'([\\()])') load_lock = threading.Lock() @@ -56,7 +57,7 @@ class WaifuDiffusionTagger: if model_name is None: model_name = shared.opts.waifudiffusion_model if model_name not in WAIFUDIFFUSION_MODELS: - shared.log.error(f'WaifuDiffusion: unknown model "{model_name}"') + logger.log.error(f'WaifuDiffusion: unknown model "{model_name}"') return False with load_lock: @@ -71,7 +72,7 @@ class WaifuDiffusionTagger: repo_id = WAIFUDIFFUSION_MODELS[model_name] t0 = time.time() - shared.log.info(f'WaifuDiffusion load: model="{model_name}" repo="{repo_id}"') + logger.log.info(f'WaifuDiffusion load: model="{model_name}" repo="{repo_id}"') try: # Download only ONNX model and tags CSV (skip safetensors/msgpack variants) @@ -86,7 +87,7 @@ class WaifuDiffusionTagger: # Load ONNX model model_file = os.path.join(self.model_path, "model.onnx") if not os.path.exists(model_file): - shared.log.error(f'WaifuDiffusion load: model file not found: {model_file}') + logger.log.error(f'WaifuDiffusion load: model file not found: {model_file}') return False import onnxruntime as ort @@ -104,12 +105,12 @@ class WaifuDiffusionTagger: self._load_tags() load_time = time.time() - t0 - shared.log.debug(f'WaifuDiffusion load: time={load_time:.2f} tags={len(self.tags)}') + logger.log.debug(f'WaifuDiffusion load: time={load_time:.2f} tags={len(self.tags)}') debug_log(f'WaifuDiffusion load: input_name={self.session.get_inputs()[0].name} output_name={self.session.get_outputs()[0].name}') return True except Exception as e: - shared.log.error(f'WaifuDiffusion load: failed error={e}') + logger.log.error(f'WaifuDiffusion load: failed error={e}') errors.display(e, 'WaifuDiffusion load') self.unload() return False @@ -120,7 +121,7 @@ class WaifuDiffusionTagger: csv_path = os.path.join(self.model_path, "selected_tags.csv") if not os.path.exists(csv_path): - shared.log.error(f'WaifuDiffusion load: tags file not found: {csv_path}') + logger.log.error(f'WaifuDiffusion load: tags file not found: {csv_path}') return self.tags = [] @@ -141,7 +142,7 @@ class WaifuDiffusionTagger: def unload(self): """Unload the model and free resources.""" if self.session is not None: - shared.log.debug(f'WaifuDiffusion unload: model="{self.model_name}"') + logger.log.debug(f'WaifuDiffusion unload: model="{self.model_name}"') self.session = None self.tags = None self.tag_categories = None @@ -240,7 +241,7 @@ class WaifuDiffusionTagger: if isinstance(image, dict) and 'name' in image: image = Image.open(image['name']) if image is None: - shared.log.error('WaifuDiffusion predict: no image provided') + logger.log.error('WaifuDiffusion predict: no image provided') return '' # Load model if needed @@ -374,19 +375,19 @@ def tag(image: Image.Image, model_name: str = None, **kwargs) -> str: """ t0 = time.time() jobid = shared.state.begin('WaifuDiffusion Tag') - shared.log.info(f'WaifuDiffusion: model="{model_name or tagger.model_name or shared.opts.waifudiffusion_model}" image_size={image.size if image else None}') + logger.log.info(f'WaifuDiffusion: model="{model_name or tagger.model_name or shared.opts.waifudiffusion_model}" image_size={image.size if image else None}') try: if model_name and model_name != tagger.model_name: tagger.load(model_name) result = tagger.predict(image, **kwargs) - shared.log.debug(f'WaifuDiffusion: complete time={time.time()-t0:.2f} tags={len(result.split(", ")) if result else 0}') + logger.log.debug(f'WaifuDiffusion: complete time={time.time()-t0:.2f} tags={len(result.split(", ")) if result else 0}') # Offload model if setting enabled if shared.opts.caption_offload: tagger.unload() except Exception as e: result = f"Exception {type(e)}" - shared.log.error(f'WaifuDiffusion: {e}') + logger.log.error(f'WaifuDiffusion: {e}') errors.display(e, 'WaifuDiffusion Tag') shared.state.end(jobid) @@ -479,19 +480,19 @@ def batch( image_files = unique_files if not image_files: - shared.log.warning('WaifuDiffusion batch: no images found') + logger.log.warning('WaifuDiffusion batch: no images found') return '' t0 = time.time() jobid = shared.state.begin('WaifuDiffusion Batch') - shared.log.info(f'WaifuDiffusion batch: model="{tagger.model_name}" images={len(image_files)} write={save_output} append={save_append} recursive={recursive}') + logger.log.info(f'WaifuDiffusion batch: model="{tagger.model_name}" images={len(image_files)} write={save_output} append={save_append} recursive={recursive}') debug_log(f'WaifuDiffusion batch: files={[str(f) for f in image_files[:5]]}{"..." if len(image_files) > 5 else ""}') results = [] # Progress bar import rich.progress as rp - pbar = rp.Progress(rp.TextColumn('[cyan]WaifuDiffusion:'), rp.BarColumn(), rp.MofNCompleteColumn(), rp.TaskProgressColumn(), rp.TimeRemainingColumn(), rp.TimeElapsedColumn(), rp.TextColumn('[cyan]{task.description}'), console=shared.console) + pbar = rp.Progress(rp.TextColumn('[cyan]WaifuDiffusion:'), rp.BarColumn(), rp.MofNCompleteColumn(), rp.TaskProgressColumn(), rp.TimeRemainingColumn(), rp.TimeElapsedColumn(), rp.TextColumn('[cyan]{task.description}'), console=logger.console) with pbar: task = pbar.add_task(total=len(image_files), description='starting...') @@ -499,7 +500,7 @@ def batch( pbar.update(task, advance=1, description=str(img_path.name)) try: if shared.state.interrupted: - shared.log.info('WaifuDiffusion batch: interrupted') + logger.log.info('WaifuDiffusion batch: interrupted') break image = Image.open(img_path) @@ -512,11 +513,11 @@ def batch( results.append(f'{img_path.name}: {tags_str[:100]}...' if len(tags_str) > 100 else f'{img_path.name}: {tags_str}') except Exception as e: - shared.log.error(f'WaifuDiffusion batch: file="{img_path}" error={e}') + logger.log.error(f'WaifuDiffusion batch: file="{img_path}" error={e}') results.append(f'{img_path.name}: ERROR - {e}') elapsed = time.time() - t0 - shared.log.info(f'WaifuDiffusion batch: complete images={len(results)} time={elapsed:.1f}s') + logger.log.info(f'WaifuDiffusion batch: complete images={len(results)} time={elapsed:.1f}s') shared.state.end(jobid) return '\n'.join(results) diff --git a/modules/cfgzero/__init__.py b/modules/cfgzero/__init__.py index f8927eb9f..0e141c2da 100644 --- a/modules/cfgzero/__init__.py +++ b/modules/cfgzero/__init__.py @@ -1,6 +1,7 @@ # reference: from modules import shared, processing, sd_models +from modules import logger orig_pipeline = None @@ -48,7 +49,7 @@ def apply(p: processing.StableDiffusionProcessing): from modules.cfgzero.hunyuan_t2v_pipeline import HunyuanVideoCFGZeroPipeline shared.sd_model = sd_models.switch_pipe(HunyuanVideoCFGZeroPipeline, shared.sd_model) - shared.log.debug(f'Apply CFGZero: cls={cls} init={shared.opts.cfgzero_enabled} star={shared.opts.cfgzero_star} steps={shared.opts.cfgzero_steps}') + logger.log.debug(f'Apply CFGZero: cls={cls} init={shared.opts.cfgzero_enabled} star={shared.opts.cfgzero_star} steps={shared.opts.cfgzero_steps}') p.task_args['use_zero_init'] = shared.opts.cfgzero_enabled p.task_args['use_cfg_zero_star'] = shared.opts.cfgzero_star p.task_args['zero_steps'] = int(shared.opts.cfgzero_steps) diff --git a/modules/civitai/download_civitai.py b/modules/civitai/download_civitai.py index d12a00830..5bf81142b 100644 --- a/modules/civitai/download_civitai.py +++ b/modules/civitai/download_civitai.py @@ -3,6 +3,7 @@ import json import rich.progress as p from PIL import Image from modules import shared, errors, paths +from modules import logger pbar = None @@ -13,15 +14,15 @@ def save_video_frame(filepath: str): try: frames, fps, duration, w, h, codec, frame = video.get_video_params(filepath, capture=True) except Exception as e: - shared.log.error(f'Video: file={filepath} {e}') + logger.log.error(f'Video: file={filepath} {e}') return None if frame is not None: basename = os.path.splitext(filepath) thumb = f'{basename[0]}.thumb.jpg' - shared.log.debug(f'Video: file={filepath} frames={frames} fps={fps} size={w}x{h} codec={codec} duration={duration} thumb={thumb}') + logger.log.debug(f'Video: file={filepath} frames={frames} fps={fps} size={w}x{h} codec={codec} duration={duration} thumb={thumb}') frame.save(thumb) else: - shared.log.error(f'Video: file={filepath} no frames found') + logger.log.error(f'Video: file={filepath} no frames found') return frame @@ -33,11 +34,11 @@ def download_civit_meta(model_path: str, model_id): try: data = r.json() shared.writefile(data, filename=fn, mode='w', silent=True) - shared.log.info(f'CivitAI download: id={model_id} url={url} file="{fn}"') + logger.log.info(f'CivitAI download: id={model_id} url={url} file="{fn}"') return r.status_code, len(data), '' # code/size/note except Exception as e: errors.display(e, 'civitai meta') - shared.log.error(f'CivitAI meta: id={model_id} url={url} file="{fn}" {e}') + logger.log.error(f'CivitAI meta: id={model_id} url={url} file="{fn}" {e}') return r.status_code, '', str(e) return r.status_code, '', '' @@ -52,7 +53,7 @@ def download_civit_preview(model_path: str, preview_url: str): is_video = preview_file.lower().endswith('.mp4') is_json = preview_file.lower().endswith('.json') if is_json: - shared.log.warning(f'CivitAI download: url="{preview_url}" skip json') + logger.log.warning(f'CivitAI download: url="{preview_url}" skip json') return 500, '', 'exepected preview image got json' if os.path.exists(preview_file): return 304, '', 'already exists' @@ -64,7 +65,7 @@ def download_civit_preview(model_path: str, preview_url: str): img = None jobid = shared.state.begin('Download CivitAI') if pbar is None: - pbar = p.Progress(p.TextColumn('[cyan]Download'), p.DownloadColumn(), p.BarColumn(), p.TaskProgressColumn(), p.TimeRemainingColumn(), p.TimeElapsedColumn(), p.TransferSpeedColumn(), p.TextColumn('[yellow]{task.description}'), console=shared.console) + pbar = p.Progress(p.TextColumn('[cyan]Download'), p.DownloadColumn(), p.BarColumn(), p.TaskProgressColumn(), p.TimeRemainingColumn(), p.TimeElapsedColumn(), p.TransferSpeedColumn(), p.TextColumn('[yellow]{task.description}'), console=logger.console) try: with open(preview_file, 'wb') as f: with pbar: @@ -81,13 +82,13 @@ def download_civit_preview(model_path: str, preview_url: str): else: img = Image.open(preview_file) except Exception as e: - shared.log.error(f'CivitAI download error: url={preview_url} file="{preview_file}" written={written} {e}') + logger.log.error(f'CivitAI download error: url={preview_url} file="{preview_file}" written={written} {e}') shared.state.end(jobid) return 500, '', str(e) shared.state.end(jobid) if img is None: return 500, '', 'image is none' - shared.log.info(f'CivitAI download: url={preview_url} file="{preview_file}" size={total_size} image={img.size}') + logger.log.info(f'CivitAI download: url={preview_url} file="{preview_file}" size={total_size} image={img.size}') img.close() return 200, str(total_size), '' # code/size/note @@ -135,17 +136,17 @@ def download_civit_model_thread(model_name: str, model_url: str, model_path: str res = f'Model download: name="{model_name}" url="{model_url}" path="{model_path}" temp="{temp_file}"' if os.path.isfile(model_file): res += ' already exists' - shared.log.warning(res) + logger.log.warning(res) return res res += f' size={round((starting_pos + total_size)/1024/1024, 2)}Mb' - shared.log.info(res) + logger.log.info(res) jobid = shared.state.begin('Download CivitAI') block_size = 16384 # 16KB blocks written = starting_pos global pbar # pylint: disable=global-statement if pbar is None: - pbar = p.Progress(p.TextColumn('[cyan]{task.description}'), p.DownloadColumn(), p.BarColumn(), p.TaskProgressColumn(), p.TimeRemainingColumn(), p.TimeElapsedColumn(), p.TransferSpeedColumn(), p.TextColumn('[cyan]{task.fields[name]}'), console=shared.console) + pbar = p.Progress(p.TextColumn('[cyan]{task.description}'), p.DownloadColumn(), p.BarColumn(), p.TaskProgressColumn(), p.TimeRemainingColumn(), p.TimeElapsedColumn(), p.TransferSpeedColumn(), p.TextColumn('[cyan]{task.fields[name]}'), console=logger.console) with pbar: task = pbar.add_task(description="Download starting", total=starting_pos+total_size, name=model_name) try: @@ -153,7 +154,7 @@ def download_civit_model_thread(model_name: str, model_url: str, model_path: str for data in r.iter_content(block_size): if written == 0: try: # check if response is JSON message instead of bytes - shared.log.error(f'Model download: response={json.loads(data.decode("utf-8"))}') + logger.log.error(f'Model download: response={json.loads(data.decode("utf-8"))}') raise ValueError('response: type=json expected=bytes') except Exception: # this is good pass @@ -164,14 +165,14 @@ def download_civit_model_thread(model_name: str, model_url: str, model_path: str os.remove(temp_file) raise ValueError(f'removed invalid download: bytes={written}') except Exception as e: - shared.log.error(f'{res} {e}') + logger.log.error(f'{res} {e}') finally: pbar.stop_task(task) pbar.remove_task(task) if starting_pos+total_size != written: - shared.log.warning(f'{res} written={round(written/1024/1024)}Mb incomplete download') + logger.log.warning(f'{res} written={round(written/1024/1024)}Mb incomplete download') elif os.path.exists(temp_file): - shared.log.debug(f'Model download complete: temp="{temp_file}" path="{model_file}"') + logger.log.debug(f'Model download complete: temp="{temp_file}" path="{model_file}"') os.rename(temp_file, model_file) shared.state.end(jobid) if os.path.exists(model_file): @@ -183,7 +184,7 @@ def download_civit_model_thread(model_name: str, model_url: str, model_path: str def download_civit_model(model_url: str, model_name: str = '', model_path: str = '', model_type: str = '', token: str = None): import threading if model_url is None or len(model_url) == 0: - shared.log.error('Model download: no url provided') + logger.log.error('Model download: no url provided') return thread = threading.Thread(target=download_civit_model_thread, args=(model_name, model_url, model_path, model_type, token)) thread.start() diff --git a/modules/civitai/search_civitai.py b/modules/civitai/search_civitai.py index b30e32311..ee2796b86 100644 --- a/modules/civitai/search_civitai.py +++ b/modules/civitai/search_civitai.py @@ -2,7 +2,8 @@ from dataclasses import dataclass import os import json import time -from installer import install, log +from installer import install +from modules.logger import log full_dct = False diff --git a/modules/control/proc/dwpose/__init__.py b/modules/control/proc/dwpose/__init__.py index 222013b8a..8f1f223af 100644 --- a/modules/control/proc/dwpose/__init__.py +++ b/modules/control/proc/dwpose/__init__.py @@ -10,7 +10,8 @@ os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE" import cv2 import numpy as np from PIL import Image -from installer import installed, pip, log +from installer import installed, pip +from modules.logger import log from modules.control.util import HWC3, resize_image from .draw import draw_bodypose, draw_handpose, draw_facepose checked_ok = False diff --git a/modules/control/proc/mediapipe_face.py b/modules/control/proc/mediapipe_face.py index 04d90c02e..834d7910c 100644 --- a/modules/control/proc/mediapipe_face.py +++ b/modules/control/proc/mediapipe_face.py @@ -9,7 +9,8 @@ checked_ok = False def check_dependencies(): global checked_ok # pylint: disable=global-statement - from installer import installed, install, log + from installer import installed, install + from modules.logger import log packages = [('mediapipe', 'mediapipe')] for pkg in packages: if not installed(pkg[1], reload=True, quiet=True): diff --git a/modules/control/processor.py b/modules/control/processor.py index db5947fe6..3ef4d0956 100644 --- a/modules/control/processor.py +++ b/modules/control/processor.py @@ -5,13 +5,14 @@ import numpy as np from PIL import Image from modules.processing_class import StableDiffusionProcessingControl from modules import shared, images, masking, sd_models +from modules import logger from modules.timer import process as process_timer from modules.control import util from modules.control import processors as control_processors debug = os.environ.get('SD_CONTROL_DEBUG', None) is not None -debug_log = shared.log.trace if debug else lambda *args, **kwargs: None +debug_log = logger.log.trace if debug else lambda *args, **kwargs: None processors = [ 'None', 'OpenPose', @@ -137,7 +138,7 @@ def preprocess_image( except Exception: pass if any(img is None for img in processed_images): - shared.log.error('Control: one or more processed images are None') + logger.log.error('Control: one or more processed images are None') processed_images = [img for img in processed_images if img is not None] if len(processed_images) > 1 and len(active_process) != len(active_model): processed_image = [np.array(i) for i in processed_images] @@ -155,7 +156,7 @@ def preprocess_image( debug_log(f'Control: inputs match: input={len(processed_images)} models={len(selected_models)}') p.init_images = processed_images elif isinstance(selected_models, list) and len(processed_images) != len(selected_models): - shared.log.error(f'Control: number of inputs does not match: input={len(processed_images)} models={len(selected_models)}') + logger.log.error(f'Control: number of inputs does not match: input={len(processed_images)} models={len(selected_models)}') elif selected_models is not None: p.init_images = processed_image else: @@ -170,7 +171,7 @@ def preprocess_image( p.task_args['ref_image'] = p.ref_image debug_log(f'Control: process=None image={p.ref_image}') if p.ref_image is None: - shared.log.error('Control: reference mode without image') + logger.log.error('Control: reference mode without image') elif unit_type == 'controlnet' and has_models: if input_type == 0: # Control only if 'control_image' in possible: @@ -198,7 +199,7 @@ def preprocess_image( p.task_args['strength'] = p.denoising_strength elif input_type == 2: # Separate init image if init_image is None: - shared.log.warning('Control: separate init image not provided') + logger.log.warning('Control: separate init image not provided') init_image = input_image if 'inpaint_image' in possible: # flex p.task_args['inpaint_image'] = p.init_images[0] if isinstance(p.init_images, list) else p.init_images @@ -254,7 +255,7 @@ def preprocess_image( p.init_images = [input_image] elif input_type == 2: if init_image is None: - shared.log.warning('Control: separate init image not provided') + logger.log.warning('Control: separate init image not provided') init_image = input_image p.init_images = [init_image] diff --git a/modules/control/processors.py b/modules/control/processors.py index 2968443fe..6ea2d0808 100644 --- a/modules/control/processors.py +++ b/modules/control/processors.py @@ -2,7 +2,7 @@ import os import time import numpy as np from PIL import Image -from installer import log +from modules.logger import log from modules.errors import display from modules import devices, images diff --git a/modules/control/run.py b/modules/control/run.py index f678fcf1d..66a7275e6 100644 --- a/modules/control/run.py +++ b/modules/control/run.py @@ -13,6 +13,7 @@ from modules.control.units import t2iadapter # TencentARC T2I-Adapter from modules.control.units import reference # ControlNet-Reference from modules.control.processor import preprocess_image from modules import devices, shared, errors, processing, images, sd_models, sd_vae, scripts_manager, masking +from modules import logger from modules.processing_class import StableDiffusionProcessingControl from modules.ui_common import infotext_to_html from modules.api import script @@ -21,7 +22,7 @@ from modules.paths import resolve_output_path debug = os.environ.get('SD_CONTROL_DEBUG', None) is not None -debug_log = shared.log.trace if debug else lambda *args, **kwargs: None +debug_log = logger.log.trace if debug else lambda *args, **kwargs: None pipe = None instance = None original_pipeline = None @@ -36,7 +37,7 @@ def restore_pipeline(): if (original_pipeline is not None) and (original_pipeline.__class__.__name__ != shared.sd_model.__class__.__name__): if debug: fn = f'{sys._getframe(2).f_code.co_name}:{sys._getframe(1).f_code.co_name}' # pylint: disable=protected-access - shared.log.trace(f'Control restored pipeline: class={shared.sd_model.__class__.__name__} to={original_pipeline.__class__.__name__} fn={fn}') + logger.log.trace(f'Control restored pipeline: class={shared.sd_model.__class__.__name__} to={original_pipeline.__class__.__name__} fn={fn}') shared.sd_model = original_pipeline pipe = None instance = None @@ -45,7 +46,7 @@ def restore_pipeline(): def terminate(msg): restore_pipeline() - shared.log.error(f'Control terminated: {msg}') + logger.log.error(f'Control terminated: {msg}') return msg @@ -67,7 +68,7 @@ def set_pipe(p, has_models, unit_type, selected_models, active_model, active_str pipe = None if has_models and not has_inputs(inits) and not has_inputs(inputs): if not any(has_inputs(u.override) for u in active_units if u.enabled): # check overrides - shared.log.error('Control: no input images') + logger.log.error('Control: no input images') return pipe if has_models: p.ops.append('control') @@ -85,7 +86,7 @@ def set_pipe(p, has_models, unit_type, selected_models, active_model, active_str instance = t2iadapter.AdapterPipeline(selected_models, shared.sd_model) pipe = instance.pipeline if inits is not None: - shared.log.warning('Control: T2I-Adapter does not support separate init image') + logger.log.warning('Control: T2I-Adapter does not support separate init image') elif unit_type == 'controlnet' and has_models: p.extra_generation_params["Control type"] = 'ControlNet' if shared.sd_model_type == 'f1': @@ -108,14 +109,14 @@ def set_pipe(p, has_models, unit_type, selected_models, active_model, active_str instance = xs.ControlNetXSPipeline(selected_models, shared.sd_model) pipe = instance.pipeline if inits is not None: - shared.log.warning('Control: ControlNet-XS does not support separate init image') + logger.log.warning('Control: ControlNet-XS does not support separate init image') elif unit_type == 'lite' and has_models: p.extra_generation_params["Control type"] = 'ControlLLLite' p.controlnet_conditioning_scale = control_conditioning instance = lite.ControlLLitePipeline(shared.sd_model) pipe = instance.pipeline if inits is not None: - shared.log.warning('Control: ControlLLLite does not support separate init image') + logger.log.warning('Control: ControlLLLite does not support separate init image') elif unit_type == 'reference' and has_models: p.extra_generation_params["Control type"] = 'Reference' p.extra_generation_params["Control attention"] = p.attention @@ -127,7 +128,7 @@ def set_pipe(p, has_models, unit_type, selected_models, active_model, active_str instance = reference.ReferencePipeline(shared.sd_model) pipe = instance.pipeline if inits is not None: - shared.log.warning('Control: ControlNet-XS does not support separate init image') + logger.log.warning('Control: ControlNet-XS does not support separate init image') else: # run in txt2img/img2img mode if len(active_strength) > 0: p.strength = active_strength[0] @@ -166,7 +167,7 @@ def check_active(p, unit_type, units): active_strength.append(float(u.strength)) p.adapter_conditioning_factor = u.factor active_units.append(u) - shared.log.debug(f'Control T2I-Adapter unit: i={num_units} process="{u.process.processor_id}" model="{u.adapter.model_id}" strength={u.strength} factor={u.factor}') + logger.log.debug(f'Control T2I-Adapter unit: i={num_units} process="{u.process.processor_id}" model="{u.adapter.model_id}" strength={u.strength} factor={u.factor}') elif unit_type == 'controlnet' and (u.controlnet.model is not None or is_unified_model()): active_process.append(u.process) active_model.append(u.controlnet) @@ -182,7 +183,7 @@ def check_active(p, unit_type, units): p.is_tile = p.is_tile or 'tile' in u.mode.lower() p.control_tile = u.tile p.extra_generation_params["Control mode"] = u.mode - shared.log.debug(f'Control unit: i={num_units} type=ControlNet process="{u.process.processor_id}" model="{u.controlnet.model_id}" strength={u.strength} guess={u.guess} start={u.start} end={u.end} mode={u.mode}') + logger.log.debug(f'Control unit: i={num_units} type=ControlNet process="{u.process.processor_id}" model="{u.controlnet.model_id}" strength={u.strength} guess={u.guess} start={u.start} end={u.end} mode={u.mode}') elif unit_type == 'xs' and u.controlnet.model is not None: active_process.append(u.process) active_model.append(u.controlnet) @@ -190,13 +191,13 @@ def check_active(p, unit_type, units): active_start.append(float(u.start)) active_end.append(float(u.end)) active_units.append(u) - shared.log.debug(f'Control unit: i={num_units} type=ControlNetXS process={u.process.processor_id} model={u.controlnet.model_id} strength={u.strength} guess={u.guess} start={u.start} end={u.end}') + logger.log.debug(f'Control unit: i={num_units} type=ControlNetXS process={u.process.processor_id} model={u.controlnet.model_id} strength={u.strength} guess={u.guess} start={u.start} end={u.end}') elif unit_type == 'lite' and u.controlnet.model is not None: active_process.append(u.process) active_model.append(u.controlnet) active_strength.append(float(u.strength)) active_units.append(u) - shared.log.debug(f'Control unit: i={num_units} type=ControlLLite process={u.process.processor_id} model={u.controlnet.model_id} strength={u.strength} guess={u.guess} start={u.start} end={u.end}') + logger.log.debug(f'Control unit: i={num_units} type=ControlLLite process={u.process.processor_id} model={u.controlnet.model_id} strength={u.strength} guess={u.guess} start={u.start} end={u.end}') elif unit_type == 'reference': p.override = u.override p.attention = u.attention @@ -204,12 +205,12 @@ def check_active(p, unit_type, units): p.adain_weight = float(u.adain_weight) p.fidelity = u.fidelity active_units.append(u) - shared.log.debug('Control Reference unit') + logger.log.debug('Control Reference unit') else: if u.process.processor_id is not None: active_process.append(u.process) active_units.append(u) - shared.log.debug(f'Control unit: i={num_units} type=Process process={u.process.processor_id}') + logger.log.debug(f'Control unit: i={num_units} type=Process process={u.process.processor_id}') active_strength.append(float(u.strength)) debug_log(f'Control active: process={len(active_process)} model={len(active_model)}') return active_process, active_model, active_strength, active_start, active_end, active_units @@ -320,7 +321,7 @@ def control_run(state: str = '', # pylint: disable=keyword-arg-before-vararg input_type = 1 # inpaint always requires control_image if sampler_index is None: - shared.log.warning('Sampler: invalid') + logger.log.warning('Sampler: invalid') sampler_index = 0 if hr_sampler_index is None: hr_sampler_index = sampler_index @@ -427,13 +428,13 @@ def control_run(state: str = '', # pylint: disable=keyword-arg-before-vararg # TODO modernui: monkey-patch for missing tabs.select event if p.selected_scale_tab_before == 0 and p.resize_name_before != 'None' and p.scale_by_before != 1 and inputs is not None and len(inputs) > 0: - shared.log.debug('Control: override resize mode=before') + logger.log.debug('Control: override resize mode=before') p.selected_scale_tab_before = 1 if p.selected_scale_tab_after == 0 and p.resize_name_after != 'None' and p.scale_by_after != 1: - shared.log.debug('Control: override resize mode=after') + logger.log.debug('Control: override resize mode=after') p.selected_scale_tab_after = 1 if p.selected_scale_tab_mask == 0 and p.resize_name_mask != 'None' and p.scale_by_mask != 1: - shared.log.debug('Control: override resize mode=mask') + logger.log.debug('Control: override resize mode=mask') p.selected_scale_tab_mask = 1 # hires/refine defined outside of main init @@ -449,7 +450,7 @@ def control_run(state: str = '', # pylint: disable=keyword-arg-before-vararg p_extra_args = {} if shared.sd_model is None: - shared.log.warning('Aborted: op=control model not loaded') + logger.log.warning('Aborted: op=control model not loaded') return [], '', '', 'Error: model not loaded' unit_type = unit_type.strip().lower() if unit_type is not None else '' @@ -491,7 +492,7 @@ def control_run(state: str = '', # pylint: disable=keyword-arg-before-vararg if isinstance(inputs, str) and os.path.exists(inputs): # only video, the rest is a list if input_type == 2: # separate init image if isinstance(inits, str) and inits != inputs: - shared.log.warning('Control: separate init video not support for video input') + logger.log.warning('Control: separate init video not support for video input') input_type = 1 try: video = cv2.VideoCapture(inputs) @@ -507,7 +508,7 @@ def control_run(state: str = '', # pylint: disable=keyword-arg-before-vararg if status: shared.state.frame_count = 1 + frames // (video_skip_frames + 1) frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) - shared.log.debug(f'Control: input video: path={inputs} frames={frames} fps={fps} size={w}x{h} codec={codec}') + logger.log.debug(f'Control: input video: path={inputs} frames={frames} fps={fps} size={w}x{h} codec={codec}') except Exception as e: if is_generator: yield terminate(f'Video open failed: path={inputs} {e}') @@ -539,7 +540,7 @@ def control_run(state: str = '', # pylint: disable=keyword-arg-before-vararg try: input_image = Image.open(input_image) except Exception as e: - shared.log.error(f'Control: image open failed: path={input_image} type=control error={e}') + logger.log.error(f'Control: image open failed: path={input_image} type=control error={e}') continue # match init input if input_type == 1: @@ -553,7 +554,7 @@ def control_run(state: str = '', # pylint: disable=keyword-arg-before-vararg try: init_image = Image.open(inits[i]) except Exception as e: - shared.log.error(f'Control: image open failed: path={inits[i]} type=init error={e}') + logger.log.error(f'Control: image open failed: path={inits[i]} type=init error={e}') continue else: debug_log(f'Control Init image: {i % len(inits) + 1} of {len(inits)}') @@ -576,7 +577,7 @@ def control_run(state: str = '', # pylint: disable=keyword-arg-before-vararg and getattr(p, 'init_images', None) is None \ and getattr(p, 'image', None) is None: if is_generator: - shared.log.debug(f'Control args: {p.task_args}') + logger.log.debug(f'Control args: {p.task_args}') yield terminate(f'Mode={p.extra_generation_params.get("Control type", None)} input image is none') return [], '', '', 'Error: Input image is none' if unit_type == 'lite': @@ -666,7 +667,7 @@ def control_run(state: str = '', # pylint: disable=keyword-arg-before-vararg debug_log(f'Control: pipeline units={len(active_model)} process={len(active_process)} outputs={len(output_images)}') except Exception as e: - shared.log.error(f'Control: type={unit_type} units={len(active_model)} {e}') + logger.log.error(f'Control: type={unit_type} units={len(active_model)} {e}') errors.display(e, 'Control') if len(output_images) == 0: diff --git a/modules/control/test.py b/modules/control/test.py index 879e1e0ae..15548008e 100644 --- a/modules/control/test.py +++ b/modules/control/test.py @@ -1,6 +1,7 @@ import math from PIL import Image, ImageChops, ImageDraw from modules import shared, errors, images +from modules import logger FONT_SIZE=48 @@ -9,17 +10,17 @@ FONT_SIZE=48 def test_processors(image): from modules.control import processors if image is None: - shared.log.error('Image not loaded') + logger.log.error('Image not loaded') return None, None, None res = [] for processor_id in processors.list_models(): if shared.state.interrupted: continue - shared.log.info(f'Testing processor: {processor_id}') + logger.log.info(f'Testing processor: {processor_id}') processor = processors.Processor(processor_id) output = image if processor is None: - shared.log.error(f'Processor load failed: id="{processor_id}"') + logger.log.error(f'Processor load failed: id="{processor_id}"') processor_id = f'{processor_id} error' else: output = processor(image) @@ -29,7 +30,7 @@ def test_processors(image): output = output.resize(image.size, Image.Resampling.LANCZOS) if output.mode != image.mode: output = output.convert(image.mode) - shared.log.debug(f'Testing processor: input={image} mode={image.mode} output={output} mode={output.mode}') + logger.log.debug(f'Testing processor: input={image} mode={image.mode} output={output} mode={output.mode}') diff = ImageChops.difference(image, output) if not diff.getbbox(): processor_id = f'{processor_id} null' @@ -44,7 +45,7 @@ def test_processors(image): w, h = 256, 256 size = (cols * w + cols, rows * h + rows) grid = Image.new('RGB', size=size, color='black') - shared.log.info(f'Test processors: images={len(res)} grid={grid}') + logger.log.info(f'Test processors: images={len(res)} grid={grid}') for i, image in enumerate(res): x = (i % cols * w) + (i % cols) y = (i // cols * h) + (i // cols) @@ -59,7 +60,7 @@ def test_controlnets(prompt, negative, image): from modules import devices, sd_models from modules.control.units import controlnet if image is None: - shared.log.error('Image not loaded') + logger.log.error('Image not loaded') return None, None, None res = [] for model_id in controlnet.list_models(): @@ -71,9 +72,9 @@ def test_controlnets(prompt, negative, image): if model_id != 'None': controlnet = controlnet.ControlNet(model_id=model_id, device=devices.device, dtype=devices.dtype) if controlnet is None: - shared.log.error(f'ControlNet load failed: id="{model_id}"') + logger.log.error(f'ControlNet load failed: id="{model_id}"') continue - shared.log.info(f'Testing ControlNet: {model_id}') + logger.log.info(f'Testing ControlNet: {model_id}') pipe = controlnet.ControlNetPipeline(controlnet=controlnet.model, pipeline=shared.sd_model) pipe.pipeline.to(device=devices.device, dtype=devices.dtype) sd_models.set_diffuser_options(pipe) @@ -95,7 +96,7 @@ def test_controlnets(prompt, negative, image): w, h = 256, 256 size = (cols * w + cols, rows * h + rows) grid = Image.new('RGB', size=size, color='black') - shared.log.info(f'Test ControlNets: images={len(res)} grid={grid}') + logger.log.info(f'Test ControlNets: images={len(res)} grid={grid}') for i, image in enumerate(res): x = (i % cols * w) + (i % cols) y = (i // cols * h) + (i // cols) @@ -110,7 +111,7 @@ def test_adapters(prompt, negative, image): from modules import devices, sd_models from modules.control.units import t2iadapter if image is None: - shared.log.error('Image not loaded') + logger.log.error('Image not loaded') return None, None, None res = [] for model_id in t2iadapter.list_models(): @@ -122,9 +123,9 @@ def test_adapters(prompt, negative, image): if model_id != 'None': adapter = t2iadapter.Adapter(model_id=model_id, device=devices.device, dtype=devices.dtype) if adapter is None: - shared.log.error(f'Adapter load failed: id="{model_id}"') + logger.log.error(f'Adapter load failed: id="{model_id}"') continue - shared.log.info(f'Testing Adapter: {model_id}') + logger.log.info(f'Testing Adapter: {model_id}') pipe = t2iadapter.AdapterPipeline(adapter=adapter.model, pipeline=shared.sd_model) pipe.pipeline.to(device=devices.device, dtype=devices.dtype) sd_models.set_diffuser_options(pipe) @@ -147,7 +148,7 @@ def test_adapters(prompt, negative, image): w, h = 256, 256 size = (cols * w + cols, rows * h + rows) grid = Image.new('RGB', size=size, color='black') - shared.log.info(f'Test Adapters: images={len(res)} grid={grid}') + logger.log.info(f'Test Adapters: images={len(res)} grid={grid}') for i, image in enumerate(res): x = (i % cols * w) + (i % cols) y = (i // cols * h) + (i // cols) @@ -162,7 +163,7 @@ def test_xs(prompt, negative, image): from modules import devices, sd_models from modules.control.units import xs if image is None: - shared.log.error('Image not loaded') + logger.log.error('Image not loaded') return None, None, None res = [] for model_id in xs.list_models(): @@ -174,9 +175,9 @@ def test_xs(prompt, negative, image): if model_id != 'None': xs = xs.ControlNetXS(model_id=model_id, device=devices.device, dtype=devices.dtype) if xs is None: - shared.log.error(f'ControlNet-XS load failed: id="{model_id}"') + logger.log.error(f'ControlNet-XS load failed: id="{model_id}"') continue - shared.log.info(f'Testing ControlNet-XS: {model_id}') + logger.log.info(f'Testing ControlNet-XS: {model_id}') pipe = xs.ControlNetXSPipeline(controlnet=xs.model, pipeline=shared.sd_model) pipe.pipeline.to(device=devices.device, dtype=devices.dtype) sd_models.set_diffuser_options(pipe) @@ -198,7 +199,7 @@ def test_xs(prompt, negative, image): w, h = 256, 256 size = (cols * w + cols, rows * h + rows) grid = Image.new('RGB', size=size, color='black') - shared.log.info(f'Test ControlNet-XS: images={len(res)} grid={grid}') + logger.log.info(f'Test ControlNet-XS: images={len(res)} grid={grid}') for i, image in enumerate(res): x = (i % cols * w) + (i % cols) y = (i // cols * h) + (i // cols) @@ -213,7 +214,7 @@ def test_lite(prompt, negative, image): from modules import devices, sd_models from modules.control.units import lite if image is None: - shared.log.error('Image not loaded') + logger.log.error('Image not loaded') return None, None, None res = [] for model_id in lite.list_models(): @@ -225,9 +226,9 @@ def test_lite(prompt, negative, image): if model_id != 'None': lite = lite.ControlLLLite(model_id=model_id, device=devices.device, dtype=devices.dtype) if lite is None: - shared.log.error(f'Control-LLite load failed: id="{model_id}"') + logger.log.error(f'Control-LLite load failed: id="{model_id}"') continue - shared.log.info(f'Testing ControlNet-XS: {model_id}') + logger.log.info(f'Testing ControlNet-XS: {model_id}') pipe = lite.ControlLLitePipeline(pipeline=shared.sd_model) pipe.apply(controlnet=lite.model, image=image, conditioning=1.0) pipe.pipeline.to(device=devices.device, dtype=devices.dtype) @@ -250,7 +251,7 @@ def test_lite(prompt, negative, image): w, h = 256, 256 size = (cols * w + cols, rows * h + rows) grid = Image.new('RGB', size=size, color='black') - shared.log.info(f'Test ControlNet-XS: images={len(res)} grid={grid}') + logger.log.info(f'Test ControlNet-XS: images={len(res)} grid={grid}') for i, image in enumerate(res): x = (i % cols * w) + (i % cols) y = (i // cols * h) + (i // cols) diff --git a/modules/control/tile.py b/modules/control/tile.py index 1d6478edc..3dd864146 100644 --- a/modules/control/tile.py +++ b/modules/control/tile.py @@ -1,6 +1,7 @@ import time from PIL import Image from modules import shared, processing, images, sd_models, sd_vae +from modules import logger def get_tile(image: Image.Image, x: int, y: int, sx: int, sy: int) -> Image.Image: @@ -37,7 +38,7 @@ def run_tiling(p: processing.StableDiffusionProcessing, input_image: Image.Image w, h = vae_scale_factor * int(sx * init_image.width) // vae_scale_factor, vae_scale_factor * int(sy * init_image.height) // vae_scale_factor init_upscaled = images.resize_image(resize_mode=1 if sx==sy else 5, im=init_image, width=w, height=h, context='add with forward') t1 = time.time() - shared.log.debug(f'Control Tile: scale={sx}x{sy} resize={"fixed" if sx==sy else "context"} control={control_upscaled} init={init_upscaled} time={t1-t0:.3f}') + logger.log.debug(f'Control Tile: scale={sx}x{sy} resize={"fixed" if sx==sy else "context"} control={control_upscaled} init={init_upscaled} time={t1-t0:.3f}') # stop processing from restoring pipeline on each iteration orig_restore_pipeline = getattr(shared.sd_model, 'restore_pipeline', None) @@ -46,7 +47,7 @@ def run_tiling(p: processing.StableDiffusionProcessing, input_image: Image.Image # run tiling for x in range(sx): for y in range(sy): - shared.log.info(f'Control Tile: tile={x+1}-{sx}/{y+1}-{sy} target={control_upscaled}') + logger.log.info(f'Control Tile: tile={x+1}-{sx}/{y+1}-{sy} target={control_upscaled}') shared.sd_model = sd_models.set_diffuser_pipe(shared.sd_model, sd_models.DiffusersTaskType.IMAGE_2_IMAGE) p.init_images = None p.task_args['control_mode'] = p.control_mode @@ -70,5 +71,5 @@ def run_tiling(p: processing.StableDiffusionProcessing, input_image: Image.Image if hasattr(shared.sd_model, 'restore_pipeline') and shared.sd_model.restore_pipeline is not None: shared.sd_model.restore_pipeline() t2 = time.time() - shared.log.debug(f'Control Tile: image={control_upscaled} time={t2-t0:.3f}') + logger.log.debug(f'Control Tile: image={control_upscaled} time={t2-t0:.3f}') return processed diff --git a/modules/control/unit.py b/modules/control/unit.py index 94f104558..43a9561aa 100644 --- a/modules/control/unit.py +++ b/modules/control/unit.py @@ -1,6 +1,6 @@ from PIL import Image import gradio as gr -from installer import log +from modules.logger import log from modules.control import processors from modules.control.units import controlnet from modules.control.units import xs diff --git a/modules/control/units/t2iadapter.py b/modules/control/units/t2iadapter.py index b9e049779..5bdf99fb8 100644 --- a/modules/control/units/t2iadapter.py +++ b/modules/control/units/t2iadapter.py @@ -3,7 +3,7 @@ import time from typing import Union import threading from diffusers import StableDiffusionPipeline, StableDiffusionXLPipeline, T2IAdapter, MultiAdapter, StableDiffusionAdapterPipeline, StableDiffusionXLAdapterPipeline # pylint: disable=unused-import -from installer import log +from modules.logger import log from modules import errors, sd_models from modules.control.units import detect diff --git a/modules/dml/__init__.py b/modules/dml/__init__.py index 82376c2d3..d35128a7e 100644 --- a/modules/dml/__init__.py +++ b/modules/dml/__init__.py @@ -1,3 +1,4 @@ +from modules import logger import platform from typing import NamedTuple, Optional from collections.abc import Callable @@ -108,9 +109,9 @@ def directml_override_opts(): if getattr(shared.opts, key) != item.value and (item.condition is None or item.condition(shared.opts)): count += 1 setattr(shared.opts, key, item.value) - shared.log.warning(f'Overriding: {key}={item.value} {item.message if item.message is not None else ""}') + logger.log.warning(f'Overriding: {key}={item.value} {item.message if item.message is not None else ""}') if count > 0: - shared.log.info(f'Options override: count={count}. If you want to keep them from overriding, run with --experimental argument.') + logger.log.info(f'Options override: count={count}. If you want to keep them from overriding, run with --experimental argument.') _set_memory_provider() diff --git a/modules/dml/hijack/realesrgan_model.py b/modules/dml/hijack/realesrgan_model.py index b951765d0..afcda99c8 100644 --- a/modules/dml/hijack/realesrgan_model.py +++ b/modules/dml/hijack/realesrgan_model.py @@ -1,7 +1,7 @@ import math import torch from modules.postprocess.realesrgan_model_arch import RealESRGANer -from installer import log +from modules.logger import log # DML Solution: Some of contents of output tensor turn to 0 after Extended Slices. Move it to cpu. diff --git a/modules/errors.py b/modules/errors.py index 110b1f5bb..24dabc808 100644 --- a/modules/errors.py +++ b/modules/errors.py @@ -1,6 +1,6 @@ import logging import warnings -from installer import get_log, get_console, setup_logging, install_traceback +from modules.logger import get_log, get_console, setup_logging, install_traceback from modules.errorlimiter import ErrorLimiterAbort diff --git a/modules/extensions.py b/modules/extensions.py index c2643a4ad..7d9543eb4 100644 --- a/modules/extensions.py +++ b/modules/extensions.py @@ -3,6 +3,7 @@ import os from datetime import datetime, timezone import git from modules import shared, errors +from modules import logger from modules.paths import extensions_dir, extensions_builtin_dir @@ -98,7 +99,7 @@ def temp_disable_extensions(): shared.opts.data['theme_type'] = 'None' shared.opts.data['gradio_theme'] = theme_name else: - shared.log.error(f'UI theme invalid: theme="{theme_name}" available={["standard/*", "modern/*", "none/*"]} fallback="standard/black-teal"') + logger.log.error(f'UI theme invalid: theme="{theme_name}" available={["standard/*", "modern/*", "none/*"]} fallback="standard/black-teal"') shared.opts.data['theme_type'] = 'Standard' shared.opts.data['gradio_theme'] = 'black-teal' @@ -155,7 +156,7 @@ class Extension: try: self.status = 'unknown' if len(repo.remotes) == 0: - shared.log.debug(f"Extension: no remotes info repo={self.name}") + logger.log.debug(f"Extension: no remotes info repo={self.name}") return self.git_name = repo.remotes.origin.url.split('.git')[0].split('/')[-1] self.description = repo.description @@ -172,7 +173,7 @@ class Extension: self.commit_hash = head.hexsha self.version = f"

{self.commit_hash[:8]}

{format_dt(ts2utc(self.commit_date))}

" except Exception as ex: - shared.log.error(f"Extension: failed reading data from git repo={self.name}: {ex}") + logger.log.error(f"Extension: failed reading data from git repo={self.name}: {ex}") self.remote = None def list_files(self, subdir, extension): @@ -190,7 +191,7 @@ class Extension: priority = str(f.read().strip()) res.append(scripts_manager.ScriptFile(self.path, filename, os.path.join(dirpath, filename), priority)) if priority != '50': - shared.log.debug(f'Extension priority override: {os.path.dirname(dirpath)}:{priority}') + logger.log.debug(f'Extension priority override: {os.path.dirname(dirpath)}:{priority}') res = [x for x in res if os.path.splitext(x.path)[1].lower() == extension and os.path.isfile(x.path)] return res @@ -233,7 +234,7 @@ def list_extensions(): if not os.path.isdir(extensions_dir): return if shared.opts.disable_all_extensions == "all" or shared.opts.disable_all_extensions == "user": - shared.log.warning(f"Option set: Disable extensions: {shared.opts.disable_all_extensions}") + logger.log.warning(f"Option set: Disable extensions: {shared.opts.disable_all_extensions}") extension_paths = [] extension_names = [] extension_folders = [extensions_builtin_dir] if shared.cmd_opts.safe else [extensions_builtin_dir, extensions_dir] @@ -245,7 +246,7 @@ def list_extensions(): if not os.path.isdir(path): continue if extension_dirname in extension_names: - shared.log.info(f'Skipping conflicting extension: {path}') + logger.log.info(f'Skipping conflicting extension: {path}') continue extension_names.append(extension_dirname) extension_paths.append((extension_dirname, path, dirname == extensions_builtin_dir)) @@ -256,4 +257,4 @@ def list_extensions(): enabled = dirname.lower() not in disabled_extensions extension = Extension(name=dirname, path=path, enabled=enabled, is_builtin=is_builtin) extensions.append(extension) - shared.log.debug(f'Extensions: disabled={[e.name for e in extensions if not e.enabled]}') + logger.log.debug(f'Extensions: disabled={[e.name for e in extensions if not e.enabled]}') diff --git a/modules/extra_networks.py b/modules/extra_networks.py index 66edf76a3..33201f524 100644 --- a/modules/extra_networks.py +++ b/modules/extra_networks.py @@ -2,6 +2,7 @@ import re import inspect from collections import defaultdict from modules import errors, shared +from modules import logger extra_network_registry = {} @@ -89,14 +90,14 @@ def activate(p, extra_network_data=None, step=0, include=None, exclude=None): stepwise = stepwise or is_stepwise(extra_network_args) functional = shared.opts.lora_functional if shared.opts.lora_force_diffusers and stepwise: - shared.log.warning("Network load: type=LoRA method=composable loader=diffusers not compatible") + logger.log.warning("Network load: type=LoRA method=composable loader=diffusers not compatible") stepwise = False shared.opts.data['lora_functional'] = stepwise or functional for extra_network_name, extra_network_args in extra_network_data.items(): extra_network = extra_network_registry.get(extra_network_name, None) if extra_network is None: - errors.log.warning(f"Skipping unknown extra network: {extra_network_name}") + logger.log.warning(f"Skipping unknown extra network: {extra_network_name}") continue try: signature = list(inspect.signature(extra_network.activate).parameters) diff --git a/modules/extras.py b/modules/extras.py index 7b2c9e6d6..6a8ffbd78 100644 --- a/modules/extras.py +++ b/modules/extras.py @@ -9,6 +9,7 @@ import gradio as gr import safetensors.torch from modules.merging import merge, merge_utils, modules_sdxl from modules import shared, images, sd_models, sd_vae, sd_samplers, devices +from modules import logger def run_pnginfo(image): @@ -35,7 +36,7 @@ def run_modelmerger(id_task, **kwargs): # pylint: disable=unused-argument try: pass # pylint: disable=unused-import except Exception as e: - shared.log.error(f"Merge: {e}") + logger.log.error(f"Merge: {e}") return [*[gr.update() for _ in range(4)], "tensordict not available"] jobid = shared.state.begin('Merge') @@ -74,7 +75,7 @@ def run_modelmerger(id_task, **kwargs): # pylint: disable=unused-argument assert len(alpha) == 26 or len(alpha) == 20, "Alpha Block Weights are wrong length (26 or 20 for SDXL)" kwargs["alpha"] = alpha except KeyError as ke: - shared.log.warning(f"Merge: Malformed manual block weight: {ke}") + logger.log.warning(f"Merge: Malformed manual block weight: {ke}") elif kwargs.get("alpha_preset", None) or kwargs.get("alpha", None): kwargs["alpha"] = kwargs.get("alpha_preset", kwargs["alpha"]) @@ -91,7 +92,7 @@ def run_modelmerger(id_task, **kwargs): # pylint: disable=unused-argument assert len(beta) == 26 or len(beta) == 20, "Beta Block Weights are wrong length (26 or 20 for SDXL)" kwargs["beta"] = beta except KeyError as ke: - shared.log.warning(f"Merge: Malformed manual block weight: {ke}") + logger.log.warning(f"Merge: Malformed manual block weight: {ke}") elif kwargs.get("beta_preset", None) or kwargs.get("beta", None): kwargs["beta"] = kwargs.get("beta_preset", kwargs["beta"]) @@ -123,7 +124,7 @@ def run_modelmerger(id_task, **kwargs): # pylint: disable=unused-argument bake_in_vae_filename = sd_vae.vae_dict.get(kwargs.get("bake_in_vae", None), None) if bake_in_vae_filename is not None: - shared.log.info(f"Merge VAE='{bake_in_vae_filename}'") + logger.log.info(f"Merge VAE='{bake_in_vae_filename}'") shared.state.textinfo = 'Merge VAE' vae_dict = sd_vae.load_vae_dict(bake_in_vae_filename) for key in vae_dict.keys(): @@ -179,7 +180,7 @@ def run_modelmerger(id_task, **kwargs): # pylint: disable=unused-argument torch.save(theta_0, output_modelname) t1 = time.time() - shared.log.info(f"Merge complete: saved='{output_modelname}' time={t1-t0:.2f}") + logger.log.info(f"Merge complete: saved='{output_modelname}' time={t1-t0:.2f}") sd_models.list_models() created_model = next((ckpt for ckpt in sd_models.checkpoints_list.values() if ckpt.name == filename), None) if created_model: @@ -200,9 +201,9 @@ def run_model_modules(model_type:str, model_name:str, custom_name:str, def msg(text, err:bool=False): nonlocal status if err: - shared.log.error(f'Modules merge: {text}') + logger.log.error(f'Modules merge: {text}') else: - shared.log.info(f'Modules merge: {text}') + logger.log.info(f'Modules merge: {text}') status += text + '
' return status diff --git a/modules/face/__init__.py b/modules/face/__init__.py index 8161f7b31..3e94d25d3 100644 --- a/modules/face/__init__.py +++ b/modules/face/__init__.py @@ -2,9 +2,10 @@ import os import gradio as gr from PIL import Image from modules import scripts_manager, processing, shared, images +from modules import logger -debug = shared.log.trace if os.environ.get('SD_FACE_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_FACE_DEBUG', None) is not None else lambda *args, **kwargs: None class Script(scripts_manager.Script): @@ -34,7 +35,7 @@ class Script(scripts_manager.Script): raise ValueError(f'Face: unknown input: {file}') init_images.append(image) except Exception as e: - shared.log.warning(f'Face: failed to load image: {e}') + logger.log.warning(f'Face: failed to load image: {e}') return init_images def mode_change(self, mode): @@ -109,10 +110,10 @@ class Script(scripts_manager.Script): if mode == 'None': return None if input_images is None or len(input_images) == 0: - shared.log.error('Face: no init images') + logger.log.error('Face: no init images') return None if shared.sd_model_type != 'sd' and shared.sd_model_type != 'sdxl': - shared.log.error('Face: base model not supported') + logger.log.error('Face: base model not supported') return None input_images = input_images.copy() @@ -142,7 +143,7 @@ class Script(scripts_manager.Script): photo_maker(p, app=app, input_images=input_images, model=pm_model, trigger=pm_trigger, strength=pm_strength, start=pm_start) elif mode == 'InstantID': if hasattr(p, 'init_images') and p.init_images is not None and len(p.init_images) > 0: - shared.log.warning('Face: InstantID with init image not supported') + logger.log.warning('Face: InstantID with init image not supported') input_images += p.init_images from modules.face.insightface import get_app app=get_app('antelopev2') diff --git a/modules/face/faceid.py b/modules/face/faceid.py index 933df80ff..296457501 100644 --- a/modules/face/faceid.py +++ b/modules/face/faceid.py @@ -6,6 +6,7 @@ import diffusers import huggingface_hub as hf from PIL import Image from modules import processing, shared, devices, extra_networks, sd_hijack_freeu, script_callbacks, ipadapter, token_merge +from modules import logger from modules.sd_hijack_hypertile import context_hypertile_vae, context_hypertile_unet @@ -21,7 +22,7 @@ FACEID_MODELS = { faceid_model_weights = None faceid_model_name = None -debug = shared.log.trace if os.environ.get("SD_FACE_DEBUG", None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get("SD_FACE_DEBUG", None) is not None else lambda *args, **kwargs: None def hijack_load_ip_adapter(self): @@ -42,7 +43,7 @@ def face_id( ): global faceid_model_weights, faceid_model_name # pylint: disable=global-statement if source_images is None or len(source_images) == 0: - shared.log.warning('FaceID: no input images') + logger.log.warning('FaceID: no input images') return None from insightface.utils import face_align @@ -57,7 +58,7 @@ def face_id( IPAdapterFaceID as IPAdapterFaceIDPortrait, ) except Exception as e: - shared.log.error(f"FaceID incorrect version of ip_adapter: {e}") + logger.log.error(f"FaceID incorrect version of ip_adapter: {e}") return None processed_images = [] @@ -80,13 +81,13 @@ def face_id( basename, _ext = os.path.splitext(filename) model_path = hf.hf_hub_download(repo_id=folder, filename=filename, cache_dir=shared.opts.hfcache_dir) if model_path is None: - shared.log.error(f'FaceID download failed: model={model} file="{ip_ckpt}"') + logger.log.error(f'FaceID download failed: model={model} file="{ip_ckpt}"') return None if faceid_model_weights is None or faceid_model_name != model or not cache: - shared.log.debug(f'FaceID load: model={model} file="{ip_ckpt}"') + logger.log.debug(f'FaceID load: model={model} file="{ip_ckpt}"') faceid_model_weights = torch.load(model_path, map_location="cpu") else: - shared.log.debug(f'FaceID cached: model={model} file="{ip_ckpt}"') + logger.log.debug(f'FaceID cached: model={model} file="{ip_ckpt}"') if "XL Plus" in model and shared.sd_model_type == 'sd': image_encoder_path = "laion/CLIP-ViT-H-14-laion2B-s32B-b79K" @@ -148,7 +149,7 @@ def face_id( torch_dtype=devices.dtype, ) else: - shared.log.error(f'FaceID model not supported: model="{model}" class={shared.sd_model.__class__.__name__}') + logger.log.error(f'FaceID model not supported: model="{model}" class={shared.sd_model.__class__.__name__}') return None if override: @@ -171,15 +172,15 @@ def face_id( np_image = cv2.cvtColor(np.array(source_image), cv2.COLOR_RGB2BGR) faces = app.get(np_image) if len(faces) == 0: - shared.log.error("FaceID: no faces found") + logger.log.error("FaceID: no faces found") break face_embeds.append(torch.from_numpy(faces[0].normed_embedding).unsqueeze(0)) face_images.append(face_align.norm_crop(np_image, landmark=faces[0].kps, image_size=224)) - shared.log.debug(f'FaceID face: i={i+1} score={faces[0].det_score:.2f} gender={"female" if faces[0].gender==0 else "male"} age={faces[0].age} bbox={faces[0].bbox}') + logger.log.debug(f'FaceID face: i={i+1} score={faces[0].det_score:.2f} gender={"female" if faces[0].gender==0 else "male"} age={faces[0].age} bbox={faces[0].bbox}') p.extra_generation_params[f"FaceID {i+1}"] = f'{faces[0].det_score:.2f} {"female" if faces[0].gender==0 else "male"} {faces[0].age}y' if len(face_embeds) == 0: - shared.log.error("FaceID: no faces found") + logger.log.error("FaceID: no faces found") return None face_embeds = torch.cat(face_embeds, dim=0) @@ -198,7 +199,7 @@ def face_id( ip_model_dict["shortcut"] = shortcut if "Plus" in model: ip_model_dict["s_scale"] = structure - shared.log.debug(f"FaceID args: {ip_model_dict}") + logger.log.debug(f"FaceID args: {ip_model_dict}") if "Plus" in model: ip_model_dict["face_image"] = face_images ip_model_dict["faceid_embeds"] = face_embeds # overwrite placeholder diff --git a/modules/face/faceswap.py b/modules/face/faceswap.py index a3e4f27fc..c20a98501 100644 --- a/modules/face/faceswap.py +++ b/modules/face/faceswap.py @@ -4,9 +4,10 @@ import numpy as np import huggingface_hub as hf from PIL import Image from modules import processing, shared, devices +from modules import logger -debug = shared.log.trace if os.environ.get('SD_FACE_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_FACE_DEBUG', None) is not None else lambda *args, **kwargs: None insightface_app = None swapper = None @@ -17,19 +18,19 @@ def face_swap(p: processing.StableDiffusionProcessing, app, input_images: list[I import insightface.model_zoo repo_id = 'ezioruan/inswapper_128.onnx' model_path = hf.hf_hub_download(repo_id=repo_id, filename='inswapper_128.onnx', cache_dir=shared.opts.hfcache_dir) - shared.log.debug(f'FaceSwap load: repo="{repo_id}" path="{model_path}"') + logger.log.debug(f'FaceSwap load: repo="{repo_id}" path="{model_path}"') # model_path = hf.hf_hub_download(repo_id='somanchiu/reswapper', filename='reswapper_256-1567500_originalInswapperClassCompatible.onnx', cache_dir=shared.opts.hfcache_dir) try: router: insightface.model_zoo.model_zoo.INSwapper = insightface.model_zoo.model_zoo.ModelRouter(model_path) swapper = router.get_model() except Exception as e: - shared.log.error(f'FaceSwap load: {e}') + logger.log.error(f'FaceSwap load: {e}') return None np_image = cv2.cvtColor(np.array(source_image), cv2.COLOR_RGB2BGR) faces = app.get(np_image) if faces is None or len(faces) == 0: - shared.log.warning('FaceSwap: No faces detected') + logger.log.warning('FaceSwap: No faces detected') return None source_face = faces[0] processed_images = [] diff --git a/modules/face/instantid.py b/modules/face/instantid.py index c991e8d7d..20bb72a13 100644 --- a/modules/face/instantid.py +++ b/modules/face/instantid.py @@ -4,11 +4,12 @@ import torch import numpy as np import huggingface_hub as hf from modules import shared, processing, sd_models, devices +from modules import logger REPO_ID = "InstantX/InstantID" controlnet_model = None -debug = shared.log.trace if os.environ.get('SD_FACE_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_FACE_DEBUG', None) is not None else lambda *args, **kwargs: None def instant_id(p: processing.StableDiffusionProcessing, app, source_images, strength=1.0, conditioning=0.5, cache=True): # pylint: disable=arguments-differ @@ -18,12 +19,12 @@ def instant_id(p: processing.StableDiffusionProcessing, app, source_images, stre # prepare pipeline if source_images is None or len(source_images) == 0: - shared.log.warning('InstantID: no input images') + logger.log.warning('InstantID: no input images') return None c = shared.sd_model.__class__.__name__ if shared.sd_loaded else '' if c not in ['StableDiffusionXLPipeline', 'StableDiffusionXLInstantIDPipeline']: - shared.log.warning(f'InstantID invalid base model: current={c} required=StableDiffusionXLPipeline') + logger.log.warning(f'InstantID invalid base model: current={c} required=StableDiffusionXLPipeline') return None # prepare face emb @@ -35,9 +36,9 @@ def instant_id(p: processing.StableDiffusionProcessing, app, source_images, stre face_embeds.append(torch.from_numpy(face['embedding'])) face_images.append(draw_kps(source_image, face['kps'])) p.extra_generation_params[f"InstantID {i+1}"] = f'{faces[0].det_score:.2f} {"female" if faces[0].gender==0 else "male"} {faces[0].age}y' - shared.log.debug(f'InstantID face: score={face.det_score:.2f} gender={"female" if face.gender==0 else "male"} age={face.age} bbox={face.bbox}') + logger.log.debug(f'InstantID face: score={face.det_score:.2f} gender={"female" if face.gender==0 else "male"} age={face.age} bbox={face.bbox}') - shared.log.debug(f'InstantID loading: model={REPO_ID}') + logger.log.debug(f'InstantID loading: model={REPO_ID}') face_adapter = hf.hf_hub_download(repo_id=REPO_ID, filename="ip-adapter.bin") if controlnet_model is None or not cache: controlnet_model = ControlNetModel.from_pretrained(REPO_ID, subfolder="ControlNetModel", torch_dtype=devices.dtype, cache_dir=shared.opts.diffusers_dir) @@ -72,7 +73,7 @@ def instant_id(p: processing.StableDiffusionProcessing, app, source_images, stre p.task_args['image'] = face_images[0] p.task_args['controlnet_conditioning_scale'] = float(conditioning) p.task_args['ip_adapter_scale'] = float(strength) - shared.log.debug(f"InstantID args: {p.task_args}") + logger.log.debug(f"InstantID args: {p.task_args}") p.task_args['prompt'] = p.all_prompts[0] if p.all_prompts else p.prompt p.task_args['negative_prompt'] = p.all_negative_prompts[0] if p.all_negative_prompts else p.negative_prompt p.task_args['image_embeds'] = face_embeds[0] # overwrite placeholder diff --git a/modules/face/photomaker.py b/modules/face/photomaker.py index cbb737b58..7c8875f82 100644 --- a/modules/face/photomaker.py +++ b/modules/face/photomaker.py @@ -3,6 +3,7 @@ import numpy as np import torch import huggingface_hub as hf from modules import shared, processing, sd_models, devices +from modules import logger original_pipeline = None @@ -21,16 +22,16 @@ def photo_maker(p: processing.StableDiffusionProcessing, app, model: str, input_ # prepare pipeline if len(input_images) == 0: - shared.log.warning('PhotoMaker: no input images') + logger.log.warning('PhotoMaker: no input images') return None if len(trigger) == 0: - shared.log.warning('PhotoMaker: no trigger word') + logger.log.warning('PhotoMaker: no trigger word') return None c = shared.sd_model.__class__.__name__ if shared.sd_loaded else '' if c != 'StableDiffusionXLPipeline': - shared.log.warning(f'PhotoMaker invalid base model: current={c} required=StableDiffusionXLPipeline') + logger.log.warning(f'PhotoMaker invalid base model: current={c} required=StableDiffusionXLPipeline') return None # validate prompt @@ -42,10 +43,10 @@ def photo_maker(p: processing.StableDiffusionProcessing, app, model: str, input_ prompt_ids2 = shared.sd_model.tokenizer_2.encode(p.all_prompts[0]) for t in trigger_ids: if prompt_ids1.count(t) != 1: - shared.log.error(f'PhotoMaker: trigger word not matched in prompt: {trigger} ids={trigger_ids} prompt={p.all_prompts[0]} ids={prompt_ids1}') + logger.log.error(f'PhotoMaker: trigger word not matched in prompt: {trigger} ids={trigger_ids} prompt={p.all_prompts[0]} ids={prompt_ids1}') return None if prompt_ids2.count(t) != 1: - shared.log.error(f'PhotoMaker: trigger word not matched in prompt: {trigger} ids={trigger_ids} prompt={p.all_prompts[0]} ids={prompt_ids1}') + logger.log.error(f'PhotoMaker: trigger word not matched in prompt: {trigger} ids={trigger_ids} prompt={p.all_prompts[0]} ids={prompt_ids1}') return None # create new pipeline @@ -70,7 +71,7 @@ def photo_maker(p: processing.StableDiffusionProcessing, app, model: str, input_ repo_id, fn = 'TencentARC/PhotoMaker', 'photomaker-v1.bin' photomaker_path = hf.hf_hub_download(repo_id=repo_id, filename=fn, repo_type="model", cache_dir=shared.opts.hfcache_dir) - shared.log.debug(f'PhotoMaker: model="{model}" uri="{repo_id}/{fn}" images={len(input_images)} trigger={trigger} args={p.task_args}') + logger.log.debug(f'PhotoMaker: model="{model}" uri="{repo_id}/{fn}" images={len(input_images)} trigger={trigger} args={p.task_args}') # load photomaker adapter shared.sd_model.load_photomaker_adapter( @@ -90,7 +91,7 @@ def photo_maker(p: processing.StableDiffusionProcessing, app, model: str, input_ faces = app.get(cv2.cvtColor(np.array(source_image), cv2.COLOR_RGB2BGR)) face = sorted(faces, key=lambda x:(x['bbox'][2]-x['bbox'][0])*x['bbox'][3]-x['bbox'][1])[-1] # only use the maximum face id_embed_list.append(torch.from_numpy(face['embedding'])) - shared.log.debug(f'PhotoMaker: face={i+1} score={face.det_score:.2f} gender={"female" if face.gender==0 else "male"} age={face.age} bbox={face.bbox}') + logger.log.debug(f'PhotoMaker: face={i+1} score={face.det_score:.2f} gender={"female" if face.gender==0 else "male"} age={face.age} bbox={face.bbox}') p.task_args['id_embeds'] = torch.stack(id_embed_list).to(device=devices.device, dtype=devices.dtype) # run processing diff --git a/modules/face/reswapper.py b/modules/face/reswapper.py index d688a51d2..d424becea 100644 --- a/modules/face/reswapper.py +++ b/modules/face/reswapper.py @@ -5,6 +5,7 @@ import numpy as np import huggingface_hub as hf from PIL import Image from modules import processing, shared, devices +from modules import logger RESWAPPER_REPO = 'somanchiu/reswapper' RESWAPPER_MODELS = { @@ -15,7 +16,7 @@ RESWAPPER_MODELS = { } reswapper_model = None reswapper_name = None -debug = shared.log.trace if os.environ.get("SD_FACE_DEBUG", None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get("SD_FACE_DEBUG", None) is not None else lambda *args, **kwargs: None dtype = devices.dtype def get_model(model_name: str): @@ -30,12 +31,12 @@ def get_model(model_name: str): reswapper_model = reswapper_model.to(device=devices.device, dtype=dtype) reswapper_model.eval() reswapper_name = model_name - shared.log.info(f'ReSwapper: model="{model_name}" url="{url}" cls={reswapper_model.__class__.__name__}') + logger.log.info(f'ReSwapper: model="{model_name}" url="{url}" cls={reswapper_model.__class__.__name__}') if reswapper_model is None: - shared.log.error(f'ReSwapper: model="{model_name}" fn="{fn}" url="{url}" failed to load model') + logger.log.error(f'ReSwapper: model="{model_name}" fn="{fn}" url="{url}" failed to load model') return reswapper_model except Exception as e: - shared.log.error(f'ReSwapper: model="{model_name}" fn="{fn}" url="{url}" {e}') + logger.log.error(f'ReSwapper: model="{model_name}" fn="{fn}" url="{url}" {e}') return reswapper_model @@ -49,7 +50,7 @@ def reswapper( ): from modules.face import reswapper_utils as utils if source_images is None or len(source_images) == 0: - shared.log.warning('ReSwapper: no input images') + logger.log.warning('ReSwapper: no input images') return None processed_images = [] @@ -67,22 +68,22 @@ def reswapper( source_np = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR) source_faces = app.get(source_np) if len(source_faces) == 0: - shared.log.error(f"ReSwapper: image={x+1} no source faces found") + logger.log.error(f"ReSwapper: image={x+1} no source faces found") return source_images if len(source_faces) != len(target_images): - shared.log.warning(f"ReSwapper: image={x+1} source-faces={len(source_faces)} target-images={len(target_images)}") + logger.log.warning(f"ReSwapper: image={x+1} source-faces={len(source_faces)} target-images={len(target_images)}") for y, source_face in enumerate(source_faces): target_image = target_images[y] if y < len(target_images) else target_images[-1] target_image = target_image.convert('RGB') target_np = cv2.cvtColor(np.array(target_image), cv2.COLOR_RGB2BGR) target_faces = app.get(target_np) if len(target_faces) != 1: - shared.log.error(f"ReSwapper: image={x+1} source-faces={y+1} target-faces={len(target_faces)} must be exactly one") + logger.log.error(f"ReSwapper: image={x+1} source-faces={y+1} target-faces={len(target_faces)} must be exactly one") return source_images target_face = target_faces[0] source_str = f'score:{source_face.det_score:.2f} gender:{"female" if source_face.gender==0 else "male"} age:{source_face.age}' target_str = f'score:{target_face.det_score:.2f} gender:{"female" if target_face.gender==0 else "male"} age:{target_face.age}' - shared.log.debug(f'ReSwapper image={x+1} face={y+1} source="{source_str}" target="{target_str}"') + logger.log.debug(f'ReSwapper image={x+1} face={y+1} source="{source_str}" target="{target_str}"') source_latent = utils.getLatent(source_face) source_tensor = torch.from_numpy(source_latent).to(device=devices.device, dtype=dtype) diff --git a/modules/files_cache.py b/modules/files_cache.py index 5ffc4d383..88f0ea05b 100644 --- a/modules/files_cache.py +++ b/modules/files_cache.py @@ -4,7 +4,7 @@ from collections import UserDict from dataclasses import dataclass, field from typing import Union from collections.abc import Callable, Iterator -from installer import log +from modules.logger import log do_cache_folders = os.environ.get('SD_NO_CACHE', None) is None diff --git a/modules/framepack/framepack_api.py b/modules/framepack/framepack_api.py index ad3bd0e70..4a6094cca 100644 --- a/modules/framepack/framepack_api.py +++ b/modules/framepack/framepack_api.py @@ -1,6 +1,7 @@ from pydantic import BaseModel, Field # pylint: disable=no-name-in-module from fastapi.exceptions import HTTPException from modules import shared +from modules import logger class ReqFramepack(BaseModel): @@ -60,7 +61,7 @@ def framepack_post(request: ReqFramepack): else: init_image = None except Exception as e: - shared.log.error(f"API FramePack: id={task_id} cannot decode init image: {e}") + logger.log.error(f"API FramePack: id={task_id} cannot decode init image: {e}") raise HTTPException(status_code=500, detail=str(e)) from e try: @@ -69,12 +70,12 @@ def framepack_post(request: ReqFramepack): else: end_image = None except Exception as e: - shared.log.error(f"API FramePack: id={task_id} cannot decode end image: {e}") + logger.log.error(f"API FramePack: id={task_id} cannot decode end image: {e}") raise HTTPException(status_code=500, detail=str(e)) from e del request.init_image del request.end_image - shared.log.trace(f"API FramePack: id={task_id} init={init_image.shape} end={end_image.shape if end_image else None} {request}") + logger.log.trace(f"API FramePack: id={task_id} init={init_image.shape} end={end_image.shape if end_image else None} {request}") generator = run_framepack( _ui_state=None, diff --git a/modules/framepack/framepack_hijack.py b/modules/framepack/framepack_hijack.py index 9d80e9290..371f23872 100644 --- a/modules/framepack/framepack_hijack.py +++ b/modules/framepack/framepack_hijack.py @@ -1,3 +1,4 @@ +from modules import logger DEFAULT_PROMPT_TEMPLATE = { # hunyuanvideo reference prompt template "template": ( "<|start_header_id|>system<|end_header_id|>\n\nDescribe the video by detailing the following aspects: " @@ -71,4 +72,4 @@ def set_prompt_template(prompt, system_prompt:str=None, optimized_prompt:bool=Tr "crop_start": tokens_system, } tokens_user = inputs['length'].item() - int(shared.sd_model.tokenizer.bos_token_id is not None) - int(shared.sd_model.tokenizer.eos_token_id is not None) - shared.log.trace(f'FramePack prompt: system={tokens_system} user={tokens_user} optimized={optimized_prompt} unmodified={unmodified_prompt} mode={mode}') + logger.log.trace(f'FramePack prompt: system={tokens_system} user={tokens_user} optimized={optimized_prompt} unmodified={unmodified_prompt} mode={mode}') diff --git a/modules/framepack/framepack_load.py b/modules/framepack/framepack_load.py index 4b99126ef..593c33573 100644 --- a/modules/framepack/framepack_load.py +++ b/modules/framepack/framepack_load.py @@ -1,6 +1,7 @@ import os import time from modules import shared, devices, errors, sd_models, sd_checkpoint, model_quant +from modules import logger models = { @@ -42,9 +43,9 @@ def set_model(receipe: str=None): k, v = line.split(':', 1) k = k.strip() if k not in default_model.keys(): - shared.log.warning(f'FramePack receipe: key={k} invalid') + logger.log.warning(f'FramePack receipe: key={k} invalid') model[k] = split_url(v) - shared.log.debug(f'FramePack receipe: set {k}={model[k]}') + logger.log.debug(f'FramePack receipe: set {k}={model[k]}') def get_model(): @@ -57,7 +58,7 @@ def get_model(): def reset_model(): global model # pylint: disable=global-statement model = default_model.copy() - shared.log.debug('FramePack receipe: reset') + logger.log.debug('FramePack receipe: reset') return '' @@ -79,7 +80,7 @@ def load_model(variant:str=None, pipeline:str=None, text_encoder:str=None, text_ model['image_encoder'] = split_url(image_encoder) if transformer is not None: model['transformer'] = split_url(transformer) - # shared.log.trace(f'FramePack load: {model}') + # logger.log.trace(f'FramePack load: {model}') try: import diffusers @@ -137,7 +138,7 @@ def load_model(variant:str=None, pipeline:str=None, text_encoder:str=None, text_ os.environ.pop('HF_HUB_OFFLINE', None) os.unsetenv('HF_HUB_OFFLINE') - shared.log.debug(f'FramePack load: module=llm {model["text_encoder"]}') + logger.log.debug(f'FramePack load: module=llm {model["text_encoder"]}') load_args, quant_args = model_quant.get_dit_args({}, module='TE', device_map=True) text_encoder = LlamaModel.from_pretrained(model["text_encoder"]["repo"], subfolder=model["text_encoder"]["subfolder"], cache_dir=shared.opts.hfcache_dir, **load_args, **quant_args, **offline_config) tokenizer = LlamaTokenizerFast.from_pretrained(model["tokenizer"]["repo"], subfolder=model["tokenizer"]["subfolder"], cache_dir=shared.opts.hfcache_dir, **offline_config) @@ -145,14 +146,14 @@ def load_model(variant:str=None, pipeline:str=None, text_encoder:str=None, text_ text_encoder.eval() sd_models.move_model(text_encoder, devices.cpu) - shared.log.debug(f'FramePack load: module=te {model["text_encoder_2"]}') + logger.log.debug(f'FramePack load: module=te {model["text_encoder_2"]}') text_encoder_2 = CLIPTextModel.from_pretrained(model["text_encoder_2"]["repo"], subfolder=model["text_encoder_2"]["subfolder"], torch_dtype=devices.dtype, cache_dir=shared.opts.hfcache_dir, **offline_config) tokenizer_2 = CLIPTokenizer.from_pretrained(model["pipeline"]["repo"], subfolder='tokenizer_2', cache_dir=shared.opts.hfcache_dir, **offline_config) text_encoder_2.requires_grad_(False) text_encoder_2.eval() sd_models.move_model(text_encoder_2, devices.cpu) - shared.log.debug(f'FramePack load: module=vae {model["vae"]}') + logger.log.debug(f'FramePack load: module=vae {model["vae"]}') vae = AutoencoderKLHunyuanVideo.from_pretrained(model["vae"]["repo"], subfolder=model["vae"]["subfolder"], torch_dtype=devices.dtype, cache_dir=shared.opts.hfcache_dir, **offline_config) vae.requires_grad_(False) vae.eval() @@ -160,14 +161,14 @@ def load_model(variant:str=None, pipeline:str=None, text_encoder:str=None, text_ vae.enable_tiling() sd_models.move_model(vae, devices.cpu) - shared.log.debug(f'FramePack load: module=encoder {model["feature_extractor"]} model={model["image_encoder"]}') + logger.log.debug(f'FramePack load: module=encoder {model["feature_extractor"]} model={model["image_encoder"]}') feature_extractor = SiglipImageProcessor.from_pretrained(model["feature_extractor"]["repo"], subfolder=model["feature_extractor"]["subfolder"], cache_dir=shared.opts.hfcache_dir, **offline_config) image_encoder = SiglipVisionModel.from_pretrained(model["image_encoder"]["repo"], subfolder=model["image_encoder"]["subfolder"], torch_dtype=devices.dtype, cache_dir=shared.opts.hfcache_dir, **offline_config) image_encoder.requires_grad_(False) image_encoder.eval() sd_models.move_model(image_encoder, devices.cpu) - shared.log.debug(f'FramePack load: module=transformer {model["transformer"]}') + logger.log.debug(f'FramePack load: module=transformer {model["transformer"]}') dit_repo = model["transformer"]["repo"] load_args, quant_args = model_quant.get_dit_args({}, module='Model', device_map=True) transformer = HunyuanVideoTransformer3DModelPacked.from_pretrained(dit_repo, subfolder=model["transformer"]["subfolder"], cache_dir=shared.opts.hfcache_dir, **load_args, **quant_args, **offline_config) @@ -194,12 +195,12 @@ def load_model(variant:str=None, pipeline:str=None, text_encoder:str=None, text_ t1 = time.time() diffusers.loaders.peft._SET_ADAPTER_SCALE_FN_MAPPING['HunyuanVideoTransformer3DModelPacked'] = lambda model_cls, weights: weights # pylint: disable=protected-access - shared.log.info(f'FramePack load: model={shared.sd_model.__class__.__name__} variant="{variant}" type={shared.sd_model_type} time={t1-t0:.2f}') + logger.log.info(f'FramePack load: model={shared.sd_model.__class__.__name__} variant="{variant}" type={shared.sd_model_type} time={t1-t0:.2f}') sd_models.apply_balanced_offload(shared.sd_model) devices.torch_gc(force=True, reason='load') except Exception as e: - shared.log.error(f'FramePack load: {e}') + logger.log.error(f'FramePack load: {e}') errors.display(e, 'FramePack') shared.state.end() return None diff --git a/modules/framepack/framepack_vae.py b/modules/framepack/framepack_vae.py index 77f20b415..2f43167bf 100644 --- a/modules/framepack/framepack_vae.py +++ b/modules/framepack/framepack_vae.py @@ -1,6 +1,7 @@ import torch import einops from modules import shared, devices +from modules import logger latent_rgb_factors = [ # from comfyui @@ -45,7 +46,7 @@ def vae_decode_tiny(latents): if taesd is None: from modules.vae import sd_vae_taesd taesd, _variant = sd_vae_taesd.get_model(variant='TAE HunyuanVideo') - shared.log.debug(f'Video VAE: type=Tiny cls={taesd.__class__.__name__} latents={latents.shape}') + logger.log.debug(f'Video VAE: type=Tiny cls={taesd.__class__.__name__} latents={latents.shape}') with devices.inference_context(): taesd = taesd.to(device=devices.device, dtype=devices.dtype) latents = latents.transpose(1, 2) # pipe produces NCTHW and tae wants NTCHW diff --git a/modules/framepack/framepack_worker.py b/modules/framepack/framepack_worker.py index 9df245d59..ee69cf157 100644 --- a/modules/framepack/framepack_worker.py +++ b/modules/framepack/framepack_worker.py @@ -2,6 +2,7 @@ import time import torch import rich.progress as rp from modules import shared, errors ,devices, sd_models, timer, memstats +from modules import logger from modules.framepack import framepack_vae # pylint: disable=wrong-import-order from modules.framepack import framepack_hijack # pylint: disable=wrong-import-order from modules.video_models.video_save import save_video # pylint: disable=wrong-import-order @@ -50,7 +51,7 @@ def worker( timer.process.reset() memstats.reset_stats() if stream is None or shared.state.interrupted or shared.state.skipped: - shared.log.error('FramePack: stream is None') + logger.log.error('FramePack: stream is None') stream.output_queue.push(('end', None)) return @@ -78,7 +79,7 @@ def worker( image_encoder = shared.sd_model.image_processor transformer = shared.sd_model.transformer sd_models.apply_balanced_offload(shared.sd_model) - pbar = rp.Progress(rp.TextColumn('[cyan]Video'), rp.BarColumn(), rp.MofNCompleteColumn(), rp.TaskProgressColumn(), rp.TimeRemainingColumn(), rp.TimeElapsedColumn(), rp.TextColumn('[cyan]{task.description}'), console=shared.console) + pbar = rp.Progress(rp.TextColumn('[cyan]Video'), rp.BarColumn(), rp.MofNCompleteColumn(), rp.TaskProgressColumn(), rp.TimeRemainingColumn(), rp.TimeElapsedColumn(), rp.TextColumn('[cyan]{task.description}'), console=logger.console) task = pbar.add_task('starting', total=steps * len(latent_paddings)) t_last = time.time() if not is_f1: @@ -89,7 +90,7 @@ def worker( pbar.update(task, description=f'text encode section={i}') t0 = time.time() torch.manual_seed(seed) - # shared.log.debug(f'FramePack: section={i} prompt="{prompt}"') + # logger.log.debug(f'FramePack: section={i} prompt="{prompt}"') shared.state.textinfo = 'Text encode' stream.output_queue.push(('progress', (None, 'Text encoding...'))) sd_models.apply_balanced_offload(shared.sd_model) @@ -110,7 +111,7 @@ def worker( def latents_encode(input_image, end_image): jobid = shared.state.begin('VAE Encode') pbar.update(task, description='image encode') - # shared.log.debug(f'FramePack: image encode init={input_image.shape} end={end_image.shape if end_image is not None else None}') + # logger.log.debug(f'FramePack: image encode init={input_image.shape} end={end_image.shape if end_image is not None else None}') t0 = time.time() torch.manual_seed(seed) stream.output_queue.push(('progress', (None, 'VAE encoding...'))) @@ -135,7 +136,7 @@ def worker( def vision_encode(input_image, end_image): pbar.update(task, description='vision encode') - # shared.log.debug(f'FramePack: vision encode init={input_image.shape} end={end_image.shape if end_image is not None else None}') + # logger.log.debug(f'FramePack: vision encode init={input_image.shape} end={end_image.shape if end_image is not None else None}') t0 = time.time() shared.state.textinfo = 'Vision encode' stream.output_queue.push(('progress', (None, 'Vision encoding...'))) @@ -165,7 +166,7 @@ def worker( stream.output_queue.push(('end', None)) raise AssertionError('Interrupted...') if shared.state.paused: - shared.log.debug('Sampling paused') + logger.log.debug('Sampling paused') while shared.state.paused: if shared.state.interrupted or shared.state.skipped: raise AssertionError('Interrupted...') @@ -215,7 +216,7 @@ def worker( sammplejob = shared.state.begin('Sample') lattent_padding_loop += 1 - # shared.log.trace(f'FramePack: op=sample section={lattent_padding_loop}/{len(latent_paddings)} frames={total_generated_frames}/{num_frames*len(latent_paddings)} window={latent_window_size} size={num_frames}') + # logger.log.trace(f'FramePack: op=sample section={lattent_padding_loop}/{len(latent_paddings)} frames={total_generated_frames}/{num_frames*len(latent_paddings)} window={latent_window_size} size={num_frames}') if is_f1: is_first_section, is_last_section = False, False else: @@ -329,7 +330,7 @@ def worker( ) except AssertionError: - shared.log.info('FramePack: interrupted') + logger.log.info('FramePack: interrupted') if shared.opts.keep_incomplete: save_video( p=None, @@ -349,11 +350,11 @@ def worker( metadata=metadata, ) except Exception as e: - shared.log.error(f'FramePack: {e}') + logger.log.error(f'FramePack: {e}') errors.display(e, 'FramePack') sd_models.apply_balanced_offload(shared.sd_model) stream.output_queue.push(('end', None)) t1 = time.time() - shared.log.info(f'Processed: frames={total_generated_frames} fps={total_generated_frames/(t1-t0):.2f} its={(shared.state.sampling_step)/(t1-t0):.2f} time={t1-t0:.2f} timers={timer.process.dct()} memory={memstats.memory_stats()}') + logger.log.info(f'Processed: frames={total_generated_frames} fps={total_generated_frames/(t1-t0):.2f} its={(shared.state.sampling_step)/(t1-t0):.2f} time={t1-t0:.2f} timers={timer.process.dct()} memory={memstats.memory_stats()}') shared.state.end(videojob) diff --git a/modules/framepack/framepack_wrappers.py b/modules/framepack/framepack_wrappers.py index 7259db5ea..fd2a02063 100644 --- a/modules/framepack/framepack_wrappers.py +++ b/modules/framepack/framepack_wrappers.py @@ -6,6 +6,7 @@ import torch import gradio as gr from PIL import Image from modules import shared, processing, timer, paths, extra_networks, progress, ui_video_vlm, call_queue +from modules import logger from modules.video_models.video_utils import check_av from modules.framepack import framepack_install # pylint: disable=wrong-import-order from modules.framepack import framepack_load # pylint: disable=wrong-import-order @@ -41,7 +42,7 @@ def prepare_image(image, resolution): image = resize_and_center_crop(image, target_height=scaled_h, target_width=scaled_w) h0, w0, _c = image.shape - shared.log.debug(f'FramePack prepare: input="{w}x{h}" resized="{w0}x{h0}" resolution={resolution} scale={scale_factor}') + logger.log.debug(f'FramePack prepare: input="{w}x{h}" resized="{w0}x{h0}" resolution={resolution} scale={scale_factor}') return image @@ -60,7 +61,7 @@ def interpolate_prompts(prompts, steps): for i in range(steps): prompt_index = int(i / factor) interpolated_prompts[i] = prompts[prompt_index] - # shared.log.trace(f'FramePack interpolate: section={i} prompt="{interpolated_prompts[i]}"') + # logger.log.trace(f'FramePack interpolate: section={i} prompt="{interpolated_prompts[i]}"') return interpolated_prompts @@ -108,7 +109,7 @@ def load_model(variant, attention): def unload_model(): - shared.log.debug('FramePack unload') + logger.log.debug('FramePack unload') framepack_load.unload_model() yield gr.update(), gr.update(), 'Model unloaded' @@ -149,8 +150,8 @@ def run_framepack(task_id, _ui_state, init_image, end_image, start_weight, end_w torch.manual_seed(seed) num_sections = len(framepack_worker.get_latent_paddings(mp4_fps, mp4_interpolate, latent_ws, duration, variant)) num_frames = (latent_ws * 4 - 3) * num_sections + 1 - shared.log.info(f'FramePack start: mode={mode} variant="{variant}" frames={num_frames} sections={num_sections} resolution={resolution} seed={seed} duration={duration} teacache={use_teacache} thres={shared.opts.teacache_thresh} cfgzero={use_cfgzero}') - shared.log.info(f'FramePack params: steps={steps} start={start_weight} end={end_weight} vision={vision_weight} scale={cfg_scale} distilled={cfg_distilled} rescale={cfg_rescale} shift={shift}') + logger.log.info(f'FramePack start: mode={mode} variant="{variant}" frames={num_frames} sections={num_sections} resolution={resolution} seed={seed} duration={duration} teacache={use_teacache} thres={shared.opts.teacache_thresh} cfgzero={use_cfgzero}') + logger.log.info(f'FramePack params: steps={steps} start={start_weight} end={end_weight} vision={vision_weight} scale={cfg_scale} distilled={cfg_distilled} rescale={cfg_rescale} shift={shift}') init_image = prepare_image(init_image, resolution) if end_image is not None: end_image = prepare_image(end_image, resolution) diff --git a/modules/framepack/pipeline/uni_pc_fm.py b/modules/framepack/pipeline/uni_pc_fm.py index 2066cd8e3..b94e0d8e9 100644 --- a/modules/framepack/pipeline/uni_pc_fm.py +++ b/modules/framepack/pipeline/uni_pc_fm.py @@ -4,6 +4,7 @@ # Attribution-ShareAlike 4.0 International Licence +from modules import logger import torch import numpy as np from tqdm.auto import trange @@ -24,7 +25,7 @@ def test_solver(): _x = torch.linalg.solve(a, b) return True except Exception as e: - shared.log.debug(f'FramePack: solver=cpu {e}') + logger.log.debug(f'FramePack: solver=cpu {e}') return False diff --git a/modules/generation_parameters_copypaste.py b/modules/generation_parameters_copypaste.py index 42f6aa864..ddf2dffde 100644 --- a/modules/generation_parameters_copypaste.py +++ b/modules/generation_parameters_copypaste.py @@ -5,6 +5,7 @@ import os from PIL import Image import gradio as gr from modules import shared, gr_tempdir, script_callbacks, images +from modules import logger from modules.infotext import parse, mapping # pylint: disable=unused-import @@ -12,7 +13,7 @@ type_of_gr_update = type(gr.update()) paste_fields: dict[str, dict] = {} field_names = {} registered_param_bindings: list[ParamBinding] = [] -debug = shared.log.trace if os.environ.get('SD_PASTE_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_PASTE_DEBUG', None) is not None else lambda *args, **kwargs: None debug('Trace: PASTE') parse_generation_parameters = parse # compatibility infotext_to_setting_name_mapping = mapping # compatibility @@ -50,7 +51,7 @@ def image_from_url_text(filedata): if is_in_right_dir: filename = filename.rsplit('?', 1)[0] if not os.path.exists(filename): - shared.log.error(f'Image file not found: {filename}') + logger.log.error(f'Image file not found: {filename}') image = Image.new('RGB', (512, 512)) image.info['parameters'] = f'Image file not found: {filename}' return image @@ -59,14 +60,14 @@ def image_from_url_text(filedata): image.info['parameters'] = geninfo return image else: - shared.log.warning(f'File access denied: {filename}') + logger.log.warning(f'File access denied: {filename}') return None if type(filedata) == list: if len(filedata) == 0: return None filedata = filedata[0] if not isinstance(filedata, str): - shared.log.warning('Incorrect filedata received') + logger.log.warning('Incorrect filedata received') return None if filedata.startswith("data:image/png;base64,"): filedata = filedata[len("data:image/png;base64,"):] @@ -88,7 +89,7 @@ def add_paste_fields(tabname: str, init_img: gr.Image | gr.HTML | None, fields: try: field_names[tabname] = [f[1] for f in fields if f[1] is not None and not callable(f[1])] if fields is not None else [] # tuple (component, label) except Exception as e: - shared.log.error(f"Paste fields: tab={tabname} fields={fields} {e}") + logger.log.error(f"Paste fields: tab={tabname} fields={fields} {e}") field_names[tabname] = [] # Build param_aliases automatically from component labels and elem_ids @@ -261,11 +262,11 @@ def connect_paste(button, local_paste_fields, input_comp, override_settings_comp if os.path.exists(params_path): with open(params_path, encoding="utf8") as file: prompt = file.read() - shared.log.debug(f'Prompt parse: type="params" prompt="{prompt}"') + logger.log.debug(f'Prompt parse: type="params" prompt="{prompt}"') else: prompt = '' else: - shared.log.debug(f'Prompt parse: type="current" prompt="{prompt}"') + logger.log.debug(f'Prompt parse: type="current" prompt="{prompt}"') params = parse(prompt) script_callbacks.infotext_pasted_callback(prompt, params) res = [] @@ -306,10 +307,10 @@ def connect_paste(button, local_paste_fields, input_comp, override_settings_comp res.append(gr.update(value=val)) applied[key] = val except Exception as e: - shared.log.error(f'Paste param: key="{key}" value="{v}" error="{e}"') + logger.log.error(f'Paste param: key="{key}" value="{v}" error="{e}"') res.append(gr.update()) list_applied = [{k: v} for k, v in applied.items() if not callable(v) and not callable(k)] - shared.log.debug(f"Prompt restore: apply={list_applied} skip={skipped}") + logger.log.debug(f"Prompt restore: apply={list_applied} skip={skipped}") return res if override_settings_component is not None: @@ -338,7 +339,7 @@ def connect_paste(button, local_paste_fields, input_comp, override_settings_comp vals[param_name] = v vals_pairs = [f"{k}: {v}" for k, v in vals.items()] if len(vals_pairs) > 0: - shared.log.debug(f'Settings overrides: {vals_pairs}') + logger.log.debug(f'Settings overrides: {vals_pairs}') return gr.Dropdown.update(value=vals_pairs, choices=vals_pairs, visible=len(vals_pairs) > 0) local_paste_fields = local_paste_fields + [(override_settings_component, paste_settings)] diff --git a/modules/ggml/__init__.py b/modules/ggml/__init__.py index e0ad9f0dc..208641bd6 100644 --- a/modules/ggml/__init__.py +++ b/modules/ggml/__init__.py @@ -1,3 +1,4 @@ +from modules import logger import os import time import torch @@ -22,7 +23,7 @@ def install_gguf(): transformers.utils.import_utils._gguf_version = ver # pylint: disable=protected-access diffusers.utils.import_utils._is_gguf_available = True # pylint: disable=protected-access diffusers.utils.import_utils._gguf_version = ver # pylint: disable=protected-access - shared.log.debug(f'Load GGUF: version={ver}') + logger.log.debug(f'Load GGUF: version={ver}') return gguf diff --git a/modules/gr_hijack.py b/modules/gr_hijack.py index 7fa1cecdd..3f3cffd88 100644 --- a/modules/gr_hijack.py +++ b/modules/gr_hijack.py @@ -3,6 +3,7 @@ from PIL import Image import gradio as gr import gradio.processing_utils from modules import scripts_manager, patches, gr_tempdir +from modules import logger hijacked = False @@ -35,7 +36,7 @@ def process_kanvas(self, x): # only used when kanvas overrides gr.Image object # mask = Image.merge("RGB", [alpha, alpha, alpha]) mask = mask.convert('L') t1 = time.time() - errors.log.debug(f'Kanvas: image={image} mask={mask} time={t1-t0:.2f}') + logger.log.debug(f'Kanvas: image={image} mask={mask} time={t1-t0:.2f}') if image is None: return None if mask is None: diff --git a/modules/gr_tempdir.py b/modules/gr_tempdir.py index 110396414..a89acf780 100644 --- a/modules/gr_tempdir.py +++ b/modules/gr_tempdir.py @@ -4,10 +4,11 @@ from collections import namedtuple from pathlib import Path from PIL import Image, PngImagePlugin from modules import shared, errors, paths +from modules import logger Savedfile = namedtuple("Savedfile", ["name"]) -debug = errors.log.trace if os.environ.get('SD_PATH_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_PATH_DEBUG', None) is not None else lambda *args, **kwargs: None def register_tmp_file(gradio, filename): @@ -77,13 +78,13 @@ def pil_to_temp_file(self, img: Image, dir: str, format="png") -> str: # pylint: use_metadata = True if not os.path.exists(folder): os.makedirs(folder, exist_ok=True) - shared.log.debug(f'Created temp folder: path="{folder}"') + logger.log.debug(f'Created temp folder: path="{folder}"') with tempfile.NamedTemporaryFile(delete=False, suffix=".png", dir=folder) as tmp: name = tmp.name img.save(name, pnginfo=(metadata if use_metadata else None)) img.already_saved_as = name size = os.path.getsize(name) - shared.log.debug(f'Save temp: image="{name}" width={img.width} height={img.height} size={size}') + logger.log.debug(f'Save temp: image="{name}" width={img.width} height={img.height} size={size}') shared.state.image_history += 1 params = ', '.join([f'{k}: {v}' for k, v in img.info.items()]) params = params[12:] if params.startswith('parameters: ') else params @@ -105,7 +106,7 @@ def cleanup_tmpdr(): temp_dir = shared.opts.temp_dir if temp_dir == "" or not os.path.isdir(temp_dir): temp_dir = os.path.join(paths.temp_dir, "gradio") - shared.log.debug(f'Temp folder: path="{temp_dir}"') + logger.log.debug(f'Temp folder: path="{temp_dir}"') if not os.path.isdir(temp_dir): return for root, _dirs, files in os.walk(temp_dir, topdown=False): diff --git a/modules/hashes.py b/modules/hashes.py index acf0893ae..eca1b0dad 100644 --- a/modules/hashes.py +++ b/modules/hashes.py @@ -1,7 +1,9 @@ +from modules import logger import hashlib import os.path from rich import progress, errors -from installer import log, console +from installer import console +from modules.logger import log from modules.json_helpers import readfile, writefile from modules.paths import data_path @@ -81,7 +83,7 @@ def sha256(filename, title, use_addnet_hash=False): if use_addnet_hash: if progress_ok: try: - with progress.open(filename, 'rb', description=f'[cyan]Calculating hash: [yellow]{filename}', auto_refresh=True, console=shared.console) as f: + with progress.open(filename, 'rb', description=f'[cyan]Calculating hash: [yellow]{filename}', auto_refresh=True, console=logger.console) as f: sha256_value = addnet_hash_safetensors(f) except errors.LiveError: log.warning('Hash: attempting to use function in a thread') diff --git a/modules/hidiffusion/__init__.py b/modules/hidiffusion/__init__.py index 858aacf88..1f44a942d 100644 --- a/modules/hidiffusion/__init__.py +++ b/modules/hidiffusion/__init__.py @@ -2,12 +2,13 @@ import time from modules import shared +from modules import logger from modules.hidiffusion import hidiffusion def apply(p, model_type): if model_type not in ['sd', 'sdxl'] and p.hidiffusion: - shared.log.warning(f'HiDiffusion: class={shared.sd_model.__class__.__name__} not supported') + logger.log.warning(f'HiDiffusion: class={shared.sd_model.__class__.__name__} not supported') return unapply() pipe = shared.sd_model.pipe if hasattr(shared.sd_model, 'pipe') else shared.sd_model @@ -34,9 +35,9 @@ def apply(p, model_type): hidiffusion.apply_hidiffusion(pipe, apply_raunet=shared.opts.hidiffusion_raunet, apply_window_attn=shared.opts.hidiffusion_attn, model_type=model_type, steps=p.steps) p.extra_generation_params['HiDiffusion'] = f'{shared.opts.hidiffusion_raunet}/{shared.opts.hidiffusion_attn}/{shared.opts.hidiffusion_steps > 0}:{shared.opts.hidiffusion_steps}' t1 = time.time() - shared.log.debug(f'Applying HiDiffusion: raunet={shared.opts.hidiffusion_raunet} attn={shared.opts.hidiffusion_attn} aggressive={shared.opts.hidiffusion_steps > 0}:{shared.opts.hidiffusion_steps} t1={shared.opts.hidiffusion_t1} t2={shared.opts.hidiffusion_t2} time={t1-t0:.2f} type={shared.sd_model_type} width={p.width} height={p.height}') + logger.log.debug(f'Applying HiDiffusion: raunet={shared.opts.hidiffusion_raunet} attn={shared.opts.hidiffusion_attn} aggressive={shared.opts.hidiffusion_steps > 0}:{shared.opts.hidiffusion_steps} t1={shared.opts.hidiffusion_t1} t2={shared.opts.hidiffusion_t2} time={t1-t0:.2f} type={shared.sd_model_type} width={p.width} height={p.height}') elif hasattr(pipe, 'unet') and getattr(pipe.unet, 'hidiffusion', False): - shared.log.warning('HiDiffusion: model reload recomended') + logger.log.warning('HiDiffusion: model reload recomended') def unapply(): diff --git a/modules/history.py b/modules/history.py index 2540aa7a0..6ff986fcf 100644 --- a/modules/history.py +++ b/modules/history.py @@ -7,6 +7,7 @@ import datetime from collections import deque import torch from modules import shared, devices +from modules import logger class Item: @@ -40,7 +41,7 @@ class History: @property def list(self): - shared.log.info(f'History: items={self.count}/{shared.opts.latent_history} size={self.size}') + logger.log.info(f'History: items={self.count}/{shared.opts.latent_history} size={self.size}') return [item.name for item in self.latents] @property @@ -51,7 +52,7 @@ class History: else: current_index = 0 item = self.latents[current_index] - shared.log.debug(f'History get: index={current_index} time={item.ts} shape={list(item.latent.shape)} dtype={item.latent.dtype} count={self.count}') + logger.log.debug(f'History get: index={current_index} time={item.ts} shape={list(item.latent.shape)} dtype={item.latent.dtype} count={self.count}') return item.latent.to(devices.device), current_index def find(self, name): @@ -74,7 +75,7 @@ class History: def clear(self): self.latents.clear() - # shared.log.debug(f'History clear: count={self.count}') + # logger.log.debug(f'History clear: count={self.count}') def load(self): pass diff --git a/modules/image/convert.py b/modules/image/convert.py index 87e06a5bb..11496a4f8 100644 --- a/modules/image/convert.py +++ b/modules/image/convert.py @@ -2,7 +2,7 @@ import sys import torch import numpy as np from PIL import Image -from installer import log +from modules.logger import log def to_tensor(image: Image.Image | np.ndarray): diff --git a/modules/image/grid.py b/modules/image/grid.py index 2b6bc2ed1..71a8e0d27 100644 --- a/modules/image/grid.py +++ b/modules/image/grid.py @@ -3,6 +3,7 @@ from collections import namedtuple import numpy as np from PIL import Image, ImageFont, ImageDraw from modules import shared, script_callbacks +from modules import logger Grid = namedtuple("Grid", ["tiles", "tile_w", "tile_h", "image_w", "image_h", "overlap"]) @@ -21,7 +22,7 @@ def check_grid_size(imgs): mp = round(mp / 1000000) ok = mp <= shared.opts.img_max_size_mp if not ok: - shared.log.warning(f'Maximum image size exceded: size={mp} maximum={shared.opts.img_max_size_mp} MPixels') + logger.log.warning(f'Maximum image size exceded: size={mp} maximum={shared.opts.img_max_size_mp} MPixels') return ok diff --git a/modules/image/metadata.py b/modules/image/metadata.py index 5b91c57c9..956d7a74d 100644 --- a/modules/image/metadata.py +++ b/modules/image/metadata.py @@ -4,6 +4,7 @@ import json import piexif from PIL import Image, ExifTags from modules import shared, errors, sd_samplers +from modules import logger from modules.image.watermark import get_watermark @@ -57,7 +58,7 @@ def parse_comfy_metadata(data: dict): prompt = parse_prompt() if len(workflow) > 0 or len(prompt) > 0: parsed = f'App: ComfyUI{workflow}{prompt}' - shared.log.info(f'Image metadata: {parsed}') + logger.log.info(f'Image metadata: {parsed}') return parsed return '' @@ -79,7 +80,7 @@ def parse_invoke_metadata(data: dict): metadata = parse_metadtaa() if len(metadata) > 0: parsed = f'App: InvokeAI{metadata}' - shared.log.info(f'Image metadata: {parsed}') + logger.log.info(f'Image metadata: {parsed}') return parsed return '' @@ -118,7 +119,7 @@ def read_info_from_image(image: Image.Image, watermark: bool = False) -> tuple[s try: exif = piexif.load(items["exif"]) except Exception as e: - shared.log.error(f'Error loading EXIF data: {e}') + logger.log.error(f'Error loading EXIF data: {e}') exif = {} for _key, subkey in exif.items(): if isinstance(subkey, dict): @@ -172,18 +173,18 @@ def image_data(data): image = Image.open(io.BytesIO(data)) image.load() info, _ = read_info_from_image(image) - errors.log.debug(f'Decoded object: image={image} metadata={info}') + logger.log.debug(f'Decoded object: image={image} metadata={info}') return info, None except Exception as e: err1 = e try: if len(data) > 1024 * 10: - errors.log.warning(f'Error decoding object: data too long: {len(data)}') + logger.log.warning(f'Error decoding object: data too long: {len(data)}') return gr.update(), None info = data.decode('utf8') - errors.log.debug(f'Decoded object: data={len(data)} metadata={info}') + logger.log.debug(f'Decoded object: data={len(data)} metadata={info}') return info, None except Exception as e: err2 = e - errors.log.error(f'Error decoding object: {err1 or err2}') + logger.log.error(f'Error decoding object: {err1 or err2}') return gr.update(), None diff --git a/modules/image/namegen.py b/modules/image/namegen.py index bbbe5026b..2a8d58ab6 100644 --- a/modules/image/namegen.py +++ b/modules/image/namegen.py @@ -8,10 +8,11 @@ import hashlib import datetime from pathlib import Path from modules import shared, errors +from modules import logger debug= os.environ.get('SD_NAMEGEN_DEBUG', None) is not None -debug_log = errors.log.trace if debug else lambda *args, **kwargs: None +debug_log = logger.log.trace if debug else lambda *args, **kwargs: None re_nonletters = re.compile(r'[\s' + string.punctuation + ']+') re_pattern = re.compile(r"(.*?)(?:\[([^\[\]]+)\]|$)") re_pattern_arg = re.compile(r"(.*)<([^>]*)>$") @@ -241,7 +242,7 @@ class FilenameGenerator: fn = self.replacements.get(k, None) debug_log(f'Namegen: key={k} value={fn(self)}') except Exception as e: - shared.log.error(f'Namegen: key={k} {e}') + logger.log.error(f'Namegen: key={k} {e}') errors.display(e, 'namegen') for m in re_pattern.finditer(x): text, pattern = m.groups() @@ -270,7 +271,7 @@ class FilenameGenerator: except Exception as e: replacement = None errors.display(e, 'namegen') - shared.log.error(f'Filename apply pattern: {x} {e}') + logger.log.error(f'Filename apply pattern: {x} {e}') if replacement == NOTHING: continue if replacement is not None: diff --git a/modules/image/resize.py b/modules/image/resize.py index a26c92714..1ba1598b1 100644 --- a/modules/image/resize.py +++ b/modules/image/resize.py @@ -4,6 +4,7 @@ import numpy as np import torch from PIL import Image from modules import shared, upscaler +from modules import logger from modules.image import sharpfin @@ -19,7 +20,7 @@ def resize_image(resize_mode: int, im: Image.Image | torch.Tensor, width: int, h image = (255.0 * image).astype(np.uint8) image = Image.fromarray(image) except Exception as e: - shared.log.error(f"Image verification failed: {e}") + logger.log.error(f"Image verification failed: {e}") return image def latent(im, scale: float, selected_upscaler: upscaler.UpscalerData): @@ -50,8 +51,8 @@ def resize_image(resize_mode: int, im: Image.Image | torch.Tensor, width: int, h else: im = selected_upscaler.scaler.upscale(im, scale, selected_upscaler.name) else: - shared.log.warning(f"Resize upscaler: invalid={upscaler_name} fallback={selected_upscaler.name}") - shared.log.debug(f"Resize upscaler: available={[u.name for u in shared.sd_upscalers]}") + logger.log.warning(f"Resize upscaler: invalid={upscaler_name} fallback={selected_upscaler.name}") + logger.log.debug(f"Resize upscaler: available={[u.name for u in shared.sd_upscalers]}") if isinstance(im, Image.Image) and (im.width != w or im.height != h): # probably downsample after upscaler created larger image im = sharpfin.resize(im, (w, h)) return im @@ -136,7 +137,7 @@ def resize_image(resize_mode: int, im: Image.Image | torch.Tensor, width: int, h return res im = verify_image(im) if not isinstance(im, Image.Image): - shared.log.error(f'Resize image: image={type(im)} invalid type') + logger.log.error(f'Resize image: image={type(im)} invalid type') return im if (resize_mode == 0) or ((im.width == width) and (im.height == height)) or (width == 0 and height == 0): # none res = im.copy() @@ -154,9 +155,9 @@ def resize_image(resize_mode: int, im: Image.Image | torch.Tensor, width: int, h res = context_aware(im, width, height, context) else: res = im.copy() - shared.log.error(f'Invalid resize mode: {resize_mode}') + logger.log.error(f'Invalid resize mode: {resize_mode}') t1 = time.time() fn = f'{sys._getframe(2).f_code.co_name}:{sys._getframe(1).f_code.co_name}' # pylint: disable=protected-access if im.width != width or im.height != height: - shared.log.debug(f'Resize image: source={im.width}:{im.height} target={width}:{height} mode="{shared.resize_modes[resize_mode]}" upscaler="{upscaler_name}" type={output_type} time={t1-t0:.2f} fn={fn}') # pylint: disable=protected-access + logger.log.debug(f'Resize image: source={im.width}:{im.height} target={width}:{height} mode="{shared.resize_modes[resize_mode]}" upscaler="{upscaler_name}" type={output_type} time={t1-t0:.2f} fn={fn}') # pylint: disable=protected-access return np.array(res) if output_type == 'np' else res diff --git a/modules/image/save.py b/modules/image/save.py index 42dd751bf..ef81e7e0c 100644 --- a/modules/image/save.py +++ b/modules/image/save.py @@ -6,13 +6,14 @@ import threading import piexif.helper from PIL import Image, PngImagePlugin from modules import shared, script_callbacks, errors, paths +from modules import logger from modules.image.grid import check_grid_size from modules.image.namegen import FilenameGenerator from modules.image.watermark import set_watermark -debug = errors.log.trace if os.environ.get('SD_PATH_DEBUG', None) is not None else lambda *args, **kwargs: None -debug_save = errors.log.trace if os.environ.get('SD_SAVE_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_PATH_DEBUG', None) is not None else lambda *args, **kwargs: None +debug_save = logger.log.trace if os.environ.get('SD_SAVE_DEBUG', None) is not None else lambda *args, **kwargs: None def sanitize_filename_part(text, replace_spaces=True): @@ -46,7 +47,7 @@ def atomically_save_image(): try: image_format = Image.registered_extensions()[extension] except Exception: - shared.log.warning(f'Save: unknown image format: {extension}') + logger.log.warning(f'Save: unknown image format: {extension}') image_format = 'JPEG' exifinfo = (exifinfo or "") if shared.opts.image_metadata else "" # additional metadata saved in files @@ -54,9 +55,9 @@ def atomically_save_image(): try: with open(filename_txt, "w", encoding="utf8") as file: file.write(f"{exifinfo}\n") - shared.log.info(f'Save: text="{filename_txt}" len={len(exifinfo)}') + logger.log.info(f'Save: text="{filename_txt}" len={len(exifinfo)}') except Exception as e: - shared.log.warning(f'Save failed: description={filename_txt} {e}') + logger.log.warning(f'Save failed: description={filename_txt} {e}') # actual save if image_format == 'PNG': @@ -67,7 +68,7 @@ def atomically_save_image(): save_args = { 'compress_level': 6, 'pnginfo': pnginfo_data if shared.opts.image_metadata else None } elif image_format == 'JPEG': if image.mode == 'RGBA': - shared.log.warning('Save: removing alpha channel') + logger.log.warning('Save: removing alpha channel') image = image.convert("RGB") elif image.mode == 'I;16': image = image.point(lambda p: p * 0.0038910505836576).convert("L") @@ -97,11 +98,11 @@ def atomically_save_image(): debug_save(f'Save args: {save_args}') image.save(fn, format=image_format, **save_args) except Exception as e: - shared.log.error(f'Save failed: file="{fn}" format={image_format} args={save_args} {e}') + logger.log.error(f'Save failed: file="{fn}" format={image_format} args={save_args} {e}') errors.display(e, 'Image save') size = os.path.getsize(fn) if os.path.exists(fn) else 0 what = 'grid' if is_grid else 'image' - shared.log.info(f'Save: {what}="{fn}" type={image_format} width={image.width} height={image.height} size={size}') + logger.log.info(f'Save: {what}="{fn}" type={image_format} width={image.width} height={image.height} size={size}') if shared.opts.save_log_fn != '' and len(exifinfo) > 0: fn = os.path.join(paths.data_path, shared.opts.save_log_fn) @@ -114,7 +115,7 @@ def atomically_save_image(): entry = { 'id': idx, 'filename': filename, 'time': datetime.datetime.now().isoformat(), 'info': exifinfo } entries.append(entry) shared.writefile(entries, fn, mode='w', silent=True) - shared.log.info(f'Save: json="{fn}" records={len(entries)}') + logger.log.info(f'Save: json="{fn}" records={len(entries)}') shared.state.outputs(filename) shared.state.end(jobid) save_queue.task_done() @@ -143,11 +144,11 @@ def save_image(image, fn = f'{sys._getframe(2).f_code.co_name}:{sys._getframe(1).f_code.co_name}' # pylint: disable=protected-access debug_save(f'Save: fn={fn}') # pylint: disable=protected-access if image is None: - shared.log.warning('Image is none') + logger.log.warning('Image is none') return None, None, None if isinstance(image, list): if len(image) > 1: - shared.log.warning(f'Save: images={image} multiple images provided only the first one will be saved') + logger.log.warning(f'Save: images={image} multiple images provided only the first one will be saved') image = image[0] if not check_grid_size([image]): return None, None, None diff --git a/modules/image/sharpfin.py b/modules/image/sharpfin.py index ecdebdf0a..d461eae48 100644 --- a/modules/image/sharpfin.py +++ b/modules/image/sharpfin.py @@ -10,7 +10,7 @@ Non-CUDA devices fall back to PIL/torch.nn.functional automatically. import sys import torch from PIL import Image -from installer import log +from modules.logger import log from modules.image.convert import to_tensor, to_pil diff --git a/modules/image/watermark.py b/modules/image/watermark.py index 016b2d524..99f74a291 100644 --- a/modules/image/watermark.py +++ b/modules/image/watermark.py @@ -2,6 +2,7 @@ import random import numpy as np from PIL import Image from modules import shared +from modules import logger def set_watermark(image, wm_text: str | None = None, wm_image: Image.Image | None = None): @@ -10,7 +11,7 @@ def set_watermark(image, wm_text: str | None = None, wm_image: Image.Image | Non try: wm_image = Image.open(wm_image) except Exception as e: - shared.log.warning(f'Set image watermark: image={wm_image} {e}') + logger.log.warning(f'Set image watermark: image={wm_image} {e}') return image if isinstance(wm_image, Image.Image): if wm_image.mode != 'RGBA': @@ -39,9 +40,9 @@ def set_watermark(image, wm_text: str | None = None, wm_image: Image.Image | Non b = int(rgba[2] * a + orig[2] * (1 - a)) if not a == 0: image.putpixel((x+position[0], y+position[1]), (r, g, b)) - shared.log.debug(f'Set image watermark: image={wm_image} position={position}') + logger.log.debug(f'Set image watermark: image={wm_image} position={position}') except Exception as e: - shared.log.warning(f'Set image watermark: image={wm_image} {e}') + logger.log.warning(f'Set image watermark: image={wm_image} {e}') if shared.opts.image_watermark_enabled and wm_text is not None: # invisible watermark from imwatermark import WatermarkEncoder @@ -59,9 +60,9 @@ def set_watermark(image, wm_text: str | None = None, wm_image: Image.Image | Non encoded = encoder.encode(data, wm_method) image = Image.fromarray(encoded) image.info = info - shared.log.debug(f'Set invisible watermark: {wm_text} method={wm_method} bits={wm_length}') + logger.log.debug(f'Set invisible watermark: {wm_text} method={wm_method} bits={wm_length}') except Exception as e: - shared.log.warning(f'Set invisible watermark error: {wm_text} method={wm_method} bits={wm_length} {e}') + logger.log.warning(f'Set invisible watermark error: {wm_text} method={wm_method} bits={wm_length} {e}') return image diff --git a/modules/img2img.py b/modules/img2img.py index 9b832e7a0..32a4dbe53 100644 --- a/modules/img2img.py +++ b/modules/img2img.py @@ -4,13 +4,14 @@ import numpy as np import filetype from PIL import Image, ImageOps, ImageFilter, ImageEnhance, ImageChops, UnidentifiedImageError from modules import scripts_manager, shared, processing, images, errors +from modules import logger from modules.generation_parameters_copypaste import create_override_settings_dict from modules.ui_common import plaintext_to_html from modules.memstats import memory_stats from modules.paths import resolve_output_path -debug = shared.log.trace if os.environ.get('SD_PROCESS_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_PROCESS_DEBUG', None) is not None else lambda *args, **kwargs: None debug('Trace: PROCESS') @@ -20,45 +21,45 @@ def validate_inputs(inputs): if filetype.is_image(image): outputs.append(image) else: - shared.log.warning(f'Input skip: file="{image}" filetype={filetype.guess(image)}') + logger.log.warning(f'Input skip: file="{image}" filetype={filetype.guess(image)}') return outputs def process_batch(p, input_files, input_dir, output_dir, inpaint_mask_dir, args): - # shared.log.debug(f'batch: {input_files}|{input_dir}|{output_dir}|{inpaint_mask_dir}') + # logger.log.debug(f'batch: {input_files}|{input_dir}|{output_dir}|{inpaint_mask_dir}') processing.fix_seed(p) image_files = [] if input_files is not None and len(input_files) > 0: image_files = [f.name for f in input_files] image_files = validate_inputs(image_files) - shared.log.info(f'Process batch: input images={len(image_files)}') + logger.log.info(f'Process batch: input images={len(image_files)}') elif os.path.isdir(input_dir): image_files = [os.path.join(input_dir, f) for f in os.listdir(input_dir)] image_files = validate_inputs(image_files) - shared.log.info(f'Process batch: input folder="{input_dir}" images={len(image_files)}') + logger.log.info(f'Process batch: input folder="{input_dir}" images={len(image_files)}') is_inpaint_batch = False if inpaint_mask_dir and os.path.isdir(inpaint_mask_dir): inpaint_masks = [os.path.join(inpaint_mask_dir, f) for f in os.listdir(inpaint_mask_dir)] inpaint_masks = validate_inputs(inpaint_masks) is_inpaint_batch = len(inpaint_masks) > 0 - shared.log.info(f'Process batch: mask folder="{input_dir}" images={len(inpaint_masks)}') + logger.log.info(f'Process batch: mask folder="{input_dir}" images={len(inpaint_masks)}') p.do_not_save_grid = True p.do_not_save_samples = True p.default_prompt = p.prompt if p.n_iter > 1: p.n_iter = 1 - shared.log.warning(f'Process batch: batch_count={p.n_iter} forced to 1') + logger.log.warning(f'Process batch: batch_count={p.n_iter} forced to 1') shared.state.job_count = len(image_files) * p.n_iter if shared.opts.batch_frame_mode: # SBM Frame mode is on, process each image in batch with same seed window_size = p.batch_size btcrept = 1 p.seed = [p.seed] * window_size # SBM MONKEYPATCH: Need to change processing to support a fixed seed value. p.subseed = [p.subseed] * window_size # SBM MONKEYPATCH - shared.log.info(f"Process batch: inputs={len(image_files)} outputs={p.n_iter}x{len(image_files)} parallel={window_size}") + logger.log.info(f"Process batch: inputs={len(image_files)} outputs={p.n_iter}x{len(image_files)} parallel={window_size}") else: # SBM Frame mode is off, standard operation of repeating same images with sequential seed. window_size = 1 btcrept = p.batch_size - shared.log.info(f"Process batch: inputs={len(image_files)} outputs={p.n_iter*p.batch_size}x{len(image_files)}") + logger.log.info(f"Process batch: inputs={len(image_files)} outputs={p.n_iter*p.batch_size}x{len(image_files)}") for i in range(0, len(image_files), window_size): if shared.state.skipped: shared.state.skipped = False @@ -86,11 +87,11 @@ def process_batch(p, input_files, input_dir, output_dir, inpaint_mask_dir, args) p.all_negative_prompts = None p.all_seeds = None p.all_subseeds = None - shared.log.debug(f'Process batch: image="{image_file}" prompt={prompt_type} i={i+1}/{len(image_files)}') + logger.log.debug(f'Process batch: image="{image_file}" prompt={prompt_type} i={i+1}/{len(image_files)}') except UnidentifiedImageError as e: - shared.log.error(f'Process batch: image="{image_file}" {e}') + logger.log.error(f'Process batch: image="{image_file}" {e}') if len(batch_images) == 0: - shared.log.warning("Process batch: no images found in batch") + logger.log.warning("Process batch: no images found in batch") continue batch_images = batch_images * btcrept # Standard mode sends the same image per batchsize. p.init_images = batch_images @@ -115,12 +116,12 @@ def process_batch(p, input_files, input_dir, output_dir, inpaint_mask_dir, args) if processed is None: processed = processing.process_images(p) except Exception as e: - shared.log.error(f'Process batch: {e}') + logger.log.error(f'Process batch: {e}') errors.display(e, 'batch') processed = None if processed is None or len(processed.images) == 0: - shared.log.warning(f'Process batch: i={i+1}/{len(image_files)} no images processed') + logger.log.warning(f'Process batch: i={i+1}/{len(image_files)} no images processed') continue for n, (image, image_file) in enumerate(itertools.zip_longest(processed.images, batch_image_files)): @@ -144,7 +145,7 @@ def process_batch(p, input_files, input_dir, output_dir, inpaint_mask_dir, args) image.info[k] = v images.save_image(image, path=output_dir, basename=basename, seed=None, prompt=None, extension=ext, info=info, grid=False, pnginfo_section_name="extras", existing_info=image.info, forced_filename=forced_filename) processed = scripts_manager.scripts_img2img.after(p, processed, *args) - shared.log.debug(f'Processed: images={len(batch_image_files)} memory={memory_stats()} batch') + logger.log.debug(f'Processed: images={len(batch_image_files)} memory={memory_stats()} batch') def img2img(id_task: str, state: str, mode: int, @@ -183,11 +184,11 @@ def img2img(id_task: str, state: str, mode: int, debug(f'img2img: {id_task}') if shared.sd_model is None: - shared.log.warning('Aborted: op=img model not loaded') + logger.log.warning('Aborted: op=img model not loaded') return [], '', '', 'Error: model not loaded' if sampler_index is None: - shared.log.warning('Sampler: invalid') + logger.log.warning('Sampler: invalid') sampler_index = 0 mode = int(mode) @@ -230,7 +231,7 @@ def img2img(id_task: str, state: str, mode: int, elif mode == 5: # process batch pass # handled later else: - shared.log.error(f'Image processing unknown mode: {mode}') + logger.log.error(f'Image processing unknown mode: {mode}') if image is not None: image = ImageOps.exif_transpose(image) diff --git a/modules/intel/openvino/__init__.py b/modules/intel/openvino/__init__.py index 0491525ad..37291c462 100644 --- a/modules/intel/openvino/__init__.py +++ b/modules/intel/openvino/__init__.py @@ -20,6 +20,7 @@ from hashlib import sha256 import functools from modules import shared, devices, sd_models +from modules import logger # importing openvino.runtime forces DeprecationWarning to "always" @@ -77,7 +78,7 @@ warned = False def warn_once(msg): global warned if not warned: - shared.log.warning(msg) + logger.log.warning(msg) warned = True class OpenVINOGraphModule(torch.nn.Module): @@ -159,7 +160,7 @@ def cached_model_name(model_hash_str, device, args, cache_root, reversed = False os.makedirs(model_cache_dir, exist_ok=True) file_name = model_cache_dir + model_hash_str + "_" + device except OSError as error: - shared.log.error(f"Cache directory {cache_root} cannot be created. Model caching is disabled. Error: {error}") + logger.log.error(f"Cache directory {cache_root} cannot be created. Model caching is disabled. Error: {error}") return None inputs_str = "" diff --git a/modules/ipadapter.py b/modules/ipadapter.py index 97ac171ae..6f237c9aa 100644 --- a/modules/ipadapter.py +++ b/modules/ipadapter.py @@ -13,6 +13,7 @@ from typing import TYPE_CHECKING from PIL import Image import transformers from modules import processing, shared, devices, sd_models, errors, model_quant +from modules import logger if TYPE_CHECKING: from diffusers import DiffusionPipeline @@ -75,10 +76,10 @@ def get_adapters(): def get_images(input_images): output_images = [] if input_images is None or len(input_images) == 0: - shared.log.error('IP adapter: no init images') + logger.log.error('IP adapter: no init images') return None if shared.sd_model_type not in ['sd', 'sdxl', 'sd3', 'f1']: - shared.log.error('IP adapter: base model not supported') + logger.log.error('IP adapter: base model not supported') return None if isinstance(input_images, str): from modules.api.api import decode_base64_to_image @@ -102,7 +103,7 @@ def get_images(input_images): pil_image.load() output_images.append(pil_image) else: - shared.log.error(f'IP adapter: unknown input: {image}') + logger.log.error(f'IP adapter: unknown input: {image}') return output_images @@ -133,9 +134,9 @@ def crop_images(images, crops): if len(cropped) == len(images[i]): images[i] = cropped else: - shared.log.error(f'IP adapter: failed to crop image: source={len(images[i])} faces={len(cropped)}') + logger.log.error(f'IP adapter: failed to crop image: source={len(images[i])} faces={len(cropped)}') except Exception as e: - shared.log.error(f'IP adapter: failed to crop image: {e}') + logger.log.error(f'IP adapter: failed to crop image: {e}') if shared.sd_model_type == 'sd3' and len(images) == 1: return images[0] return images @@ -148,7 +149,7 @@ def unapply(pipe, unload: bool = False): # pylint: disable=arguments-differ if hasattr(pipe, 'set_ip_adapter_scale'): pipe.set_ip_adapter_scale(0) if unload: - shared.log.debug('IP adapter unload') + logger.log.debug('IP adapter unload') pipe.unload_ip_adapter() if hasattr(pipe, 'unet') and pipe.unet is not None: module = pipe.unet @@ -187,7 +188,7 @@ def load_image_encoder(pipe: DiffusionPipeline, adapter_names: list[str]): clip_repo = OPEN_ID clip_subfolder = None else: - shared.log.error(f'IP adapter: unknown model type: {adapter_name}') + logger.log.error(f'IP adapter: unknown model type: {adapter_name}') return False # load image encoder used by ip adapter @@ -200,10 +201,10 @@ def load_image_encoder(pipe: DiffusionPipeline, adapter_names: list[str]): else: if clip_subfolder is None: image_encoder = transformers.CLIPVisionModelWithProjection.from_pretrained(clip_repo, torch_dtype=devices.dtype, cache_dir=shared.opts.hfcache_dir, use_safetensors=True, **offline_config) - shared.log.debug(f'IP adapter load: encoder="{clip_repo}" cls={pipe.image_encoder.__class__.__name__}') + logger.log.debug(f'IP adapter load: encoder="{clip_repo}" cls={pipe.image_encoder.__class__.__name__}') else: image_encoder = transformers.CLIPVisionModelWithProjection.from_pretrained(clip_repo, subfolder=clip_subfolder, torch_dtype=devices.dtype, cache_dir=shared.opts.hfcache_dir, use_safetensors=True, **offline_config) - shared.log.debug(f'IP adapter load: encoder="{clip_repo}/{clip_subfolder}" cls={pipe.image_encoder.__class__.__name__}') + logger.log.debug(f'IP adapter load: encoder="{clip_repo}/{clip_subfolder}" cls={pipe.image_encoder.__class__.__name__}') sd_models.clear_caches() image_encoder = model_quant.do_post_load_quant(image_encoder, allow=True) if hasattr(pipe, 'register_modules'): @@ -212,7 +213,7 @@ def load_image_encoder(pipe: DiffusionPipeline, adapter_names: list[str]): pipe.image_encoder = image_encoder clip_loaded = f'{clip_repo}/{clip_subfolder}' except Exception as e: - shared.log.error(f'IP adapter load: encoder="{clip_repo}/{clip_subfolder}" {e}') + logger.log.error(f'IP adapter load: encoder="{clip_repo}/{clip_subfolder}" {e}') errors.display(e, 'IP adapter: type=encoder') return False shared.state.end(jobid) @@ -235,9 +236,9 @@ def load_feature_extractor(pipe): else: pipe.feature_extractor = feature_extractor sd_models.apply_balanced_offload(pipe.feature_extractor) - shared.log.debug(f'IP adapter load: extractor={pipe.feature_extractor.__class__.__name__}') + logger.log.debug(f'IP adapter load: extractor={pipe.feature_extractor.__class__.__name__}') except Exception as e: - shared.log.error(f'IP adapter load: extractor {e}') + logger.log.error(f'IP adapter load: extractor {e}') errors.display(e, 'IP adapter: type=extractor') return False shared.state.end(jobid) @@ -268,14 +269,14 @@ def parse_params(p: processing.StableDiffusionProcessing, adapters: list, adapte adapter_masks[i] = mask_processor.preprocess(adapter_masks[i], height=p.height, width=p.width) adapter_masks = mask_processor.preprocess(adapter_masks, height=p.height, width=p.width) if adapter_images is None: - shared.log.error('IP adapter: no image provided') + logger.log.error('IP adapter: no image provided') return [], [], [], [], [], [] if len(adapters) < len(adapter_images): adapter_images = adapter_images[:len(adapters)] if len(adapters) < len(adapter_masks): adapter_masks = adapter_masks[:len(adapters)] if len(adapter_masks) > 0 and len(adapter_masks) != len(adapter_images): - shared.log.error('IP adapter: image and mask count mismatch') + logger.log.error('IP adapter: image and mask count mismatch') return [], [], [], [], [], [] adapter_scales = get_scales(adapter_scales, adapter_images) p.ip_adapter_scales = adapter_scales.copy() @@ -319,7 +320,7 @@ def apply(pipe, p: processing.StableDiffusionProcessing, adapter_names=None, ada del p.ip_adapter_images return False if shared.sd_model_type not in ['sd', 'sdxl', 'sd3', 'f1']: - shared.log.error(f'IP adapter: model={shared.sd_model_type} class={pipe.__class__.__name__} not supported') + logger.log.error(f'IP adapter: model={shared.sd_model_type} class={pipe.__class__.__name__} not supported') return False adapter_images, adapter_masks, adapter_scales, adapter_crops, adapter_starts, adapter_ends = parse_params(p, adapters, adapter_scales, adapter_crops, adapter_starts, adapter_ends, adapter_images) @@ -328,7 +329,7 @@ def apply(pipe, p: processing.StableDiffusionProcessing, adapter_names=None, ada if pipe is None: return False if len(adapter_images) == 0: - shared.log.error('IP adapter: no image provided') + logger.log.error('IP adapter: no image provided') adapters = [] # unload adapter if previously loaded as it will cause runtime errors if len(adapters) == 0: unapply(pipe, getattr(p, 'ip_adapter_unload', False)) @@ -336,7 +337,7 @@ def apply(pipe, p: processing.StableDiffusionProcessing, adapter_names=None, ada del p.ip_adapter_images return False if not hasattr(pipe, 'load_ip_adapter'): - shared.log.error(f'IP adapter: pipeline not supported: {pipe.__class__.__name__}') + logger.log.error(f'IP adapter: pipeline not supported: {pipe.__class__.__name__}') return False if not load_image_encoder(pipe, adapter_names): @@ -383,16 +384,16 @@ def apply(pipe, p: processing.StableDiffusionProcessing, adapter_names=None, ada from nunchaku.models.ip_adapter.diffusers_adapters import apply_IPA_on_pipe apply_IPA_on_pipe(pipe, ip_adapter_scale=adapter_scales[0], repo_id=repos) pipe = sd_models.apply_balanced_offload(pipe) - shared.log.debug(f'IP adapter load: engine=nunchaku scale={adapter_scales[0]} repo="{repos}"') + logger.log.debug(f'IP adapter load: engine=nunchaku scale={adapter_scales[0]} repo="{repos}"') else: - shared.log.error('IP adapter: Nunchaku only supports single adapter') + logger.log.error('IP adapter: Nunchaku only supports single adapter') p.task_args['ip_adapter_image'] = crop_images(adapter_images, adapter_crops) if len(adapter_masks) > 0: p.cross_attention_kwargs = { 'ip_adapter_masks': adapter_masks } p.extra_generation_params["IP Adapter"] = ';'.join(ip_str) t1 = time.time() - shared.log.info(f'IP adapter: {ip_str} image={adapter_images} mask={adapter_masks is not None} time={t1-t0:.2f}') + logger.log.info(f'IP adapter: {ip_str} image={adapter_images} mask={adapter_masks is not None} time={t1-t0:.2f}') except Exception as e: - shared.log.error(f'IP adapter load: adapters={adapter_names} repo={repos} folders={subfolders} names={names} {e}') + logger.log.error(f'IP adapter load: adapters={adapter_names} repo={repos} folders={subfolders} names={names} {e}') errors.display(e, 'IP adapter: type=adapter') return True diff --git a/modules/json_helpers.py b/modules/json_helpers.py index 51049482f..d118e42cd 100644 --- a/modules/json_helpers.py +++ b/modules/json_helpers.py @@ -5,7 +5,7 @@ import json from typing import overload, Literal import fasteners import orjson -from installer import log +from modules.logger import log locking_available = True # used by file read/write locking diff --git a/modules/lama.py b/modules/lama.py index 36e27b24c..1fc01a9c0 100644 --- a/modules/lama.py +++ b/modules/lama.py @@ -7,7 +7,7 @@ from torch.hub import download_url_to_file, get_dir from PIL import Image from modules import devices from modules.image import convert -from installer import log +from modules.logger import log LAMA_MODEL_URL = "https://github.com/enesmsahin/simple-lama-inpainting/releases/download/v0.1.0/big-lama.pt" diff --git a/modules/linfusion/__init__.py b/modules/linfusion/__init__.py index 01b894af9..f9ec1d3b4 100644 --- a/modules/linfusion/__init__.py +++ b/modules/linfusion/__init__.py @@ -1,3 +1,4 @@ +from modules import logger from modules import shared, sd_models, devices, attention from .linfusion import LinFusion from .attention import GeneralizedLinearAttention @@ -29,18 +30,18 @@ def apply(pipeline, pretrained: bool = True): else: model_path = detect(pipeline) if model_path is None: - shared.log.error('LinFusion: unsupported model type') + logger.log.error('LinFusion: unsupported model type') return applied = LinFusion.from_pretrained(model_path, cache_dir=shared.opts.hfcache_dir).to(device=pipeline.unet.device, dtype=pipeline.unet.dtype) applied.mount_to(unet=pipeline.unet) - shared.log.info(f'Applying LinFusion: class={applied.__class__.__name__} model="{model_path}" modules={len(applied.modules_dict)}') + logger.log.info(f'Applying LinFusion: class={applied.__class__.__name__} model="{model_path}" modules={len(applied.modules_dict)}') def unapply(pipeline): global applied # pylint: disable=global-statement if applied is None: return - # shared.log.debug('LinFusion: unapply') + # logger.log.debug('LinFusion: unapply') attention.set_diffusers_attention(pipeline) devices.torch_gc() applied = None diff --git a/modules/loader.py b/modules/loader.py index f00f39882..67b83ab13 100644 --- a/modules/loader.py +++ b/modules/loader.py @@ -7,13 +7,27 @@ import logging import warnings import urllib3 from modules import timer, errors +from modules import logger + + +try: + import math + cores = os.cpu_count() + affinity = len(os.sched_getaffinity(0)) # pylint: disable=no-member + threads = torch.get_num_threads() + if threads < (affinity / 2): + torch.set_num_threads(math.floor(affinity / 2)) + threads = torch.get_num_threads() + logger.log.debug(f'System: cores={cores} affinity={affinity} threads={threads}') +except Exception: + pass initialized = False errors.install() logging.getLogger("DeepSpeed").disabled = True timer.startup.record("loader") -errors.log.debug('Initializing: libraries') +logger.log.debug('Initializing: libraries') np = None try: @@ -32,8 +46,8 @@ try: return npwarn_decorator np._no_nep50_warning = getattr(np, '_no_nep50_warning', dummy_npwarn_decorator_factory) # pylint: disable=protected-access except Exception as e: - errors.log.error(f'Loader: numpy=={np.__version__ if np is not None else None} {e}') - errors.log.error('Please restart the app to fix this issue') + logger.log.error(f'Loader: numpy=={np.__version__ if np is not None else None} {e}') + logger.log.error('Please restart the app to fix this issue') sys.exit(1) timer.startup.record("numpy") @@ -41,8 +55,8 @@ scipy = None try: import scipy # pylint: disable=W0611,C0411 except Exception as e: - errors.log.error(f'Loader: scipy=={scipy.__version__ if scipy is not None else None} {e}') - errors.log.error('Please restart the app to fix this issue') + logger.log.error(f'Loader: scipy=={scipy.__version__ if scipy is not None else None} {e}') + logger.log.error('Please restart the app to fix this issue') sys.exit(1) timer.startup.record("scipy") @@ -55,17 +69,17 @@ except Exception: import torch # pylint: disable=C0411 if torch.__version__.startswith('2.5.0'): - errors.log.warning(f'Disabling cuDNN for SDP on torch={torch.__version__}') + logger.log.warning(f'Disabling cuDNN for SDP on torch={torch.__version__}') torch.backends.cuda.enable_cudnn_sdp(False) try: import intel_extension_for_pytorch as ipex # pylint: disable=import-error,unused-import - errors.log.debug(f'Load IPEX=={ipex.__version__}') + logger.log.debug(f'Load IPEX=={ipex.__version__}') except Exception: pass try: pass # pylint: disable=unused-import,ungrouped-imports except Exception: - errors.log.warning('Loader: torch is not built with distributed support') + logger.log.warning('Loader: torch is not built with distributed support') urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) @@ -74,10 +88,10 @@ torchvision = None try: import torchvision # pylint: disable=W0611,C0411 except Exception as e: - errors.log.error(f'Loader: torchvision=={torchvision.__version__ if "torchvision" in sys.modules else None} {e}') + logger.log.error(f'Loader: torchvision=={torchvision.__version__ if "torchvision" in sys.modules else None} {e}') if '_no_nep' in str(e): - errors.log.error('Loaded versions of packaged are not compatible') - errors.log.error('Please restart the app to fix this issue') + logger.log.error('Loaded versions of packaged are not compatible') + logger.log.error('Please restart the app to fix this issue') logging.getLogger("xformers").addFilter(lambda record: 'A matching Triton is not available' not in record.getMessage()) logging.getLogger("pytorch_lightning").disabled = True warnings.filterwarnings(action="ignore", category=DeprecationWarning) @@ -92,7 +106,7 @@ try: torch._dynamo.config.verbose = False # pylint: disable=protected-access torch._dynamo.config.suppress_errors = True # pylint: disable=protected-access except Exception as e: - errors.log.warning(f'Torch logging: {e}') + logger.log.warning(f'Torch logging: {e}') if ".dev" in torch.__version__ or "+git" in torch.__version__: torch.__long_version__ = torch.__version__ torch.__version__ = re.search(r'[\d.]+[\d]', torch.__version__).group(0) @@ -128,7 +142,7 @@ try: onnxruntime.set_default_logger_verbosity(1) onnxruntime.disable_telemetry_events() except Exception as e: - errors.log.warning(f'Torch onnxruntime: {e}') + logger.log.warning(f'Torch onnxruntime: {e}') timer.startup.record("onnx") timer.startup.record("fastapi") @@ -154,8 +168,8 @@ try: diffusers.loaders.single_file.logging.tqdm = partial(tqdm, unit='C') timer.startup.record("diffusers") except Exception as e: - errors.log.error(f'Loader: diffusers=={diffusers.__version__ if "diffusers" in sys.modules else None} {e}') - errors.log.error('Please restart re-run the installer') + logger.log.error(f'Loader: diffusers=={diffusers.__version__ if "diffusers" in sys.modules else None} {e}') + logger.log.error('Please restart re-run the installer') sys.exit(1) try: @@ -196,18 +210,6 @@ def get_packages(): "hub": huggingface_hub.__version__, } -try: - import math - cores = os.cpu_count() - affinity = len(os.sched_getaffinity(0)) # pylint: disable=no-member - threads = torch.get_num_threads() - if threads < (affinity / 2): - torch.set_num_threads(math.floor(affinity / 2)) - threads = torch.get_num_threads() - errors.log.debug(f'System: cores={cores} affinity={affinity} threads={threads}') -except Exception: - pass - try: import torchvision.transforms.functional_tensor # pylint: disable=unused-import, ungrouped-imports except ImportError: @@ -223,7 +225,7 @@ def deprecate_warn(*args, **kwargs): try: deprecate_diffusers(*args, **kwargs) except Exception as e: - errors.log.warning(f'Deprecation: {e}') + logger.log.warning(f'Deprecation: {e}') diffusers.utils.deprecation_utils.deprecate = deprecate_warn diffusers.utils.deprecate = deprecate_warn @@ -238,5 +240,5 @@ class VersionString(str): # support both string and tuple for version check torch.__version__ = VersionString(torch.__version__) -errors.log.info(f'Torch: torch=={torch.__version__} torchvision=={torchvision.__version__}') -errors.log.info(f'Packages: diffusers=={diffusers.__version__} transformers=={transformers.__version__} accelerate=={accelerate.__version__} gradio=={gradio.__version__} pydantic=={pydantic.__version__} numpy=={np.__version__} cv2=={cv2.__version__}') +logger.log.info(f'Torch: torch=={torch.__version__} torchvision=={torchvision.__version__}') +logger.log.info(f'Packages: diffusers=={diffusers.__version__} transformers=={transformers.__version__} accelerate=={accelerate.__version__} gradio=={gradio.__version__} pydantic=={pydantic.__version__} numpy=={np.__version__} cv2=={cv2.__version__}') diff --git a/modules/localization.py b/modules/localization.py index e6fc9fdbe..f091fb989 100644 --- a/modules/localization.py +++ b/modules/localization.py @@ -1,5 +1,6 @@ import json import modules.errors as errors +from modules import logger localizations = {} @@ -31,7 +32,7 @@ def localization_js(current_localization_name): with open(fn, encoding="utf8") as file: data = json.load(file) except Exception as e: - errors.log.error(f"Error loading localization from {fn}:") + logger.log.error(f"Error loading localization from {fn}:") errors.display(e, 'localization') return f"var localization = {json.dumps(data)}\n" diff --git a/modules/logger.py b/modules/logger.py new file mode 100644 index 000000000..3e6b63d63 --- /dev/null +++ b/modules/logger.py @@ -0,0 +1,237 @@ +import os +import sys +import logging +import socket +import time +from functools import partial, partialmethod +from logging.handlers import RotatingFileHandler + +# rich imports +from rich.theme import Theme +from rich.logging import RichHandler +from rich.console import Console +from rich.padding import Padding +from rich.segment import Segment +from rich import box +from rich import print as rprint +from rich.pretty import install as pretty_install +from rich.traceback import install as traceback_install + +# Global logger and console instances +log = logging.getLogger("sd") +console = None +log_file = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'sdnext.log') # adjusted path relative to modules/ +hostname = socket.gethostname() +log_rolled = False + + +def str_to_bool(val: str | bool | None) -> bool | None: + if isinstance(val, str): + if val.strip() and val.strip().lower() in ("1", "true"): + return True + return False + return val + + +def get_console(): + return console + + +def get_log(): + return log + + +def install_traceback(suppress: list = None): + if suppress is None: + suppress = [] + width = os.environ.get("SD_TRACEWIDTH", console.width if console else None) + if width is not None: + width = int(width) + log.excepthook = traceback_install( + console=console, + extra_lines=int(os.environ.get("SD_TRACELINES", 1)), + max_frames=int(os.environ.get("SD_TRACEFRAMES", 16)), + width=width, + word_wrap=str_to_bool(os.environ.get("SD_TRACEWRAP", False)), + indent_guides=str_to_bool(os.environ.get("SD_TRACEINDENT", False)), + show_locals=str_to_bool(os.environ.get("SD_TRACELOCALS", False)), + locals_hide_dunder=str_to_bool(os.environ.get("SD_TRACEDUNDER", True)), + locals_hide_sunder=str_to_bool(os.environ.get("SD_TRACESUNDER", None)), + suppress=suppress, + ) + pretty_install(console=console) + + + +_log_config = {'debug': False, 'trace': False, 'log_filename': None} + +def setup_logging(debug=None, trace=None, log_filename=None): + global log_file, console, log_rolled, _log_config # pylint: disable=global-statement + + if debug is not None: _log_config['debug'] = debug + if trace is not None: _log_config['trace'] = trace + if log_filename is not None: _log_config['log_filename'] = log_filename + + debug = _log_config['debug'] + trace = _log_config['trace'] + log_filename = _log_config['log_filename'] + + class RingBuffer(logging.StreamHandler): + def __init__(self, capacity): + super().__init__() + self.capacity = capacity + self.buffer = [] + self.formatter = logging.Formatter('{ "asctime":"%(asctime)s", "created":%(created)f, "facility":"%(name)s", "pid":%(process)d, "tid":%(thread)d, "level":"%(levelname)s", "module":"%(module)s", "func":"%(funcName)s", "msg":"%(message)s" }') + + def emit(self, record): + if record.msg is not None and not isinstance(record.msg, str): + record.msg = str(record.msg) + try: + record.msg = record.msg.replace('"', "'") + except Exception: + pass + msg = self.format(record) + self.buffer.append(msg) + if len(self.buffer) > self.capacity: + self.buffer.pop(0) + + def get(self): + return self.buffer + + class LogFilter(logging.Filter): + def __init__(self): + super().__init__() + + def filter(self, record): + return len(record.getMessage()) > 2 + + def override_padding(self, console, options): # pylint: disable=redefined-outer-name + style = console.get_style(self.style) + width = options.max_width + self.left = 0 + render_options = options.update_width(width - self.left - self.right) + if render_options.height is not None: + render_options = render_options.update_height(height=render_options.height - self.top - self.bottom) + lines = console.render_lines(self.renderable, render_options, style=style, pad=False) + _Segment = Segment + left = _Segment(" " * self.left, style) if self.left else None + right = [_Segment.line()] + blank_line: list[Segment] | None = None + if self.top: + blank_line = [_Segment(f'{" " * width}\\n', style)] + yield from blank_line * self.top + if left: + for line in lines: + yield left + yield from line + yield from right + else: + for line in lines: + yield from line + yield from right + if self.bottom: + blank_line = blank_line or [_Segment(f'{" " * width}\\n', style)] + yield from blank_line * self.bottom + + if log_filename: + log_file = log_filename + + logging.TRACE = 25 + logging.addLevelName(logging.TRACE, 'TRACE') + logging.Logger.trace = partialmethod(logging.Logger.log, logging.TRACE) + logging.trace = partial(logging.log, logging.TRACE) + + def exception_hook(e: Exception, suppress=None): + from rich.traceback import Traceback + if suppress is None: + suppress = [] + tb = Traceback.from_exception(type(e), e, e.__traceback__, show_locals=False, max_frames=16, extra_lines=1, suppress=suppress, theme="ansi_dark", word_wrap=False, width=console.width) + # print-to-console, does not get printed-to-file + exc_type, exc_value, exc_traceback = sys.exc_info() + log.excepthook(exc_type, exc_value, exc_traceback) + # print-to-file, temporarily disable-console-handler + for handler in log.handlers.copy(): + if isinstance(handler, RichHandler): + log.removeHandler(handler) + with console.capture() as capture: + console.print(tb) + log.critical(capture.get()) + log.addHandler(rh) + + log.traceback = exception_hook + + level = logging.DEBUG if (debug or trace) else logging.INFO + log.setLevel(logging.DEBUG) # log to file is always at level debug for facility `sd` + log.print = rprint + + theme = Theme({ + "traceback.border": "black", + "inspect.value.border": "black", + "traceback.border.syntax_error": "dark_red", + "logging.level.info": "blue_violet", + "logging.level.debug": "purple4", + "logging.level.trace": "dark_blue", + }) + + Padding.__rich_console__ = override_padding + box.ROUNDED = box.SIMPLE + console = Console( + log_time=True, + log_time_format='%H:%M:%S-%f', + tab_size=4, + soft_wrap=True, + safe_box=True, + theme=theme, + ) + + logging.basicConfig(level=logging.ERROR, format='%(asctime)s | %(name)s | %(levelname)s | %(module)s | %(message)s', handlers=[logging.NullHandler()]) # redirect default logger to null + + pretty_install(console=console) + install_traceback() + + while log.hasHandlers() and len(log.handlers) > 0: + log.removeHandler(log.handlers[0]) + + log_filter = LogFilter() + # handlers + rh = RichHandler(show_time=True, omit_repeated_times=False, show_level=True, show_path=False, markup=False, rich_tracebacks=True, log_time_format='%H:%M:%S-%f', level=level, console=console) + if trace: + rh.formatter = logging.Formatter('[%(module)s][%(pathname)s:%(lineno)d] %(message)s') + rh.addFilter(log_filter) + rh.setLevel(level) + log.addHandler(rh) + + fh = RotatingFileHandler(log_file, maxBytes=32*1024*1024, backupCount=9, encoding='utf-8', delay=True) # 10MB default for log rotation + if trace: + fh.formatter = logging.Formatter(f'%(asctime)s | {hostname} | %(name)s | %(levelname)s | %(module)s | | %(pathname)s:%(lineno)d | %(message)s') + else: + fh.formatter = logging.Formatter(f'%(asctime)s | {hostname} | %(name)s | %(levelname)s | %(module)s | %(message)s') + fh.addFilter(log_filter) + fh.setLevel(logging.DEBUG) + log.addHandler(fh) + + if not log_rolled and debug and not log_filename: + try: + fh.doRollover() + except Exception: + pass + log_rolled = True + + rb = RingBuffer(100) # 100 entries default in log ring buffer + rb.addFilter(log_filter) + rb.setLevel(level) + log.addHandler(rb) + log.buffer = rb.buffer + + def quiet_log(quiet: bool=False, *args, **kwargs): # pylint: disable=redefined-outer-name,keyword-arg-before-vararg + if not quiet: + log.debug(*args, **kwargs) + log.quiet = quiet_log + + # overrides + logging.getLogger("urllib3").setLevel(logging.ERROR) + logging.getLogger("httpx").setLevel(logging.ERROR) + logging.getLogger("diffusers").setLevel(logging.ERROR) + logging.getLogger("torch").setLevel(logging.ERROR) + logging.getLogger("ControlNet").handlers = log.handlers + logging.getLogger("lycoris").handlers = log.handlers diff --git a/modules/lora/extra_networks_lora.py b/modules/lora/extra_networks_lora.py index 1dabaaa01..96ad6ff6d 100644 --- a/modules/lora/extra_networks_lora.py +++ b/modules/lora/extra_networks_lora.py @@ -4,10 +4,11 @@ import numpy as np from modules.lora import networks, lora_overrides, lora_load, lora_diffusers from modules.lora import lora_common as l from modules import extra_networks, shared, sd_models +from modules import logger debug = os.environ.get('SD_LORA_DEBUG', None) is not None -debug_log = shared.log.trace if debug else lambda *args, **kwargs: None +debug_log = logger.log.trace if debug else lambda *args, **kwargs: None def get_stepwise(param, step, steps): # from https://github.com/cheald/sd-webui-loractl/blob/master/loractl/lib/utils.py @@ -53,7 +54,7 @@ def prompt(p): all_tags = list(set(all_tags)) all_tags = [t for t in all_tags if t not in p.prompt] if len(all_tags) > 0: - shared.log.debug(f"Network load: type=LoRA tags={all_tags} max={shared.opts.lora_apply_tags} apply") + logger.log.debug(f"Network load: type=LoRA tags={all_tags} max={shared.opts.lora_apply_tags} apply") all_tags = ', '.join(all_tags) p.extra_generation_params["LoRA tags"] = all_tags if '_tags_' in p.prompt: @@ -236,7 +237,7 @@ class ExtraNetworkLora(extra_networks.ExtraNetwork): if has_changed: jobid = shared.state.begin('LoRA') if len(l.previously_loaded_networks) > 0: - shared.log.info(f'Network unload: type=LoRA networks={[n.name for n in l.previously_loaded_networks]} mode={"fuse" if shared.opts.lora_fuse_native else "backup"}') + logger.log.info(f'Network unload: type=LoRA networks={[n.name for n in l.previously_loaded_networks]} mode={"fuse" if shared.opts.lora_fuse_native else "backup"}') networks.network_deactivate(include, exclude) networks.network_activate(include, exclude) debug_log(f'Network change: type=LoRA previous={[n.name for n in l.previously_loaded_networks]} current={[n.name for n in l.loaded_networks]}') @@ -248,7 +249,7 @@ class ExtraNetworkLora(extra_networks.ExtraNetwork): infotext(p) prompt(p) if has_changed and len(include) == 0: # print only once - shared.log.info(f'Network load: type=LoRA networks={[n.name for n in l.loaded_networks]} method={load_method} mode={"fuse" if shared.opts.lora_fuse_native else "backup"} te={te_multipliers} unet={unet_multipliers} time={l.timer.summary}') + logger.log.info(f'Network load: type=LoRA networks={[n.name for n in l.loaded_networks]} method={load_method} mode={"fuse" if shared.opts.lora_fuse_native else "backup"} te={te_multipliers} unet={unet_multipliers} time={l.timer.summary}') def deactivate(self, p, force=False): if len(lora_diffusers.diffuser_loaded) > 0 and (shared.opts.lora_force_reload or force): @@ -256,8 +257,8 @@ class ExtraNetworkLora(extra_networks.ExtraNetwork): if force: networks.network_deactivate() if self.active and l.debug: - shared.log.debug(f"Network end: type=LoRA time={l.timer.summary}") + logger.log.debug(f"Network end: type=LoRA time={l.timer.summary}") if self.errors: for k, v in self.errors.items(): - shared.log.error(f'Network: type=LoRA name="{k}" errors={v}') + logger.log.error(f'Network: type=LoRA name="{k}" errors={v}') self.errors.clear() diff --git a/modules/lora/lora_apply.py b/modules/lora/lora_apply.py index 5cf0a4d38..d615bccc9 100644 --- a/modules/lora/lora_apply.py +++ b/modules/lora/lora_apply.py @@ -5,6 +5,7 @@ import diffusers.models.lora from modules.errorlimiter import ErrorLimiter from modules.lora import lora_common as l from modules import shared, devices, errors, model_quant +from modules import logger bnb = None @@ -137,7 +138,7 @@ def network_calc_weights(self: torch.nn.Conv2d | torch.nn.Linear | torch.nn.Grou except RuntimeError as e: l.extra_network_lora.errors[net.name] = l.extra_network_lora.errors.get(net.name, 0) + 1 module_name = net.modules.get(network_layer_name, None) - shared.log.error(f'Network: type=LoRA name="{net.name}" module="{module_name}" layer="{network_layer_name}" apply weight: {e}') + logger.log.error(f'Network: type=LoRA name="{net.name}" module="{module_name}" layer="{network_layer_name}" apply weight: {e}') if l.debug: errors.display(e, 'LoRA') raise RuntimeError('LoRA apply weight') from e @@ -163,7 +164,7 @@ def network_add_weights(self: torch.nn.Conv2d | torch.nn.Linear | torch.nn.Group # TODO lora: maybe force imediate quantization # weight._quantize(devices.device) / weight.to(device=device) except Exception as e: - shared.log.error(f'Network load: type=LoRA quant=bnb cls={self.__class__.__name__} type={self.quant_type} blocksize={self.blocksize} state={vars(self.quant_state)} weight={self.weight} bias={lora_weights} {e}') + logger.log.error(f'Network load: type=LoRA quant=bnb cls={self.__class__.__name__} type={self.quant_type} blocksize={self.blocksize} state={vars(self.quant_state)} weight={self.weight} bias={lora_weights} {e}') elif not bias and hasattr(self, "sdnq_dequantizer"): try: from modules.sdnq import sdnq_quantize_layer @@ -218,14 +219,14 @@ def network_add_weights(self: torch.nn.Conv2d | torch.nn.Linear | torch.nn.Group weight = None del dequant_weight except Exception as e: - shared.log.error(f'Network load: type=LoRA quant=sdnq cls={self.__class__.__name__} weight={self.weight} lora_weights={lora_weights} {e}') + logger.log.error(f'Network load: type=LoRA quant=sdnq cls={self.__class__.__name__} weight={self.weight} lora_weights={lora_weights} {e}') else: try: new_weight = model_weights.to(devices.device) + lora_weights.to(devices.device) except Exception as e: - shared.log.warning(f'Network load: {e}') + logger.log.warning(f'Network load: {e}') if 'The size of tensor' in str(e): - shared.log.error(f'Network load: type=LoRA model={shared.sd_model.__class__.__name__} incompatible lora shape') + logger.log.error(f'Network load: type=LoRA model={shared.sd_model.__class__.__name__} incompatible lora shape') new_weight = model_weights else: new_weight = model_weights + lora_weights # try without device cast diff --git a/modules/lora/lora_diffusers.py b/modules/lora/lora_diffusers.py index 02179fb21..6a2017fee 100644 --- a/modules/lora/lora_diffusers.py +++ b/modules/lora/lora_diffusers.py @@ -2,6 +2,7 @@ import os import time import diffusers from modules import shared, errors +from modules import logger from modules.lora import network from modules.lora import lora_common as l @@ -11,7 +12,7 @@ diffuser_scales = [] def load_per_module(sd_model: diffusers.DiffusionPipeline, filename: str, adapter_name: str, lora_modules: list[str]): - shared.log.debug(f'LoRA load: modules={lora_modules}') + logger.log.debug(f'LoRA load: modules={lora_modules}') try: state_dict = sd_model.lora_state_dict(filename) if isinstance(state_dict, tuple) and len(state_dict) == 2: @@ -19,7 +20,7 @@ def load_per_module(sd_model: diffusers.DiffusionPipeline, filename: str, adapte else: network_alphas = {} except Exception as e: - shared.log.error(f'LoRA load: {e}') + logger.log.error(f'LoRA load: {e}') if l.debug: errors.display(e, "LoRA") return None @@ -28,24 +29,24 @@ def load_per_module(sd_model: diffusers.DiffusionPipeline, filename: str, adapte if hasattr(sd_model, 'transformer') and sd_model.transformer is not None: sd_model.load_lora_into_transformer(state_dict, transformer=sd_model.transformer, adapter_name=adapter_name) else: - shared.log.warning(f'LoRA load: requested={lora_module} missing') + logger.log.warning(f'LoRA load: requested={lora_module} missing') elif lora_module == 'transformer_2': if hasattr(sd_model, 'transformer_2') and sd_model.transformer_2 is not None: sd_model.load_lora_into_transformer(state_dict, transformer=sd_model.transformer_2, adapter_name=adapter_name) else: - shared.log.warning(f'LoRA load: requested={lora_module} missing') + logger.log.warning(f'LoRA load: requested={lora_module} missing') elif lora_module == 'unet': if hasattr(sd_model, 'unet') and sd_model.unet is not None: sd_model.load_lora_into_unet(state_dict, network_alphas, unet=sd_model.unet, adapter_name=adapter_name) else: - shared.log.warning(f'LoRA load: requested={lora_module} missing') + logger.log.warning(f'LoRA load: requested={lora_module} missing') elif lora_module == 'text_encoder' or lora_module == 'te': if hasattr(sd_model, 'text_encoder') and sd_model.text_encoder is not None: sd_model.load_lora_into_text_encoder(state_dict, network_alphas, text_encoder=sd_model.text_encoder, adapter_name=adapter_name) else: - shared.log.warning(f'LoRA load: requested={lora_module} missing') + logger.log.warning(f'LoRA load: requested={lora_module} missing') else: - shared.log.warning(f'LoRA load: requested={lora_module} unknown') + logger.log.warning(f'LoRA load: requested={lora_module} unknown') return adapter_name @@ -53,9 +54,9 @@ def load_diffusers(name: str, network_on_disk: network.NetworkOnDisk, lora_scale t0 = time.time() name = name.replace(".", "_") sd_model: diffusers.DiffusionPipeline = getattr(shared.sd_model, "pipe", shared.sd_model) - shared.log.debug(f'Network load: type=LoRA name="{name}" file="{network_on_disk.filename}" detected={network_on_disk.sd_version} method=diffusers scale={lora_scale} fuse={shared.opts.lora_fuse_native}:{shared.opts.lora_fuse_diffusers}') + logger.log.debug(f'Network load: type=LoRA name="{name}" file="{network_on_disk.filename}" detected={network_on_disk.sd_version} method=diffusers scale={lora_scale} fuse={shared.opts.lora_fuse_native}:{shared.opts.lora_fuse_diffusers}') if not hasattr(sd_model, 'load_lora_weights'): - shared.log.error(f'Network load: type=LoRA class={sd_model.__class__} does not implement load lora') + logger.log.error(f'Network load: type=LoRA class={sd_model.__class__} does not implement load lora') return None try: if lora_module is not None and isinstance(lora_module, list) and len(lora_module) > 0: @@ -68,11 +69,11 @@ def load_diffusers(name: str, network_on_disk: network.NetworkOnDisk, lora_scale pass else: if 'following keys have not been correctly renamed' in str(e): - shared.log.error(f'Network load: type=LoRA name="{name}" diffusers unsupported format') + logger.log.error(f'Network load: type=LoRA name="{name}" diffusers unsupported format') elif 'object has no attribute' in str(e): - shared.log.error(f'Network load: type=LoRA name="{name}" diffusers empty module') + logger.log.error(f'Network load: type=LoRA name="{name}" diffusers empty module') else: - shared.log.error(f'Network load: type=LoRA name="{name}" {e}') + logger.log.error(f'Network load: type=LoRA name="{name}" {e}') if l.debug: errors.display(e, "LoRA") return None @@ -82,7 +83,7 @@ def load_diffusers(name: str, network_on_disk: network.NetworkOnDisk, lora_scale list_adapters = sd_model.get_list_adapters() list_adapters = [adapter for adapters in list_adapters.values() for adapter in adapters] if name not in list_adapters: - shared.log.error(f'Network load: type=LoRA name="{name}" adapters={list_adapters} not loaded') + logger.log.error(f'Network load: type=LoRA name="{name}" adapters={list_adapters} not loaded') else: diffuser_loaded.append(name) diffuser_scales.append(lora_scale) diff --git a/modules/lora/lora_extract.py b/modules/lora/lora_extract.py index 25cf4a438..e235994da 100644 --- a/modules/lora/lora_extract.py +++ b/modules/lora/lora_extract.py @@ -7,6 +7,7 @@ from safetensors.torch import save_file import gradio as gr from rich import progress as rp from modules import shared, devices +from modules import logger from modules.ui_common import create_refresh_button from modules.call_queue import wrap_gradio_gpu_call @@ -118,26 +119,26 @@ def make_meta(fn, maxrank, rank_ratio): def make_lora(fn, maxrank, auto_rank, rank_ratio, modules, overwrite): if not shared.sd_loaded: msg = "LoRA extract: model not loaded" - shared.log.warning(msg) + logger.log.warning(msg) yield msg return if loaded_lora() == "": msg = "LoRA extract: no LoRA detected" - shared.log.warning(msg) + logger.log.warning(msg) yield msg return if not fn: msg = "LoRA extract: target filename required" - shared.log.warning(msg) + logger.log.warning(msg) yield msg return t0 = time.time() maxrank = int(maxrank) rank_ratio = 1 if not auto_rank else rank_ratio - shared.log.debug(f'LoRA extract: modules={modules} maxrank={maxrank} auto={auto_rank} ratio={rank_ratio} fn="{fn}"') + logger.log.debug(f'LoRA extract: modules={modules} maxrank={maxrank} auto={auto_rank} ratio={rank_ratio} fn="{fn}"') jobid = shared.state.begin('LoRA extract') - with rp.Progress(rp.TextColumn('[cyan]LoRA extract'), rp.BarColumn(), rp.TaskProgressColumn(), rp.TimeRemainingColumn(), rp.TimeElapsedColumn(), rp.TextColumn('[cyan]{task.description}'), console=shared.console) as progress: + with rp.Progress(rp.TextColumn('[cyan]LoRA extract'), rp.BarColumn(), rp.TaskProgressColumn(), rp.TimeRemainingColumn(), rp.TimeElapsedColumn(), rp.TextColumn('[cyan]{task.description}'), console=logger.console) as progress: if 'te' in modules and getattr(shared.sd_model, 'text_encoder', None) is not None: modules = shared.sd_model.text_encoder.named_modules() @@ -222,25 +223,25 @@ def make_lora(fn, maxrank, auto_rank, rank_ratio, modules, overwrite): os.remove(fn) else: msg = f'LoRA extract: fn="{fn}" file exists' - shared.log.warning(msg) + logger.log.warning(msg) yield msg return shared.state.end(jobid) meta = make_meta(fn, maxrank, rank_ratio) - shared.log.debug(f'LoRA metadata: {meta}') + logger.log.debug(f'LoRA metadata: {meta}') try: save_file(tensors=lora_state_dict, metadata=meta, filename=fn) except Exception as e: msg = f'LoRA extract error: fn="{fn}" {e}' - shared.log.error(msg) + logger.log.error(msg) yield msg return t5 = time.time() - shared.log.debug(f'LoRA extract: time={t5-t0:.2f} te1={t1-t0:.2f} te2={t2-t1:.2f} unet={t3-t2:.2f} save={t5-t4:.2f}') + logger.log.debug(f'LoRA extract: time={t5-t0:.2f} te1={t1-t0:.2f} te2={t2-t1:.2f} unet={t3-t2:.2f} save={t5-t4:.2f}') keys = list(lora_state_dict.keys()) msg = f'LoRA extract: fn="{fn}" keys={len(keys)}' - shared.log.info(msg) + logger.log.info(msg) yield msg diff --git a/modules/lora/lora_load.py b/modules/lora/lora_load.py index ff5659ea5..4dd38a10d 100644 --- a/modules/lora/lora_load.py +++ b/modules/lora/lora_load.py @@ -2,6 +2,7 @@ import os import time import concurrent from modules import shared, errors, sd_models, sd_models_compile, files_cache +from modules import logger from modules.lora import network, lora_overrides, lora_convert, lora_diffusers from modules.lora import lora_common as l @@ -22,18 +23,18 @@ def lora_dump(lora, dct): sd_model = getattr(shared.sd_model, "pipe", shared.sd_model) ty = shared.sd_model_type cn = sd_model.__class__.__name__ - shared.log.trace(f'LoRA dump: type={ty} model={cn} fn="{lora}"') + logger.log.trace(f'LoRA dump: type={ty} model={cn} fn="{lora}"') bn = os.path.splitext(os.path.basename(lora))[0] fn = os.path.join(tempfile.gettempdir(), f'LoRA-{ty}-{cn}-{bn}.txt') with open(fn, 'w', encoding='utf8') as f: keys = sorted(dct.keys()) - shared.log.trace(f'LoRA dump: type=LoRA fn="{fn}" keys={len(keys)}') + logger.log.trace(f'LoRA dump: type=LoRA fn="{fn}" keys={len(keys)}') for line in keys: f.write(line + "\n") fn = os.path.join(tempfile.gettempdir(), f'Model-{ty}-{cn}.txt') with open(fn, 'w', encoding='utf8') as f: keys = sd_model.network_layer_mapping.keys() - shared.log.trace(f'LoRA dump: type=Mapping fn="{fn}" keys={len(keys)}') + logger.log.trace(f'LoRA dump: type=Mapping fn="{fn}" keys={len(keys)}') for line in keys: f.write(line + "\n") @@ -45,7 +46,7 @@ def load_safetensors(name, network_on_disk: network.NetworkOnDisk) -> network.Ne sd_model = getattr(shared.sd_model, "pipe", shared.sd_model) cached = lora_cache.get(name, None) if l.debug: - shared.log.debug(f'Network load: type=LoRA name="{name}" file="{network_on_disk.filename}" type=lora {"cached" if cached else ""}') + logger.log.debug(f'Network load: type=LoRA name="{name}" file="{network_on_disk.filename}" type=lora {"cached" if cached else ""}') if cached is not None: return cached net = network.Network(name, network_on_disk) @@ -117,17 +118,17 @@ def load_safetensors(name, network_on_disk: network.NetworkOnDisk) -> network.Ne if net_module is None: module_errors += 1 if l.debug: - shared.log.error(f'LoRA unhandled: name={name} key={key} weights={weights.w.keys()}') + logger.log.error(f'LoRA unhandled: name={name} key={key} weights={weights.w.keys()}') else: net.modules[key] = net_module if module_errors > 0: - shared.log.error(f'Network load: type=LoRA name="{name}" file="{network_on_disk.filename}" errors={module_errors} empty modules') + logger.log.error(f'Network load: type=LoRA name="{name}" file="{network_on_disk.filename}" errors={module_errors} empty modules') if len(keys_failed_to_match) > 0: - shared.log.warning(f'Network load: type=LoRA name="{name}" type={set(network_types)} unmatched={len(keys_failed_to_match)} matched={len(matched_networks)}') + logger.log.warning(f'Network load: type=LoRA name="{name}" type={set(network_types)} unmatched={len(keys_failed_to_match)} matched={len(matched_networks)}') if l.debug: - shared.log.debug(f'Network load: type=LoRA name="{name}" unmatched={keys_failed_to_match}') + logger.log.debug(f'Network load: type=LoRA name="{name}" unmatched={keys_failed_to_match}') else: - shared.log.debug(f'Network load: type=LoRA name="{name}" type={set(network_types)} keys={len(matched_networks)} dtypes={dtypes} fuse={shared.opts.lora_fuse_native}:{shared.opts.lora_fuse_diffusers}') + logger.log.debug(f'Network load: type=LoRA name="{name}" type={set(network_types)} keys={len(matched_networks)} dtypes={dtypes} fuse={shared.opts.lora_fuse_native}:{shared.opts.lora_fuse_diffusers}') if len(matched_networks) == 0: return None lora_cache[name] = net @@ -150,14 +151,14 @@ def maybe_recompile_model(names, te_multipliers): if not recompile_model: skip_lora_load = True if len(l.loaded_networks) > 0 and l.debug: - shared.log.debug('Model Compile: Skipping LoRa loading') + logger.log.debug('Model Compile: Skipping LoRa loading') return recompile_model, skip_lora_load else: recompile_model = True shared.compiled_model_state.lora_model = [] if recompile_model: current_task = sd_models.get_diffusers_task(shared.sd_model) - shared.log.debug(f'Compile: task={current_task} force model reload') + logger.log.debug(f'Compile: task={current_task} force model reload') backup_cuda_compile = shared.opts.cuda_compile backup_scheduler = getattr(sd_model, "scheduler", None) sd_models.unload_model_weights(op='model') @@ -178,7 +179,7 @@ def list_available_networks(): available_network_hash_lookup.clear() forbidden_network_aliases.update({"none": 1, "Addams": 1}) if not os.path.exists(shared.cmd_opts.lora_dir): - shared.log.warning(f'LoRA directory not found: path="{shared.cmd_opts.lora_dir}"') + logger.log.warning(f'LoRA directory not found: path="{shared.cmd_opts.lora_dir}"') def add_network(filename): if not os.path.isfile(filename): @@ -194,7 +195,7 @@ def list_available_networks(): if entry.shorthash: available_network_hash_lookup[entry.shorthash] = entry except OSError as e: # should catch FileNotFoundError and PermissionError etc. - shared.log.error(f'LoRA: filename="{filename}" {e}') + logger.log.error(f'LoRA: filename="{filename}" {e}') candidates = sorted(files_cache.list_files(shared.cmd_opts.lora_dir, ext_filter=[".pt", ".ckpt", ".safetensors"])) with concurrent.futures.ThreadPoolExecutor(max_workers=shared.max_workers) as executor: @@ -202,7 +203,7 @@ def list_available_networks(): executor.submit(add_network, fn) t1 = time.time() l.timer.list = t1 - t0 - shared.log.info(f'Available LoRAs: path="{shared.cmd_opts.lora_dir}" items={len(available_networks)} folders={len(forbidden_network_aliases)} time={t1 - t0:.2f}') + logger.log.info(f'Available LoRAs: path="{shared.cmd_opts.lora_dir}" items={len(available_networks)} folders={len(forbidden_network_aliases)} time={t1 - t0:.2f}') def network_download(name): @@ -245,7 +246,7 @@ def network_load(names, te_multipliers=None, unet_multipliers=None, dyn_dims=Non if network_on_disk is not None: shorthash = getattr(network_on_disk, 'shorthash', '').lower() if l.debug: - shared.log.debug(f'Network load: type=LoRA name="{name}" file="{network_on_disk.filename}" hash="{shorthash}"') + logger.log.debug(f'Network load: type=LoRA name="{name}" file="{network_on_disk.filename}" hash="{shorthash}"') try: lora_scale = te_multipliers[i] if te_multipliers else shared.opts.extra_networks_default_multiplier lora_module = lora_modules[i] if lora_modules and len(lora_modules) > i else None @@ -262,13 +263,13 @@ def network_load(names, te_multipliers=None, unet_multipliers=None, dyn_dims=Non net.mentioned_name = name network_on_disk.read_hash() except Exception as e: - shared.log.error(f'Network load: type=LoRA file="{network_on_disk.filename}" {e}') + logger.log.error(f'Network load: type=LoRA file="{network_on_disk.filename}" {e}') if l.debug: errors.display(e, 'LoRA') continue if net is None: failed_to_load_networks.append(name) - shared.log.error(f'Network load: type=LoRA name="{name}" detected={network_on_disk.sd_version if network_on_disk is not None else None} not found') + logger.log.error(f'Network load: type=LoRA name="{name}" detected={network_on_disk.sd_version if network_on_disk is not None else None} not found') continue if hasattr(sd_model, 'embedding_db'): sd_model.embedding_db.load_diffusers_embedding(None, net.bundle_embeddings) @@ -282,16 +283,16 @@ def network_load(names, te_multipliers=None, unet_multipliers=None, dyn_dims=Non lora_cache.pop(name, None) if not skip_lora_load and len(lora_diffusers.diffuser_loaded) > 0: - shared.log.debug(f'Network load: type=LoRA loaded={lora_diffusers.diffuser_loaded} available={sd_model.get_list_adapters()} active={sd_model.get_active_adapters()} scales={lora_diffusers.diffuser_scales}') + logger.log.debug(f'Network load: type=LoRA loaded={lora_diffusers.diffuser_loaded} available={sd_model.get_list_adapters()} active={sd_model.get_active_adapters()} scales={lora_diffusers.diffuser_scales}') try: t1 = time.time() if l.debug: - shared.log.trace(f'Network load: type=LoRA list={sd_model.get_list_adapters()}') - shared.log.trace(f'Network load: type=LoRA active={sd_model.get_active_adapters()}') + logger.log.trace(f'Network load: type=LoRA list={sd_model.get_list_adapters()}') + logger.log.trace(f'Network load: type=LoRA active={sd_model.get_active_adapters()}') sd_model.set_adapters(adapter_names=lora_diffusers.diffuser_loaded, adapter_weights=lora_diffusers.diffuser_scales) except Exception as e: if str(e) not in exclude_errors: - shared.log.error(f'Network load: type=LoRA action=strength {str(e)}') + logger.log.error(f'Network load: type=LoRA action=strength {str(e)}') if l.debug: errors.display(e, 'LoRA') try: @@ -300,16 +301,16 @@ def network_load(names, te_multipliers=None, unet_multipliers=None, dyn_dims=Non sd_model.unload_lora_weights() l.timer.activate += time.time() - t1 except Exception as e: - shared.log.error(f'Network load: type=LoRA action=fuse {str(e)}') + logger.log.error(f'Network load: type=LoRA action=fuse {str(e)}') if l.debug: errors.display(e, 'LoRA') shared.sd_model = sd_models.apply_balanced_offload(shared.sd_model, force=True, silent=True) # some layers may end up on cpu without hook if len(l.loaded_networks) > 0 and l.debug: - shared.log.debug(f'Network load: type=LoRA loaded={[n.name for n in l.loaded_networks]} cache={list(lora_cache)} fuse={shared.opts.lora_fuse_native}:{shared.opts.lora_fuse_diffusers}') + logger.log.debug(f'Network load: type=LoRA loaded={[n.name for n in l.loaded_networks]} cache={list(lora_cache)} fuse={shared.opts.lora_fuse_native}:{shared.opts.lora_fuse_diffusers}') if recompile_model: - shared.log.info("Network load: type=LoRA recompiling model") + logger.log.info("Network load: type=LoRA recompiling model") if shared.compiled_model_state is not None: backup_lora_model = shared.compiled_model_state.lora_model else: diff --git a/modules/lora/lora_nunchaku.py b/modules/lora/lora_nunchaku.py index 318e25398..78019dedf 100644 --- a/modules/lora/lora_nunchaku.py +++ b/modules/lora/lora_nunchaku.py @@ -1,5 +1,6 @@ import time from modules import shared, errors +from modules import logger from modules.lora import lora_load, lora_common @@ -16,7 +17,7 @@ def load_nunchaku(names, strengths): if not is_changed: return False if not hasattr(shared.sd_model, 'transformer') or not hasattr(shared.sd_model.transformer, 'update_lora_params'): - shared.log.error(f'Network load: type=LoRA method=nunchaku model={shared.sd_model.__class__.__name__} unsupported') + logger.log.error(f'Network load: type=LoRA method=nunchaku model={shared.sd_model.__class__.__name__} unsupported') return False previously_loaded = loras @@ -28,9 +29,9 @@ def load_nunchaku(names, strengths): lora_common.loaded_networks = [n[0] for n in networks] # used by infotext t1 = time.time() lora_common.timer.load = t1 - t0 - shared.log.debug(f"Network load: type=LoRA method=nunchaku loras={names} strength={strengths} time={t1-t0:.3f}") + logger.log.debug(f"Network load: type=LoRA method=nunchaku loras={names} strength={strengths} time={t1-t0:.3f}") except Exception as e: - shared.log.error(f'Network load: type=LoRA method=nunchaku {e}') + logger.log.error(f'Network load: type=LoRA method=nunchaku {e}') if lora_common.debug: errors.display(e, 'LoRA') return is_changed diff --git a/modules/lora/networks.py b/modules/lora/networks.py index 512a63698..4a4883756 100644 --- a/modules/lora/networks.py +++ b/modules/lora/networks.py @@ -5,6 +5,7 @@ from modules.errorlimiter import limit_errors from modules.lora import lora_common as l from modules.lora.lora_apply import network_apply_weights, network_apply_direct, network_backup_weights, network_calc_weights from modules import shared, devices, sd_models +from modules import logger applied_layers: list[str] = [] @@ -34,7 +35,7 @@ def network_activate(include=None, exclude=None): modules[name] = list(component.named_modules()) total = sum(len(x) for x in modules.values()) if len(l.loaded_networks) > 0: - pbar = rp.Progress(rp.TextColumn('[cyan]Network: type=LoRA action=activate'), rp.BarColumn(), rp.TaskProgressColumn(), rp.TimeRemainingColumn(), rp.TimeElapsedColumn(), rp.TextColumn('[cyan]{task.description}'), console=shared.console) + pbar = rp.Progress(rp.TextColumn('[cyan]Network: type=LoRA action=activate'), rp.BarColumn(), rp.TaskProgressColumn(), rp.TimeRemainingColumn(), rp.TimeElapsedColumn(), rp.TextColumn('[cyan]{task.description}'), console=logger.console) task = pbar.add_task(description='' , total=total) else: task = None @@ -75,7 +76,7 @@ def network_activate(include=None, exclude=None): pbar.remove_task(task) # hide progress bar for no action l.timer.activate += time.time() - t0 if l.debug and len(l.loaded_networks) > 0: - shared.log.debug(f'Network load: type=LoRA networks={[n.name for n in l.loaded_networks]} modules={active_components} layers={total} weights={applied_weight} bias={applied_bias} backup={round(backup_size/1024/1024/1024, 2)} fuse={shared.opts.lora_fuse_native}:{shared.opts.lora_fuse_diffusers} device={device} time={l.timer.summary}') + logger.log.debug(f'Network load: type=LoRA networks={[n.name for n in l.loaded_networks]} modules={active_components} layers={total} weights={applied_weight} bias={applied_bias} backup={round(backup_size/1024/1024/1024, 2)} fuse={shared.opts.lora_fuse_native}:{shared.opts.lora_fuse_diffusers} device={device} time={l.timer.summary}') modules.clear() if len(applied_layers) > 0 or shared.opts.diffusers_offload_mode == "sequential": sd_models.set_diffuser_offload(sd_model, op="model") @@ -108,7 +109,7 @@ def network_deactivate(include=None, exclude=None): active_components.append(name) total = sum(len(x) for x in modules.values()) if len(l.previously_loaded_networks) > 0 and l.debug: - pbar = rp.Progress(rp.TextColumn('[cyan]Network: type=LoRA action=deactivate'), rp.BarColumn(), rp.TaskProgressColumn(), rp.TimeRemainingColumn(), rp.TimeElapsedColumn(), rp.TextColumn('[cyan]{task.description}'), console=shared.console) + pbar = rp.Progress(rp.TextColumn('[cyan]Network: type=LoRA action=deactivate'), rp.BarColumn(), rp.TaskProgressColumn(), rp.TimeRemainingColumn(), rp.TimeElapsedColumn(), rp.TextColumn('[cyan]{task.description}'), console=logger.console) task = pbar.add_task(description='', total=total) else: task = None @@ -136,7 +137,7 @@ def network_deactivate(include=None, exclude=None): pbar.update(task, advance=1, description=f'networks={len(l.previously_loaded_networks)} modules={active_components} layers={total} unapply={len(applied_layers)}') l.timer.deactivate = time.time() - t0 if l.debug and len(l.previously_loaded_networks) > 0: - shared.log.debug(f'Network deactivate: type=LoRA networks={[n.name for n in l.previously_loaded_networks]} modules={active_components} layers={total} apply={len(applied_layers)} fuse={shared.opts.lora_fuse_native}:{shared.opts.lora_fuse_diffusers} time={l.timer.summary}') + logger.log.debug(f'Network deactivate: type=LoRA networks={[n.name for n in l.previously_loaded_networks]} modules={active_components} layers={total} apply={len(applied_layers)} fuse={shared.opts.lora_fuse_native}:{shared.opts.lora_fuse_diffusers} time={l.timer.summary}') modules.clear() if len(applied_layers) > 0 or shared.opts.diffusers_offload_mode == "sequential": sd_models.set_diffuser_offload(sd_model, op="model") diff --git a/modules/ltx/ltx_process.py b/modules/ltx/ltx_process.py index 3e77966a0..84503630c 100644 --- a/modules/ltx/ltx_process.py +++ b/modules/ltx/ltx_process.py @@ -4,6 +4,7 @@ import torch from PIL import Image from modules import shared, errors, timer, memstats, progress, processing, sd_models, sd_samplers, extra_networks, call_queue +from modules import logger from modules.video_models.video_vae import set_vae_params from modules.video_models.video_save import save_video from modules.video_models.video_utils import check_av @@ -11,7 +12,7 @@ from modules.processing_callbacks import diffusers_callback from modules.ltx.ltx_util import get_bucket, get_frames, load_model, load_upsample, get_conditions, get_generator, get_prompts, vae_decode -debug = shared.log.trace if os.environ.get('SD_VIDEO_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_VIDEO_DEBUG', None) is not None else lambda *args, **kwargs: None # engine, model = 'LTX Video', 'LTXVideo 0.9.7 13B' upsample_repo_id = "a-r-r-o-w/LTX-Video-0.9.7-Latent-Spatial-Upsampler-diffusers" upsample_pipe = None @@ -56,9 +57,9 @@ def run_ltx(task_id, def abort(e, ok:bool=False, p=None): if ok: - shared.log.info(e) + logger.log.info(e) else: - shared.log.error(f'Video: cls={shared.sd_model.__class__.__name__} op=base {e}') + logger.log.error(f'Video: cls={shared.sd_model.__class__.__name__} op=base {e}') errors.display(e, 'LTX') if p is not None: extra_networks.deactivate(p) @@ -121,7 +122,7 @@ def run_ltx(task_id, prompt, negative, networks = get_prompts(prompt, negative, styles) sampler_name = processing.get_sampler_name(sampler_index) sd_samplers.create_sampler(sampler_name, shared.sd_model) - shared.log.debug(f'Video: cls={shared.sd_model.__class__.__name__} op=init styles={styles} networks={networks} sampler={shared.sd_model.scheduler.__class__.__name__}') + logger.log.debug(f'Video: cls={shared.sd_model.__class__.__name__} op=init styles={styles} networks={networks} sampler={shared.sd_model.scheduler.__class__.__name__}') extra_networks.activate(p, networks) framewise = 'LTX2' not in shared.sd_model.__class__.__name__ @@ -151,10 +152,10 @@ def run_ltx(task_id, base_args["image_cond_noise_scale"] = image_cond_noise_scale if len(conditions) > 0: base_args["conditions"] = conditions - shared.log.debug(f'Video: cls={shared.sd_model.__class__.__name__} op=base {base_args}') + logger.log.debug(f'Video: cls={shared.sd_model.__class__.__name__} op=base {base_args}') if debug: - shared.log.trace(f'LTX args: {base_args}') + logger.log.trace(f'LTX args: {base_args}') yield None, 'LTX: Generate in progress...' samplejob = shared.state.begin('Sample') try: @@ -172,7 +173,7 @@ def run_ltx(task_id, audio = None try: if debug: - shared.log.trace(f'LTX result frames={latents.shape if latents is not None else None} audio={audio.shape if audio is not None else None}') + logger.log.trace(f'LTX result frames={latents.shape if latents is not None else None} audio={audio.shape if audio is not None else None}') except Exception: pass @@ -198,7 +199,7 @@ def run_ltx(task_id, } if latents.ndim == 4: latents = latents.unsqueeze(0) # add batch dimension - shared.log.debug(f'Video: cls={shared.sd_model.__class__.__name__} op=upsample latents={latents.shape} {upscale_args}') + logger.log.debug(f'Video: cls={shared.sd_model.__class__.__name__} op=upsample latents={latents.shape} {upscale_args}') yield None, 'LTX: Upsample in progress...' try: upsampled_latents = upsample_pipe(latents=latents, **upscale_args).frames[0] @@ -236,7 +237,7 @@ def run_ltx(task_id, if latents.ndim == 4: latents = latents.unsqueeze(0) # add batch dimension - shared.log.debug(f'Video: cls={shared.sd_model.__class__.__name__} op=refine latents={latents.shape} {refine_args}') + logger.log.debug(f'Video: cls={shared.sd_model.__class__.__name__} op=refine latents={latents.shape} {refine_args}') if len(conditions) > 0: refine_args["conditions"] = conditions yield None, 'LTX: Refine in progress...' @@ -316,5 +317,5 @@ def run_ltx(task_id, shared.state.end(videojob) progress.finish_task(task_id) - shared.log.info(f'Processed: fn="{video_file}" frames={num_frames} fps={fps} its={its} resolution={resolution} time={t_end-t0:.2f} timers={timer.process.dct()} memory={memstats.memory_stats()}') + logger.log.info(f'Processed: fn="{video_file}" frames={num_frames} fps={fps} its={its} resolution={resolution} time={t_end-t0:.2f} timers={timer.process.dct()} memory={memstats.memory_stats()}') yield video_file, f'LTX: Generation completed | File {video_file} | Frames {len(frames)} | Resolution {resolution} | f/s {fps} | it/s {its} '+ f"

{summary} {memory}

" diff --git a/modules/ltx/ltx_ui.py b/modules/ltx/ltx_ui.py index f2e96dbc1..f539f83ce 100644 --- a/modules/ltx/ltx_ui.py +++ b/modules/ltx/ltx_ui.py @@ -1,11 +1,12 @@ import os import gradio as gr from modules import shared, ui_sections +from modules import logger from modules.video_models.models_def import models from modules.ltx import ltx_process -debug = shared.log.trace if os.environ.get('SD_VIDEO_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_VIDEO_DEBUG', None) is not None else lambda *args, **kwargs: None def create_ui(prompt, negative, styles, overrides, init_image, init_strength, last_image, mp4_fps, mp4_interpolate, mp4_codec, mp4_ext, mp4_opt, mp4_video, mp4_frames, mp4_sf, width, height, frames, seed): diff --git a/modules/ltx/ltx_util.py b/modules/ltx/ltx_util.py index 5264b11dc..c29cad2a4 100644 --- a/modules/ltx/ltx_util.py +++ b/modules/ltx/ltx_util.py @@ -2,6 +2,7 @@ import time import torch from PIL import Image from modules import devices, shared, sd_models, timer, extra_networks +from modules import logger loaded_model: str = None @@ -28,7 +29,7 @@ def load_model(engine: str, model: str): t0 = time.time() from modules.video_models import models_def, video_load selected: models_def.Model = [m for m in models_def.models[engine] if m.name == model][0] - shared.log.info(f'Video load: engine="{engine}" selected="{model}" {selected}') + logger.log.info(f'Video load: engine="{engine}" selected="{model}" {selected}') video_load.load_model(selected) loaded_model = model t1 = time.time() @@ -42,7 +43,7 @@ def load_upsample(upsample_pipe, upsample_repo_id): if upsample_pipe is None: t0 = time.time() from diffusers.pipelines.ltx.pipeline_ltx_latent_upsample import LTXLatentUpsamplePipeline - shared.log.info(f'Video load: cls={LTXLatentUpsamplePipeline.__class__.__name__} repo="{upsample_repo_id}"') + logger.log.info(f'Video load: cls={LTXLatentUpsamplePipeline.__class__.__name__} repo="{upsample_repo_id}"') upsample_pipe = LTXLatentUpsamplePipeline.from_pretrained( upsample_repo_id, vae=shared.sd_model.vae, @@ -65,9 +66,9 @@ def get_conditions(width, height, condition_strength, condition_images, conditio condition_image = decode_base64_to_image(condition_image) condition_image = condition_image.convert('RGB').resize((width, height), resample=Image.Resampling.LANCZOS) conditions.append(LTXVideoCondition(image=condition_image, frame_index=0, strength=condition_strength)) - shared.log.debug(f'Video condition: image={condition_image.size} strength={condition_strength}') + logger.log.debug(f'Video condition: image={condition_image.size} strength={condition_strength}') except Exception as e: - shared.log.error(f'LTX condition image: {e}') + logger.log.error(f'LTX condition image: {e}') if condition_files is not None: condition_images = [] for fn in condition_files: @@ -78,10 +79,10 @@ def get_conditions(width, height, condition_strength, condition_images, conditio condition_image = fn.convert('RGB').resize((width, height), resample=Image.Resampling.LANCZOS) condition_images.append(condition_image) except Exception as e: - shared.log.error(f'LTX condition files: {e}') + logger.log.error(f'LTX condition files: {e}') if len(condition_images) > 0: conditions.append(LTXVideoCondition(video=condition_images, frame_index=0, strength=condition_strength)) - shared.log.debug(f'Video condition: files={len(condition_images)} size={condition_images[0].size} strength={condition_strength}') + logger.log.debug(f'Video condition: files={len(condition_images)} size={condition_images[0].size} strength={condition_strength}') if condition_video is not None: from modules.video_models.video_utils import get_video_frames try: @@ -89,9 +90,9 @@ def get_conditions(width, height, condition_strength, condition_images, conditio condition_frames = [f.convert('RGB').resize((width, height), resample=Image.Resampling.LANCZOS) for f in condition_frames] if len(condition_frames) > 0: conditions.append(LTXVideoCondition(video=condition_frames, frame_index=0, strength=condition_strength)) - shared.log.debug(f'Video condition: frames={len(condition_frames)} size={condition_frames[0].size} strength={condition_strength}') + logger.log.debug(f'Video condition: frames={len(condition_frames)} size={condition_frames[0].size} strength={condition_strength}') except Exception as e: - shared.log.error(f'LTX condition video: {e}') + logger.log.error(f'LTX condition video: {e}') return conditions @@ -113,7 +114,7 @@ def get_generator(seed): def vae_decode(latents, decode_timestep, seed): t0 = time.time() - shared.log.debug(f'Video: cls={shared.sd_model.vae.__class__.__name__} op=vae latents={latents.shape} timestep={decode_timestep}') + logger.log.debug(f'Video: cls={shared.sd_model.vae.__class__.__name__} op=vae latents={latents.shape} timestep={decode_timestep}') from diffusers.utils.torch_utils import randn_tensor latents = shared.sd_model._denormalize_latents( # pylint: disable=protected-access latents, diff --git a/modules/masking.py b/modules/masking.py index 92de3bb75..d41024ef2 100644 --- a/modules/masking.py +++ b/modules/masking.py @@ -8,10 +8,11 @@ import cv2 from PIL import Image, ImageFilter, ImageOps from transformers import SamModel, SamImageProcessor, MaskGenerationPipeline from modules import shared, errors, devices, paths, sd_models +from modules import logger from modules.memstats import memory_stats -debug = shared.log.trace if os.environ.get('SD_MASK_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_MASK_DEBUG', None) is not None else lambda *args, **kwargs: None debug('Trace: MASK') @@ -177,7 +178,7 @@ def init_model(selected_model: str): model_path = MODELS[selected_model] if model_path is None: # none if generator is not None: - shared.log.debug('Mask segment unloading model') + logger.log.debug('Mask segment unloading model') opts.model = None generator = None devices.torch_gc() @@ -190,7 +191,7 @@ def init_model(selected_model: str): if opts.model != selected_model or generator is None: # sam pipeline busy = True t0 = time.time() - shared.log.debug(f'Mask segment loading: model="{selected_model}" path={model_path}') + logger.log.debug(f'Mask segment loading: model="{selected_model}" path={model_path}') model = SamModel.from_pretrained(model_path, cache_dir=cache_dir).to(device=devices.device) processor = SamImageProcessor.from_pretrained(model_path, cache_dir=cache_dir) generator = MaskGenerationPipeline( @@ -201,7 +202,7 @@ def init_model(selected_model: str): # output_rle_masks=False, ) devices.torch_gc() - shared.log.debug(f'Mask segment loaded: model="{selected_model}" path={model_path} time={time.time()-t0:.2f}s') + logger.log.debug(f'Mask segment loaded: model="{selected_model}" path={model_path} time={time.time()-t0:.2f}s') opts.model = selected_model busy = False return selected_model @@ -222,7 +223,7 @@ def run_segment(input_image: gr.Image, input_mask: np.ndarray): crop_n_points_downscale_factor=1, ) except Exception as e: - shared.log.error(f'Mask segment error: {e}') + logger.log.error(f'Mask segment error: {e}') errors.display(e, 'Mask segment') return outputs devices.torch_gc() @@ -260,7 +261,7 @@ def run_rembg(input_image: Image, input_mask: np.ndarray): try: import rembg except Exception as e: - shared.log.error(f'Mask Rembg load failed: {e}') + logger.log.error(f'Mask Rembg load failed: {e}') return input_mask if "U2NET_HOME" not in os.environ: os.environ["U2NET_HOME"] = os.path.join(paths.models_path, "Rembg") @@ -432,21 +433,21 @@ def run_mask(input_image: Image.Image, input_mask: Image.Image = None, return_ty mask = cv2.erode(mask, kernel, iterations=opts.kernel_iterations) # remove noise debug(f'Mask erode={opts.mask_erode:.3f} kernel={kernel.shape} mask={mask.shape}') except Exception as e: - shared.log.error(f'Mask erode: {e}') + logger.log.error(f'Mask erode: {e}') if opts.mask_dilate > 0: try: kernel = np.ones((int(opts.mask_dilate * size / 4) + 1, int(opts.mask_dilate * size / 4) + 1), np.uint8) mask = cv2.dilate(mask, kernel, iterations=opts.kernel_iterations) # expand area debug(f'Mask dilate={opts.mask_dilate:.3f} kernel={kernel.shape} mask={mask.shape}') except Exception as e: - shared.log.error(f'Mask dilate: {e}') + logger.log.error(f'Mask dilate: {e}') if opts.mask_blur > 0: try: sigmax, sigmay = 1 + int(opts.mask_blur * size / 4), 1 + int(opts.mask_blur * size / 4) mask = cv2.GaussianBlur(mask, (0, 0), sigmaX=sigmax, sigmaY=sigmay) # blur mask debug(f'Mask blur={opts.mask_blur:.3f} x={sigmax} y={sigmay} mask={mask.shape}') except Exception as e: - shared.log.error(f'Mask blur: {e}') + logger.log.error(f'Mask blur: {e}') if opts.invert: mask = np.invert(mask) @@ -476,7 +477,7 @@ def run_mask(input_image: Image.Image, input_mask: Image.Image = None, return_ty combined_image = cv2.addWeighted(orig, opts.weight_original, colored_mask, opts.weight_mask, 0) return Image.fromarray(combined_image) else: - shared.log.error(f'Mask unknown return type: {return_type}') + logger.log.error(f'Mask unknown return type: {return_type}') return input_mask @@ -490,9 +491,9 @@ def run_lama(input_image: gr.Image, input_mask: gr.Image = None): input_mask = run_mask(input_image, input_mask, return_type='Grayscale') if lama_model is None: import modules.lama - shared.log.debug(f'Mask LaMa loading: model={modules.lama.LAMA_MODEL_URL}') + logger.log.debug(f'Mask LaMa loading: model={modules.lama.LAMA_MODEL_URL}') lama_model = modules.lama.SimpleLama() - shared.log.debug(f'Mask LaMa loaded: {memory_stats()}') + logger.log.debug(f'Mask LaMa loaded: {memory_stats()}') sd_models.move_model(lama_model.model, devices.device) result = lama_model(input_image, input_mask) @@ -574,7 +575,7 @@ def process_kanvas(kanvas_data): if kanvas_data is None or 'kanvas' not in kanvas_data: return None input_image, input_mask = ui_control_helpers.process_kanvas(kanvas_data) - shared.log.debug(f'Kanvas mask: opts={vars(opts)}') + logger.log.debug(f'Kanvas mask: opts={vars(opts)}') output_mask = run_mask(input_image, input_mask) return output_mask @@ -584,7 +585,7 @@ def process_kanvas_lama(kanvas_data): if kanvas_data is None or 'kanvas' not in kanvas_data: return None input_image, input_mask = ui_control_helpers.process_kanvas(kanvas_data) - shared.log.debug(f'Kanvas LaMa: opts={vars(opts)}') + logger.log.debug(f'Kanvas LaMa: opts={vars(opts)}') output_mask = run_lama(input_image, input_mask) return output_mask diff --git a/modules/memstats.py b/modules/memstats.py index 0d67da44d..8f05d7508 100644 --- a/modules/memstats.py +++ b/modules/memstats.py @@ -4,6 +4,7 @@ import os import psutil import torch from modules import shared, errors +from modules import logger fail_once = False @@ -60,7 +61,7 @@ def ram_stats(): ram['rss'] = 0 ram['error'] = str(e) if not fail_once: - shared.log.error(f'RAM stats: {e}') + logger.log.error(f'RAM stats: {e}') errors.display(e, 'RAM stats') fail_once = True try: @@ -78,7 +79,7 @@ def ram_stats(): ram['cached'] = 0 ram['error'] = str(e) if not fail_once: - shared.log.error(f'RAM stats: {e}') + logger.log.error(f'RAM stats: {e}') errors.display(e, 'RAM stats') fail_once = True return ram @@ -102,7 +103,7 @@ def gpu_stats(): gpu['used'] = 0 gpu['error'] = str(e) if not fail_once: - shared.log.warning(f'GPU stats: {e}') + logger.log.warning(f'GPU stats: {e}') # errors.display(e, 'GPU stats') fail_once = True return gpu @@ -168,6 +169,6 @@ def get_objects(gcl=None, threshold:int=0): objects = sorted(objects, key=lambda x: x.size, reverse=True) for obj in objects: - shared.log.trace(obj) + logger.log.trace(obj) return objects diff --git a/modules/merging/merge.py b/modules/merging/merge.py index ec493de2e..4bf3a72df 100644 --- a/modules/merging/merge.py +++ b/modules/merging/merge.py @@ -5,7 +5,8 @@ import safetensors.torch import torch import modules.memstats import modules.devices as devices -from installer import log, console +from installer import console +from modules.logger import log from modules.sd_models import read_state_dict from modules.merging import merge_methods from modules.merging.merge_utils import WeightClass diff --git a/modules/merging/merge_rebasin.py b/modules/merging/merge_rebasin.py index 1e6780c2a..e0180ad4c 100644 --- a/modules/merging/merge_rebasin.py +++ b/modules/merging/merge_rebasin.py @@ -4,7 +4,7 @@ from random import shuffle from typing import NamedTuple import torch from scipy.optimize import linear_sum_assignment -from installer import log +from modules.logger import log SPECIAL_KEYS = [ diff --git a/modules/merging/modules_sdxl.py b/modules/merging/modules_sdxl.py index 529066fc7..07d2a3020 100644 --- a/modules/merging/modules_sdxl.py +++ b/modules/merging/modules_sdxl.py @@ -9,6 +9,7 @@ from safetensors.torch import load_file import diffusers import transformers from modules import shared, devices, errors +from modules import logger class Recipe: @@ -57,9 +58,9 @@ status = '' def msg(text, err:bool=False): global status # pylint: disable=global-statement if err: - shared.log.error(f'Modules merge: {text}') + logger.log.error(f'Modules merge: {text}') else: - shared.log.info(f'Modules merge: {text}') + logger.log.info(f'Modules merge: {text}') status += text + '
' return status @@ -271,12 +272,12 @@ def save_model(pipe: diffusers.StableDiffusionXLPipeline): if len(recipe.version) > 0: folder += f'-{recipe.version}' if not (recipe.diffusers or recipe.safetensors): - shared.log.debug(f'Modules merge: type=sdxl {recipe} skipping save') + logger.log.debug(f'Modules merge: type=sdxl {recipe} skipping save') return try: yield msg('save') yield msg(f'pretrained={folder}') - shared.log.info(f'Modules merge save: type=sdxl diffusers="{folder}"') + logger.log.info(f'Modules merge save: type=sdxl diffusers="{folder}"') pipe.save_pretrained(folder, safe_serialization=True, push_to_hub=False) with open(os.path.join(folder, 'vae', 'config.json'), encoding='utf8') as f: vae_config = json.load(f) @@ -293,7 +294,7 @@ def save_model(pipe: diffusers.StableDiffusionXLPipeline): fn = os.path.join(shared.opts.ckpt_dir, fn) if not fn.endswith('.safetensors'): fn += '.safetensors' - shared.log.info(f'Modules merge save: type=sdxl safetensors="{fn}"') + logger.log.info(f'Modules merge save: type=sdxl safetensors="{fn}"') yield msg(f'safetensors={fn}') from modules.merging import convert_sdxl metadata = convert_sdxl.convert(model_path=folder, checkpoint_path=fn, metadata=get_metadata()) @@ -301,7 +302,7 @@ def save_model(pipe: diffusers.StableDiffusionXLPipeline): metadata['modelspec.thumbnail'] = f"{metadata['modelspec.thumbnail'].split(',')[0]}:{len(metadata['modelspec.thumbnail'])}" # pylint: disable=use-maxsplit-arg yield msg(f'metadata={metadata}') except Exception as e: - shared.log.error(f'Modules merge save: {e}') + logger.log.error(f'Modules merge save: {e}') errors.display(e, 'merge') yield msg(f'save: {e}') @@ -311,7 +312,7 @@ def merge(): yield from load_base() if pipeline is None: return - shared.log.info(f'Modules merge: type=sdxl {recipe}') + logger.log.info(f'Modules merge: type=sdxl {recipe}') pipeline = pipeline.to(device=devices.device, dtype=recipe.dtype) yield from load_scheduler(pipeline) yield from load_unet(pipeline) diff --git a/modules/migrate.py b/modules/migrate.py index 6ab421c78..5cc5949dd 100644 --- a/modules/migrate.py +++ b/modules/migrate.py @@ -1,6 +1,6 @@ import os from modules.paths import data_path -from installer import log +from modules.logger import log files = [ diff --git a/modules/mit_nunchaku.py b/modules/mit_nunchaku.py index 6ba77007e..f4daafe5d 100644 --- a/modules/mit_nunchaku.py +++ b/modules/mit_nunchaku.py @@ -1,6 +1,7 @@ # MIT-Han-Lab Nunchaku: -from installer import log, pip +from installer import pip +from modules.logger import log from modules import devices diff --git a/modules/model_quant.py b/modules/model_quant.py index 1d7da4cf9..adbdb6ee6 100644 --- a/modules/model_quant.py +++ b/modules/model_quant.py @@ -1,3 +1,4 @@ +from modules import logger import os import re import sys @@ -6,7 +7,8 @@ import json import time import diffusers import transformers -from installer import installed, install, log, setup_logging +from installer import installed, install, setup_logging +from modules.logger import log ao = None @@ -45,7 +47,7 @@ def dont_quant(): models_list = re.split(r'[ ,]+', shared.opts.models_not_to_quant) models_list = [m.lower().strip() for m in models_list] if shared.sd_model_type.lower() in models_list: - shared.log.debug(f'Quantization: model={shared.sd_model_type} skip') + logger.log.debug(f'Quantization: model={shared.sd_model_type} skip') return True return False @@ -169,7 +171,7 @@ def create_sdnq_config(kwargs = None, allow: bool = True, module: str = 'Model', from modules.sdnq.common import use_torch_compile as sdnq_use_torch_compile if shared.opts.sdnq_use_quantized_matmul and not sdnq_use_torch_compile: - shared.log.warning('SDNQ Quantized MatMul requires a working Triton install. Disabling Quantized MatMul.') + logger.log.warning('SDNQ Quantized MatMul requires a working Triton install. Disabling Quantized MatMul.') shared.opts.sdnq_use_quantized_matmul = False if weights_dtype is None: @@ -514,7 +516,7 @@ def sdnq_quantize_model(model, op=None, sd_model=None, do_gc: bool = True, weigh from modules.sdnq.common import use_torch_compile as sdnq_use_torch_compile if shared.opts.sdnq_use_quantized_matmul and not sdnq_use_torch_compile: - shared.log.warning('SDNQ Quantized MatMul requires a working Triton install. Disabling Quantized MatMul.') + logger.log.warning('SDNQ Quantized MatMul requires a working Triton install. Disabling Quantized MatMul.') shared.opts.sdnq_use_quantized_matmul = False if weights_dtype is None: @@ -807,15 +809,15 @@ def do_post_load_quant(sd_model, allow=True): if dont_quant(): return sd_model if shared.opts.sdnq_quantize_weights and (shared.opts.sdnq_quantize_mode == 'post' or (allow and shared.opts.sdnq_quantize_mode == 'auto')): - shared.log.debug('Load model: post_quant=sdnq') + logger.log.debug('Load model: post_quant=sdnq') sd_model = sdnq_quantize_weights(sd_model) if len(shared.opts.optimum_quanto_weights) > 0: - shared.log.debug('Load model: post_quant=quanto') + logger.log.debug('Load model: post_quant=quanto') sd_model = optimum_quanto_weights(sd_model) if shared.opts.torchao_quantization and (shared.opts.torchao_quantization_mode == 'post' or (allow and shared.opts.torchao_quantization_mode == 'auto')): - shared.log.debug('Load model: post_quant=torchao') + logger.log.debug('Load model: post_quant=torchao') sd_model = torchao_quantization(sd_model) if shared.opts.layerwise_quantization: - shared.log.debug('Load model: post_quant=layerwise') + logger.log.debug('Load model: post_quant=layerwise') apply_layerwise(sd_model) return sd_model diff --git a/modules/model_te.py b/modules/model_te.py index 82a6a40a0..29e7c2515 100644 --- a/modules/model_te.py +++ b/modules/model_te.py @@ -4,6 +4,7 @@ import torch import transformers from safetensors.torch import load_file from modules import shared, devices, files_cache, errors, model_quant +from modules import logger te_dict = {} @@ -48,7 +49,7 @@ def load_t5(name=None, cache_dir=None): try: t5 = t5.to(dtype=devices.dtype) except Exception: - shared.log.error(f"T5: Failed to cast text encoder to {devices.dtype}, set dtype to {t5.dtype}") + logger.log.error(f"T5: Failed to cast text encoder to {devices.dtype}, set dtype to {t5.dtype}") raise del state_dict @@ -96,7 +97,7 @@ def load_t5(name=None, cache_dir=None): t5 = transformers.T5EncoderModel.from_pretrained(repo_id, subfolder='text_encoder_3', quantization_config=quantization_config, cache_dir=cache_dir, torch_dtype=devices.dtype) elif '/' in name: - shared.log.debug(f'Load model: type=T5 repo={name}') + logger.log.debug(f'Load model: type=T5 repo={name}') quant_config = model_quant.create_config(module='TE') if quantization_config is not None: t5 = transformers.T5EncoderModel.from_pretrained(name, cache_dir=cache_dir, torch_dtype=devices.dtype, **quant_config) @@ -118,7 +119,7 @@ def set_t5(pipe, module, t5=None, cache_dir=None): try: t5 = load_t5(name=t5, cache_dir=cache_dir) except Exception as e: - shared.log.error(f'Load module: type={module} class="T5" file="{shared.opts.sd_text_encoder}" {e}') + logger.log.error(f'Load module: type={module} class="T5" file="{shared.opts.sd_text_encoder}" {e}') if debug: errors.display(e, 'TE:') t5 = None @@ -169,13 +170,13 @@ def set_clip(pipe): try: te = load_vit_l() except Exception as e: - shared.log.error(f'Load module: type="text_encoder" class="ViT-L" file="{shared.opts.sd_text_encoder}" {e}') + logger.log.error(f'Load module: type="text_encoder" class="ViT-L" file="{shared.opts.sd_text_encoder}" {e}') if debug: errors.display(e, 'TE:') te = None if te is not None: pipe.text_encoder = te - shared.log.info(f'Load module: type="text_encoder" class="ViT-L" file="{shared.opts.sd_text_encoder}"') + logger.log.info(f'Load module: type="text_encoder" class="ViT-L" file="{shared.opts.sd_text_encoder}"') import modules.prompt_parser_diffusers modules.prompt_parser_diffusers.cache.clear() move_model(pipe.text_encoder, devices.device) @@ -184,13 +185,13 @@ def set_clip(pipe): try: te = load_vit_g() except Exception as e: - shared.log.error(f'Load module: type module="text_encoder_2" class="ViT-G" file="{shared.opts.sd_text_encoder}" {e}') + logger.log.error(f'Load module: type module="text_encoder_2" class="ViT-G" file="{shared.opts.sd_text_encoder}" {e}') if debug: errors.display(e, 'TE:') te = None if te is not None: pipe.text_encoder_2 = te - shared.log.info(f'Load module: type="text_encoder_2" class="ViT-G" file="{shared.opts.sd_text_encoder}"') + logger.log.info(f'Load module: type="text_encoder_2" class="ViT-G" file="{shared.opts.sd_text_encoder}"') import modules.prompt_parser_diffusers modules.prompt_parser_diffusers.cache.clear() move_model(pipe.text_encoder_2, devices.device) @@ -203,4 +204,4 @@ def refresh_te_list(): basename = os.path.basename(file) name = os.path.splitext(basename)[0] if '.safetensors' in basename else basename te_dict[name] = file - shared.log.info(f'Available TEs: path="{shared.opts.te_dir}" items={len(te_dict)}') + logger.log.info(f'Available TEs: path="{shared.opts.te_dir}" items={len(te_dict)}') diff --git a/modules/model_tools.py b/modules/model_tools.py index 8e473ba23..56ba7fd86 100644 --- a/modules/model_tools.py +++ b/modules/model_tools.py @@ -3,6 +3,7 @@ import diffusers import transformers import safetensors.torch from modules import shared, devices, model_quant +from modules import logger def remove_entries_after_depth(d, depth, current_depth=0): @@ -51,7 +52,7 @@ def get_modules(model: callable): signature = inspect.signature(model.__init__, follow_wrapped=True) params = {param.name: param.annotation for param in signature.parameters.values() if param.annotation != inspect._empty and hasattr(param.annotation, 'from_pretrained')} # pylint: disable=protected-access for name, cls in params.items(): - shared.log.debug(f'Analyze: model={model} module={name} class={cls.__name__} loadable={getattr(cls, "from_pretrained", None)}') + logger.log.debug(f'Analyze: model={model} module={name} class={cls.__name__} loadable={getattr(cls, "from_pretrained", None)}') return params @@ -76,6 +77,6 @@ def load_modules(repo_id: str, params: dict): kwargs = model_quant.create_config(kwargs) if subfolder is None: continue - shared.log.debug(f'Load: module={name} class={cls.__name__} repo={repo_id} location={subfolder}') + logger.log.debug(f'Load: module={name} class={cls.__name__} repo={repo_id} location={subfolder}') modules[name] = cls.from_pretrained(repo_id, subfolder=subfolder, cache_dir=cache_dir, torch_dtype=devices.dtype, **kwargs) return modules diff --git a/modules/modeldata.py b/modules/modeldata.py index 48172baa3..8b850bf89 100644 --- a/modules/modeldata.py +++ b/modules/modeldata.py @@ -2,6 +2,7 @@ import os import sys import threading from modules import shared, errors +from modules import logger def get_model_type(pipe): @@ -130,7 +131,7 @@ class ModelData: if self.locked: if self.sd_model is None: fn = f'{os.path.basename(sys._getframe(2).f_code.co_filename)}:{sys._getframe(2).f_code.co_name}:{sys._getframe(1).f_code.co_name}' # pylint: disable=protected-access - shared.log.warning(f'Model locked: fn={fn}') + logger.log.warning(f'Model locked: fn={fn}') return self.sd_model elif (self.sd_model is None) and (shared.opts.sd_model_checkpoint != 'None') and (not self.lock.locked()): with self.lock: @@ -139,7 +140,7 @@ class ModelData: self.sd_model = reload_model_weights(op='model') # note: reload_model_weights directly updates model_data.sd_model and returns it at the end self.initial = False except Exception as e: - shared.log.error("Failed to load stable diffusion model") + logger.log.error("Failed to load stable diffusion model") errors.display(e, "loading stable diffusion model") self.sd_model = None return self.sd_model @@ -156,7 +157,7 @@ class ModelData: self.sd_refiner = reload_model_weights(op='refiner') self.initial = False except Exception as e: - shared.log.error("Failed to load stable diffusion model") + logger.log.error("Failed to load stable diffusion model") errors.display(e, "loading stable diffusion model") self.sd_refiner = None return self.sd_refiner @@ -178,7 +179,7 @@ class Shared(sys.modules[__name__].__class__): import modules.sd_models # pylint: disable=W0621 if modules.sd_models.model_data.sd_model is None: fn = f'{os.path.basename(sys._getframe(2).f_code.co_filename)}:{sys._getframe(2).f_code.co_name}:{sys._getframe(1).f_code.co_name}' # pylint: disable=protected-access - shared.log.debug(f'Model requested: fn={fn}') # pylint: disable=protected-access + logger.log.debug(f'Model requested: fn={fn}') # pylint: disable=protected-access return modules.sd_models.model_data.get_sd_model() @sd_model.setter @@ -223,7 +224,7 @@ class Shared(sys.modules[__name__].__class__): @property def console(self): try: - from installer import get_console + from modules.logger import get_console return get_console() except ImportError: return None diff --git a/modules/modelloader.py b/modules/modelloader.py index c168d981b..de2729395 100644 --- a/modules/modelloader.py +++ b/modules/modelloader.py @@ -6,10 +6,12 @@ import importlib import contextlib from urllib.parse import urlparse import huggingface_hub as hf -from installer import install, log +from installer import install +from modules.logger import log from modules import shared, errors, files_cache from modules.upscaler import Upscaler from modules import paths +from modules import logger loggedin = None @@ -78,7 +80,7 @@ def download_diffusers_model(hub_id: str, cache_dir: str = None, download_config download_config["mirror"] = mirror if custom_pipeline is not None and len(custom_pipeline) > 0: download_config["custom_pipeline"] = custom_pipeline - shared.log.debug(f'HF download: id="{hub_id}" args={download_config}') + logger.log.debug(f'HF download: id="{hub_id}" args={download_config}') token = token or shared.opts.huggingface_token if token is not None and len(token) > 2: hf_login(token) @@ -90,11 +92,11 @@ def download_diffusers_model(hub_id: str, cache_dir: str = None, download_config except Exception as e: debug(f'HF download error: id="{hub_id}" {e}') if 'gated' in str(e): - shared.log.error(f'HF download error: id="{hub_id}" model access requires login') + logger.log.error(f'HF download error: id="{hub_id}" model access requires login') shared.state.end(jobid) return None if pipeline_dir is None: - shared.log.error(f'HF download error: id="{hub_id}" no data') + logger.log.error(f'HF download error: id="{hub_id}" no data') shared.state.end(jobid) return None try: @@ -140,7 +142,7 @@ def load_diffusers_models(clear=True): snapshots = os.listdir(os.path.join(folder, "snapshots")) if len(snapshots) == 0: - shared.log.warning(f'Diffusers folder has no snapshots: location="{place}" folder="{folder}" name="{name}"') + logger.log.warning(f'Diffusers folder has no snapshots: location="{place}" folder="{folder}" name="{name}"') continue for snapshot in snapshots: # download using from_pretrained which uses huggingface_hub or huggingface_hub directly and creates snapshot-like structure commit = os.path.join(folder, 'snapshots', snapshot) @@ -162,8 +164,8 @@ def load_diffusers_models(clear=True): except Exception as e: debug(f'Error analyzing diffusers model: "{folder}" {e}') except Exception as e: - shared.log.error(f"Error listing diffusers: {place} {e}") - # shared.log.debug(f'Scanning diffusers cache: folder="{place}" items={len(list(diffuser_repos))} time={time.time()-t0:.2f}') + logger.log.error(f"Error listing diffusers: {place} {e}") + # logger.log.debug(f'Scanning diffusers cache: folder="{place}" items={len(list(diffuser_repos))} time={time.time()-t0:.2f}') return diffuser_repos @@ -183,7 +185,7 @@ def find_diffuser(name: str, full=False): if len(models) == 0: models = list(hf_api.list_models(model_name=name, full=True, limit=20, sort="downloads", direction=-1)) # widen search models = [m for m in models if m.id.startswith(name)] # filter exact - shared.log.debug(f'Search model: repo="{name}" {len(models) > 0}') + logger.log.debug(f'Search model: repo="{name}" {len(models) > 0}') if len(models) > 0: if not full: return models[0].id + suffix @@ -209,12 +211,12 @@ def get_reference_opts(name: str, quiet=False): model_opts = v break if not model_opts: - # shared.log.error(f'Reference: model="{name}" not found') + # logger.log.error(f'Reference: model="{name}" not found') return {} if not quiet: desc = model_opts.copy() desc.pop('desc', None) - shared.log.debug(f'Reference: model="{name}" {desc}') + logger.log.debug(f'Reference: model="{name}" {desc}') return model_opts @@ -229,7 +231,7 @@ def load_reference(name: str, variant: str = None, revision: str = None, mirror: model_opts = get_reference_opts(name) if model_opts.get('skip', False): return True - shared.log.debug(f'Reference: download="{name}"') + logger.log.debug(f'Reference: download="{name}"') model_dir = download_diffusers_model( hub_id=name, cache_dir=shared.opts.diffusers_dir, @@ -239,10 +241,10 @@ def load_reference(name: str, variant: str = None, revision: str = None, mirror: custom_pipeline=custom_pipeline or model_opts.get('custom_pipeline', None) ) if model_dir is None: - shared.log.error(f'Reference download: model="{name}"') + logger.log.error(f'Reference download: model="{name}"') return False else: - shared.log.debug(f'Reference download complete: model="{name}"') + logger.log.debug(f'Reference download complete: model="{name}"') model_opts = get_reference_opts(name) from modules import sd_models sd_models.list_models() @@ -257,17 +259,17 @@ def load_civitai(model: str, url: str): _model_opts = get_reference_opts(info.model_name) return name # already downloaded else: - shared.log.debug(f'Reference download start: model="{name}"') + logger.log.debug(f'Reference download start: model="{name}"') from modules.civitai.download_civitai import download_civit_model_thread download_civit_model_thread(model_name=model, model_url=url, model_path='', model_type='safetensors', token=shared.opts.civitai_token) - shared.log.debug(f'Reference download complete: model="{name}"') + logger.log.debug(f'Reference download complete: model="{name}"') sd_models.list_models() info = sd_models.get_closest_checkpoint_match(name) if info is not None: - shared.log.debug(f'Reference: model="{name}"') + logger.log.debug(f'Reference: model="{name}"') return name # already downloaded else: - shared.log.error(f'Reference model="{name}" not found') + logger.log.error(f'Reference model="{name}" not found') return None @@ -299,10 +301,10 @@ def download_url_to_file(url: str, dst: str): continue break else: - shared.log.error(f'Error downloading: url={url} no usable temporary filename found') + logger.log.error(f'Error downloading: url={url} no usable temporary filename found') return try: - with Progress(TextColumn('[cyan]{task.description}'), BarColumn(), TaskProgressColumn(), TimeRemainingColumn(), TimeElapsedColumn(), console=shared.console) as progress: + with Progress(TextColumn('[cyan]{task.description}'), BarColumn(), TaskProgressColumn(), TimeRemainingColumn(), TimeElapsedColumn(), console=logger.console) as progress: task = progress.add_task(description="Downloading", total=file_size) while True: buffer = u.read(8192) @@ -321,14 +323,14 @@ def download_url_to_file(url: str, dst: str): def load_file_from_url(url: str, *, model_dir: str, progress: bool = True, file_name = None): # pylint: disable=unused-argument """Download a file from url into model_dir, using the file present if possible. Returns the path to the downloaded file.""" if model_dir is None: - shared.log.error('Download folder is none') + logger.log.error('Download folder is none') os.makedirs(model_dir, exist_ok=True) if not file_name: parts = urlparse(url) file_name = os.path.basename(parts.path) cached_file = os.path.abspath(os.path.join(model_dir, file_name)) if not os.path.exists(cached_file): - shared.log.info(f'Downloading: url="{url}" file="{cached_file}"') + logger.log.info(f'Downloading: url="{url}" file="{cached_file}"') download_url_to_file(url, cached_file) if os.path.exists(cached_file): return cached_file @@ -414,13 +416,13 @@ def move_files(src_path: str, dest_path: str, ext_filter: str = None): if ext_filter is not None: if ext_filter not in file: continue - shared.log.warning(f"Moving {file} from {src_path} to {dest_path}.") + logger.log.warning(f"Moving {file} from {src_path} to {dest_path}.") try: shutil.move(fullpath, dest_path) except Exception: pass if len(os.listdir(src_path)) == 0: - shared.log.info(f"Removing empty folder: {src_path}") + logger.log.info(f"Removing empty folder: {src_path}") shutil.rmtree(src_path, True) except Exception: pass @@ -437,7 +439,7 @@ def load_upscalers(): try: importlib.import_module(full_model) except Exception as e: - shared.log.error(f'Error loading upscaler: {model_name} {e}') + logger.log.error(f'Error loading upscaler: {model_name} {e}') upscalers = [] commandline_options = vars(shared.cmd_opts) # some of upscaler classes will not go away after reloading their modules, and we'll end up with two copies of those classes. The newest copy will always be the last in the list, so we go from end to beginning and ignore duplicates @@ -458,5 +460,5 @@ def load_upscalers(): upscaler_types.append(name[8:]) shared.sd_upscalers = upscalers t1 = time.time() - shared.log.info(f"Available Upscalers: items={len(shared.sd_upscalers)} downloaded={len([x for x in shared.sd_upscalers if x.data_path is not None and os.path.isfile(x.data_path)])} user={len([x for x in shared.sd_upscalers if x.custom])} time={t1-t0:.2f} types={upscaler_types}") + logger.log.info(f"Available Upscalers: items={len(shared.sd_upscalers)} downloaded={len([x for x in shared.sd_upscalers if x.data_path is not None and os.path.isfile(x.data_path)])} user={len([x for x in shared.sd_upscalers if x.custom])} time={t1-t0:.2f} types={upscaler_types}") return [x.name for x in shared.sd_upscalers] diff --git a/modules/models_hf.py b/modules/models_hf.py index 2fcf0e420..51c439aeb 100644 --- a/modules/models_hf.py +++ b/modules/models_hf.py @@ -1,7 +1,8 @@ import os import time import gradio as gr -from installer import log, install +from installer import install +from modules.logger import log from modules.shared import opts diff --git a/modules/modelstats.py b/modules/modelstats.py index b1fc54d8d..ed2b3d53c 100644 --- a/modules/modelstats.py +++ b/modules/modelstats.py @@ -2,6 +2,7 @@ import os from datetime import datetime import torch from modules import shared, sd_models +from modules import logger def walk(folder: str): @@ -107,5 +108,5 @@ def analyze(): component = getattr(shared.sd_model, k, None) module = Module(k, component) model.modules.append(module) - shared.log.debug(f'Analyzed: {model}') + logger.log.debug(f'Analyzed: {model}') return model diff --git a/modules/modular.py b/modules/modular.py index ac744f6d0..c5186d3f3 100644 --- a/modules/modular.py +++ b/modules/modular.py @@ -1,6 +1,7 @@ import time import diffusers from modules import shared +from modules import logger modular_map= { @@ -22,7 +23,7 @@ def is_compatible(diffusion_pipeline: diffusers.DiffusionPipeline) -> bool: return False compatible = diffusion_pipeline.__class__.__name__ in modular_map if not compatible: - shared.log.debug(f'Modular: source={diffusion_pipeline.__class__.__name__} incompatible pipeline') + logger.log.debug(f'Modular: source={diffusion_pipeline.__class__.__name__} incompatible pipeline') return compatible @@ -47,23 +48,23 @@ def convert_to_modular(diffusion_pipeline: diffusers.DiffusionPipeline) -> diffu modular_pipe.update_components(**components_dct, **diffusion_pipeline.parameters) modular_pipe.original_pipe = diffusion_pipeline t1 = time.time() - shared.log.debug(f'Modular: source={diffusion_pipeline.__class__.__name__} target={modular_pipe.__class__.__name__} time={t1 - t0:.2f}') + logger.log.debug(f'Modular: source={diffusion_pipeline.__class__.__name__} target={modular_pipe.__class__.__name__} time={t1 - t0:.2f}') """ for expected_input_param in modular_pipe.blocks.inputs: name = expected_input_param.name default = expected_input_param.default kwargs_type = expected_input_param.kwargs_type - shared.log.trace(f'Modular input: name={name} type={kwargs_type} default={default}') + logger.log.trace(f'Modular input: name={name} type={kwargs_type} default={default}') """ except Exception as e: - shared.log.error(f'Modular: {e}') + logger.log.error(f'Modular: {e}') raise e return modular_pipe def restore_standard(modular_pipe): if hasattr(modular_pipe, 'original_pipe'): - shared.log.debug(f'Modular: source={modular_pipe.__class__.__name__} target={modular_pipe.original_pipe.__class__.__name__}') + logger.log.debug(f'Modular: source={modular_pipe.__class__.__name__} target={modular_pipe.original_pipe.__class__.__name__}') return modular_pipe.original_pipe return modular_pipe diff --git a/modules/modular_guiders.py b/modules/modular_guiders.py index 8ddc8e572..cacd31063 100644 --- a/modules/modular_guiders.py +++ b/modules/modular_guiders.py @@ -1,5 +1,6 @@ import diffusers from modules import shared, errors, processing +from modules import logger # ['Default', 'CFG', 'Zero', 'PAG', 'APG', 'SLG', 'SEG', 'TCFG', 'FDG'] @@ -49,11 +50,11 @@ def set_guider(p: processing.StableDiffusionProcessing): guider_args = {k: v for k, v in guider_info.config.items() if not k.startswith('_') and v is not None} else: guider_args = {} - shared.log.info(f'Guider: name={guidance_name} cls={guider_cls.__name__ if guider_cls is not None else None} args={guider_args}') + logger.log.info(f'Guider: name={guidance_name} cls={guider_cls.__name__ if guider_cls is not None else None} args={guider_args}') return if guidance_name == 'None': shared.sd_model.update_components(guider=None) # breaks the pipeline - shared.log.info(f'Guider: name={guidance_name}') + logger.log.info(f'Guider: name={guidance_name}') return guider_info = guiders[guidance_name] @@ -62,7 +63,7 @@ def set_guider(p: processing.StableDiffusionProcessing): for k, v in base_args.items(): if v is not None and v >= 0.0: guider_args[k] = v - shared.log.warning('Guiders: partially implemented') # TODO: guiders + logger.log.warning('Guiders: partially implemented') # TODO: guiders for k, v in guider_info['args'].items(): try: if k is None: @@ -82,14 +83,14 @@ def set_guider(p: processing.StableDiffusionProcessing): elif isinstance(v, str) and (len(v) > 0): guider_args[k] = v except Exception as e: - shared.log.error(f'Guiders: arg={k} value={v} error={e}') + logger.log.error(f'Guiders: arg={k} value={v} error={e}') errors.display(e, 'Guiders') # guider_args.update(guider_info['args']) if guider_cls is not None: try: guider_instance = guider_cls(**guider_args) - shared.log.info(f'Guider: name={guidance_name} cls={guider_cls.__name__} args={guider_args}') + logger.log.info(f'Guider: name={guidance_name} cls={guider_cls.__name__} args={guider_args}') shared.sd_model.update_components(guider=guider_instance) except Exception as e: - shared.log.error(f'Guider: name={guidance_name} cls={guider_cls.__name__} args={guider_args} {e}') + logger.log.error(f'Guider: name={guidance_name} cls={guider_cls.__name__} args={guider_args} {e}') return diff --git a/modules/onnx_impl/__init__.py b/modules/onnx_impl/__init__.py index 1decd1d41..bf020ea12 100644 --- a/modules/onnx_impl/__init__.py +++ b/modules/onnx_impl/__init__.py @@ -1,8 +1,10 @@ +from modules import logger from typing import Any, Dict, Optional import numpy as np import torch import diffusers -from installer import log, installed, install +from installer import installed, install +from modules.logger import log initialized = False @@ -161,12 +163,12 @@ def check_parameters_changed(p, refiner_enabled: bool): shared.compiled_model_state.height != compile_height or shared.compiled_model_state.width != compile_width or shared.compiled_model_state.batch_size != p.batch_size): - shared.log.info("Olive: Parameter change detected") - shared.log.info("Olive: Recompiling base model") + logger.log.info("Olive: Parameter change detected") + logger.log.info("Olive: Recompiling base model") sd_models.unload_model_weights(op='model') sd_models.reload_model_weights(op='model') if refiner_enabled: - shared.log.info("Olive: Recompiling refiner") + logger.log.info("Olive: Recompiling refiner") sd_models.unload_model_weights(op='refiner') sd_models.reload_model_weights(op='refiner') shared.compiled_model_state.height = compile_height @@ -178,7 +180,7 @@ def check_parameters_changed(p, refiner_enabled: bool): def preprocess_pipeline(p): from modules import shared, sd_models if "ONNX" not in shared.opts.diffusers_pipeline: - shared.log.warning(f"Unsupported pipeline for 'olive-ai' compile backend: {shared.opts.diffusers_pipeline}. You should select one of the ONNX pipelines.") + logger.log.warning(f"Unsupported pipeline for 'olive-ai' compile backend: {shared.opts.diffusers_pipeline}. You should select one of the ONNX pipelines.") return shared.sd_model if hasattr(shared.sd_model, "preprocess"): shared.sd_model = shared.sd_model.preprocess(p) diff --git a/modules/onnx_impl/execution_providers.py b/modules/onnx_impl/execution_providers.py index b220692de..e8978aa06 100644 --- a/modules/onnx_impl/execution_providers.py +++ b/modules/onnx_impl/execution_providers.py @@ -1,6 +1,6 @@ import sys from enum import Enum -from installer import log +from modules.logger import log from modules import devices diff --git a/modules/onnx_impl/pipelines/__init__.py b/modules/onnx_impl/pipelines/__init__.py index 9b57d6577..fedf9dad0 100644 --- a/modules/onnx_impl/pipelines/__init__.py +++ b/modules/onnx_impl/pipelines/__init__.py @@ -7,7 +7,8 @@ from abc import ABCMeta from typing import Type, Tuple, List, Any, Dict, TYPE_CHECKING import torch import diffusers -from installer import log, install +from installer import install +from modules.logger import log from modules import shared from modules.paths import sd_configs_path, models_path from modules.sd_models import CheckpointInfo diff --git a/modules/options.py b/modules/options.py index 83e9e4a11..99d01ad2f 100644 --- a/modules/options.py +++ b/modules/options.py @@ -1,7 +1,7 @@ from __future__ import annotations from dataclasses import dataclass from typing import TYPE_CHECKING, Any -from installer import log +from modules.logger import log if TYPE_CHECKING: diff --git a/modules/options_handler.py b/modules/options_handler.py index 61ee1a29f..52f41bb47 100644 --- a/modules/options_handler.py +++ b/modules/options_handler.py @@ -6,7 +6,7 @@ from typing import TYPE_CHECKING from modules import cmd_args, errors from modules.json_helpers import readfile, writefile from modules.shared_legacy import LegacyOption -from installer import log +from modules.logger import log if TYPE_CHECKING: diff --git a/modules/pag/__init__.py b/modules/pag/__init__.py index 55d4bc5f8..ebb14363b 100644 --- a/modules/pag/__init__.py +++ b/modules/pag/__init__.py @@ -1,5 +1,6 @@ from diffusers.pipelines import StableDiffusionPipeline, StableDiffusionXLPipeline # pylint: disable=unused-import from modules import shared, processing, sd_models +from modules import logger from modules.pag.pipe_sd import StableDiffusionPAGPipeline from modules.pag.pipe_sdxl import StableDiffusionXLPAGPipeline from modules.control.units import detect @@ -19,20 +20,20 @@ def apply(p: processing.StableDiffusionProcessing): # pylint: disable=arguments- pass elif detect.is_sd15(cls): if sd_models.get_diffusers_task(shared.sd_model) != sd_models.DiffusersTaskType.TEXT_2_IMAGE: - shared.log.warning(f'PAG: pipeline={cls.__name__} not implemented') + logger.log.warning(f'PAG: pipeline={cls.__name__} not implemented') return None orig_pipeline = shared.sd_model shared.sd_model = sd_models.switch_pipe(StableDiffusionPAGPipeline, shared.sd_model) elif detect.is_sdxl(cls): if sd_models.get_diffusers_task(shared.sd_model) != sd_models.DiffusersTaskType.TEXT_2_IMAGE: - shared.log.warning(f'PAG: pipeline={cls.__name__} not implemented') + logger.log.warning(f'PAG: pipeline={cls.__name__} not implemented') return None orig_pipeline = shared.sd_model shared.sd_model = sd_models.switch_pipe(StableDiffusionXLPAGPipeline, shared.sd_model) elif detect.is_f1(cls): p.task_args['true_cfg_scale'] = p.pag_scale else: - # shared.log.warning(f'PAG: pipeline={cls.__name__} required={StableDiffusionPipeline.__name__}') + # logger.log.warning(f'PAG: pipeline={cls.__name__} required={StableDiffusionPipeline.__name__}') return None p.task_args['pag_scale'] = p.pag_scale @@ -44,7 +45,7 @@ def apply(p: processing.StableDiffusionProcessing): # pylint: disable=arguments- p.task_args['pag_applied_layers_index'] = pag_applied_layers_index if len(pag_applied_layers_index) > 0 else ['m0'] # Available layers: d[0-5], m[0], u[0-8] p.extra_generation_params["CFG true"] = p.pag_scale p.extra_generation_params["CFG adaptive"] = p.pag_adaptive - # shared.log.debug(f'{c}: args={p.task_args}') + # logger.log.debug(f'{c}: args={p.task_args}') def unapply(): diff --git a/modules/para_attention.py b/modules/para_attention.py index 20bb4f480..5a1328e9f 100644 --- a/modules/para_attention.py +++ b/modules/para_attention.py @@ -1,3 +1,4 @@ +from modules import logger from modules import shared @@ -14,11 +15,11 @@ def apply_first_block_cache(): try: if 'Nunchaku' in shared.sd_model.transformer.__class__.__name__: from nunchaku.caching.diffusers_adapters import apply_cache_on_pipe - shared.log.info(f'Transformers cache: type=nunchaku rdt={shared.opts.para_diff_threshold} cls={shared.sd_model.transformer.__class__.__name__}') + logger.log.info(f'Transformers cache: type=nunchaku rdt={shared.opts.para_diff_threshold} cls={shared.sd_model.transformer.__class__.__name__}') else: from para_attn.first_block_cache.diffusers_adapters import apply_cache_on_pipe - shared.log.info(f'Transformers cache: type=paraattn rdt={shared.opts.para_diff_threshold} cls={shared.sd_model.transformer.__class__.__name__}') + logger.log.info(f'Transformers cache: type=paraattn rdt={shared.opts.para_diff_threshold} cls={shared.sd_model.transformer.__class__.__name__}') apply_cache_on_pipe(shared.sd_model, residual_diff_threshold=shared.opts.para_diff_threshold) except Exception as e: - shared.log.error(f'Transformers cache: type=paraattn {e}') + logger.log.error(f'Transformers cache: type=paraattn {e}') return diff --git a/modules/paths.py b/modules/paths.py index cd7b6e5d4..a2f460c3b 100644 --- a/modules/paths.py +++ b/modules/paths.py @@ -4,7 +4,7 @@ import sys import json import argparse import tempfile -from installer import log +from modules.logger import log # parse args, parse again after we have the data-dir and early-read the config file diff --git a/modules/postprocess/aurasr_model.py b/modules/postprocess/aurasr_model.py index c2030d184..fe77facec 100644 --- a/modules/postprocess/aurasr_model.py +++ b/modules/postprocess/aurasr_model.py @@ -1,6 +1,7 @@ import torch from PIL import Image from modules import shared, devices +from modules import logger from modules.upscaler import Upscaler, UpscalerData @@ -28,6 +29,6 @@ class UpscalerAuraSR(Upscaler): if shared.opts.upscaler_unload: self.model = None - shared.log.debug(f"Upscaler unloaded: type={self.name} model={selected_model}") + logger.log.debug(f"Upscaler unloaded: type={self.name} model={selected_model}") devices.torch_gc(force=True) return image diff --git a/modules/postprocess/esrgan_model.py b/modules/postprocess/esrgan_model.py index 41a3585bd..c2a39c314 100644 --- a/modules/postprocess/esrgan_model.py +++ b/modules/postprocess/esrgan_model.py @@ -4,6 +4,7 @@ from PIL import Image from rich.progress import Progress, TextColumn, BarColumn, TaskProgressColumn, TimeRemainingColumn, TimeElapsedColumn import modules.postprocess.esrgan_model_arch as arch from modules import images, devices, shared +from modules import logger from modules.upscaler import Upscaler, UpscalerData, compile_upscaler @@ -131,7 +132,7 @@ class UpscalerESRGAN(Upscaler): img = esrgan_upscale(model, img) if shared.opts.upscaler_unload and selected_model in self.models: del self.models[selected_model] - shared.log.debug(f"Upscaler unloaded: type={self.name} model={selected_model}") + logger.log.debug(f"Upscaler unloaded: type={self.name} model={selected_model}") devices.torch_gc(force=True) return img @@ -140,10 +141,10 @@ class UpscalerESRGAN(Upscaler): if info is None: return if self.models.get(info.local_data_path, None) is not None: - shared.log.debug(f"Upscaler cached: type={self.name} model={info.local_data_path}") + logger.log.debug(f"Upscaler cached: type={self.name} model={info.local_data_path}") return self.models[info.local_data_path] state_dict = torch.load(info.local_data_path, map_location='cpu' if devices.device.type in {'mps', 'cpu'} else None) - shared.log.info(f"Upscaler loaded: type={self.name} model={info.local_data_path}") + logger.log.info(f"Upscaler loaded: type={self.name} model={info.local_data_path}") if "params_ema" in state_dict: state_dict = state_dict["params_ema"] @@ -196,7 +197,7 @@ def esrgan_upscale(model, img): newtiles = [] scale_factor = 1 - with Progress(TextColumn('[cyan]{task.description}'), BarColumn(), TaskProgressColumn(), TimeRemainingColumn(), TimeElapsedColumn(), console=shared.console) as progress: + with Progress(TextColumn('[cyan]{task.description}'), BarColumn(), TaskProgressColumn(), TimeRemainingColumn(), TimeElapsedColumn(), console=logger.console) as progress: total = 0 for _y, _h, row in grid.tiles: total += len(row) diff --git a/modules/postprocess/realesrgan_model_arch.py b/modules/postprocess/realesrgan_model_arch.py index dd350e4d9..5308ea46d 100644 --- a/modules/postprocess/realesrgan_model_arch.py +++ b/modules/postprocess/realesrgan_model_arch.py @@ -9,6 +9,7 @@ from torch import nn from torch.nn import functional as F from rich.progress import Progress, TextColumn, BarColumn, TaskProgressColumn, TimeRemainingColumn, TimeElapsedColumn from modules import devices, shared +from modules import logger from modules.upscaler import compile_upscaler ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -66,7 +67,7 @@ class RealESRGANer: from modules.modelloader import load_file_from_url model_path = load_file_from_url(url=model_path, model_dir=os.path.join(ROOT_DIR, 'weights'), progress=True, file_name=None) loadnet = torch.load(model_path, map_location=torch.device('cpu')) - shared.log.info(f"Upscaler loaded: type={self.name} model={model_path}") + logger.log.info(f"Upscaler loaded: type={self.name} model={model_path}") # prefer to use params_ema if 'params_ema' in loadnet: @@ -138,7 +139,7 @@ class RealESRGANer: tiles_y = math.ceil(height / self.tile_size) # loop over all tiles - with Progress(TextColumn('[cyan]{task.description}'), BarColumn(), TaskProgressColumn(), TimeRemainingColumn(), TimeElapsedColumn(), console=shared.console) as progress: + with Progress(TextColumn('[cyan]{task.description}'), BarColumn(), TaskProgressColumn(), TimeRemainingColumn(), TimeElapsedColumn(), console=logger.console) as progress: task = progress.add_task(description="Upscaling", total=tiles_y * tiles_x) with torch.no_grad(): for y in range(tiles_y): @@ -172,7 +173,7 @@ class RealESRGANer: try: output_tile = self.model(input_tile) except Exception as e: - shared.log.error(f'Upscale error: type=R-ESRGAN {e}') + logger.log.error(f'Upscale error: type=R-ESRGAN {e}') # output tile area on total image output_start_x = input_start_x * self.scale diff --git a/modules/postprocess/sdupscaler_model.py b/modules/postprocess/sdupscaler_model.py index de6a621cc..5c3c120ec 100644 --- a/modules/postprocess/sdupscaler_model.py +++ b/modules/postprocess/sdupscaler_model.py @@ -2,6 +2,7 @@ import torch import diffusers from PIL import Image from modules import shared, devices +from modules import logger from modules.upscaler import Upscaler, UpscalerData @@ -23,11 +24,11 @@ class UpscalerDiffusion(Upscaler): from modules.sd_models import set_diffuser_options scaler: UpscalerData = [x for x in self.scalers if x.data_path == path or x.name == path] if len(scaler) == 0: - shared.log.error(f"Upscaler cannot match model: type={self.name} model={path}") + logger.log.error(f"Upscaler cannot match model: type={self.name} model={path}") return None scaler = scaler[0] if self.models.get(path, None) is not None: - shared.log.debug(f"Upscaler cached: type={scaler.name} model={path}") + logger.log.debug(f"Upscaler cached: type={scaler.name} model={path}") return self.models[path] else: model = diffusers.DiffusionPipeline.from_pretrained(scaler.data_path, cache_dir=shared.opts.diffusers_dir, torch_dtype=devices.dtype) @@ -69,6 +70,6 @@ class UpscalerDiffusion(Upscaler): image = output.images[0] if shared.opts.upscaler_unload and selected_model in self.models: del self.models[selected_model] - shared.log.debug(f"Upscaler unloaded: type={self.name} model={selected_model}") + logger.log.debug(f"Upscaler unloaded: type={self.name} model={selected_model}") devices.torch_gc(force=True) return image diff --git a/modules/postprocess/swinir_model.py b/modules/postprocess/swinir_model.py index 60a0d267f..ede1e533f 100644 --- a/modules/postprocess/swinir_model.py +++ b/modules/postprocess/swinir_model.py @@ -5,6 +5,7 @@ from rich.progress import Progress, TextColumn, BarColumn, TaskProgressColumn, T from modules.postprocess.swinir_model_arch import SwinIR as net from modules.postprocess.swinir_model_arch_v2 import Swin2SR as net2 from modules import devices, shared +from modules import logger from modules.upscaler import Upscaler, compile_upscaler @@ -21,7 +22,7 @@ class UpscalerSwinIR(Upscaler): if info is None: return if self.models.get(info.local_data_path, None) is not None: - shared.log.debug(f"Upscaler cached: type={self.name} model={info.local_data_path}") + logger.log.debug(f"Upscaler cached: type={self.name} model={info.local_data_path}") return self.models[info.local_data_path] pretrained_model = torch.load(info.local_data_path) model_v2 = net2( @@ -57,12 +58,12 @@ class UpscalerSwinIR(Upscaler): model.load_state_dict(pretrained_model[param], strict=True) else: model.load_state_dict(pretrained_model, strict=True) - shared.log.info(f"Upscaler loaded: type={self.name} model={info.local_data_path} param={param}") + logger.log.info(f"Upscaler loaded: type={self.name} model={info.local_data_path} param={param}") model = compile_upscaler(model) self.models[info.local_data_path] = model return model except Exception as e: - shared.log.error(f'Upscaler invalid parameters: type={self.name} model={info.local_data_path} {e}') + logger.log.error(f'Upscaler invalid parameters: type={self.name} model={info.local_data_path} {e}') return model def do_upscale(self, img, selected_model): @@ -73,7 +74,7 @@ class UpscalerSwinIR(Upscaler): img = upscale(img, model) if shared.opts.upscaler_unload and selected_model in self.models: del self.models[selected_model] - shared.log.debug(f"Upscaler unloaded: type={self.name} model={selected_model}") + logger.log.debug(f"Upscaler unloaded: type={self.name} model={selected_model}") devices.torch_gc(force=True) return img @@ -122,7 +123,7 @@ def inference(img, model, tile, tile_overlap, window_size, scale): E = torch.zeros(b, c, h * sf, w * sf, dtype=devices.dtype, device=devices.device).type_as(img) W = torch.zeros_like(E, dtype=devices.dtype, device=devices.device) - with Progress(TextColumn('[cyan]{task.description}'), BarColumn(), TaskProgressColumn(), TimeRemainingColumn(), TimeElapsedColumn(), console=shared.console) as progress: + with Progress(TextColumn('[cyan]{task.description}'), BarColumn(), TaskProgressColumn(), TimeRemainingColumn(), TimeElapsedColumn(), console=logger.console) as progress: task = progress.add_task(description="Upscaling Initializing", total=len(h_idx_list) * len(w_idx_list)) for h_idx in h_idx_list: if shared.state.interrupted: diff --git a/modules/postprocess/yolo.py b/modules/postprocess/yolo.py index 473f8ec3f..f64a57d4c 100644 --- a/modules/postprocess/yolo.py +++ b/modules/postprocess/yolo.py @@ -7,6 +7,7 @@ import numpy as np import gradio as gr from PIL import Image, ImageDraw from modules import shared, processing, devices, processing_class, ui_common, ui_components, ui_symbols, images, extra_networks, sd_models +from modules import logger from modules.detailer import Detailer @@ -70,7 +71,7 @@ class YoloRestorer(Detailer): name = os.path.splitext(os.path.basename(f))[0] if name not in files: self.list[name] = os.path.join(shared.opts.yolo_dir, f) - shared.log.info(f'Available Detailer: path="{shared.opts.yolo_dir}" items={len(list(self.list))} downloaded={downloaded}') + logger.log.info(f'Available Detailer: path="{shared.opts.yolo_dir}" items={len(list(self.list))} downloaded={downloaded}') return list(self.list) def dependencies(self): @@ -126,7 +127,7 @@ class YoloRestorer(Detailer): if offload: model.to('cpu') except Exception as e: - shared.log.error(f'Detailer predict: {e}') + logger.log.error(f'Detailer predict: {e}') return result desired = shared.opts.detailer_classes.split(',') @@ -192,14 +193,14 @@ class YoloRestorer(Detailer): else: model_url = self.list.get(model_name, None) if model_url is None: - shared.log.error(f'Load: type=Detailer name="{model_name}" error="model not found"') + logger.log.error(f'Load: type=Detailer name="{model_name}" error="model not found"') return None, None file_name = os.path.basename(model_url) model_file = None try: model_file = modelloader.load_file_from_url(url=model_url, model_dir=shared.opts.yolo_dir, file_name=file_name) if model_file is None: - shared.log.error(f'Load: type=Detailer name="{model_name}" url="{model_url}" error="failed to fetch model"') + logger.log.error(f'Load: type=Detailer name="{model_name}" url="{model_url}" error="failed to fetch model"') elif model_file.endswith('.onnx'): import onnxruntime as ort options = ort.SessionOptions() @@ -212,11 +213,11 @@ class YoloRestorer(Detailer): import ultralytics model = ultralytics.YOLO(model_file) classes = list(model.names.values()) - shared.log.info(f'Load: type=Detailer name="{model_name}" model="{model_file}" ultralytics={ultralytics.__version__} classes={classes}') + logger.log.info(f'Load: type=Detailer name="{model_name}" model="{model_file}" ultralytics={ultralytics.__version__} classes={classes}') self.models[model_name] = model return model_name, model except Exception as e: - shared.log.error(f'Load: type=Detailer name="{model_name}" error="{e}"') + logger.log.error(f'Load: type=Detailer name="{model_name}" error="{e}"') return None, None def merge(self, items: list[YoloResult]) -> list[YoloResult]: @@ -245,7 +246,7 @@ class YoloRestorer(Detailer): size = min(image.width, image.height) // 32 font = images.get_font(size) color = (0, 190, 190) - shared.log.debug(f'Detailer: draw={items}') + logger.log.debug(f'Detailer: draw={items}') for i, item in enumerate(items): if shared.opts.detailer_seg and item.mask is not None: mask = item.mask.convert('L') @@ -276,7 +277,7 @@ class YoloRestorer(Detailer): shared.sd_model = sd_models.set_diffuser_pipe(shared.sd_model, sd_models.DiffusersTaskType.INPAINTING) if (sd_models.get_diffusers_task(shared.sd_model) != sd_models.DiffusersTaskType.INPAINTING) and (shared.sd_model.__class__.__name__ not in sd_models.pipe_switch_task_exclude): - shared.log.error(f'Detailer: model="{shared.sd_model.__class__.__name__}" not compatible') + logger.log.error(f'Detailer: model="{shared.sd_model.__class__.__name__}" not compatible') return np_image models = [] @@ -286,9 +287,9 @@ class YoloRestorer(Detailer): if len(models) == 0: models = shared.opts.detailer_models if len(models) == 0: - shared.log.warning('Detailer: model=None') + logger.log.warning('Detailer: model=None') return np_image - shared.log.debug(f'Detailer: models={models}') + logger.log.debug(f'Detailer: models={models}') # create backups orig_apply_overlay = shared.opts.mask_apply_overlay @@ -309,7 +310,7 @@ class YoloRestorer(Detailer): name, model = self.load(model_name) if model is None: - shared.log.warning(f'Detailer: model="{name}" not loaded') + logger.log.warning(f'Detailer: model="{name}" not loaded') continue if image is None: @@ -317,11 +318,11 @@ class YoloRestorer(Detailer): items = self.predict(model, image) if len(items) == 0: - shared.log.info(f'Detailer: model="{name}" no items detected') + logger.log.info(f'Detailer: model="{name}" no items detected') continue if shared.opts.detailer_merge and len(items) > 1: - shared.log.debug(f'Detailer: model="{name}" items={len(items)} merge') + logger.log.debug(f'Detailer: model="{name}" items={len(items)} merge') items = self.merge(items) shared.opts.data['mask_apply_overlay'] = True @@ -362,7 +363,7 @@ class YoloRestorer(Detailer): } args.update(model_args) if args['denoising_strength'] == 0: - shared.log.debug(f'Detailer: model="{name}" strength=0 skip') + logger.log.debug(f'Detailer: model="{name}" strength=0 skip') return np_image control_pipeline = None orig_class = shared.sd_model.__class__ @@ -380,7 +381,7 @@ class YoloRestorer(Detailer): p.steps = orig_p.get('steps', 0) # report = [{'label': i.label, 'score': i.score, 'size': f'{i.width}x{i.height}' } for i in items] - # shared.log.info(f'Detailer: model="{name}" items={report} args={args}') + # logger.log.info(f'Detailer: model="{name}" items={report} args={args}') models_used.append(name) mask_all = [] @@ -409,7 +410,7 @@ class YoloRestorer(Detailer): pc.negative_prompts = [pc.negative_prompt] pc.prompts, pc.network_data = extra_networks.parse_prompts(pc.prompts) extra_networks.activate(pc, pc.network_data) - shared.log.debug(f'Detail: model="{i+1}:{name}" item={j+1}/{len(items)} box={item.box} label="{item.label}" score={item.score:.2f} seg={shared.opts.detailer_seg} prompt="{pc.prompt}"') + logger.log.debug(f'Detail: model="{i+1}:{name}" item={j+1}/{len(items)} box={item.box} label="{item.label}" score={item.score:.2f} seg={shared.opts.detailer_seg} prompt="{pc.prompt}"') pc.init_images = [image] pc.image_mask = [item.mask] pc.overlay_images = [] @@ -488,9 +489,9 @@ class YoloRestorer(Detailer): shared.opts.detailer_seg = seg # shared.opts.detailer_resolution = resolution shared.opts.save(silent=True) - shared.log.debug(f'Detailer settings: models={detailers} classes={classes} strength={strength} conf={min_confidence} max={max_detected} iou={iou} size={min_size}-{max_size} padding={padding} steps={steps} resolution={resolution} save={save} sort={sort} seg={seg}') + logger.log.debug(f'Detailer settings: models={detailers} classes={classes} strength={strength} conf={min_confidence} max={max_detected} iou={iou} size={min_size}-{max_size} padding={padding} steps={steps} resolution={resolution} save={save} sort={sort} seg={seg}') if not self.ui_mode: - shared.log.debug(f'Detailer expert: {text}') + logger.log.debug(f'Detailer expert: {text}') with gr.Accordion(open=False, label="Detailer", elem_id=f"{tab}_detailer_accordion", elem_classes=["small-accordion"]): with gr.Row(): diff --git a/modules/postprocessing.py b/modules/postprocessing.py index 318750493..c919d4a08 100644 --- a/modules/postprocessing.py +++ b/modules/postprocessing.py @@ -4,6 +4,7 @@ import tempfile from PIL import Image from modules import shared, images, devices, scripts_manager, scripts_postprocessing, infotext +from modules import logger from modules.shared import opts from modules.paths import resolve_output_path @@ -28,14 +29,14 @@ def run_postprocessing(extras_mode, image, image_folder: list[tempfile.NamedTemp try: image = Image.open(os.path.abspath(img.name)) except Exception as e: - shared.log.error(f'Failed to open image: file="{img.name}" {e}') + logger.log.error(f'Failed to open image: file="{img.name}" {e}') continue fn, ext = os.path.splitext(img.orig_name) image_fullnames.append(img.name) image_data.append(image) image_names.append(fn) image_ext.append(ext) - shared.log.debug(f'Process: mode=batch inputs={len(image_folder)} images={len(image_data)}') + logger.log.debug(f'Process: mode=batch inputs={len(image_folder)} images={len(image_data)}') elif extras_mode == 2: assert input_dir, 'input directory not selected' image_list = os.listdir(input_dir) @@ -44,13 +45,13 @@ def run_postprocessing(extras_mode, image, image_folder: list[tempfile.NamedTemp try: image = Image.open(fn) except Exception as e: - shared.log.error(f'Failed to open image: file="{fn}" {e}') + logger.log.error(f'Failed to open image: file="{fn}" {e}') continue image_fullnames.append(fn) image_data.append(image) image_names.append(fn) image_ext.append(None) - shared.log.debug(f'Process: mode=folder inputs={input_dir} files={len(image_list)} images={len(image_data)}') + logger.log.debug(f'Process: mode=folder inputs={input_dir} files={len(image_list)} images={len(image_data)}') else: image_data.append(image) image_names.append(None) @@ -61,10 +62,10 @@ def run_postprocessing(extras_mode, image, image_folder: list[tempfile.NamedTemp outpath = resolve_output_path(opts.outdir_samples, opts.outdir_extras_samples) processed_images = [] for image, name, ext in zip(image_data, image_names, image_ext, strict=False): # pylint: disable=redefined-argument-from-local - shared.log.debug(f'Process: image={image} {args}') + logger.log.debug(f'Process: image={image} {args}') info = '' if shared.state.interrupted: - shared.log.debug('Postprocess interrupted') + logger.log.debug('Postprocess interrupted') break if image is None: continue diff --git a/modules/processing.py b/modules/processing.py index 8c47ce83a..a7520d486 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -4,6 +4,7 @@ import time import numpy as np from PIL import Image, ImageOps from modules import shared, devices, errors, images, scripts_manager, memstats, script_callbacks, extra_networks, detailer, sd_models, sd_checkpoint, sd_vae, processing_helpers, timer +from modules import logger from modules.sd_hijack_hypertile import context_hypertile_vae, context_hypertile_unet from modules.processing_class import ( # pylint: disable=unused-import StableDiffusionProcessing, @@ -18,7 +19,7 @@ from modules.modeldata import model_data opt_C = 4 opt_f = 8 -debug = shared.log.trace if os.environ.get('SD_PROCESS_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_PROCESS_DEBUG', None) is not None else lambda *args, **kwargs: None debug('Trace: PROCESS') create_binary_mask = processing_helpers.create_binary_mask apply_overlay = processing_helpers.apply_overlay @@ -139,10 +140,10 @@ def process_images(p: StableDiffusionProcessing) -> Processed: timer.process.reset() debug(f'Process images: class={p.__class__.__name__} {vars(p)}') if not hasattr(p.sd_model, 'sd_checkpoint_info'): - shared.log.error('Processing: incomplete model') + logger.log.error('Processing: incomplete model') return None if p.abort: - shared.log.debug('Processing: aborted') + logger.log.debug('Processing: aborted') return None if p.scripts is not None and isinstance(p.scripts, scripts_manager.ScriptRunner): p.scripts.before_process(p) @@ -159,11 +160,11 @@ def process_images(p: StableDiffusionProcessing) -> Processed: try: # if no checkpoint override or the override checkpoint can't be found, remove override entry and load opts checkpoint if p.override_settings.get('sd_model_checkpoint', None) is not None and sd_checkpoint.checkpoint_aliases.get(p.override_settings.get('sd_model_checkpoint')) is None: - shared.log.warning(f"Override not found: checkpoint={p.override_settings.get('sd_model_checkpoint', None)}") + logger.log.warning(f"Override not found: checkpoint={p.override_settings.get('sd_model_checkpoint', None)}") p.override_settings.pop('sd_model_checkpoint', None) sd_models.reload_model_weights() if p.override_settings.get('sd_model_refiner', None) is not None and sd_checkpoint.checkpoint_aliases.get(p.override_settings.get('sd_model_refiner')) is None: - shared.log.warning(f"Override not found: refiner={p.override_settings.get('sd_model_refiner', None)}") + logger.log.warning(f"Override not found: refiner={p.override_settings.get('sd_model_refiner', None)}") p.override_settings.pop('sd_model_refiner', None) sd_models.reload_model_weights() if p.override_settings.get('sd_vae', None) is not None: @@ -176,7 +177,7 @@ def process_images(p: StableDiffusionProcessing) -> Processed: if p.override_settings.get('Hires upscaler', None) is not None: p.enable_hr = True if len(p.override_settings.keys()) > 0: - shared.log.debug(f'Override: {p.override_settings}') + logger.log.debug(f'Override: {p.override_settings}') for k, v in p.override_settings.items(): setattr(shared.opts, k, v) if k == 'sd_model_checkpoint': @@ -206,7 +207,7 @@ def process_images(p: StableDiffusionProcessing) -> Processed: activities.append(torch.profiler.ProfilerActivity.CUDA) if devices.has_xpu() and hasattr(torch.profiler.ProfilerActivity, "XPU"): activities.append(torch.profiler.ProfilerActivity.XPU) - shared.log.debug(f'Torch profile: activities={activities}') + logger.log.debug(f'Torch profile: activities={activities}') if shared.profiler is None: profile_args = { 'activities': activities, @@ -218,7 +219,7 @@ def process_images(p: StableDiffusionProcessing) -> Processed: 'record_shapes': os.environ.get('SD_PROFILE_SHAPES', None) is not None, 'on_trace_ready': torch.profiler.tensorboard_trace_handler(os.environ.get('SD_PROFILE_FOLDER', None)) if os.environ.get('SD_PROFILE_FOLDER', None) is not None else None, } - shared.log.debug(f'Torch profile: {profile_args}') + logger.log.debug(f'Torch profile: {profile_args}') shared.profiler = torch.profiler.profile(**profile_args) shared.profiler.start() results = process_images_inner(p) @@ -295,7 +296,7 @@ def process_samples(p: StableDiffusionProcessing, samples): if isinstance(image, list): if len(image) > 1: - shared.log.warning(f'Processing: images={image} contains multiple images using first one only') + logger.log.warning(f'Processing: images={image} contains multiple images using first one only') image = image[0] if not shared.state.interrupted and not shared.state.skipped: @@ -408,15 +409,15 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed: for n in range(p.n_iter): p.init_images = p.iter_init_images if p.n_iter > 1: - shared.log.debug(f'Processing: batch={n+1} total={p.n_iter} progress={(n+1)/p.n_iter:.2f}') + logger.log.debug(f'Processing: batch={n+1} total={p.n_iter} progress={(n+1)/p.n_iter:.2f}') shared.state.batch_no = n + 1 debug(f'Processing inner: iteration={n+1}/{p.n_iter}') p.iteration = n if shared.state.interrupted: - shared.log.debug(f'Process interrupted: {n+1}/{p.n_iter}') + logger.log.debug(f'Process interrupted: {n+1}/{p.n_iter}') break if shared.state.skipped: - shared.log.debug(f'Process skipped: {n+1}/{p.n_iter}') + logger.log.debug(f'Process skipped: {n+1}/{p.n_iter}') shared.state.skipped = False continue @@ -450,7 +451,7 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed: timer.process.record('process') if shared.state.interrupted: - shared.log.debug(f'Process: batch={n+1}/{p.n_iter} interrupted') + logger.log.debug(f'Process: batch={n+1}/{p.n_iter} interrupted') p.do_not_save_samples = not shared.opts.keep_incomplete if shared.state.current_image is not None and isinstance(shared.state.current_image, Image.Image): samples = [shared.state.current_image] @@ -525,9 +526,9 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed: timer.process.record('post') p.ops = list(set(p.ops)) if not p.disable_extra_networks: - shared.log.info(f'Processed: images={len(output_images)} its={(p.steps * len(output_images)) / (t1 - t0):.2f} ops={p.ops}') - shared.log.debug(f'Processed: timers={timer.process.dct()}') - shared.log.debug(f'Processed: memory={memstats.memory_stats()}') + logger.log.info(f'Processed: images={len(output_images)} its={(p.steps * len(output_images)) / (t1 - t0):.2f} ops={p.ops}') + logger.log.debug(f'Processed: timers={timer.process.dct()}') + logger.log.debug(f'Processed: memory={memstats.memory_stats()}') if shared.cmd_opts.lowvram or shared.cmd_opts.medvram: devices.torch_gc(force=True, reason='final') diff --git a/modules/processing_args.py b/modules/processing_args.py index 97f4d69c9..48a445c44 100644 --- a/modules/processing_args.py +++ b/modules/processing_args.py @@ -7,6 +7,7 @@ import torch import numpy as np from PIL import Image from modules import shared, sd_models, processing, processing_vae, processing_helpers, sd_hijack_hypertile, extra_networks, sd_vae +from modules import logger from modules.processing_callbacks import diffusers_callback_legacy, diffusers_callback, set_callbacks_p from modules.processing_helpers import get_generator, apply_circular # pylint: disable=unused-import from modules.processing_prompt import set_prompt @@ -14,7 +15,7 @@ from modules.api import helpers debug_enabled = os.environ.get('SD_DIFFUSERS_DEBUG', None) -debug_log = shared.log.trace if debug_enabled else lambda *args, **kwargs: None +debug_log = logger.log.trace if debug_enabled else lambda *args, **kwargs: None disable_pbar = os.environ.get('SD_DISABLE_PBAR', None) is not None @@ -160,7 +161,7 @@ def task_specific_kwargs(p, model): task_args['image'] = p.init_images if 'BlipDiffusionPipeline' in model_cls: if len(p.init_images) == 0: - shared.log.error('BLiP diffusion requires init image') + logger.log.error('BLiP diffusion requires init image') return task_args task_args = { 'reference_image': p.init_images[0], @@ -235,14 +236,14 @@ def set_pipeline_args(p, model, prompts:list, negative_prompts:list, prompts_2:l p.timesteps = [int(x) for x in timesteps if x.isdigit()] p.steps = len(timesteps) args['timesteps'] = p.timesteps - shared.log.debug(f'Sampler: steps={len(p.timesteps)} timesteps={p.timesteps}') + logger.log.debug(f'Sampler: steps={len(p.timesteps)} timesteps={p.timesteps}') elif ('sigmas' in possible) and hasattr(model.scheduler, 'set_timesteps') and ("sigmas" in set(inspect.signature(model.scheduler.set_timesteps).parameters.keys())): p.timesteps = [float(x)/1000.0 for x in timesteps if x.isdigit()] p.steps = len(p.timesteps) args['sigmas'] = p.timesteps - shared.log.debug(f'Sampler: steps={len(p.timesteps)} sigmas={p.timesteps}') + logger.log.debug(f'Sampler: steps={len(p.timesteps)} sigmas={p.timesteps}') else: - shared.log.warning(f'Sampler: cls={model.scheduler.__class__.__name__} timesteps not supported') + logger.log.warning(f'Sampler: cls={model.scheduler.__class__.__name__} timesteps not supported') if hasattr(model, 'scheduler') and hasattr(model.scheduler, 'noise_sampler_seed') and hasattr(model.scheduler, 'noise_sampler'): model.scheduler.noise_sampler = None # noise needs to be reset instead of using cached values @@ -426,13 +427,13 @@ def set_pipeline_args(p, model, prompts:list, negative_prompts:list, prompts_2:l del clean[k] clean['prompt'] = 'embeds' task = str(sd_models.get_diffusers_task(model)).replace('DiffusersTaskType.', '') - shared.log.info(f'{desc}: pipeline={model.__class__.__name__} task={task} batch={p.iteration + 1}/{p.n_iter}x{p.batch_size} set={clean}') + logger.log.info(f'{desc}: pipeline={model.__class__.__name__} task={task} batch={p.iteration + 1}/{p.n_iter}x{p.batch_size} set={clean}') if p.hdr_clamp or p.hdr_maximize or p.hdr_brightness != 0 or p.hdr_color != 0 or p.hdr_sharpen != 0: - shared.log.debug(f'HDR: clamp={p.hdr_clamp} maximize={p.hdr_maximize} brightness={p.hdr_brightness} color={p.hdr_color} sharpen={p.hdr_sharpen} threshold={p.hdr_threshold} boundary={p.hdr_boundary} max={p.hdr_max_boundary} center={p.hdr_max_center}') + logger.log.debug(f'HDR: clamp={p.hdr_clamp} maximize={p.hdr_maximize} brightness={p.hdr_brightness} color={p.hdr_color} sharpen={p.hdr_sharpen} threshold={p.hdr_threshold} boundary={p.hdr_boundary} max={p.hdr_max_boundary} center={p.hdr_max_center}') if shared.cmd_opts.profile: t1 = time.time() - shared.log.debug(f'Profile: pipeline args: {t1-t0:.2f}') + logger.log.debug(f'Profile: pipeline args: {t1-t0:.2f}') if debug_enabled: debug_log(f'Process pipeline args: {args}') diff --git a/modules/processing_callbacks.py b/modules/processing_callbacks.py index ea5720eef..e1e689d9f 100644 --- a/modules/processing_callbacks.py +++ b/modules/processing_callbacks.py @@ -3,11 +3,12 @@ import time import torch import numpy as np from modules import shared, devices, processing_correction, timer, prompt_parser_diffusers +from modules import logger p = None debug = os.environ.get('SD_CALLBACK_DEBUG', None) is not None -debug_callback = shared.log.trace if debug else lambda *args, **kwargs: None +debug_callback = logger.log.trace if debug else lambda *args, **kwargs: None warned = False @@ -43,7 +44,7 @@ def diffusers_callback_legacy(step: int, timestep: int, latents: torch.FloatTens if shared.state.interrupted or shared.state.skipped: raise AssertionError('Interrupted...') if shared.state.paused: - shared.log.debug('Sampling paused') + logger.log.debug('Sampling paused') while shared.state.paused: if shared.state.interrupted or shared.state.skipped: raise AssertionError('Interrupted...') @@ -67,7 +68,7 @@ def diffusers_callback(pipe, step: int = 0, timestep: int = 0, kwargs: dict = No if shared.state.interrupted or shared.state.skipped: raise AssertionError('Interrupted...') if shared.state.paused: - shared.log.debug('Sampling paused') + logger.log.debug('Sampling paused') while shared.state.paused: if shared.state.interrupted or shared.state.skipped: raise AssertionError('Interrupted...') @@ -175,7 +176,7 @@ def diffusers_callback(pipe, step: int = 0, timestep: int = 0, kwargs: dict = No except Exception as e: global warned # pylint: disable=global-statement if not warned: - shared.log.error(f'Callback: {e}') + logger.log.error(f'Callback: {e}') warned = True # from modules import errors # errors.display(e, 'Callback') diff --git a/modules/processing_class.py b/modules/processing_class.py index 93f2bf135..d9509494c 100644 --- a/modules/processing_class.py +++ b/modules/processing_class.py @@ -7,11 +7,12 @@ from dataclasses import dataclass, field import numpy as np from PIL import Image, ImageOps from modules import shared, images, scripts_manager, masking, sd_models, sd_vae, processing_helpers +from modules import logger from modules.paths import resolve_output_path from modules.image.util import flatten -debug = shared.log.trace if os.environ.get('SD_PROCESS_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_PROCESS_DEBUG', None) is not None else lambda *args, **kwargs: None @dataclass(repr=False) @@ -314,7 +315,7 @@ class StableDiffusionProcessing: try: self.override_settings = {k: v for k, v in (override_settings or {}).items() if k not in shared.restricted_opts} except Exception as e: - shared.log.error(f'Override: {override_settings} {e}') + logger.log.error(f'Override: {override_settings} {e}') self.override_settings = {} self.prompts = [] @@ -388,7 +389,7 @@ class StableDiffusionProcessing: if sd_model_checkpoint is not None and len(sd_model_checkpoint) > 0: from modules import sd_checkpoint if sd_checkpoint.select_checkpoint(op='model', sd_model_checkpoint=sd_model_checkpoint) is None: - shared.log.error(f'Processing: model="{sd_model_checkpoint}" not found') + logger.log.error(f'Processing: model="{sd_model_checkpoint}" not found') self.abort = True else: shared.opts.sd_model_checkpoint = sd_model_checkpoint @@ -479,7 +480,7 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing): elif self.hr_resize_x > 0 and self.hr_resize_y > 0: self.hr_upscale_to_x = int(self.hr_resize_x) self.hr_upscale_to_y = int(self.hr_resize_y) - shared.log.debug(f'Init hires: upscaler="{self.hr_upscaler}" sampler="{self.hr_sampler_name}" resize={self.hr_resize_x}x{self.hr_resize_y} upscale={self.hr_upscale_to_x}x{self.hr_upscale_to_y}') + logger.log.debug(f'Init hires: upscaler="{self.hr_upscaler}" sampler="{self.hr_sampler_name}" resize={self.hr_resize_x}x{self.hr_resize_y} upscale={self.hr_upscale_to_x}x{self.hr_upscale_to_y}') class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): diff --git a/modules/processing_correction.py b/modules/processing_correction.py index 7069a8fa9..cdb749f33 100644 --- a/modules/processing_correction.py +++ b/modules/processing_correction.py @@ -6,11 +6,12 @@ https://huggingface.co/blog/TimothyAlexisVass/explaining-the-sdxl-latent-space import os import torch from modules import shared, devices +from modules import logger from modules.vae import sd_vae_taesd debug_enabled = os.environ.get('SD_HDR_DEBUG', None) is not None -debug = shared.log.trace if debug_enabled else lambda *args, **kwargs: None +debug = logger.log.trace if debug_enabled else lambda *args, **kwargs: None debug('Trace: HDR') skip_correction = False warned = False @@ -19,7 +20,7 @@ warned = False def warn_once(message): global warned # pylint: disable=global-statement if not warned: - shared.log.warning(f'VAE: {message}') + logger.log.warning(f'VAE: {message}') warned = True diff --git a/modules/processing_diffusers.py b/modules/processing_diffusers.py index 5bb170557..fb449df41 100644 --- a/modules/processing_diffusers.py +++ b/modules/processing_diffusers.py @@ -5,6 +5,7 @@ import numpy as np import torch from PIL import Image from modules import shared, devices, processing, sd_models, errors, sd_hijack_hypertile, processing_vae, sd_models_compile, timer, modelstats, extra_networks, attention +from modules import logger from modules.processing_helpers import resize_hires, calculate_base_steps, calculate_hires_steps, calculate_refiner_steps, save_intermediate, update_sampler, is_txt2img, is_refiner_enabled, get_job_name from modules.processing_args import set_pipeline_args from modules.onnx_impl import preprocess_pipeline as preprocess_onnx_pipeline, check_parameters_changed as olive_check_parameters_changed @@ -22,13 +23,13 @@ def restore_state(p: processing.StableDiffusionProcessing): if p.state in ['reprocess_refine', 'reprocess_detail']: # validate if last_p is None: - shared.log.warning(f'Restore state: op={p.state} last state missing') + logger.log.warning(f'Restore state: op={p.state} last state missing') return p if p.__class__ != last_p.__class__: - shared.log.warning(f'Restore state: op={p.state} last state is different type') + logger.log.warning(f'Restore state: op={p.state} last state is different type') return p if shared.history.count == 0: - shared.log.warning(f'Restore state: op={p.state} last latents missing') + logger.log.warning(f'Restore state: op={p.state} last latents missing') return p state = p.state @@ -63,13 +64,13 @@ def restore_state(p: processing.StableDiffusionProcessing): if state == 'reprocess_detail': p.skip = ['encode', 'base', 'hires'] p.detailer_enabled = True - shared.log.info(f'Restore state: op={p.state} skip={p.skip}') + logger.log.info(f'Restore state: op={p.state} skip={p.skip}') return p def process_pre(p: processing.StableDiffusionProcessing): from modules import ipadapter, sd_hijack_freeu, para_attention, teacache, hidiffusion, ras, pag, cfgzero, transformer_cache, token_merge, linfusion, cachedit - shared.log.info('Processing modifiers: apply') + logger.log.info('Processing modifiers: apply') try: # apply-with-unapply @@ -89,7 +90,7 @@ def process_pre(p: processing.StableDiffusionProcessing): para_attention.apply_first_block_cache() teacache.apply_teacache(p) except Exception as e: - shared.log.error(f'Processing apply: {e}') + logger.log.error(f'Processing apply: {e}') errors.display(e, 'apply') shared.sd_model = sd_models.apply_balanced_offload(shared.sd_model) @@ -112,7 +113,7 @@ def process_pre(p: processing.StableDiffusionProcessing): def process_post(p: processing.StableDiffusionProcessing): from modules import ipadapter, hidiffusion, ras, pag, cfgzero, token_merge, linfusion, cachedit - shared.log.info('Processing modifiers: unapply') + logger.log.info('Processing modifiers: unapply') try: sd_models_compile.check_deepcache(enable=False) @@ -125,7 +126,7 @@ def process_post(p: processing.StableDiffusionProcessing): linfusion.unapply(shared.sd_model) cachedit.unapply_cache_dir(shared.sd_model) except Exception as e: - shared.log.error(f'Processing unapply: {e}') + logger.log.error(f'Processing unapply: {e}') errors.display(e, 'unapply') timer.process.record('post') @@ -195,24 +196,24 @@ def process_base(p: processing.StableDiffusionProcessing): sd_models_compile.openvino_post_compile(op="base") # only executes on compiled vino models if shared.cmd_opts.profile: t1 = time.time() - shared.log.debug(f'Profile: pipeline call: {t1-t0:.2f}') + logger.log.debug(f'Profile: pipeline call: {t1-t0:.2f}') if not hasattr(output, 'images') and hasattr(output, 'frames'): if hasattr(output.frames[0], 'shape'): - shared.log.debug(f'Generated: frames={output.frames[0].shape[1]}') + logger.log.debug(f'Generated: frames={output.frames[0].shape[1]}') else: - shared.log.debug(f'Generated: frames={len(output.frames[0])}') + logger.log.debug(f'Generated: frames={len(output.frames[0])}') output.images = output.frames[0] if hasattr(output, 'images') and isinstance(output.images, np.ndarray): output.images = torch.from_numpy(output.images) except AssertionError as e: - shared.log.info(e) + logger.log.info(e) except ValueError as e: shared.state.interrupted = True err_args = base_args.copy() for k, v in base_args.items(): if isinstance(v, torch.Tensor): err_args[k] = f'{v.device}:{v.dtype}:{v.shape}' - shared.log.error(f'Processing: args={err_args} {e}') + logger.log.error(f'Processing: args={err_args} {e}') if shared.cmd_opts.debug: errors.display(e, 'Processing') except RuntimeError as e: @@ -221,7 +222,7 @@ def process_base(p: processing.StableDiffusionProcessing): for k, v in base_args.items(): if isinstance(v, torch.Tensor): err_args[k] = f'{v.device}:{v.dtype}:{v.shape}' - shared.log.error(f'Processing: step=base args={err_args} {e}') + logger.log.error(f'Processing: step=base args={err_args} {e}') errors.display(e, 'Processing') modelstats.analyze() finally: @@ -257,12 +258,12 @@ def process_hires(p: processing.StableDiffusionProcessing, output): if hasattr(shared.sd_model, 'restore_pipeline') and (shared.sd_model.restore_pipeline is not None) and (not shared.opts.control_hires): shared.sd_model.restore_pipeline() if (getattr(shared.sd_model, 'controlnet', None) is not None) and (((isinstance(shared.sd_model.controlnet, list) and len(shared.sd_model.controlnet) > 1)) or ('Multi' in type(shared.sd_model.controlnet).__name__)): - shared.log.warning(f'Process: control={type(shared.sd_model.controlnet)} not supported in hires') + logger.log.warning(f'Process: control={type(shared.sd_model.controlnet)} not supported in hires') return output # upscale if hasattr(p, 'height') and hasattr(p, 'width') and p.hr_resize_mode > 0 and (p.hr_upscaler != 'None' or p.hr_resize_mode == 5): - shared.log.info(f'Upscale: mode={p.hr_resize_mode} upscaler="{p.hr_upscaler}" context="{p.hr_resize_context}" resize={p.hr_resize_x}x{p.hr_resize_y} upscale={p.hr_upscale_to_x}x{p.hr_upscale_to_y}') + logger.log.info(f'Upscale: mode={p.hr_resize_mode} upscaler="{p.hr_upscaler}" context="{p.hr_resize_context}" resize={p.hr_resize_x}x{p.hr_resize_y} upscale={p.hr_upscale_to_x}x{p.hr_upscale_to_y}') p.ops.append('upscale') if shared.opts.samples_save and not p.do_not_save_samples and shared.opts.save_images_before_highres_fix and hasattr(shared.sd_model, 'vae'): save_intermediate(p, latents=output.images, suffix="-before-hires") @@ -284,7 +285,7 @@ def process_hires(p: processing.StableDiffusionProcessing, output): # hires if p.hr_force and strength == 0: - shared.log.warning('Hires skip: denoising=0') + logger.log.warning('Hires skip: denoising=0') p.hr_force = False if p.hr_force: shared.sd_model = sd_models.set_diffuser_pipe(shared.sd_model, sd_models.DiffusersTaskType.IMAGE_2_IMAGE) @@ -339,10 +340,10 @@ def process_hires(p: processing.StableDiffusionProcessing, output): sd_models_compile.check_deepcache(enable=False) sd_models_compile.openvino_post_compile(op="base") except AssertionError as e: - shared.log.info(e) + logger.log.info(e) except RuntimeError as e: shared.state.interrupted = True - shared.log.error(f'Processing step=hires: args={hires_args} {e}') + logger.log.error(f'Processing step=hires: args={hires_args} {e}') errors.display(e, 'Processing') modelstats.analyze() finally: @@ -367,7 +368,7 @@ def process_refine(p: processing.StableDiffusionProcessing, output): if shared.opts.samples_save and not p.do_not_save_samples and shared.opts.save_images_before_refiner and hasattr(shared.sd_model, 'vae'): save_intermediate(p, latents=output.images, suffix="-before-refiner") if shared.opts.diffusers_move_base: - shared.log.debug('Moving to CPU: model=base') + logger.log.debug('Moving to CPU: model=base') sd_models.move_model(shared.sd_model, devices.cpu) if shared.state.interrupted or shared.state.skipped: shared.sd_model = orig_pipeline @@ -426,17 +427,17 @@ def process_refine(p: processing.StableDiffusionProcessing, output): shared.history.add(output.images, info=processing.create_infotext(p), ops=p.ops) sd_models_compile.openvino_post_compile(op="refiner") except AssertionError as e: - shared.log.info(e) + logger.log.info(e) except RuntimeError as e: shared.state.interrupted = True - shared.log.error(f'Processing step=refine: args={refiner_args} {e}') + logger.log.error(f'Processing step=refine: args={refiner_args} {e}') errors.display(e, 'Processing') modelstats.analyze() if shared.opts.diffusers_offload_mode == "balanced": shared.sd_refiner = sd_models.apply_balanced_offload(shared.sd_refiner) elif shared.opts.diffusers_move_refiner: - shared.log.debug('Moving to CPU: model=refiner') + logger.log.debug('Moving to CPU: model=refiner') sd_models.move_model(shared.sd_refiner, devices.cpu) shared.state.end(jobid) shared.state.nextjob() @@ -449,10 +450,10 @@ def process_decode(p: processing.StableDiffusionProcessing, output): shared.sd_model = sd_models.apply_balanced_offload(shared.sd_model, exclude=['vae']) if output is not None: if hasattr(output, 'bytes') and output.bytes is not None: - shared.log.debug(f'Generated: bytes={len(output.bytes)}') + logger.log.debug(f'Generated: bytes={len(output.bytes)}') return output if not hasattr(output, 'images') and hasattr(output, 'frames'): - shared.log.debug(f'Generated: frames={len(output.frames[0])}') + logger.log.debug(f'Generated: frames={len(output.frames[0])}') output.images = output.frames[0] if output.images is not None and len(output.images) > 0 and isinstance(output.images[0], Image.Image): return output.images @@ -495,17 +496,17 @@ def process_decode(p: processing.StableDiffusionProcessing, output): elif hasattr(output, 'images'): results = output.images else: - shared.log.warning('Processing: no results') + logger.log.warning('Processing: no results') results = [] else: - shared.log.warning('Processing: no results') + logger.log.warning('Processing: no results') results = [] return results def update_pipeline(sd_model, p: processing.StableDiffusionProcessing): if sd_models.get_diffusers_task(sd_model) == sd_models.DiffusersTaskType.INPAINTING and getattr(p, 'image_mask', None) is None and p.task_args.get('image_mask', None) is None and getattr(p, 'mask', None) is None: - shared.log.warning('Processing: mode=inpaint mask=None') + logger.log.warning('Processing: mode=inpaint mask=None') sd_model = sd_models.set_diffuser_pipe(sd_model, sd_models.DiffusersTaskType.IMAGE_2_IMAGE) if shared.opts.cuda_compile_backend == "olive-ai": sd_model = olive_check_parameters_changed(p, is_refiner_enabled(p)) @@ -514,7 +515,7 @@ def update_pipeline(sd_model, p: processing.StableDiffusionProcessing): global orig_pipeline # pylint: disable=global-statement orig_pipeline = sd_model # processed ONNX pipeline should not be replaced with original pipeline. if getattr(sd_model, "current_attn_name", None) != shared.opts.cross_attention_optimization: - shared.log.info(f"Setting attention optimization: {shared.opts.cross_attention_optimization}") + logger.log.info(f"Setting attention optimization: {shared.opts.cross_attention_optimization}") attention.set_diffusers_attention(sd_model) return sd_model @@ -532,10 +533,10 @@ def validate_pipeline(p: processing.StableDiffusionProcessing): override_video_pipelines = ['WanPipeline', 'WanImageToVideoPipeline', 'WanVACEPipeline'] is_video_pipeline = ('video' in p.__class__.__name__.lower()) or (shared.sd_model.__class__.__name__ in override_video_pipelines) if is_video_model and not is_video_pipeline: - shared.log.error(f'Mismatch: type={shared.sd_model_type} cls={shared.sd_model.__class__.__name__} request={p.__class__.__name__} video model with non-video pipeline') + logger.log.error(f'Mismatch: type={shared.sd_model_type} cls={shared.sd_model.__class__.__name__} request={p.__class__.__name__} video model with non-video pipeline') return False elif not is_video_model and is_video_pipeline: - shared.log.error(f'Mismatch: type={shared.sd_model_type} cls={shared.sd_model.__class__.__name__} request={p.__class__.__name__} non-video model with video pipeline') + logger.log.error(f'Mismatch: type={shared.sd_model_type} cls={shared.sd_model.__class__.__name__} request={p.__class__.__name__} non-video model with video pipeline') return False return True @@ -543,7 +544,7 @@ def validate_pipeline(p: processing.StableDiffusionProcessing): def process_diffusers(p: processing.StableDiffusionProcessing): results = [] if debug: - shared.log.trace(f'Process diffusers args: {vars(p)}') + logger.log.trace(f'Process diffusers args: {vars(p)}') if not validate_pipeline(p): return results @@ -591,7 +592,7 @@ def process_diffusers(p: processing.StableDiffusionProcessing): if (output is None or (hasattr(output, 'images') and len(output.images) == 0)) and has_images: if output is not None: - shared.log.debug('Processing: using input as base output') + logger.log.debug('Processing: using input as base output') output.images = p.init_images if shared.state.interrupted or shared.state.skipped: diff --git a/modules/processing_helpers.py b/modules/processing_helpers.py index 8477b2218..ff471f81b 100644 --- a/modules/processing_helpers.py +++ b/modules/processing_helpers.py @@ -8,11 +8,12 @@ import numpy as np import cv2 from PIL import Image from modules import shared, devices, images, sd_models, sd_samplers, sd_vae, sd_hijack_hypertile, processing_vae, timer +from modules import logger from modules.api import helpers -debug = shared.log.trace if os.environ.get('SD_PROCESS_DEBUG', None) is not None else lambda *args, **kwargs: None -debug_steps = shared.log.trace if os.environ.get('SD_STEPS_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_PROCESS_DEBUG', None) is not None else lambda *args, **kwargs: None +debug_steps = logger.log.trace if os.environ.get('SD_STEPS_DEBUG', None) is not None else lambda *args, **kwargs: None debug_steps('Trace: STEPS') @@ -40,7 +41,7 @@ def apply_color_correction(correction, original_image): install('blendmodes', quiet=True) from skimage import exposure from blendmodes.blend import blendLayers, BlendType - shared.log.debug(f"Applying color correction: correction={correction.shape} image={original_image}") + logger.log.debug(f"Applying color correction: correction={correction.shape} image={original_image}") np_image = np.asarray(original_image) np_recolor = cv2.cvtColor(np_image, cv2.COLOR_RGB2LAB) np_match = exposure.match_histograms(np_recolor, correction, channel_axis=2) @@ -71,7 +72,7 @@ def apply_overlay(image: Image, paste_loc, index, overlays): image.alpha_composite(overlay) image = image.convert('RGB') except Exception as e: - shared.log.error(f'Apply overlay: {e}') + logger.log.error(f'Apply overlay: {e}') return image @@ -105,10 +106,10 @@ def get_sampler_name(sampler_index: int, img: bool = False) -> str: sampler_name = sd_samplers.samplers[sampler_index].name else: sampler_name = "Default" - shared.log.warning(f'Sampler not found: index={sampler_index} available={[s.name for s in sd_samplers.samplers]} fallback={sampler_name}') + logger.log.warning(f'Sampler not found: index={sampler_index} available={[s.name for s in sd_samplers.samplers]} fallback={sampler_name}') if img and sampler_name == "PLMS": sampler_name = "Default" - shared.log.warning(f'Sampler not compatible: name=PLMS fallback={sampler_name}') + logger.log.warning(f'Sampler not compatible: name=PLMS fallback={sampler_name}') return sampler_name @@ -210,7 +211,7 @@ def create_random_tensors(shape, seeds, subseeds=None, subseed_strength=0.0, see def decode_first_stage(model, x): if not shared.opts.keep_incomplete and (shared.state.skipped or shared.state.interrupted): - shared.log.debug(f'Decode VAE: skipped={shared.state.skipped} interrupted={shared.state.interrupted}') + logger.log.debug(f'Decode VAE: skipped={shared.state.skipped} interrupted={shared.state.interrupted}') x_sample = torch.zeros((len(x), 3, x.shape[2] * 8, x.shape[3] * 8), dtype=devices.dtype_vae, device=devices.device) return x_sample with devices.autocast(disable = x.dtype==devices.dtype_vae): @@ -222,10 +223,10 @@ def decode_first_stage(model, x): x_sample = processing_vae.vae_decode(latents=x, model=model, output_type='np') else: x_sample = x - shared.log.error('Decode VAE unknown model') + logger.log.error('Decode VAE unknown model') except Exception as e: x_sample = x - shared.log.error(f'Decode VAE: {e}') + logger.log.error(f'Decode VAE: {e}') return x_sample @@ -273,7 +274,7 @@ def validate_sample(tensor): elif isinstance(tensor, np.ndarray): sample = tensor else: - shared.log.warning(f'Decode: type={type(tensor)} unknown sample') + logger.log.warning(f'Decode: type={type(tensor)} unknown sample') return tensor sample = 255.0 * sample with warnings.catch_warnings(record=True) as w: @@ -284,10 +285,10 @@ def validate_sample(tensor): cast = cast.astype(np.uint8) vae = shared.sd_model.vae.dtype if hasattr(shared.sd_model, 'vae') else None upcast = getattr(shared.sd_model.vae.config, 'force_upcast', None) if hasattr(shared.sd_model, 'vae') and hasattr(shared.sd_model.vae, 'config') else None - shared.log.error(f'Decode: sample={sample.shape} invalid={nans} dtype={dtype} vae={vae} upcast={upcast} failed to validate') + logger.log.error(f'Decode: sample={sample.shape} invalid={nans} dtype={dtype} vae={vae} upcast={upcast} failed to validate') if upcast is not None and not upcast: setattr(shared.sd_model.vae.config, 'force_upcast', True) # noqa: B010 - shared.log.info('Decode: set upcast=True and attempt to retry operation') + logger.log.info('Decode: set upcast=True and attempt to retry operation') t1 = time.time() timer.process.add('validate', t1 - t0) return cast @@ -301,24 +302,24 @@ def decode_images(image): try: decoded.append(helpers.decode_base64_to_image(img, quiet=True)) except Exception as e: - shared.log.error(f'Decode image[{i}]: {e}') + logger.log.error(f'Decode image[{i}]: {e}') elif isinstance(img, Image.Image): decoded.append(img) else: - shared.log.error(f'Decode image[{i}]: {type(img)} unknown type') + logger.log.error(f'Decode image[{i}]: {type(img)} unknown type') return decoded elif isinstance(image, str): try: return helpers.decode_base64_to_image(image, quiet=True) except Exception as e: - shared.log.error(f'Decode image: {e}') + logger.log.error(f'Decode image: {e}') # elif isinstance(image, Image.Image): # return image # elif torch.is_tensor(image): # return image else: return image - # shared.log.error(f'Decode image: {type(image)} unknown type') + # logger.log.error(f'Decode image: {type(image)} unknown type') return None @@ -332,7 +333,7 @@ def resize_init_images(p): tgt_width = vae_scale_factor * math.ceil(p.init_images[0].width / vae_scale_factor) tgt_height = vae_scale_factor * math.ceil(p.init_images[0].height / vae_scale_factor) if p.init_images[0].size != (tgt_width, tgt_height): - shared.log.debug(f'Resizing init images: original={p.init_images[0].width}x{p.init_images[0].height} target={tgt_width}x{tgt_height}') + logger.log.debug(f'Resizing init images: original={p.init_images[0].width}x{p.init_images[0].height} target={tgt_width}x{tgt_height}') p.init_images = [images.resize_image(1, image, tgt_width, tgt_height, upscaler_name=None) for image in p.init_images] p.height = tgt_height p.width = tgt_width @@ -354,7 +355,7 @@ def resize_init_images(p): def resize_hires(p, latents): # input=latents output=pil if not latent_upscaler else latent if (p.hr_upscale_to_x == 0 or p.hr_upscale_to_y == 0) and hasattr(p, 'init_hr'): - shared.log.error('Hires: missing upscaling dimensions') + logger.log.error('Hires: missing upscaling dimensions') return latents jobid = shared.state.begin('Resize') @@ -364,14 +365,14 @@ def resize_hires(p, latents): # input=latents output=pil if not latent_upscaler try: for i in range(len(latents)): if not torch.is_tensor(latents[i]): - shared.log.warning(f'Hires: input[{i}]={type(latents[i])} not tensor') + logger.log.warning(f'Hires: input[{i}]={type(latents[i])} not tensor') latents[i] = processing_vae.vae_encode(image=latents[i], model=shared.sd_model, vae_type=p.vae_type) latents = torch.cat(latents, dim=0) except Exception as e: - shared.log.error(f'Hires: prepare latents: {e}') + logger.log.error(f'Hires: prepare latents: {e}') resized = latents elif not torch.is_tensor(latents): - shared.log.warning(f'Hires: input={type(latents)} not tensor') + logger.log.warning(f'Hires: input={type(latents)} not tensor') resized = images.resize_image(p.hr_resize_mode, latents, p.hr_upscale_to_x, p.hr_upscale_to_y, upscaler_name=p.hr_upscaler, context=p.hr_resize_context) else: decoded = processing_vae.vae_decode(latents=latents, model=shared.sd_model, vae_type=p.vae_type, output_type='pil', width=p.width, height=p.height) @@ -457,7 +458,7 @@ def get_generator(p): devices.randn(p.seeds[0]) generator = [torch.Generator(generator_device).manual_seed(s) for s in p.seeds] except Exception as e: - shared.log.error(f'Torch generator: seeds={p.seeds} device={generator_device} {e}') + logger.log.error(f'Torch generator: seeds={p.seeds} device={generator_device} {e}') generator = None return generator @@ -492,7 +493,7 @@ def apply_circular(enable: bool, model): layer.padding_mode = 'circular' if enable else 'zeros' model.texture_tiling = enable if current is not None or enable: - shared.log.debug(f'Apply texture tiling: enabled={enable} layers={i} cls={model.__class__.__name__} ') + logger.log.debug(f'Apply texture tiling: enabled={enable} layers={i} cls={model.__class__.__name__} ') except Exception as e: debug(f"Diffusers tiling failed: {e}") @@ -513,7 +514,7 @@ def update_sampler(p, sd_model, second_pass=False): return sampler = sd_samplers.find_sampler(sampler_selection) if sampler is None: - shared.log.warning(f'Sampler: "{sampler_selection}" not found') + logger.log.warning(f'Sampler: "{sampler_selection}" not found') sampler = sd_samplers.all_samplers_map.get("UniPC") sampler = sd_samplers.create_sampler(sampler.name, sd_model) if sampler is None or sampler_selection == 'Default': diff --git a/modules/processing_info.py b/modules/processing_info.py index 60bfb27fe..fad119e31 100644 --- a/modules/processing_info.py +++ b/modules/processing_info.py @@ -1,12 +1,13 @@ import os from installer import git_commit from modules import shared, sd_samplers_common, sd_vae, generation_parameters_copypaste +from modules import logger from modules.processing_class import StableDiffusionProcessing args = {} # maintain history infotext = '' # maintain history -debug = shared.log.trace if os.environ.get('SD_PROCESS_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_PROCESS_DEBUG', None) is not None else lambda *args, **kwargs: None def get_last_args(): @@ -16,7 +17,7 @@ def get_last_args(): def create_infotext(p: StableDiffusionProcessing, all_prompts=None, all_seeds=None, all_subseeds=None, comments=None, iteration=0, position_in_batch=0, index=None, all_negative_prompts=None, grid=None): global args, infotext # pylint: disable=global-statement if p is None: - shared.log.warning('Processing info: no data') + logger.log.warning('Processing info: no data') return '' if not hasattr(shared.sd_model, 'sd_checkpoint_info'): return '' diff --git a/modules/processing_prompt.py b/modules/processing_prompt.py index 81b713934..d45e1c012 100644 --- a/modules/processing_prompt.py +++ b/modules/processing_prompt.py @@ -1,10 +1,11 @@ import os import torch from modules import shared, errors, timer, prompt_parser_diffusers +from modules import logger debug_enabled = os.environ.get('SD_PROMPT_DEBUG', None) is not None -debug_log = shared.log.trace if debug_enabled else lambda *args, **kwargs: None +debug_log = logger.log.trace if debug_enabled else lambda *args, **kwargs: None def fix_prompt_batch(p, prompts, negative_prompts, prompts_2, negative_prompts_2): @@ -94,7 +95,7 @@ def set_prompt(p, prompt_parser_diffusers.embedder = prompt_parser_diffusers.PromptEmbedder(prompts, negative_prompts, steps, clip_skip, p) except Exception as e: prompt_parser_diffusers.embedder = None - shared.log.error(f'Prompt parser encode: {e}') + logger.log.error(f'Prompt parser encode: {e}') if debug_enabled: errors.display(e, 'Prompt parser encode') timer.process.record('prompt', reset=False) @@ -114,12 +115,12 @@ def set_prompt(p, prompt_attention_masks = prompt_parser_diffusers.embedder('prompt_attention_masks') if prompt_embeds is None: - shared.log.warning('Prompt parser encode: empty prompt embeds') + logger.log.warning('Prompt parser encode: empty prompt embeds') prompt_parser_diffusers.embedder = None args = set_fallback_prompt(args, possible, prompts=prompts, negative_prompts=None, prompts_2=None, negative_prompts_2=None) prompt_attention = 'fixed' elif prompt_embeds.device == torch.device('meta'): - shared.log.warning('Prompt parser encode: embeds on meta device') + logger.log.warning('Prompt parser encode: embeds on meta device') prompt_parser_diffusers.embedder = None args = set_fallback_prompt(args, possible, prompts=prompts, negative_prompts=None, prompts_2=None, negative_prompts_2=None) prompt_attention = 'fixed' @@ -145,12 +146,12 @@ def set_prompt(p, negative_attention_masks = prompt_parser_diffusers.embedder('negative_prompt_attention_masks') if negative_embeds is None: - shared.log.warning('Prompt parser encode: empty negative prompt embeds') + logger.log.warning('Prompt parser encode: empty negative prompt embeds') prompt_parser_diffusers.embedder = None args = set_fallback_prompt(args, possible, prompts=None, negative_prompts=negative_prompts, prompts_2=None, negative_prompts_2=None) prompt_attention = 'fixed' elif negative_embeds.device == torch.device('meta'): - shared.log.warning('Prompt parser encode: negative embeds on meta device') + logger.log.warning('Prompt parser encode: negative embeds on meta device') prompt_parser_diffusers.embedder = None args = set_fallback_prompt(args, possible, prompts=None, negative_prompts=negative_prompts, prompts_2=None, negative_prompts_2=None) prompt_attention = 'fixed' diff --git a/modules/processing_vae.py b/modules/processing_vae.py index c2cbffb57..281238548 100644 --- a/modules/processing_vae.py +++ b/modules/processing_vae.py @@ -3,11 +3,12 @@ import time import numpy as np import torch from modules import shared, devices, sd_models, sd_vae, errors +from modules import logger from modules.vae import sd_vae_taesd debug = os.environ.get('SD_VAE_DEBUG', None) is not None -log_debug = shared.log.trace if debug else lambda *args, **kwargs: None +log_debug = logger.log.trace if debug else lambda *args, **kwargs: None log_debug('Trace: VAE') @@ -22,7 +23,7 @@ def create_latents(image, p, dtype=None, device=None): latents = [vae_encode(i, model=shared.sd_model, vae_type=p.vae_type).squeeze(dim=0) for i in image] latents = torch.stack(latents, dim=0).to(shared.device) else: - shared.log.warning(f'Latents: input type: {type(image)} {image}') + logger.log.warning(f'Latents: input type: {type(image)} {image}') return image noise = p.denoising_strength * create_random_tensors(latents.shape[1:], seeds=p.all_seeds, subseeds=p.all_subseeds, subseed_strength=p.subseed_strength, p=p) latents = (1 - p.denoising_strength) * latents + noise @@ -36,7 +37,7 @@ def create_latents(image, p, dtype=None, device=None): def full_vqgan_decode(latents, model): t0 = time.time() if model is None or not hasattr(model, 'vqgan'): - shared.log.error('VQGAN not found in model') + logger.log.error('VQGAN not found in model') return [] if debug: devices.torch_gc(force=True) @@ -62,7 +63,7 @@ def full_vqgan_decode(latents, model): try: decoded = model.vqgan.decode(latents).sample.clamp(0, 1) except Exception as e: - shared.log.error(f'VAE decode: {e}') + logger.log.error(f'VAE decode: {e}') errors.display(e, 'VAE decode') decoded = [] @@ -81,7 +82,7 @@ def full_vqgan_decode(latents, model): if debug: log_debug(f'VAE memory: {shared.mem_mon.read()}') vae_name = os.path.splitext(os.path.basename(sd_vae.loaded_vae_file))[0] if sd_vae.loaded_vae_file is not None else "default" - shared.log.debug(f'VAE decode: vae="{vae_name}" type="vqgan" dtype={model.vqgan.dtype} device={model.vqgan.device} time={round(t1-t0, 3)}') + logger.log.debug(f'VAE decode: vae="{vae_name}" type="vqgan" dtype={model.vqgan.dtype} device={model.vqgan.device} time={round(t1-t0, 3)}') return decoded @@ -90,7 +91,7 @@ def full_vae_decode(latents, model): if not hasattr(model, 'vae') and hasattr(model, 'pipe'): model = model.pipe if model is None or not hasattr(model, 'vae'): - shared.log.error('VAE not found in model') + logger.log.error('VAE not found in model') return [] if debug: devices.torch_gc(force=True) @@ -152,7 +153,7 @@ def full_vae_decode(latents, model): with devices.inference_context(): decoded = model.vae.decode(latents, return_dict=False)[0] except Exception as e: - shared.log.error(f'VAE decode: {e}') + logger.log.error(f'VAE decode: {e}') if 'out of memory' not in str(e) and 'no data' not in str(e): errors.display(e, 'VAE decode') decoded = [] @@ -176,7 +177,7 @@ def full_vae_decode(latents, model): log_debug(f'VAE memory: {shared.mem_mon.read()}') vae_name = os.path.splitext(os.path.basename(sd_vae.loaded_vae_file))[0] if sd_vae.loaded_vae_file is not None else "default" vae_scale_factor = sd_vae.get_vae_scale_factor(model) - shared.log.debug(f'Decode: vae="{vae_name}" scale={vae_scale_factor} upcast={upcast} slicing={getattr(model.vae, "use_slicing", None)} tiling={getattr(model.vae, "use_tiling", None)} latents={list(latents.shape)}:{latents.device} dtype={latents.dtype} time={t1-t0:.3f}') + logger.log.debug(f'Decode: vae="{vae_name}" scale={vae_scale_factor} upcast={upcast} slicing={getattr(model.vae, "use_slicing", None)} tiling={getattr(model.vae, "use_tiling", None)} latents={list(latents.shape)}:{latents.device} dtype={latents.dtype} time={t1-t0:.3f}') return decoded @@ -209,7 +210,7 @@ def full_vae_encode(image, model): if shared.opts.diffusers_move_unet and not getattr(model, 'has_accelerate', False) and hasattr(model, 'unet'): sd_models.move_model(model.unet, unet_device) t1 = time.time() - shared.log.debug(f'Encode: vae="{vae_name}" upcast={upcast} slicing={getattr(model.vae, "use_slicing", None)} tiling={getattr(model.vae, "use_tiling", None)} latents={encoded.shape}:{encoded.device}:{encoded.dtype} time={t1-t0:.3f}') + logger.log.debug(f'Encode: vae="{vae_name}" upcast={upcast} slicing={getattr(model.vae, "use_slicing", None)} tiling={getattr(model.vae, "use_tiling", None)} latents={encoded.shape}:{encoded.device}:{encoded.dtype} time={t1-t0:.3f}') return encoded @@ -224,12 +225,12 @@ def taesd_vae_decode(latents): else: decoded = sd_vae_taesd.decode(latents) t1 = time.time() - shared.log.debug(f'Decode: vae="taesd" latents={latents.shape}:{latents.device} dtype={latents.dtype} time={t1-t0:.3f}') + logger.log.debug(f'Decode: vae="taesd" latents={latents.shape}:{latents.device} dtype={latents.dtype} time={t1-t0:.3f}') return decoded def taesd_vae_encode(image): - shared.log.debug(f'Encode: vae="taesd" image={image.shape}') + logger.log.debug(f'Encode: vae="taesd" image={image.shape}') encoded = sd_vae_taesd.encode(image) return encoded @@ -263,7 +264,7 @@ def vae_postprocess(tensor, model, output_type='np'): else: images = tensor if isinstance(tensor, list) or isinstance(tensor, np.ndarray) else [tensor] except Exception as e: - shared.log.error(f'VAE postprocess: {e}') + logger.log.error(f'VAE postprocess: {e}') errors.display(e, 'VAE') return images @@ -277,12 +278,12 @@ def vae_decode(latents, model, output_type='np', vae_type='Full', width=None, he return latents if latents.shape[0] == 0: - shared.log.error(f'VAE nothing to decode: {latents.shape}') + logger.log.error(f'VAE nothing to decode: {latents.shape}') return [] if shared.state.interrupted or shared.state.skipped: return [] if not hasattr(model, 'vae') and not hasattr(model, 'vqgan'): - shared.log.error('VAE not found in model') + logger.log.error('VAE not found in model') return [] if vae_type == 'Remote': @@ -320,13 +321,13 @@ def vae_decode(latents, model, output_type='np', vae_type='Full', width=None, he elif hasattr(model, "vae"): decoded = full_vae_decode(latents=latents, model=model) else: - shared.log.error('VAE not found in model') + logger.log.error('VAE not found in model') decoded = [] images = vae_postprocess(decoded, model, output_type) if shared.cmd_opts.profile or debug: t1 = time.time() - shared.log.debug(f'Profile: VAE decode: {t1-t0:.2f}') + logger.log.debug(f'Profile: VAE decode: {t1-t0:.2f}') devices.torch_gc() shared.state.end(jobid) return images @@ -340,7 +341,7 @@ def vae_encode(image, model, vae_type='Full'): # pylint: disable=unused-variable if not hasattr(model, 'vae') and hasattr(model, 'pipe'): model = model.pipe if not hasattr(model, 'vae'): - shared.log.error('VAE not found in model') + logger.log.error('VAE not found in model') return [] tensor = convert.to_tensor(image.convert("RGB")).unsqueeze(0).to(devices.device, devices.dtype_vae) if vae_type == 'Tiny': @@ -349,7 +350,7 @@ def vae_encode(image, model, vae_type='Full'): # pylint: disable=unused-variable tensor = tensor * 2 - 1 latents = full_vae_encode(image=tensor, model=shared.sd_model) else: - shared.log.error('VAE not found in model') + logger.log.error('VAE not found in model') latents = [] devices.torch_gc() shared.state.end(jobid) @@ -362,7 +363,7 @@ def reprocess(gallery): latent, index = shared.history.selected if latent is None or gallery is None: return None - shared.log.info(f'Reprocessing: latent={latent.shape}') + logger.log.info(f'Reprocessing: latent={latent.shape}') reprocessed = vae_decode(latent, shared.sd_model, output_type='pil') outputs = [] for i0, i1 in zip(gallery, reprocessed, strict=False): diff --git a/modules/progress.py b/modules/progress.py index bbdbee553..44f92ac01 100644 --- a/modules/progress.py +++ b/modules/progress.py @@ -4,6 +4,7 @@ import io import time from pydantic import BaseModel, Field # pylint: disable=no-name-in-module import modules.shared as shared +from modules import logger current_task = None @@ -12,7 +13,7 @@ finished_tasks = [] recorded_results = [] recorded_results_limit = 2 debug = os.environ.get('SD_PREVIEW_DEBUG', None) is not None -debug_log = shared.log.trace if debug else lambda *args, **kwargs: None +debug_log = logger.log.trace if debug else lambda *args, **kwargs: None def start_task(id_task): diff --git a/modules/prompt_parser_diffusers.py b/modules/prompt_parser_diffusers.py index 17f4821f0..b90e385dd 100644 --- a/modules/prompt_parser_diffusers.py +++ b/modules/prompt_parser_diffusers.py @@ -6,10 +6,11 @@ import torch from compel.embeddings_provider import BaseTextualInversionManager, EmbeddingsProvider from transformers import PreTrainedTokenizer from modules import shared, prompt_parser, devices, sd_models +from modules import logger from modules.prompt_parser_xhinker import get_weighted_text_embeddings_sd15, get_weighted_text_embeddings_sdxl_2p, get_weighted_text_embeddings_sd3, get_weighted_text_embeddings_flux1, get_weighted_text_embeddings_chroma debug_enabled = os.environ.get('SD_PROMPT_DEBUG', None) -debug = shared.log.trace if debug_enabled else lambda *args, **kwargs: None +debug = logger.log.trace if debug_enabled else lambda *args, **kwargs: None debug('Trace: PROMPT') orig_encode_token_ids_to_embeddings = EmbeddingsProvider._encode_token_ids_to_embeddings # pylint: disable=protected-access token_dict = None # used by helper get_tokens @@ -29,7 +30,7 @@ def prompt_compatible(pipe = None): 'Chroma' not in pipe.__class__.__name__ and 'HiDreamImage' not in pipe.__class__.__name__ ): - shared.log.warning(f"Prompt parser not supported: {pipe.__class__.__name__}") + logger.log.warning(f"Prompt parser not supported: {pipe.__class__.__name__}") return False return True @@ -80,7 +81,7 @@ class PromptEmbedder: return self.pipe = prepare_model(p.sd_model) if self.pipe is None: - shared.log.error("Prompt encode: cannot find text encoder in model") + logger.log.error("Prompt encode: cannot find text encoder in model") return seen_prompts = {} # per prompt in batch @@ -295,7 +296,7 @@ class PromptEmbedder: res = pad_to_same_length(self.pipe, res) return torch.cat(res) except Exception as e: - shared.log.error(f"Prompt encode: {e}") + logger.log.error(f"Prompt encode: {e}") return None @@ -419,7 +420,7 @@ def get_tokens(pipe, msg, prompt): added_tokens = getattr(tokenizer, 'added_tokens_decoder', {}) for k, v in added_tokens.items(): token_dict[str(v)] = k - shared.log.debug(f'Tokenizer: words={len(token_dict)} file="{fn}"') + logger.log.debug(f'Tokenizer: words={len(token_dict)} file="{fn}"') has_bos_token = getattr(tokenizer, 'bos_token_id', None) is not None has_eos_token = getattr(tokenizer, 'eos_token_id', None) is not None try: @@ -636,7 +637,7 @@ def get_weighted_text_embeddings(pipe, prompt: str = "", neg_prompt: str = "", c embedding_providers = prepare_embedding_providers(pipe, clip_skip) if len(embedding_providers) == 0: - shared.log.error("Prompt encode: cannot find text encoder in model") + logger.log.error("Prompt encode: cannot find text encoder in model") return None, None, None, None, None, None empty_embedding_providers = None if 'StableCascade' in pipe.__class__.__name__: diff --git a/modules/ras/__init__.py b/modules/ras/__init__.py index 891dae240..957f10d67 100644 --- a/modules/ras/__init__.py +++ b/modules/ras/__init__.py @@ -2,6 +2,7 @@ # original: from modules import shared, processing +from modules import logger def apply(pipe, p: processing.StableDiffusionProcessing): @@ -18,7 +19,7 @@ def apply(pipe, p: processing.StableDiffusionProcessing): MANAGER.width = p.width MANAGER.height = p.height MANAGER.error_reset_steps = [int(1*p.steps/3), int(2*p.steps/3)] - shared.log.info(f'RAS: scheduler={pipe.scheduler.__class__.__name__} {str(MANAGER)}') + logger.log.info(f'RAS: scheduler={pipe.scheduler.__class__.__name__} {str(MANAGER)}') MANAGER.reset_cache() MANAGER.generate_skip_token_list() pipe.transformer.old_forward = pipe.transformer.forward diff --git a/modules/rife/__init__.py b/modules/rife/__init__.py index ba2a66d8b..67f970472 100644 --- a/modules/rife/__init__.py +++ b/modules/rife/__init__.py @@ -13,6 +13,7 @@ from tqdm.rich import tqdm from modules.rife.ssim import ssim_matlab from modules.rife.model_rife import RifeModel from modules import devices, shared, paths +from modules import logger model_url = 'https://github.com/vladmandic/rife/raw/main/model/flownet-v46.pkl' @@ -25,7 +26,7 @@ def load(model_path: str = 'rife/flownet-v46.pkl'): from modules import modelloader model_dir = os.path.join(paths.models_path, 'RIFE') model_path = modelloader.load_file_from_url(url=model_url, model_dir=model_dir, file_name='flownet-v46.pkl') - shared.log.debug(f'Video interpolate: model="{model_path}"') + logger.log.debug(f'Video interpolate: model="{model_path}"') model = RifeModel() model.load_model(model_path, -1) model.eval() @@ -114,7 +115,7 @@ def interpolate(images: list, count: int = 2, scale: float = 1.0, pad: int = 1, while not buffer.qsize() > 0: time.sleep(0.1) t1 = time.time() - shared.log.info(f'Video interpolate: input={len(images)} frames={len(interpolated)} buffer={buffer.qsize()} duplicate={duplicate} width={w} height={h} interpolate={count} scale={scale} pad={pad} change={change} time={round(t1 - t0, 2)}') + logger.log.info(f'Video interpolate: input={len(images)} frames={len(interpolated)} buffer={buffer.qsize()} duplicate={duplicate} width={w} height={h} interpolate={count} scale={scale} pad={pad} change={change} time={round(t1 - t0, 2)}') return interpolated @@ -148,5 +149,5 @@ def interpolate_nchw(images: list, count: int = 2, scale: float = 1.0): pbar.update(1) t1 = time.time() - shared.log.info(f'Video interpolate: input={len(images)} frames={len(interpolated)} width={w} height={h} interpolate={count} scale={scale} time={round(t1 - t0, 2)}') + logger.log.info(f'Video interpolate: input={len(images)} frames={len(interpolated)} width={w} height={h} interpolate={count} scale={scale} time={round(t1 - t0, 2)}') return interpolated diff --git a/modules/rocm.py b/modules/rocm.py index 42af4db75..39fe46403 100644 --- a/modules/rocm.py +++ b/modules/rocm.py @@ -293,7 +293,7 @@ if sys.platform == "win32": try: import torch import numpy as np - from installer import log + from modules.logger import log from modules.devices import get_hip_agent from modules.rocm_triton_windows import apply_triton_patches @@ -364,7 +364,6 @@ else: # sys.platform != "win32" def rocm_init(): try: - from installer import log from modules.devices import get_hip_agent agent = get_hip_agent() diff --git a/modules/rocm_triton_windows.py b/modules/rocm_triton_windows.py index 022e27b10..310dc677a 100644 --- a/modules/rocm_triton_windows.py +++ b/modules/rocm_triton_windows.py @@ -1,6 +1,7 @@ import sys import torch from modules import shared, devices +from modules import logger from modules.rocm import Agent @@ -87,7 +88,7 @@ if sys.platform == "win32": props["mem_bus_width"] = MEM_BUS_WIDTH[name] else: props["mem_bus_width"] = 128 - shared.log.warning(f'[TRITON] defaulting mem_bus_width=128 for device "{name}".') + logger.log.warning(f'[TRITON] defaulting mem_bus_width=128 for device "{name}".') return props triton.runtime.driver.active.utils.get_device_properties = triton_runtime_driver_active_utils_get_device_properties except Exception: diff --git a/modules/script_callbacks.py b/modules/script_callbacks.py index fad126ce1..72c1297ce 100644 --- a/modules/script_callbacks.py +++ b/modules/script_callbacks.py @@ -6,6 +6,7 @@ from typing import Any from fastapi import FastAPI from gradio import Blocks import modules.errors as errors +from modules import logger def report_exception(e, c, job): @@ -141,7 +142,7 @@ def print_timers(): if v > 0.05: long_callbacks.append(f'{k}={v:.2f}') if len(long_callbacks) > 0: - errors.log.debug(f'Script init: {long_callbacks}') + logger.log.debug(f'Script init: {long_callbacks}') def clear_callbacks(): diff --git a/modules/script_loading.py b/modules/script_loading.py index 0dd243214..e6afdc49e 100644 --- a/modules/script_loading.py +++ b/modules/script_loading.py @@ -3,6 +3,7 @@ import os import contextlib import importlib.util import modules.errors as errors +from modules import logger from installer import setup_logging @@ -29,7 +30,7 @@ def load_module(path): if '2;36m' in line: # color escape sequence print(line.strip()) else: - errors.log.info(f"Extension: script='{os.path.relpath(path)}' {line.strip()}") + logger.log.info(f"Extension: script='{os.path.relpath(path)}' {line.strip()}") except Exception as e: errors.display(e, f'Module load: {path}') return module diff --git a/modules/scripts_manager.py b/modules/scripts_manager.py index 1ac69bdf5..69c67757c 100644 --- a/modules/scripts_manager.py +++ b/modules/scripts_manager.py @@ -6,13 +6,14 @@ from collections import namedtuple from dataclasses import dataclass import gradio as gr from modules import paths, script_callbacks, extensions, script_loading, scripts_postprocessing, errors, timer +from modules import logger from installer import control_extensions AlwaysVisible = object() time_component = {} time_setup = {} -debug = errors.log.trace if os.environ.get('SD_SCRIPT_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_SCRIPT_DEBUG', None) is not None else lambda *args, **kwargs: None class PostprocessImageArgs: @@ -236,7 +237,7 @@ def list_scripts(scriptdirname, extension): if os.path.isfile(os.path.join(base, "..", ".priority")): with open(os.path.join(base, "..", ".priority"), encoding="utf-8") as f: priority = priority + str(f.read().strip()) - errors.log.debug(f'Script priority override: ${script.name}:{priority}') + logger.log.debug(f'Script priority override: ${script.name}:{priority}') else: priority = priority + script.priority priority_list.append(ScriptFile(script.basedir, script.filename, script.path, priority)) @@ -325,7 +326,7 @@ class ScriptSummary: if total == 0: return scripts = [f'{k}:{v}' for k, v in self.time.items() if v > 0] - errors.log.debug(f'Script: op={self.op} total={total} scripts={scripts}') + logger.log.debug(f'Script: op={self.op} total={total} scripts={scripts}') class ScriptRunner: @@ -367,7 +368,7 @@ class ScriptRunner: self.scripts.append(script) self.selectable_scripts.append(script) except Exception as e: - errors.log.error(f'Script initialize: {path} {e}') + logger.log.error(f'Script initialize: {path} {e}') errors.display(e, 'script') def initialize_scripts(self, is_img2img=False, is_control=False): @@ -425,11 +426,11 @@ class ScriptRunner: debug(f'Script control: parent={script.parent} script="{script.name}" label="{control.label}" type={control} id={control.elem_id}') if hasattr(gr.components, 'IOComponent'): if not isinstance(control, gr.components.IOComponent): - errors.log.error(f'Invalid script control: "{script.filename}" control={control}') + logger.log.error(f'Invalid script control: "{script.filename}" control={control}') continue else: if not isinstance(control, gr.components.Component): - errors.log.error(f'Invalid script control: "{script.filename}" control={control}') + logger.log.error(f'Invalid script control: "{script.filename}" control={control}') continue control.custom_script_source = os.path.basename(script.filename) arg_info = api_models.ScriptArg(label=control.label or "") @@ -462,7 +463,7 @@ class ScriptRunner: if not script.standalone: continue if (self.name == 'control') and (script.name not in control_extensions) and (script.title() not in control_extensions): - errors.log.debug(f'Script: fn="{script.filename}" type={self.name} skip') + logger.log.debug(f'Script: fn="{script.filename}" type={self.name} skip') continue t0 = time.time() with gr.Group(elem_id=f'{parent}_script_{script.title().lower().replace(" ", "_")}', elem_classes=['group-extension']) as group: @@ -476,7 +477,7 @@ class ScriptRunner: if script.standalone: continue if (self.name == 'control') and (paths.extensions_dir in script.filename) and (script.title() not in control_extensions): - errors.log.debug(f'Script: fn="{script.filename}" type={self.name} skip') + logger.log.debug(f'Script: fn="{script.filename}" type={self.name} skip') continue t0 = time.time() with gr.Group(elem_id=f'{parent}_script_{script.title().lower().replace(" ", "_")}', elem_classes=['group-extension']) as group: @@ -486,7 +487,7 @@ class ScriptRunner: for script in self.selectable_scripts: if (self.name == 'control') and (paths.extensions_dir in script.filename) and (script.title() not in control_extensions): - errors.log.debug(f'Script: fn="{script.filename}" type={self.name} skip') + logger.log.debug(f'Script: fn="{script.filename}" type={self.name} skip') continue with gr.Group(elem_id=f'{parent}_script_{script.title().lower().replace(" ", "_")}', elem_classes=['group-scripts'], visible=False) as group: t0 = time.time() @@ -504,7 +505,7 @@ class ScriptRunner: if title == 'None': # called when an initial value is set from ui-config.json to show script's UI components return if title not in self.titles: - errors.log.error(f'Script: title="{title}" op=init not found') + logger.log.error(f'Script: title="{title}" op=init not found') return script_index = self.titles.index(title) self.selectable_scripts[script_index].group.visible = True @@ -525,7 +526,7 @@ class ScriptRunner: self.script_load_ctr = (self.script_load_ctr + 1) % len(self.titles) return gr.update(visible=visibility) else: - # errors.log.warning(f'Script: title="{title}" op=visibility not found') + # logger.log.warning(f'Script: title="{title}" op=visibility not found') return gr.update(visible=False) self.infotext_fields.append((dropdown, lambda x: gr.update(value=x.get('Script', 'None')))) @@ -552,7 +553,7 @@ class ScriptRunner: processed = script.run(p, *parsed) else: processed = None - errors.log.error(f'Script: file="{script.filename}" no run function defined') + logger.log.error(f'Script: file="{script.filename}" no run function defined') s.record(script.title()) s.report() return processed diff --git a/modules/scripts_postprocessing.py b/modules/scripts_postprocessing.py index 1bea4e219..00d5c3ff0 100644 --- a/modules/scripts_postprocessing.py +++ b/modules/scripts_postprocessing.py @@ -1,6 +1,7 @@ import os import gradio as gr from modules import errors, shared +from modules import logger class PostprocessedImage: @@ -103,7 +104,7 @@ class ScriptPostprocessingRunner: process_args = {} for (name, _component), value in zip(script.controls.items(), script_args, strict=False): process_args[name] = value - shared.log.debug(f'Process: script="{script.name}" args={process_args}') + logger.log.debug(f'Process: script="{script.name}" args={process_args}') script.process(pp, **process_args) shared.state.end(jobid) @@ -133,6 +134,6 @@ class ScriptPostprocessingRunner: process_args = {} for (name, _component), value in zip(script.controls.items(), script_args, strict=False): process_args[name] = value - shared.log.debug(f'Postprocess: script={script.name} args={process_args}') + logger.log.debug(f'Postprocess: script={script.name} args={process_args}') script.postprocess(filenames, **process_args) shared.state.end(jobid) diff --git a/modules/sd_checkpoint.py b/modules/sd_checkpoint.py index c050811fe..68c8648f0 100644 --- a/modules/sd_checkpoint.py +++ b/modules/sd_checkpoint.py @@ -7,6 +7,7 @@ import json import collections from PIL import Image from modules import shared, paths, modelloader, hashes, sd_hijack_accelerate +from modules import logger checkpoints_list = {} @@ -87,7 +88,7 @@ class CheckpointInfo: self.path = self.filename self.model_name = os.path.basename(self.name) self.metadata = read_metadata_from_safetensors(filename) - # shared.log.debug(f'Checkpoint: type={self.type} name={self.name} filename={self.filename} hash={self.shorthash} title={self.title}') + # logger.log.debug(f'Checkpoint: type={self.type} name={self.name} filename={self.filename} hash={self.shorthash} title={self.title}') def register(self): checkpoints_list[self.title] = self @@ -153,8 +154,8 @@ def list_models(): checkpoint_info.register() shared.opts.data['sd_model_checkpoint'] = checkpoint_info.title elif shared.cmd_opts.ckpt != shared.default_sd_model_file: - shared.log.warning(f'Load model: path="{shared.cmd_opts.ckpt}" not found') - shared.log.info(f'Available Models: safetensors="{shared.opts.ckpt_dir}":{len(safetensors_list)} diffusers="{shared.opts.diffusers_dir}":{len(diffusers_list)} reference={len(list(shared.reference_models))} items={len(checkpoints_list)} time={time.time()-t0:.2f}') + logger.log.warning(f'Load model: path="{shared.cmd_opts.ckpt}" not found') + logger.log.info(f'Available Models: safetensors="{shared.opts.ckpt_dir}":{len(safetensors_list)} diffusers="{shared.opts.diffusers_dir}":{len(diffusers_list)} reference={len(list(shared.reference_models))} items={len(checkpoints_list)} time={time.time()-t0:.2f}') checkpoints_list = dict(sorted(checkpoints_list.items(), key=lambda cp: cp[1].filename)) @@ -181,14 +182,14 @@ def update_model_hashes(): """ except Exception as e: - shared.log.error(f'Model list: row={row} {e}') + logger.log.error(f'Model list: row={row} {e}') return html.format(tbody=tbody) lst = [ckpt for ckpt in checkpoints_list.values() if ckpt.hash is None] for ckpt in lst: ckpt.hash = model_hash(ckpt.filename) lst = [ckpt for ckpt in checkpoints_list.values() if ckpt.sha256 is None or ckpt.shorthash is None] - shared.log.info(f'Models list: hash missing={len(lst)} total={len(checkpoints_list)}') + logger.log.info(f'Models list: hash missing={len(lst)} total={len(checkpoints_list)}') updated = [] for ckpt in lst: ckpt.sha256 = hashes.sha256(ckpt.filename, f"checkpoint/{ckpt.name}") @@ -207,7 +208,7 @@ def get_closest_checkpoint_match(s: str) -> CheckpointInfo: model_name = s.replace('https://huggingface.co/', '') checkpoint_info = CheckpointInfo(model_name) # create a virutal model info checkpoint_info.type = 'huggingface' - shared.log.debug(f'Seach model: name="{s}" matched="{checkpoint_info.path}" type=huggingface') + logger.log.debug(f'Seach model: name="{s}" matched="{checkpoint_info.path}" type=huggingface') return checkpoint_info if s.startswith('huggingface/'): model_name = s.replace('huggingface/', '') @@ -218,28 +219,28 @@ def get_closest_checkpoint_match(s: str) -> CheckpointInfo: # alias search checkpoint_info = checkpoint_aliases.get(s, None) if checkpoint_info is not None: - shared.log.debug(f'Search model: name="{s}" matched="{checkpoint_info.path}" type=alias') + logger.log.debug(f'Search model: name="{s}" matched="{checkpoint_info.path}" type=alias') return checkpoint_info # models search found = sorted([info for info in checkpoints_list.values() if os.path.basename(info.title).lower() == s.lower()], key=lambda x: len(x.title)) if found and len(found) == 1: checkpoint_info = found[0] - shared.log.debug(f'Search model: name="{s}" matched="{checkpoint_info.path}" type=hash') + logger.log.debug(f'Search model: name="{s}" matched="{checkpoint_info.path}" type=hash') return checkpoint_info # nohash search found = sorted([info for info in checkpoints_list.values() if remove_hash(info.title).lower() == remove_hash(s).lower()], key=lambda x: len(x.title)) if found and len(found) == 1: checkpoint_info = found[0] - shared.log.debug(f'Search model: name="{s}" matched="{checkpoint_info.path}" type=model') + logger.log.debug(f'Search model: name="{s}" matched="{checkpoint_info.path}" type=model') return checkpoint_info # absolute path if s.endswith('.safetensors') and os.path.isfile(s): checkpoint_info = CheckpointInfo(s) checkpoint_info.type = 'safetensors' - shared.log.debug(f'Search model: name="{s}" matched="{checkpoint_info.path}" type=safetensors') + logger.log.debug(f'Search model: name="{s}" matched="{checkpoint_info.path}" type=safetensors') return checkpoint_info # reference search @@ -251,7 +252,7 @@ def get_closest_checkpoint_match(s: str) -> CheckpointInfo: checkpoint_info = CheckpointInfo(s) checkpoint_info.subfolder = info.get('subfolder', None) checkpoint_info.type = 'reference' - shared.log.debug(f'Search model: name="{s}" matched="{checkpoint_info.path}" type=reference') + logger.log.debug(f'Search model: name="{s}" matched="{checkpoint_info.path}" type=reference') return checkpoint_info # huggingface search @@ -266,13 +267,13 @@ def get_closest_checkpoint_match(s: str) -> CheckpointInfo: if found is None: return None found = [f for f in found if f == s] - shared.log.info(f'HF search: model="{s}" results={found}') + logger.log.info(f'HF search: model="{s}" results={found}') if found is not None and len(found) == 1: checkpoint_info = CheckpointInfo(s) checkpoint_info.type = 'huggingface' if subfolder is not None and len(subfolder) > 0: checkpoint_info.subfolder = subfolder - shared.log.debug(f'Search model: name="{s}" matched="{checkpoint_info.path}" type=huggingface') + logger.log.debug(f'Search model: name="{s}" matched="{checkpoint_info.path}" type=huggingface') return checkpoint_info # civitai search @@ -281,7 +282,7 @@ def get_closest_checkpoint_match(s: str) -> CheckpointInfo: fn = download_civit_model_thread(model_name=None, model_url=s, model_path='', model_type='Model', token=None) if fn is not None: checkpoint_info = CheckpointInfo(fn) - shared.log.debug(f'Search model: name="{s}" matched="{checkpoint_info.path}" type=civitai') + logger.log.debug(f'Search model: name="{s}" matched="{checkpoint_info.path}" type=civitai') return checkpoint_info return None @@ -309,24 +310,24 @@ def select_checkpoint(op='model', sd_model_checkpoint=None): return None checkpoint_info = get_closest_checkpoint_match(model_checkpoint) if checkpoint_info is not None: - shared.log.info(f'Load {op}: select="{checkpoint_info.title if checkpoint_info is not None else None}"') + logger.log.info(f'Load {op}: select="{checkpoint_info.title if checkpoint_info is not None else None}"') return checkpoint_info if len(checkpoints_list) == 0: - shared.log.error("No models found") + logger.log.error("No models found") global warn_once # pylint: disable=global-statement if not warn_once: warn_once = True - shared.log.info("Set system paths to use existing folders") - shared.log.info(" or use --models-dir to specify base folder with all models") - shared.log.info(" or use --ckpt to force using specific model") + logger.log.info("Set system paths to use existing folders") + logger.log.info(" or use --models-dir to specify base folder with all models") + logger.log.info(" or use --ckpt to force using specific model") return None if model_checkpoint is not None: if model_checkpoint != 'model.safetensors' and model_checkpoint != 'stabilityai/stable-diffusion-xl-base-1.0': - shared.log.error(f'Load {op}: search="{model_checkpoint}" not found') + logger.log.error(f'Load {op}: search="{model_checkpoint}" not found') else: - shared.log.info("Selecting first available checkpoint") + logger.log.info("Selecting first available checkpoint") else: - shared.log.info(f'Load {op}: select="{checkpoint_info.title if checkpoint_info is not None else None}"') + logger.log.info(f'Load {op}: select="{checkpoint_info.title if checkpoint_info is not None else None}"') return checkpoint_info @@ -347,7 +348,7 @@ def extract_thumbnail(filename, data): fn = os.path.splitext(filename)[0] thumbnail = thumbnail.save(f"{fn}.thumb.jpg", quality=50) except Exception as e: - shared.log.error(f"Error extracting thumbnail: {filename} {e}") + logger.log.error(f"Error extracting thumbnail: {filename} {e}") def read_metadata_from_safetensors(filename): @@ -370,7 +371,7 @@ def read_metadata_from_safetensors(filename): metadata_len = int.from_bytes(metadata_len, "little") json_start = file.read(2) if metadata_len <= 2 or json_start not in (b'{"', b"{'"): - shared.log.error(f'Model metadata invalid: file="{filename}" len={metadata_len} start={json_start}') + logger.log.error(f'Model metadata invalid: file="{filename}" len={metadata_len} start={json_start}') return res json_data = json_start + file.read(metadata_len-2) json_obj = json.loads(json_data) @@ -395,7 +396,7 @@ def read_metadata_from_safetensors(filename): pass res[k] = v except Exception as e: - shared.log.error(f'Model metadata: file="{filename}" {e}') + logger.log.error(f'Model metadata: file="{filename}" {e}') from modules import errors errors.display(e, 'Model metadata') sd_metadata[filename] = res @@ -423,8 +424,8 @@ def scrub_dict(dict_obj, keys): def write_metadata(): global sd_metadata_pending # pylint: disable=global-statement if sd_metadata_pending == 0: - shared.log.debug(f'Model metadata: file="{sd_metadata_file}" no changes') + logger.log.debug(f'Model metadata: file="{sd_metadata_file}" no changes') return shared.writefile(sd_metadata, sd_metadata_file) - shared.log.info(f'Model metadata saved: file="{sd_metadata_file}" items={sd_metadata_pending} time={sd_metadata_timer:.2f}') + logger.log.info(f'Model metadata saved: file="{sd_metadata_file}" items={sd_metadata_pending} time={sd_metadata_timer:.2f}') sd_metadata_pending = 0 diff --git a/modules/sd_detect.py b/modules/sd_detect.py index d1f584502..cbdfe8620 100644 --- a/modules/sd_detect.py +++ b/modules/sd_detect.py @@ -3,6 +3,7 @@ import time import torch import diffusers from modules import shared, shared_items, devices, errors, model_tools +from modules import logger debug_load = os.environ.get('SD_LOAD_DEBUG', None) @@ -13,9 +14,9 @@ def guess_by_size(fn, current_guess): if os.path.isfile(fn) and fn.endswith('.safetensors'): size = round(os.path.getsize(fn) / 1024 / 1024) if (size > 0 and size < 128): - shared.log.warning(f'Model size smaller than expected: file="{fn}" size={size} MB') + logger.log.warning(f'Model size smaller than expected: file="{fn}" size={size} MB') elif (size >= 316 and size <= 324) or (size >= 156 and size <= 164): # 320 or 160 - shared.log.warning(f'Model detected as VAE model, but attempting to load as model: file="{fn}" size={size} MB') + logger.log.warning(f'Model detected as VAE model, but attempting to load as model: file="{fn}" size={size} MB') new_guess = 'VAE' elif (size >= 2002 and size <= 2038): # 2032 new_guess = 'Stable Diffusion 1.5' @@ -40,7 +41,7 @@ def guess_by_size(fn, current_guess): elif (size >= 20000 and size <= 40000): new_guess = 'FLUX' if debug_load: - shared.log.trace(f'Autodetect: method=size file="{fn}" size={size} previous="{current_guess}" current="{new_guess}"') + logger.log.trace(f'Autodetect: method=size file="{fn}" size={size} previous="{current_guess}" current="{new_guess}"') return new_guess or current_guess @@ -60,7 +61,7 @@ def guess_by_name(fn, current_guess): new_guess = 'Stable Diffusion 3' elif 'stable-cascade' in fn.lower() or 'stablecascade' in fn.lower() or 'wuerstchen3' in fn.lower() or ('sotediffusion' in fn.lower() and "v2" in fn.lower()): if devices.dtype == torch.float16: - shared.log.warning('Stable Cascade does not support Float16') + logger.log.warning('Stable Cascade does not support Float16') new_guess = 'Stable Cascade' elif 'pixart-sigma' in fn.lower(): new_guess = 'PixArt Sigma' @@ -99,7 +100,7 @@ def guess_by_name(fn, current_guess): elif 'flux' in fn.lower() or 'flex.1' in fn.lower(): size = round(os.path.getsize(fn) / 1024 / 1024) if os.path.isfile(fn) else 0 if size > 11000 and size < 16000: - shared.log.warning(f'Model detected as FLUX UNET model, but attempting to load a base model: file="{fn}" size={size} MB') + logger.log.warning(f'Model detected as FLUX UNET model, but attempting to load a base model: file="{fn}" size={size} MB') new_guess = 'FLUX' elif 'flex.2' in fn.lower(): new_guess = 'FLEX' @@ -150,7 +151,7 @@ def guess_by_name(fn, current_guess): elif 'glm-image' in fn.lower(): new_guess = 'GLM-Image' if debug_load: - shared.log.trace(f'Autodetect: method=name file="{fn}" previous="{current_guess}" current="{new_guess}"') + logger.log.trace(f'Autodetect: method=name file="{fn}" previous="{current_guess}" current="{new_guess}"') return new_guess or current_guess @@ -200,7 +201,7 @@ def guess_by_diffusers(fn, current_guess): if is_quant: k = f'{k} SDNQ' if debug_load: - shared.log.trace(f'Autodetect: method=diffusers file="{fn}" previous="{current_guess}" current="{k}"') + logger.log.trace(f'Autodetect: method=diffusers file="{fn}" previous="{current_guess}" current="{k}"') return k, v return current_guess, None @@ -218,7 +219,7 @@ def guess_variant(fn, current_guess): elif current_guess == 'Stable Diffusion XL': new_guess = 'Stable Diffusion XL Instruct' if debug_load: - shared.log.trace(f'Autodetect: method=variant file="{fn}" previous="{current_guess}" current="{new_guess}"') + logger.log.trace(f'Autodetect: method=variant file="{fn}" previous="{current_guess}" current="{new_guess}"') return new_guess or current_guess @@ -233,7 +234,7 @@ def detect_pipeline(f: str, op: str = 'model'): guess, pipeline = guess_by_diffusers(f, guess) guess = guess_variant(f, guess) pipeline = shared_items.get_pipelines().get(guess, None) if pipeline is None else pipeline - shared.log.info(f'Autodetect {op}: detect="{guess}" class={getattr(pipeline, "__name__", None)} file="{f}"') + logger.log.info(f'Autodetect {op}: detect="{guess}" class={getattr(pipeline, "__name__", None)} file="{f}"') if debug_load is not None: t0 = time.time() keys = model_tools.get_safetensor_keys(f) @@ -242,18 +243,18 @@ def detect_pipeline(f: str, op: str = 'model'): modules = model_tools.remove_entries_after_depth(modules, 3) lst = model_tools.list_compact(keys) t1 = time.time() - shared.log.debug(f'Autodetect: modules={modules} list={lst} time={t1-t0:.2f}') + logger.log.debug(f'Autodetect: modules={modules} list={lst} time={t1-t0:.2f}') except Exception as e: - shared.log.error(f'Autodetect {op}: file="{f}" {e}') + logger.log.error(f'Autodetect {op}: file="{f}" {e}') if debug_load: errors.display(e, f'Load {op}: {f}') return None, None else: try: pipeline = shared_items.get_pipelines().get(guess, None) if pipeline is None else pipeline - shared.log.info(f'Load {op}: detect="{guess}" class={getattr(pipeline, "__name__", None)} file="{f}"') + logger.log.info(f'Load {op}: detect="{guess}" class={getattr(pipeline, "__name__", None)} file="{f}"') except Exception as e: - shared.log.error(f'Load {op}: detect="{guess}" file="{f}" {e}') + logger.log.error(f'Load {op}: detect="{guess}" file="{f}" {e}') if pipeline is None: pipeline = diffusers.DiffusionPipeline diff --git a/modules/sd_hijack_freeu.py b/modules/sd_hijack_freeu.py index 9019301e3..f84d04cfa 100644 --- a/modules/sd_hijack_freeu.py +++ b/modules/sd_hijack_freeu.py @@ -1,6 +1,7 @@ import math import torch from modules import shared, devices +from modules import logger # based on # official params are b1,b2,s1,s2 @@ -87,7 +88,7 @@ def get_fft_device(): torch_fft_device = devices.device except Exception: torch_fft_device = devices.cpu - shared.log.warning(f'FreeU: device={devices.device} dtype={devices.dtype} does not support FFT') + logger.log.warning(f'FreeU: device={devices.device} dtype={devices.dtype} does not support FFT') return torch_fft_device @@ -156,4 +157,4 @@ def apply_freeu(p): p.sd_model.disable_freeu() state_enabled = False if shared.opts.freeu_enabled and state_enabled: - shared.log.info(f'Applying Free-U: b1={shared.opts.freeu_b1} b2={shared.opts.freeu_b2} s1={shared.opts.freeu_s1} s2={shared.opts.freeu_s2}') + logger.log.info(f'Applying Free-U: b1={shared.opts.freeu_b1} b2={shared.opts.freeu_b2} s1={shared.opts.freeu_s1} s2={shared.opts.freeu_s2}') diff --git a/modules/sd_hijack_hypertile.py b/modules/sd_hijack_hypertile.py index f25ac8078..be474d10c 100644 --- a/modules/sd_hijack_hypertile.py +++ b/modules/sd_hijack_hypertile.py @@ -2,6 +2,7 @@ # based on: https://github.com/tfernd/HyperTile/tree/main/hyper_tile/utils.py + https://github.com/tfernd/HyperTile/tree/main/hyper_tile/hyper_tile.py from __future__ import annotations +from modules import logger from collections.abc import Callable from functools import wraps, cache from contextlib import contextmanager, nullcontext @@ -10,7 +11,7 @@ import math import torch import torch.nn as nn from einops import rearrange -from installer import log +from modules.logger import log # global variables to keep track of changing image size in multiple passes @@ -179,7 +180,7 @@ def context_hypertile_vae(p): if p.sd_model is None or not shared.opts.hypertile_vae_enabled: return nullcontext() if shared.opts.cross_attention_optimization == 'Sub-quadratic': - shared.log.warning('Hypertile UNet is not compatible with Sub-quadratic cross-attention optimization') + logger.log.warning('Hypertile UNet is not compatible with Sub-quadratic cross-attention optimization') return nullcontext() global max_h, max_w, error_reported # pylint: disable=global-statement error_reported = False @@ -198,7 +199,7 @@ def context_hypertile_vae(p): else: tile_size = shared.opts.hypertile_vae_tile if shared.opts.hypertile_vae_tile > 0 else max(128, 64 * min(p.width // 128, p.height // 128)) min_tile_size = shared.opts.hypertile_unet_min_tile if shared.opts.hypertile_unet_min_tile > 0 else 128 - shared.log.info(f'Applying HyperTile: vae={min_tile_size}/{tile_size}') + logger.log.info(f'Applying HyperTile: vae={min_tile_size}/{tile_size}') p.extra_generation_params['Hypertile VAE'] = tile_size return split_attention(vae, tile_size=tile_size, min_tile_size=min_tile_size, swap_size=shared.opts.hypertile_vae_swap_size) @@ -208,7 +209,7 @@ def context_hypertile_unet(p): if p.sd_model is None or not shared.opts.hypertile_unet_enabled: return nullcontext() if shared.opts.cross_attention_optimization == 'Sub-quadratic' and not shared.cmd_opts.experimental: - shared.log.warning('Hypertile UNet is not compatible with Sub-quadratic cross-attention optimization') + logger.log.warning('Hypertile UNet is not compatible with Sub-quadratic cross-attention optimization') return nullcontext() global max_h, max_w, error_reported # pylint: disable=global-statement error_reported = False @@ -222,12 +223,12 @@ def context_hypertile_unet(p): log.warning(f'Hypertile UNet disabled: width={width} height={height} are not divisible by 8') return nullcontext() if unet is None: - # shared.log.warning('Hypertile UNet is enabled but no Unet model was found') + # logger.log.warning('Hypertile UNet is enabled but no Unet model was found') return nullcontext() else: tile_size = shared.opts.hypertile_unet_tile if shared.opts.hypertile_unet_tile > 0 else max(128, 64 * min(p.width // 128, p.height // 128)) min_tile_size = shared.opts.hypertile_unet_min_tile if shared.opts.hypertile_unet_min_tile > 0 else 128 - shared.log.info(f'Applying HyperTile: unet={min_tile_size}/{tile_size}') + logger.log.info(f'Applying HyperTile: unet={min_tile_size}/{tile_size}') p.extra_generation_params['Hypertile UNet'] = tile_size return split_attention(unet, tile_size=tile_size, min_tile_size=min_tile_size, swap_size=shared.opts.hypertile_unet_swap_size, depth=shared.opts.hypertile_unet_depth) diff --git a/modules/sd_hijack_safetensors.py b/modules/sd_hijack_safetensors.py index a9ca5ca78..8514e1df6 100644 --- a/modules/sd_hijack_safetensors.py +++ b/modules/sd_hijack_safetensors.py @@ -1,6 +1,7 @@ import safetensors.torch import transformers -from installer import install, log +from installer import install +from modules.logger import log from modules import errors diff --git a/modules/sd_hijack_te.py b/modules/sd_hijack_te.py index d753eaa9b..232322fc0 100644 --- a/modules/sd_hijack_te.py +++ b/modules/sd_hijack_te.py @@ -1,6 +1,7 @@ import os import time from modules import shared, errors, timer, sd_models +from modules import logger def hijack_encode_prompt(*args, **kwargs): @@ -11,10 +12,10 @@ def hijack_encode_prompt(*args, **kwargs): try: prompt = kwargs.get('prompt', None) or (args[0] if len(args) > 0 else None) if prompt is not None: - shared.log.debug(f'Encode: prompt="{prompt}" hijack=True') + logger.log.debug(f'Encode: prompt="{prompt}" hijack=True') res = shared.sd_model.orig_encode_prompt(*args, **kwargs) except Exception as e: - shared.log.error(f'Encode prompt: {e}') + logger.log.error(f'Encode prompt: {e}') errors.display(e, 'Encode prompt') res = None t1 = time.time() diff --git a/modules/sd_hijack_vae.py b/modules/sd_hijack_vae.py index 8034a6428..6742963ed 100644 --- a/modules/sd_hijack_vae.py +++ b/modules/sd_hijack_vae.py @@ -2,9 +2,10 @@ import os import time import torch from modules import shared, sd_models, devices, timer, errors +from modules import logger -debug = shared.log.trace if os.environ.get('SD_VIDEO_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_VIDEO_DEBUG', None) is not None else lambda *args, **kwargs: None def hijack_vae_upscale(*args, **kwargs): @@ -30,13 +31,13 @@ def hijack_vae_decode(*args, **kwargs): res = shared.sd_model.vae.orig_decode(latents, *args[1:], **kwargs) t1 = time.time() try: - shared.log.debug(f'Decode: vae={shared.sd_model.vae.__class__.__name__} dtype={latents.dtype} latents={list(latents.shape)}:{latents.device} decoded={list(res[0].shape)} slicing={getattr(shared.sd_model.vae, "use_slicing", None)} tiling={getattr(shared.sd_model.vae, "use_tiling", None)} time={t1-t0:.3f}') + logger.log.debug(f'Decode: vae={shared.sd_model.vae.__class__.__name__} dtype={latents.dtype} latents={list(latents.shape)}:{latents.device} decoded={list(res[0].shape)} slicing={getattr(shared.sd_model.vae, "use_slicing", None)} tiling={getattr(shared.sd_model.vae, "use_tiling", None)} time={t1-t0:.3f}') except Exception: pass else: res = shared.sd_model.vae.orig_decode(*args, **kwargs) except Exception as e: - shared.log.error(f'Decode: vae={shared.sd_model.vae.__class__.__name__} {e}') + logger.log.error(f'Decode: vae={shared.sd_model.vae.__class__.__name__} {e}') errors.display(e, 'vae') res = None t1 = time.time() @@ -56,11 +57,11 @@ def hijack_vae_encode(*args, **kwargs): latents = args[0].to(device=devices.device, dtype=shared.sd_model.vae.dtype) # upcast to vae dtype res = shared.sd_model.vae.orig_encode(latents, *args[1:], **kwargs) t1 = time.time() - shared.log.debug(f'Encode: vae={shared.sd_model.vae.__class__.__name__} slicing={getattr(shared.sd_model.vae, "use_slicing", None)} tiling={getattr(shared.sd_model.vae, "use_tiling", None)} latents={list(latents.shape)}:{latents.device}:{latents.dtype} time={t1-t0:.3f}') + logger.log.debug(f'Encode: vae={shared.sd_model.vae.__class__.__name__} slicing={getattr(shared.sd_model.vae, "use_slicing", None)} tiling={getattr(shared.sd_model.vae, "use_tiling", None)} latents={list(latents.shape)}:{latents.device}:{latents.dtype} time={t1-t0:.3f}') else: res = shared.sd_model.vae.orig_encode(*args, **kwargs) except Exception as e: - shared.log.error(f'Encode: vae={shared.sd_model.vae.__class__.__name__} {e}') + logger.log.error(f'Encode: vae={shared.sd_model.vae.__class__.__name__} {e}') errors.display(e, 'vae') res = None t1 = time.time() diff --git a/modules/sd_models.py b/modules/sd_models.py index 6590ebf3c..7ddb276d0 100644 --- a/modules/sd_models.py +++ b/modules/sd_models.py @@ -10,8 +10,9 @@ import diffusers import diffusers.loaders.single_file_utils import torch import huggingface_hub as hf -from installer import log +from modules.logger import log from modules import timer, paths, shared, shared_items, modelloader, devices, script_callbacks, sd_vae, sd_unet, errors, sd_models_compile, sd_detect, model_quant, sd_hijack_te, sd_hijack_accelerate, sd_hijack_safetensors, attention +from modules import logger from modules.memstats import memory_stats from modules.modeldata import model_data from modules.sd_checkpoint import CheckpointInfo, select_checkpoint, list_models, checkpoint_titles, get_closest_checkpoint_match, update_model_hashes, write_metadata, checkpoints_list # pylint: disable=unused-import @@ -123,12 +124,12 @@ def set_vae_options(sd_model, vae=None, op:str='model', quiet:bool=False): ops['upcast'] = True sd_model.vqvae.to(torch.float32) # vqvae is producing nans in fp16 if not quiet and len(ops) > 0: - shared.log.quiet(quiet, f'Setting {op}: component=vae {ops}') + logger.log.quiet(quiet, f'Setting {op}: component=vae {ops}') def set_diffuser_options(sd_model, vae=None, op:str='model', offload:bool=True, quiet:bool=False): if sd_model is None: - shared.log.warning(f'{op} is not loaded') + logger.log.warning(f'{op} is not loaded') return if hasattr(sd_model, "watermark"): @@ -143,17 +144,17 @@ def set_diffuser_options(sd_model, vae=None, op:str='model', offload:bool=True, if shared.opts.diffusers_fuse_projections and hasattr(sd_model, 'fuse_qkv_projections'): try: sd_model.fuse_qkv_projections() - shared.log.quiet(quiet, f'Setting {op}: fused-qkv=True') + logger.log.quiet(quiet, f'Setting {op}: fused-qkv=True') except Exception as e: - shared.log.error(f'Setting {op}: fused-qkv=True {e}') + logger.log.error(f'Setting {op}: fused-qkv=True {e}') if shared.opts.diffusers_fuse_projections and hasattr(sd_model, 'transformer') and hasattr(sd_model.transformer, 'fuse_qkv_projections'): try: sd_model.transformer.fuse_qkv_projections() - shared.log.quiet(quiet, f'Setting {op}: fused-qkv=True') + logger.log.quiet(quiet, f'Setting {op}: fused-qkv=True') except Exception as e: - shared.log.error(f'Setting {op}: fused-qkv=True {e}') + logger.log.error(f'Setting {op}: fused-qkv=True {e}') if shared.opts.diffusers_eval: - shared.log.debug(f'Setting {op}: eval=True') + logger.log.debug(f'Setting {op}: eval=True') def eval_model(model, op=None, sd_model=None): # pylint: disable=unused-argument if hasattr(model, "requires_grad_"): model.requires_grad_(False) @@ -162,7 +163,7 @@ def set_diffuser_options(sd_model, vae=None, op:str='model', offload:bool=True, sd_model = apply_function_to_model(sd_model, eval_model, ["Model", "VAE", "TE"], op="eval") if shared.opts.opt_channelslast and hasattr(sd_model, 'unet'): - shared.log.quiet(quiet, f'Setting {op}: channels-last=True') + logger.log.quiet(quiet, f'Setting {op}: channels-last=True') sd_model.unet.to(memory_format=torch.channels_last) for module_name in get_module_names(sd_model): @@ -170,11 +171,11 @@ def set_diffuser_options(sd_model, vae=None, op:str='model', offload:bool=True, if hasattr(module, "quantization_config") and getattr(module.quantization_config, "quant_method", None) == "sdnq": from modules.sdnq.common import use_torch_compile as sdnq_use_torch_compile if shared.opts.sdnq_use_quantized_matmul and not sdnq_use_torch_compile: - shared.log.warning('SDNQ Quantized MatMul requires a working Triton install. Disabling Quantized MatMul.') + logger.log.warning('SDNQ Quantized MatMul requires a working Triton install. Disabling Quantized MatMul.') shared.opts.sdnq_use_quantized_matmul = False if module.quantization_config.use_quantized_matmul != shared.opts.sdnq_use_quantized_matmul: from modules.sdnq.loader import apply_sdnq_options_to_model - shared.log.debug(f'Setting {op} {module_name}: sdnq_use_quantized_matmul={shared.opts.sdnq_use_quantized_matmul}') + logger.log.debug(f'Setting {op} {module_name}: sdnq_use_quantized_matmul={shared.opts.sdnq_use_quantized_matmul}') module = apply_sdnq_options_to_model(module, use_quantized_matmul=shared.opts.sdnq_use_quantized_matmul) setattr(sd_model, module_name, module) @@ -198,7 +199,7 @@ def move_model(model, device=None, force=False): # module._hf_hook.offload = True except Exception as e: if os.environ.get('SD_MOVE_DEBUG', None): - shared.log.error(f'Model move execution device: device={device} {e}') + logger.log.error(f'Model move execution device: device={device} {e}') if model is None or device is None: return @@ -249,7 +250,7 @@ def move_model(model, device=None, force=False): except Exception as e2: if 'Cannot copy out of meta tensor' in str(e2): if os.environ.get('SD_MOVE_DEBUG', None): - shared.log.warning(f'Model move meta: module={module.__class__}') + logger.log.warning(f'Model move meta: module={module.__class__}') module.to_empty(device=device) elif 'enable_sequential_cpu_offload' in str(e0): pass # ignore model move if sequential offload is enabled @@ -264,12 +265,12 @@ def move_model(model, device=None, force=False): t1 = time.time() except Exception as e1: t1 = time.time() - shared.log.warning(f'Model move: device={device} {e1}') + logger.log.warning(f'Model move: device={device} {e1}') if 'move' not in timer.process.records: timer.process.records['move'] = 0 timer.process.records['move'] += t1 - t0 if os.environ.get('SD_MOVE_DEBUG', None) is not None or (t1-t0) > 2: - shared.log.debug(f'Model move: device={device} class={model.__class__.__name__} accelerate={getattr(model, "has_accelerate", False)} fn={fn} time={t1-t0:.2f}') # pylint: disable=protected-access + logger.log.debug(f'Model move: device={device} class={model.__class__.__name__} accelerate={getattr(model, "has_accelerate", False)} fn={fn} time={t1-t0:.2f}') # pylint: disable=protected-access devices.torch_gc() @@ -279,9 +280,9 @@ def move_base(model, device): elif hasattr(model, 'unet'): key = 'unet' else: - shared.log.warning(f'Model move: model={model.__class__} device={device} key=unknown') + logger.log.warning(f'Model move: model={model.__class__} device={device} key=unknown') return None - shared.log.debug(f'Model move: module={key} device={device}') + logger.log.debug(f'Model move: module={key} device={device}') model = getattr(model, key) R = model.device move_model(model, device) @@ -294,13 +295,13 @@ def load_diffuser_initial(diffusers_load_config, op='model'): ckpt_basename = os.path.basename(shared.cmd_opts.ckpt) model_name = modelloader.find_diffuser(ckpt_basename) if model_name is not None: - shared.log.info(f'Load model {op}: path="{model_name}"') + logger.log.info(f'Load model {op}: path="{model_name}"') model_file = modelloader.download_diffusers_model(hub_id=model_name, variant=diffusers_load_config.get('variant', None)) try: - shared.log.debug(f'Load {op}: config={diffusers_load_config}') + logger.log.debug(f'Load {op}: config={diffusers_load_config}') sd_model = diffusers.DiffusionPipeline.from_pretrained(model_file, **diffusers_load_config) except Exception as e: - shared.log.error(f'Failed loading model: {model_file} {e}') + logger.log.error(f'Failed loading model: {model_file} {e}') errors.display(e, f'Load {op}: path="{model_file}"') return None, None list_models() # rescan for downloaded model @@ -495,7 +496,7 @@ def load_diffuser_force(detected_model_type, checkpoint_info, diffusers_load_con sd_model = load_glm_image(checkpoint_info, diffusers_load_config) allow_post_quant = False except Exception as e: - shared.log.error(f'Load {op}: path="{checkpoint_info.path}" {e}') + logger.log.error(f'Load {op}: path="{checkpoint_info.path}" {e}') if debug_load: errors.display(e, 'Load') return None, True @@ -514,10 +515,10 @@ def load_diffuser_folder(model_type, pipeline, checkpoint_info, diffusers_load_c err0, err1, err2, err3 = None, None, None, None if os.path.exists(checkpoint_info.path) and os.path.isdir(checkpoint_info.path): if os.path.exists(os.path.join(checkpoint_info.path, 'unet', 'diffusion_pytorch_model.bin')): - shared.log.debug(f'Load {op}: type=pickle') + logger.log.debug(f'Load {op}: type=pickle') diffusers_load_config['use_safetensors'] = False if debug_load: - shared.log.debug(f'Load {op}: args={diffusers_load_config}') + logger.log.debug(f'Load {op}: args={diffusers_load_config}') try: #0 - using detected model type and pipeline if (model_type is not None) and (pipeline is not None): @@ -538,12 +539,12 @@ def load_diffuser_folder(model_type, pipeline, checkpoint_info, diffusers_load_c sd_model.model_type = sd_model.__class__.__name__ except ValueError as e: if 'no variant default' in str(e): - shared.log.warning(f'Load {op}: variant={diffusers_load_config["variant"]} model="{checkpoint_info.path}" using default variant') + logger.log.warning(f'Load {op}: variant={diffusers_load_config["variant"]} model="{checkpoint_info.path}" using default variant') diffusers_load_config.pop('variant', None) sd_model = diffusers.AutoPipelineForText2Image.from_pretrained(checkpoint_info.path, cache_dir=shared.opts.diffusers_dir, **diffusers_load_config) sd_model.model_type = sd_model.__class__.__name__ elif 'safetensors found in directory' in str(err1): - shared.log.warning(f'Load {op}: type=pickle') + logger.log.warning(f'Load {op}: type=pickle') diffusers_load_config['use_safetensors'] = False sd_model = diffusers.AutoPipelineForText2Image.from_pretrained(checkpoint_info.path, cache_dir=shared.opts.diffusers_dir, **diffusers_load_config) sd_model.model_type = sd_model.__class__.__name__ @@ -569,12 +570,12 @@ def load_diffuser_folder(model_type, pipeline, checkpoint_info, diffusers_load_c sd_model.model_type = sd_model.__class__.__name__ except Exception as e: err3 = e # ignore last error - shared.log.error(f"StableDiffusionPipeline: {e}") + logger.log.error(f"StableDiffusionPipeline: {e}") if debug_load: errors.display(e, "Load StableDiffusionPipeline") if err3 is not None: - shared.log.error(f'Load {op}: {checkpoint_info.path} detected={err0} auto={err1} diffusion={err2} base={err3}') + logger.log.error(f'Load {op}: {checkpoint_info.path} detected={err0} auto={err1} diffusion={err2} base={err3}') return None return sd_model @@ -584,7 +585,7 @@ def load_diffuser_file(model_type, pipeline, checkpoint_info, diffusers_load_con sd_model = None diffusers_load_config["extract_ema"] = shared.opts.diffusers_extract_ema if pipeline is None: - shared.log.error(f'Load {op}: pipeline={shared.opts.diffusers_pipeline} not initialized') + logger.log.error(f'Load {op}: pipeline={shared.opts.diffusers_pipeline} not initialized') return None try: if model_type.startswith('Stable Diffusion'): @@ -594,7 +595,7 @@ def load_diffuser_file(model_type, pipeline, checkpoint_info, diffusers_load_con model_config = sd_detect.get_load_config(checkpoint_info.path, model_type, config_type='json') if model_config is not None: if debug_load: - shared.log.debug(f'Load {op}: config="{model_config}"') + logger.log.debug(f'Load {op}: config="{model_config}"') diffusers_load_config['config'] = model_config if model_type.startswith('Stable Diffusion 3'): from pipelines.model_sd3 import load_sd3 @@ -614,23 +615,23 @@ def load_diffuser_file(model_type, pipeline, checkpoint_info, diffusers_load_con diffusers_load_config['cache_dir'] = shared.opts.hfcache_dir sd_model = pipeline.from_ckpt(checkpoint_info.path, **diffusers_load_config) else: - shared.log.error(f'Load {op}: file="{checkpoint_info.path}" {shared.opts.diffusers_pipeline} cannot load safetensor model') + logger.log.error(f'Load {op}: file="{checkpoint_info.path}" {shared.opts.diffusers_pipeline} cannot load safetensor model') return None if shared.opts.diffusers_vae_upcast != 'default' and model_type in ['Stable Diffusion', 'Stable Diffusion XL']: diffusers_load_config['force_upcast'] = True if shared.opts.diffusers_vae_upcast == 'true' else False # if debug_load: - # shared.log.debug(f'Model args: {diffusers_load_config}') + # logger.log.debug(f'Model args: {diffusers_load_config}') if sd_model is not None: diffusers_load_config.pop('vae', None) diffusers_load_config.pop('safety_checker', None) diffusers_load_config.pop('requires_safety_checker', None) diffusers_load_config.pop('config_files', None) diffusers_load_config.pop('local_files_only', None) - shared.log.debug(f'Setting {op}: pipeline={sd_model.__class__.__name__} config={diffusers_load_config}') # pylint: disable=protected-access + logger.log.debug(f'Setting {op}: pipeline={sd_model.__class__.__name__} config={diffusers_load_config}') # pylint: disable=protected-access except Exception as e: - shared.log.error(f'Load {op}: file="{checkpoint_info.path}" pipeline={shared.opts.diffusers_pipeline} config={diffusers_load_config} {e}') + logger.log.error(f'Load {op}: file="{checkpoint_info.path}" pipeline={shared.opts.diffusers_pipeline} config={diffusers_load_config} {e}') if 'Weights for this component appear to be missing in the checkpoint' in str(e): - shared.log.error(f'Load {op}: file="{checkpoint_info.path}" is not a complete model') + logger.log.error(f'Load {op}: file="{checkpoint_info.path}" is not a complete model') else: errors.display(e, 'Load') return None @@ -661,7 +662,7 @@ def load_sdnq_module(fn: str, module_name: str, load_method: str): t1 = time.time() return module, module_name, t1 - t0 except Exception as e: - shared.log.error(f'Load sdnq: model="{fn}" module="{module_name}" {e}') + logger.log.error(f'Load sdnq: model="{fn}" module="{module_name}" {e}') errors.display(e, 'Load') return None, module_name, 0 @@ -685,7 +686,7 @@ def load_sdnq_model(checkpoint_info, pipeline, diffusers_load_config, op): module, name, t = load_sdnq_module(checkpoint_info.path, module_name, load_method=load_method) if module is not None: modules[name] = module - shared.log.debug(f'Load {op}: module="{checkpoint_info.name}" module="{name}" direct={shared.opts.diffusers_to_gpu} prequant=sdnq method={load_method} time={t:.2f}') + logger.log.debug(f'Load {op}: module="{checkpoint_info.name}" module="{name}" direct={shared.opts.diffusers_to_gpu} prequant=sdnq method={load_method} time={t:.2f}') """ futures = [] @@ -697,11 +698,11 @@ def load_sdnq_model(checkpoint_info, pipeline, diffusers_load_config, op): for future in futures: loaded_module, name, t = future.result() if loaded_module is not None: - shared.log.debug(f'Load module: model="{checkpoint_info.name}" module="{name}" direct={shared.opts.diffusers_to_gpu} prequant=sdnq time={t:.2f}') + logger.log.debug(f'Load module: model="{checkpoint_info.name}" module="{name}" direct={shared.opts.diffusers_to_gpu} prequant=sdnq time={t:.2f}') modules[name] = loaded_module """ t1 = time.time() - shared.log.debug(f'Load {op}: model="{checkpoint_info.name}" modules={list(modules.keys())} prequant=sdnq time={t1-t0:.2f}') + logger.log.debug(f'Load {op}: model="{checkpoint_info.name}" modules={list(modules.keys())} prequant=sdnq time={t1-t0:.2f}') sd_model = pipeline.from_pretrained( checkpoint_info.path, cache_dir=shared.opts.diffusers_dir, @@ -730,14 +731,14 @@ def set_overrides(sd_model, checkpoint_info, model_type): scheduler_config['use_flow_sigmas'] = True scheduler_config["flow_shift"] = 2.5 sd_model.scheduler = diffusers.UniPCMultistepScheduler.from_config(scheduler_config) - shared.log.info(f'Setting override: model="{checkpoint_info.name}" component=scheduler prediction="flow-prediction"') + logger.log.info(f'Setting override: model="{checkpoint_info.name}" component=scheduler prediction="flow-prediction"') elif 'vpred' in checkpoint_info_name or 'v-pred' in checkpoint_info_name or 'v_pred' in checkpoint_info_name: scheduler_config = sd_model.scheduler.config scheduler_config['prediction_type'] = 'v_prediction' scheduler_config['beta_schedule'] = 'scaled_linear' scheduler_config['rescale_betas_zero_snr'] = True sd_model.scheduler = diffusers.EulerAncestralDiscreteScheduler.from_config(scheduler_config) - shared.log.info(f'Setting override: model="{checkpoint_info.name}" component=scheduler prediction="v-prediction" rescale=True') + logger.log.info(f'Setting override: model="{checkpoint_info.name}" component=scheduler prediction="v-prediction" rescale=True') else: try: from safetensors import safe_open @@ -750,9 +751,9 @@ def set_overrides(sd_model, checkpoint_info, model_type): if 'ztsnr' in keys: scheduler_config['rescale_betas_zero_snr'] = True sd_model.scheduler = diffusers.EulerAncestralDiscreteScheduler.from_config(scheduler_config) - shared.log.info(f'Setting override: model="{checkpoint_info.name}" component=scheduler prediction="v-prediction" rescale={scheduler_config.get("rescale_betas_zero_snr", False)}') + logger.log.info(f'Setting override: model="{checkpoint_info.name}" component=scheduler prediction="v-prediction" rescale={scheduler_config.get("rescale_betas_zero_snr", False)}') except Exception as e: - shared.log.debug(f'Setting override from keys failed: {e}') + logger.log.debug(f'Setting override from keys failed: {e}') def set_defaults(sd_model, checkpoint_info): @@ -790,7 +791,7 @@ def load_diffuser(checkpoint_info=None, op='model', revision=None): # pylint: di if shared.opts.diffusers_model_load_variant != 'default': diffusers_load_config['variant'] = shared.opts.diffusers_model_load_variant if shared.opts.diffusers_pipeline == 'Custom Diffusers Pipeline' and len(shared.opts.custom_diffusers_pipeline) > 0: - shared.log.debug(f'Model pipeline: pipeline="{shared.opts.custom_diffusers_pipeline}"') + logger.log.debug(f'Model pipeline: pipeline="{shared.opts.custom_diffusers_pipeline}"') diffusers_load_config['custom_pipeline'] = shared.opts.custom_diffusers_pipeline if shared.opts.data.get('sd_model_checkpoint', '') == 'model.safetensors' or shared.opts.data.get('sd_model_checkpoint', '') == '': shared.opts.data['sd_model_checkpoint'] = "stabilityai/stable-diffusion-xl-base-1.0" @@ -818,7 +819,7 @@ def load_diffuser(checkpoint_info=None, op='model', revision=None): # pylint: di # handle offline mode if shared.opts.offline_mode: - shared.log.info(f'Load {op}: offline=True') + logger.log.info(f'Load {op}: offline=True') diffusers_load_config["local_files_only"] = True os.environ['HF_HUB_OFFLINE'] = '1' else: @@ -833,7 +834,7 @@ def load_diffuser(checkpoint_info=None, op='model', revision=None): # pylint: di vae = None sd_vae.loaded_vae_file = None if model_type is None: - shared.log.error(f'Load {op}: pipeline={shared.opts.diffusers_pipeline} not detected') + logger.log.error(f'Load {op}: pipeline={shared.opts.diffusers_pipeline} not detected') return vae_file = None if model_type.startswith('Stable Diffusion') and (op == 'model' or op == 'refiner'): # preload vae for sd models @@ -847,7 +848,7 @@ def load_diffuser(checkpoint_info=None, op='model', revision=None): # pylint: di if sd_model is None and not handled: sd_model, handled = load_diffuser_force(model_type, checkpoint_info, diffusers_load_config, op) if sd_model is not None and not sd_model: - shared.log.error(f'Load {op}: type="{model_type}" pipeline="{pipeline}" not loaded') + logger.log.error(f'Load {op}: type="{model_type}" pipeline="{pipeline}" not loaded') return # load sdnq-prequantized model @@ -867,7 +868,7 @@ def load_diffuser(checkpoint_info=None, op='model', revision=None): # pylint: di sd_model = load_diffuser_folder(model_type, pipeline, checkpoint_info, diffusers_load_config, op) if sd_model is None: - shared.log.error(f'Load {op}: name="{checkpoint_info.name if checkpoint_info is not None else None}" not loaded') + logger.log.error(f'Load {op}: name="{checkpoint_info.name if checkpoint_info is not None else None}" not loaded') return set_overrides(sd_model, checkpoint_info, model_type) @@ -889,7 +890,7 @@ def load_diffuser(checkpoint_info=None, op='model', revision=None): # pylint: di timer.load.record("te") if debug_load: - shared.log.trace(f'Model components: {list(get_signature(sd_model).values())}') + logger.log.trace(f'Model components: {list(get_signature(sd_model).values())}') from modules import textual_inversion sd_model.embedding_db = textual_inversion.EmbeddingDatabase() @@ -911,7 +912,7 @@ def load_diffuser(checkpoint_info=None, op='model', revision=None): # pylint: di if getattr(shared.sd_model, 'sd_checkpoint_info', None) is not None and vae_file is not None: sd_vae.apply_vae_config(shared.sd_model.sd_checkpoint_info.filename, vae_file, sd_model) if op == 'refiner' and shared.opts.diffusers_move_refiner: - shared.log.debug('Moving refiner model to CPU') + logger.log.debug('Moving refiner model to CPU') move_model(sd_model, devices.cpu) else: move_model(sd_model, devices.device) @@ -925,7 +926,7 @@ def load_diffuser(checkpoint_info=None, op='model', revision=None): # pylint: di timer.load.record("compile") except Exception as e: - shared.log.error(f"Load {op}: {e}") + logger.log.error(f"Load {op}: {e}") errors.display(e, "Model") if shared.opts.diffusers_offload_mode != 'balanced': @@ -937,7 +938,7 @@ def load_diffuser(checkpoint_info=None, op='model', revision=None): # pylint: di from modules import modelstats modelstats.analyze() - shared.log.info(f"Load {op}: family={shared.sd_model_type} time={timer.load.dct()} native={get_native(sd_model)} memory={memory_stats()}") + logger.log.info(f"Load {op}: family={shared.sd_model_type} time={timer.load.dct()} native={get_native(sd_model)} memory={memory_stats()}") shared.opts.save(silent=True) @@ -980,7 +981,7 @@ def switch_pipe(cls: type[diffusers.DiffusionPipeline] | str, pipeline: diffuser if args is None: args = {} if isinstance(cls, str): - shared.log.debug(f'Pipeline switch: custom={cls}') + logger.log.debug(f'Pipeline switch: custom={cls}') cls_object = diffusers.utils.get_class_from_dynamic_module(cls, module_file='pipeline.py') if not cls_object: log.error(f"Pipeline switch: Failed to get class for '{cls}'") @@ -1016,7 +1017,7 @@ def switch_pipe(cls: type[diffusers.DiffusionPipeline] | str, pipeline: diffuser if signature[item].default != inspect._empty: # has default value so we dont have to worry about it # pylint: disable=protected-access continue if item not in components_used: - shared.log.warning(f'Pipeling switch: missing component={item} type={signature[item].annotation}') + logger.log.warning(f'Pipeling switch: missing component={item} type={signature[item].annotation}') pipe_dict[item] = None # try but not likely to work components_missing.append(item) new_pipe = cls_object(**pipe_dict) @@ -1048,7 +1049,7 @@ def switch_pipe(cls: type[diffusers.DiffusionPipeline] | str, pipeline: diffuser move_model(new_pipe, pipeline.device) switch_mode = 'sd' else: - shared.log.error(f'Pipeline switch error: {pipeline.__class__.__name__} unrecognized') + logger.log.error(f'Pipeline switch error: {pipeline.__class__.__name__} unrecognized') return pipeline if new_pipe is not None: for k, v in args.items(): @@ -1056,7 +1057,7 @@ def switch_pipe(cls: type[diffusers.DiffusionPipeline] | str, pipeline: diffuser setattr(new_pipe, k, v) components_used.append(k) else: - shared.log.warning(f'Pipeline switch skipping unknown: component={k}') + logger.log.warning(f'Pipeline switch skipping unknown: component={k}') components_skipped.append(k) if new_pipe is not None: copy_diffuser_options(new_pipe, pipeline) @@ -1064,14 +1065,14 @@ def switch_pipe(cls: type[diffusers.DiffusionPipeline] | str, pipeline: diffuser if hasattr(new_pipe, "watermark"): new_pipe.watermark = NoWatermark() if switch_mode == 'auto': - shared.log.debug(f'Pipeline switch: from={pipeline.__class__.__name__} to={new_pipe.__class__.__name__} components={components_used} skipped={components_skipped} missing={components_missing}') + logger.log.debug(f'Pipeline switch: from={pipeline.__class__.__name__} to={new_pipe.__class__.__name__} components={components_used} skipped={components_skipped} missing={components_missing}') else: - shared.log.debug(f'Pipeline switch: from={pipeline.__class__.__name__} to={new_pipe.__class__.__name__} mode={switch_mode}') + logger.log.debug(f'Pipeline switch: from={pipeline.__class__.__name__} to={new_pipe.__class__.__name__} mode={switch_mode}') return new_pipe else: - shared.log.error(f'Pipeline switch error: from={pipeline.__class__.__name__} to={cls_object.__name__} empty pipeline') + logger.log.error(f'Pipeline switch error: from={pipeline.__class__.__name__} to={cls_object.__name__} empty pipeline') except Exception as e: - shared.log.error(f'Pipeline switch error: from={pipeline.__class__.__name__} to={cls if isinstance(cls, str) else cls.__name__} {e}') + logger.log.error(f'Pipeline switch error: from={pipeline.__class__.__name__} to={cls if isinstance(cls, str) else cls.__name__} {e}') errors.display(e, 'Pipeline switch') return pipeline @@ -1200,12 +1201,12 @@ def set_diffuser_pipe(pipe, new_pipe_type): elif new_pipe_type == DiffusersTaskType.INPAINTING: new_pipe = diffusers.AutoPipelineForInpainting.from_pipe(pipe) else: - shared.log.warning(f'Pipeline class change failed: type={new_pipe_type} pipeline={cls}') + logger.log.warning(f'Pipeline class change failed: type={new_pipe_type} pipeline={cls}') return pipe except Exception as e: # pylint: disable=unused-variable fn = f'{sys._getframe(2).f_code.co_name}:{sys._getframe(1).f_code.co_name}' # pylint: disable=protected-access - shared.log.trace(f"Pipeline class change requested: target={new_pipe_type} fn={fn}") # pylint: disable=protected-access - shared.log.warning(f'Pipeline class change failed: type={new_pipe_type} pipeline={cls} {e}') + logger.log.trace(f"Pipeline class change requested: target={new_pipe_type} fn={fn}") # pylint: disable=protected-access + logger.log.warning(f'Pipeline class change failed: type={new_pipe_type} pipeline={cls} {e}') has_errors = True if not hasattr(pipe, 'config') or has_errors: try: # maybe a wrapper pipeline so just change the class @@ -1219,10 +1220,10 @@ def set_diffuser_pipe(pipe, new_pipe_type): pipe.__class__ = diffusers.pipelines.auto_pipeline._get_task_class(diffusers.pipelines.auto_pipeline.AUTO_INPAINT_PIPELINES_MAPPING, cls) # pylint: disable=protected-access new_pipe = pipe else: - shared.log.error(f'Pipeline class set failed: type={new_pipe_type} pipeline={cls}') + logger.log.error(f'Pipeline class set failed: type={new_pipe_type} pipeline={cls}') return pipe except Exception as e: # pylint: disable=unused-variable - shared.log.warning(f'Pipeline class set failed: type={new_pipe_type} pipeline={cls} {e}') + logger.log.warning(f'Pipeline class set failed: type={new_pipe_type} pipeline={cls} {e}') has_errors = True return pipe @@ -1244,7 +1245,7 @@ def set_diffuser_pipe(pipe, new_pipe_type): add_noise_pred_to_diffusers_callback(new_pipe.pipe) fn = f'{sys._getframe(2).f_code.co_name}:{sys._getframe(1).f_code.co_name}' # pylint: disable=protected-access - shared.log.debug(f"Pipeline class change: original={cls} target={new_pipe.__class__.__name__} device={pipe.device} fn={fn}") # pylint: disable=protected-access + logger.log.debug(f"Pipeline class change: original={cls} target={new_pipe.__class__.__name__} device={pipe.device} fn={fn}") # pylint: disable=protected-access if shared.opts.diffusers_offload_mode == 'none': move_model(new_pipe, pipe.device) @@ -1298,11 +1299,11 @@ def reload_text_encoder(initial=False): set_clip(pipe=shared.sd_model) elif len(t5) > 0: from modules.model_te import set_t5 - shared.log.debug(f'Load module: type=t5 path="{shared.opts.sd_text_encoder}" module="{t5[0]}"') + logger.log.debug(f'Load module: type=t5 path="{shared.opts.sd_text_encoder}" module="{t5[0]}"') set_t5(pipe=shared.sd_model, module=t5[0], t5=shared.opts.sd_text_encoder, cache_dir=shared.opts.diffusers_dir) elif hasattr(shared.sd_model, 'text_encoder_3'): from modules.model_te import set_t5 - shared.log.debug(f'Load module: type=t5 path="{shared.opts.sd_text_encoder}" module="text_encoder_3"') + logger.log.debug(f'Load module: type=t5 path="{shared.opts.sd_text_encoder}" module="text_encoder_3"') set_t5(pipe=shared.sd_model, module='text_encoder_3', t5=shared.opts.sd_text_encoder, cache_dir=shared.opts.diffusers_dir) clear_caches(full=True) apply_balanced_offload(shared.sd_model) @@ -1353,7 +1354,7 @@ def clear_caches(full:bool=False): lora_common.previously_loaded_networks.clear() lora_load.lora_cache.clear() if full: - shared.log.debug('Cache clear') + logger.log.debug('Cache clear') sd_offload.offload_hook_instance = None @@ -1365,25 +1366,25 @@ def unload_model_weights(op='model'): shared.compiled_model_state.req_cache.clear() shared.compiled_model_state.partitioned_modules.clear() if (op == 'model' or op == 'dict') and model_data.sd_model: - shared.log.debug(f'Current {op}: {memory_stats()}') + logger.log.debug(f'Current {op}: {memory_stats()}') if not ('Model' in shared.opts.cuda_compile and shared.opts.cuda_compile_backend == "openvino_fx"): disable_offload(model_data.sd_model) move_model(model_data.sd_model, 'meta') model_data.sd_model = None devices.torch_gc(force=True, reason='unload') - shared.log.debug(f'Unload {op}: {memory_stats()} fn={fn}') + logger.log.debug(f'Unload {op}: {memory_stats()} fn={fn}') elif (op == 'refiner') and model_data.sd_refiner: - shared.log.debug(f'Current {op}: {memory_stats()}') + logger.log.debug(f'Current {op}: {memory_stats()}') disable_offload(model_data.sd_refiner) move_model(model_data.sd_refiner, 'meta') model_data.sd_refiner = None devices.torch_gc(force=True, reason='unload') - shared.log.debug(f'Unload {op}: {memory_stats()} fn={fn}') + logger.log.debug(f'Unload {op}: {memory_stats()} fn={fn}') def hf_auth_check(checkpoint_info, force:bool=False): if shared.opts.offline_mode: - shared.log.info('Offline mode: skipping auth check') + logger.log.info('Offline mode: skipping auth check') return False login = None if not force: @@ -1399,23 +1400,23 @@ 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'Auth: repo="{repo_id}" login={login} {e}') + logger.log.error(f'Auth: repo="{repo_id}" login={login} {e}') return False def save_model(name: str, path: str = None, shard: str = None, overwrite: bool = False): if (name is None) or len(name.strip()) == 0: - shared.log.error('Save model: invalid model name') + logger.log.error('Save model: invalid model name') return 'Invalid model name' if not shared.sd_loaded: - shared.log.error('Save model: model not loaded') + logger.log.error('Save model: model not loaded') return 'Model not loaded' from modules.sdnq import save_sdnq_model if path is None: path = shared.opts.diffusers_dir model_name = os.path.join(path.strip(), name.strip()) if os.path.exists(model_name) and not overwrite: - shared.log.error(f'Save model: path="{model_name}" exists') + logger.log.error(f'Save model: path="{model_name}" exists') return f'Path exists: {model_name}' try: t0 = time.time() @@ -1426,9 +1427,9 @@ def save_model(name: str, path: str = None, shard: str = None, overwrite: bool = is_pipeline=True, ) t1 = time.time() - shared.log.info(f'Save model: path="{model_name}" cls={shared.sd_model.__class__.__name__} time={t1 - t0:.2f}') + logger.log.info(f'Save model: path="{model_name}" cls={shared.sd_model.__class__.__name__} time={t1 - t0:.2f}') return f'Saved: {model_name}' except Exception as e: - shared.log.error(f'Save model: path="{model_name}" {e}') + logger.log.error(f'Save model: path="{model_name}" {e}') errors.display(e, 'Save model') return f'Error: {e}' diff --git a/modules/sd_models_compile.py b/modules/sd_models_compile.py index 564a64556..d9b8c7a4a 100644 --- a/modules/sd_models_compile.py +++ b/modules/sd_models_compile.py @@ -2,6 +2,7 @@ import time import logging import torch from modules import shared, devices, sd_models, errors +from modules import logger from installer import setup_logging @@ -57,9 +58,9 @@ def ipex_optimize(sd_model, apply_to_components=True, op="Model"): sd_model = ipex_optimize_model(sd_model, op=op) t1 = time.time() - shared.log.info(f"{op} IPEX Optimize: time={t1-t0:.2f}") + logger.log.info(f"{op} IPEX Optimize: time={t1-t0:.2f}") except Exception as e: - shared.log.warning(f"{op} IPEX Optimize: error: {e}") + logger.log.warning(f"{op} IPEX Optimize: error: {e}") return sd_model @@ -77,7 +78,7 @@ def optimize_openvino(sd_model, clear_cache=True): shared.compiled_model_state.first_pass_refiner = 'precompile' not in shared.opts.cuda_compile_options sd_models.set_accelerate(sd_model) except Exception as e: - shared.log.warning(f"Model compile: task=OpenVINO: {e}") + logger.log.warning(f"Model compile: task=OpenVINO: {e}") return sd_model @@ -86,7 +87,7 @@ def compile_onediff(sd_model): from onediff.infer_compiler import oneflow_compile except Exception as e: - shared.log.warning(f"Model compile: task=onediff {e}") + logger.log.warning(f"Model compile: task=onediff {e}") return sd_model try: @@ -106,12 +107,12 @@ def compile_onediff(sd_model): # as it was for sfast. setup_logging() # compile messes with logging so reset is needed if 'precompile' in shared.opts.cuda_compile_options: - shared.log.debug("Model compile: task=onediff precompile") + logger.log.debug("Model compile: task=onediff precompile") sd_model("dummy prompt") t1 = time.time() - shared.log.info(f"Model compile: task=onediff time={t1-t0:.2f}") + logger.log.info(f"Model compile: task=onediff time={t1-t0:.2f}") except Exception as e: - shared.log.info(f"Model compile: task=onediff {e}") + logger.log.info(f"Model compile: task=onediff {e}") return sd_model @@ -119,7 +120,7 @@ def compile_stablefast(sd_model): try: import sfast.compilers.stable_diffusion_pipeline_compiler as sf except Exception as e: - shared.log.warning(f'Model compile: task=stablefast: {e}') + logger.log.warning(f'Model compile: task=stablefast: {e}') return sd_model config = sf.CompilationConfig.Default() try: @@ -144,12 +145,12 @@ def compile_stablefast(sd_model): sd_model.sfast = True setup_logging() # compile messes with logging so reset is needed if 'precompile' in shared.opts.cuda_compile_options: - shared.log.debug("Model compile: task=stablefast precompile") + logger.log.debug("Model compile: task=stablefast precompile") sd_model("dummy prompt") t1 = time.time() - shared.log.info(f"Model compile: task=stablefast config={config.__dict__} time={t1-t0:.2f}") + logger.log.info(f"Model compile: task=stablefast config={config.__dict__} time={t1-t0:.2f}") except Exception as e: - shared.log.info(f"Model compile: task=stablefast {e}") + logger.log.info(f"Model compile: task=stablefast {e}") return sd_model @@ -158,7 +159,7 @@ def compile_torch(sd_model, apply_to_components=True, op="Model"): t0 = time.time() import torch._dynamo # pylint: disable=unused-import,redefined-outer-name torch._dynamo.reset() # pylint: disable=protected-access - shared.log.debug(f"{op} compile: task=torch backends={torch._dynamo.list_backends()}") # pylint: disable=protected-access + logger.log.debug(f"{op} compile: task=torch backends={torch._dynamo.list_backends()}") # pylint: disable=protected-access def torch_compile_model(model, op=None, sd_model=None): # pylint: disable=unused-argument if hasattr(model, 'compile_repeated_blocks') and 'repeated' in shared.opts.cuda_compile_options: @@ -208,7 +209,7 @@ def compile_torch(sd_model, apply_to_components=True, op="Model"): torch._inductor.config.use_mixed_mm = True # pylint: disable=protected-access # torch._inductor.config.force_fuse_int_mm_with_mul = True # pylint: disable=protected-access except Exception as e: - shared.log.error(f"{op} compile: torch inductor config error: {e}") + logger.log.error(f"{op} compile: torch inductor config error: {e}") if apply_to_components: sd_model = sd_models.apply_function_to_model(sd_model, function=torch_compile_model, options=shared.opts.cuda_compile, op="compile") @@ -218,14 +219,14 @@ def compile_torch(sd_model, apply_to_components=True, op="Model"): setup_logging() # compile messes with logging so reset is needed if apply_to_components and 'precompile' in shared.opts.cuda_compile_options: try: - shared.log.debug(f"{op} compile: task=torch precompile") + logger.log.debug(f"{op} compile: task=torch precompile") sd_model("dummy prompt") except Exception: pass t1 = time.time() - shared.log.info(f"{op} compile: task=torch time={t1-t0:.2f}") + logger.log.info(f"{op} compile: task=torch time={t1-t0:.2f}") except Exception as e: - shared.log.warning(f"{op} compile: task=torch {e}") + logger.log.warning(f"{op} compile: task=torch {e}") errors.display(e, 'Compile') return sd_model @@ -241,28 +242,28 @@ def check_deepcache(enable: bool): def compile_deepcache(sd_model): global deepcache_worker # pylint: disable=global-statement if not hasattr(sd_model, 'unet'): - shared.log.warning(f'Model compile: task=deepcache pipeline={sd_model.__class__} not supported') + logger.log.warning(f'Model compile: task=deepcache pipeline={sd_model.__class__} not supported') return sd_model try: from DeepCache import DeepCacheSDHelper except Exception as e: - shared.log.warning(f'Model compile: task=deepcache {e}') + logger.log.warning(f'Model compile: task=deepcache {e}') return sd_model t0 = time.time() check_deepcache(False) deepcache_worker = DeepCacheSDHelper(pipe=sd_model) deepcache_worker.set_params(cache_interval=shared.opts.deep_cache_interval, cache_branch_id=0) t1 = time.time() - shared.log.info(f"Model compile: task=deepcache config={deepcache_worker.params} time={t1-t0:.2f}") + logger.log.info(f"Model compile: task=deepcache config={deepcache_worker.params} time={t1-t0:.2f}") # config={'cache_interval': 3, 'cache_layer_id': 0, 'cache_block_id': 0, 'skip_mode': 'uniform'} time=0.00 return sd_model def compile_diffusers(sd_model, apply_to_components=True, op="Model"): if shared.opts.cuda_compile_backend == 'none': - shared.log.warning(f'{op} compile enabled but no backend specified') + logger.log.warning(f'{op} compile enabled but no backend specified') return sd_model - shared.log.info(f"{op} compile: pipeline={sd_model.__class__.__name__} mode={shared.opts.cuda_compile_mode} backend={shared.opts.cuda_compile_backend} options={shared.opts.cuda_compile_options} compile={shared.opts.cuda_compile}") + logger.log.info(f"{op} compile: pipeline={sd_model.__class__.__name__} mode={shared.opts.cuda_compile_mode} backend={shared.opts.cuda_compile_backend} options={shared.opts.cuda_compile_options} compile={shared.opts.cuda_compile}") if shared.opts.cuda_compile_backend == 'onediff': sd_model = compile_onediff(sd_model) elif shared.opts.cuda_compile_backend == 'stable-fast': @@ -297,16 +298,16 @@ def openvino_recompile_model(p, hires=False, refiner=False): # recompile if a pa ) )): if refiner: - shared.log.info("OpenVINO: Recompiling refiner") + logger.log.info("OpenVINO: Recompiling refiner") sd_models.unload_model_weights(op='refiner') sd_models.reload_model_weights(op='refiner') else: - shared.log.info("OpenVINO: Recompiling base model") + logger.log.info("OpenVINO: Recompiling base model") sd_models.unload_model_weights(op='model') sd_models.reload_model_weights(op='model') """ if shared.compiled_model_state is None: - shared.log.warning("OpenVINO: Compile Model State is not found, model is not compiled!") + logger.log.warning("OpenVINO: Compile Model State is not found, model is not compiled!") else: shared.compiled_model_state.height = compile_height shared.compiled_model_state.width = compile_width diff --git a/modules/sd_models_utils.py b/modules/sd_models_utils.py index f766270b7..71410448b 100644 --- a/modules/sd_models_utils.py +++ b/modules/sd_models_utils.py @@ -8,6 +8,7 @@ import torch import safetensors.torch from modules import paths, shared, errors +from modules import logger from modules.sd_checkpoint import CheckpointInfo # pylint: disable=unused-import @@ -44,7 +45,7 @@ def path_to_repo(checkpoint_info): repo_id = repo_id.split('models--')[-1] repo_id = repo_id.replace('--', '/') if repo_id.count('/') != 1: - shared.log.warning(f'Model: repo="{repo_id}" repository not recognized') + logger.log.warning(f'Model: repo="{repo_id}" repository not recognized') if '+' in repo_id: repo_id = repo_id.split('+')[0] return repo_id @@ -63,14 +64,14 @@ def convert_to_faketensors(tensor): def read_state_dict(checkpoint_file, map_location=None, what:str='model'): # pylint: disable=unused-argument if not os.path.isfile(checkpoint_file): - shared.log.error(f'Load dict: path="{checkpoint_file}" not a file') + logger.log.error(f'Load dict: path="{checkpoint_file}" not a file') return None try: pl_sd = None - with progress.open(checkpoint_file, 'rb', description=f'[cyan]Load {what}: [yellow]{checkpoint_file}', auto_refresh=True, console=shared.console) as f: + with progress.open(checkpoint_file, 'rb', description=f'[cyan]Load {what}: [yellow]{checkpoint_file}', auto_refresh=True, console=logger.console) as f: _, extension = os.path.splitext(checkpoint_file) if extension.lower() == ".ckpt" and shared.opts.sd_disable_ckpt: - shared.log.warning(f"Checkpoint loading disabled: {checkpoint_file}") + logger.log.warning(f"Checkpoint loading disabled: {checkpoint_file}") return None if shared.opts.stream_load: if extension.lower() == ".safetensors": diff --git a/modules/sd_offload.py b/modules/sd_offload.py index d0efd5d47..a38946455 100644 --- a/modules/sd_offload.py +++ b/modules/sd_offload.py @@ -6,8 +6,9 @@ import inspect import torch import accelerate.hooks import accelerate.utils.modeling -from installer import log +from modules.logger import log from modules import shared, devices, errors, model_quant, sd_models +from modules import logger from modules.timer import process as process_timer @@ -51,7 +52,7 @@ def disable_offload(sd_model): try: module = accelerate.hooks.remove_hook_from_module(module, recurse=True) except Exception as e: - shared.log.warning(f'Offload remove hook: module={module_name} {e}') + logger.log.warning(f'Offload remove hook: module={module_name} {e}') if network_layer_name: module.network_layer_name = network_layer_name sd_model.has_accelerate = False @@ -87,40 +88,40 @@ def apply_group_offload(sd_model, op:str='model'): } if shared.opts.group_offload_type == 'block_level': offload_dct['exclude_modules'] = ['vae'] - shared.log.debug(f'Setting {op}: offload={shared.opts.diffusers_offload_mode} options={offload_dct}') + logger.log.debug(f'Setting {op}: offload={shared.opts.diffusers_offload_mode} options={offload_dct}') if hasattr(sd_model, "enable_group_offload"): sd_model.enable_group_offload(**offload_dct) else: - shared.log.warning(f'Setting {op}: offload={shared.opts.diffusers_offload_mode} not supported') + logger.log.warning(f'Setting {op}: offload={shared.opts.diffusers_offload_mode} not supported') set_accelerate(sd_model) return sd_model def apply_model_offload(sd_model, op:str='model', quiet:bool=False): try: - shared.log.quiet(quiet, f'Setting {op}: offload={shared.opts.diffusers_offload_mode} limit={shared.opts.cuda_mem_fraction}') + logger.log.quiet(quiet, f'Setting {op}: offload={shared.opts.diffusers_offload_mode} limit={shared.opts.cuda_mem_fraction}') if shared.opts.diffusers_move_base or shared.opts.diffusers_move_unet or shared.opts.diffusers_move_refiner: shared.opts.diffusers_move_base = False shared.opts.diffusers_move_unet = False shared.opts.diffusers_move_refiner = False - shared.log.warning(f'Disabling {op} "Move model to CPU" since "Model CPU offload" is enabled') + logger.log.warning(f'Disabling {op} "Move model to CPU" since "Model CPU offload" is enabled') if not hasattr(sd_model, "_all_hooks") or len(sd_model._all_hooks) == 0: # pylint: disable=protected-access sd_model.enable_model_cpu_offload(device=devices.device) else: sd_model.maybe_free_model_hooks() set_accelerate(sd_model) except Exception as e: - shared.log.error(f'Setting {op}: offload={shared.opts.diffusers_offload_mode} {e}') + logger.log.error(f'Setting {op}: offload={shared.opts.diffusers_offload_mode} {e}') def apply_sequential_offload(sd_model, op:str='model', quiet:bool=False): try: - shared.log.quiet(quiet, f'Setting {op}: offload={shared.opts.diffusers_offload_mode} limit={shared.opts.cuda_mem_fraction}') + logger.log.quiet(quiet, f'Setting {op}: offload={shared.opts.diffusers_offload_mode} limit={shared.opts.cuda_mem_fraction}') if shared.opts.diffusers_move_base or shared.opts.diffusers_move_unet or shared.opts.diffusers_move_refiner: shared.opts.diffusers_move_base = False shared.opts.diffusers_move_unet = False shared.opts.diffusers_move_refiner = False - shared.log.warning(f'Disabling {op} "Move model to CPU" since "Sequential CPU offload" is enabled') + logger.log.warning(f'Disabling {op} "Move model to CPU" since "Sequential CPU offload" is enabled') if sd_model.has_accelerate: if op == "vae": # reapply sequential offload to vae from accelerate import cpu_offload @@ -132,14 +133,14 @@ def apply_sequential_offload(sd_model, op:str='model', quiet:bool=False): sd_model.enable_sequential_cpu_offload(device=devices.device) set_accelerate(sd_model) except Exception as e: - shared.log.error(f'Setting {op}: offload={shared.opts.diffusers_offload_mode} {e}') + logger.log.error(f'Setting {op}: offload={shared.opts.diffusers_offload_mode} {e}') def apply_none_offload(sd_model, op:str='model', quiet:bool=False): if shared.sd_model_type not in offload_allow_none: - shared.log.warning(f'Setting {op}: offload={shared.opts.diffusers_offload_mode} type={shared.sd_model.__class__.__name__} large model') + logger.log.warning(f'Setting {op}: offload={shared.opts.diffusers_offload_mode} type={shared.sd_model.__class__.__name__} large model') else: - shared.log.quiet(quiet, f'Setting {op}: offload={shared.opts.diffusers_offload_mode} limit={shared.opts.cuda_mem_fraction}') + logger.log.quiet(quiet, f'Setting {op}: offload={shared.opts.diffusers_offload_mode} limit={shared.opts.cuda_mem_fraction}') try: sd_model.has_accelerate = False if hasattr(sd_model, 'maybe_free_model_hooks'): @@ -154,7 +155,7 @@ def set_diffuser_offload(sd_model, op:str='model', quiet:bool=False, force:bool= global accelerate_dtype_byte_size # pylint: disable=global-statement t0 = time.time() if sd_model is None: - shared.log.warning(f'{op} is not loaded') + logger.log.warning(f'{op} is not loaded') return if not (hasattr(sd_model, "has_accelerate") and sd_model.has_accelerate): sd_model.has_accelerate = False @@ -200,7 +201,7 @@ class OffloadHook(accelerate.hooks.ModelHook): self.last_post = None self.last_cls = None gpu = f'{(shared.gpu_memory * shared.opts.diffusers_offload_min_gpu_memory):.2f}-{(shared.gpu_memory * shared.opts.diffusers_offload_max_gpu_memory):.2f}:{shared.gpu_memory:.2f}' - shared.log.info(f'Offload: type=balanced op=init watermark={self.min_watermark}-{self.max_watermark} gpu={gpu} cpu={shared.cpu_memory:.3f} limit={shared.opts.cuda_mem_fraction:.2f} always={self.offload_always} never={self.offload_never} pre={shared.opts.diffusers_offload_pre} streams={shared.opts.diffusers_offload_streams}') + logger.log.info(f'Offload: type=balanced op=init watermark={self.min_watermark}-{self.max_watermark} gpu={gpu} cpu={shared.cpu_memory:.3f} limit={shared.opts.cuda_mem_fraction:.2f} always={self.offload_always} never={self.offload_never} pre={shared.opts.diffusers_offload_pre} streams={shared.opts.diffusers_offload_streams}') self.validate() super().__init__() @@ -209,15 +210,15 @@ class OffloadHook(accelerate.hooks.ModelHook): return if shared.opts.diffusers_offload_min_gpu_memory < 0 or shared.opts.diffusers_offload_min_gpu_memory > 1: shared.opts.diffusers_offload_min_gpu_memory = 0.2 - shared.log.warning(f'Offload: type=balanced op=validate: watermark low={shared.opts.diffusers_offload_min_gpu_memory} invalid value') + logger.log.warning(f'Offload: type=balanced op=validate: watermark low={shared.opts.diffusers_offload_min_gpu_memory} invalid value') if shared.opts.diffusers_offload_max_gpu_memory < 0.1 or shared.opts.diffusers_offload_max_gpu_memory > 1: shared.opts.diffusers_offload_max_gpu_memory = 0.7 - shared.log.warning(f'Offload: type=balanced op=validate: watermark high={shared.opts.diffusers_offload_max_gpu_memory} invalid value') + logger.log.warning(f'Offload: type=balanced op=validate: watermark high={shared.opts.diffusers_offload_max_gpu_memory} invalid value') if shared.opts.diffusers_offload_min_gpu_memory > shared.opts.diffusers_offload_max_gpu_memory: shared.opts.diffusers_offload_min_gpu_memory = shared.opts.diffusers_offload_max_gpu_memory - shared.log.warning(f'Offload: type=balanced op=validate: watermark low={shared.opts.diffusers_offload_min_gpu_memory} reset') + logger.log.warning(f'Offload: type=balanced op=validate: watermark low={shared.opts.diffusers_offload_min_gpu_memory} reset') if shared.opts.diffusers_offload_max_gpu_memory * shared.gpu_memory < 4: - shared.log.warning(f'Offload: type=balanced op=validate: watermark high={shared.opts.diffusers_offload_max_gpu_memory} low memory') + logger.log.warning(f'Offload: type=balanced op=validate: watermark high={shared.opts.diffusers_offload_max_gpu_memory} low memory') def model_size(self): return sum(self.offload_map.values()) @@ -273,7 +274,7 @@ class OffloadHook(accelerate.hooks.ModelHook): if isinstance(v, int): device_map[k] = f"{devices.device.type}:{v}" # int implies CUDA or XPU device, but it will break DirectML backend so we add type if debug: - shared.log.trace(f'Offload: type=balanced op=dispatch map={device_map}') + logger.log.trace(f'Offload: type=balanced op=dispatch map={device_map}') if device_map is not None: skip_keys = getattr(module, "_skip_keys", None) module = accelerate.dispatch_model(module, @@ -292,7 +293,7 @@ class OffloadHook(accelerate.hooks.ModelHook): for _i, pipe in enumerate(get_pipe_variants()): for module_name in get_module_names(pipe): module_instance = getattr(pipe, module_name, None) - shared.log.trace(f'Offload: type=balanced op=pre:status forward={module.__class__.__name__} module={module_name} class={module_instance.__class__.__name__} pipe={_i} device={module_instance.device} dtype={module_instance.dtype}') + logger.log.trace(f'Offload: type=balanced op=pre:status forward={module.__class__.__name__} module={module_name} class={module_instance.__class__.__name__} pipe={_i} device={module_instance.device} dtype={module_instance.dtype}') self.last_pre = _id return args, kwargs @@ -373,7 +374,7 @@ def get_module_sizes(pipe=None, exclude=None): module_size = sum(p.numel() * p.element_size() for p in module.parameters(recurse=True)) / 1024 / 1024 / 1024 param_num = sum(p.numel() for p in module.parameters(recurse=True)) / 1024 / 1024 / 1024 except Exception as e: - shared.log.error(f'Offload: type=balanced op=calc module={module_name} {e}') + logger.log.error(f'Offload: type=balanced op=calc module={module_name} {e}') module_size = 0 offload_hook_instance.offload_map[module_name] = module_size offload_hook_instance.param_map[module_name] = param_num @@ -425,7 +426,7 @@ def move_module_to_cpu(module, op='unk', force:bool=False): elif 'bitsandbytes' in str(e): pass else: - shared.log.error(f'Offload: type=balanced op=apply module={getattr(module, "__name__", None)} cls={module.__class__ if inspect.isclass(module) else None} {e}') + logger.log.error(f'Offload: type=balanced op=apply module={getattr(module, "__name__", None)} cls={module.__class__ if inspect.isclass(module) else None} {e}') if os.environ.get('SD_MOVE_DEBUG', None): errors.display(e, f'Offload: type=balanced op=apply module={getattr(module, "__name__", None)}') @@ -438,12 +439,12 @@ def apply_balanced_offload_to_module(module, op="apply", force:bool=False): try: module = accelerate.hooks.remove_hook_from_module(module, recurse=True) except Exception as e: - shared.log.warning(f'Offload remove hook: module={module_name} {e}') + logger.log.warning(f'Offload remove hook: module={module_name} {e}') move_module_to_cpu(module, op=op, force=force) try: module = accelerate.hooks.add_hook_to_module(module, offload_hook_instance, append=True) except Exception as e: - shared.log.warning(f'Offload add hook: module={module_name} {e}') + logger.log.warning(f'Offload add hook: module={module_name} {e}') module._hf_hook.execution_device = torch.device(devices.device) # pylint: disable=protected-access if network_layer_name: module.network_layer_name = network_layer_name @@ -461,9 +462,9 @@ def report_model_stats(module_name, module): size = offload_hook_instance.offload_map.get(module_name, 0) quant = getattr(module, "quantization_method", None) params = sum(p.numel() for p in module.parameters(recurse=True)) - shared.log.debug(f'Module: name={module_name} cls={module.__class__.__name__} size={size:.3f} params={params} quant={quant}') + logger.log.debug(f'Module: name={module_name} cls={module.__class__.__name__} size={size:.3f} params={params} quant={quant}') except Exception as e: - shared.log.error(f'Module stats: name={module_name} {e}') + logger.log.error(f'Module stats: name={module_name} {e}') def apply_balanced_offload(sd_model=None, exclude:list[str]=None, force:bool=False, silent:bool=False): @@ -508,5 +509,5 @@ def apply_balanced_offload(sd_model=None, exclude:list[str]=None, force:bool=Fal fn = f'{sys._getframe(2).f_code.co_name}:{sys._getframe(1).f_code.co_name}' # pylint: disable=protected-access debug_move(f'Apply offload: time={t:.2f} type=balanced fn={fn}') if not cached: - shared.log.info(f'Model class={sd_model.__class__.__name__} modules={len(offload_hook_instance.offload_map)} size={offload_hook_instance.model_size():.3f}') + logger.log.info(f'Model class={sd_model.__class__.__name__} modules={len(offload_hook_instance.offload_map)} size={offload_hook_instance.model_size():.3f}') return sd_model diff --git a/modules/sd_samplers.py b/modules/sd_samplers.py index c0e45f7a5..8a16131df 100644 --- a/modules/sd_samplers.py +++ b/modules/sd_samplers.py @@ -1,9 +1,10 @@ import os import copy from modules import shared +from modules import logger -debug = shared.log.trace if os.environ.get('SD_SAMPLER_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_SAMPLER_DEBUG', None) is not None else lambda *args, **kwargs: None debug('Trace: SAMPLER') all_samplers = [] all_samplers_map = {} @@ -37,7 +38,7 @@ def list_samplers(): samplers_for_img2img = all_samplers samplers_map = {} return all_samplers - # shared.log.debug(f'Available samplers: {[x.name for x in all_samplers]}') + # logger.log.debug(f'Available samplers: {[x.name for x in all_samplers]}') def find_sampler_config(name): @@ -61,7 +62,7 @@ def restore_default(model): shared.state.prediction_type = "flow_prediction" elif hasattr(model.scheduler, "config") and hasattr(model.scheduler.config, "prediction_type"): shared.state.prediction_type = model.scheduler.config.prediction_type - shared.log.debug(f'Sampler: "Default" cls={model.scheduler.__class__.__name__} config={config}') + logger.log.debug(f'Sampler: "Default" cls={model.scheduler.__class__.__name__} config={config}') return model.scheduler @@ -97,10 +98,10 @@ def create_sampler(name, model): if (model is not None) and is_flexible: pass elif (model is not None) and (is_flow and not requires_flow): - shared.log.error(f'Sampler: "{sampler.name}" cls={sampler.sampler.__class__.__name__} pipe={model.__class__.__name__} model requires sampler with discrete prediction') + logger.log.error(f'Sampler: "{sampler.name}" cls={sampler.sampler.__class__.__name__} pipe={model.__class__.__name__} model requires sampler with discrete prediction') return restore_default(model) elif (model is not None) and (not is_flow and requires_flow): - shared.log.error(f'Sampler: "{sampler.name}" cls={sampler.sampler.__class__.__name__} pipe={model.__class__.__name__} model requires sampler with flow prediction') + logger.log.error(f'Sampler: "{sampler.name}" cls={sampler.sampler.__class__.__name__} pipe={model.__class__.__name__} model requires sampler with flow prediction') return restore_default(model) # assign sampler @@ -124,7 +125,7 @@ def create_sampler(name, model): clean_config = {k: v for k, v in sampler.sampler.config.items() if not k.startswith('_') and v is not None and v is not False} cls = sampler.sampler.__class__.__name__ name = sampler.name if sampler is not None and sampler.sampler is not None else 'Default' - shared.log.debug(f'Sampler: "{name}" class={cls} config={clean_config}') + logger.log.debug(f'Sampler: "{name}" class={cls} config={clean_config}') return sampler.sampler diff --git a/modules/sd_samplers_common.py b/modules/sd_samplers_common.py index ee58c4057..f31000f9b 100644 --- a/modules/sd_samplers_common.py +++ b/modules/sd_samplers_common.py @@ -4,6 +4,7 @@ from collections import namedtuple import torch from PIL import Image from modules import shared, devices, processing, images, sd_samplers, timer +from modules import logger from modules.vae import sd_vae_approx, sd_vae_taesd, sd_vae_stablecascade from modules.image import convert @@ -18,7 +19,7 @@ queue_lock = threading.Lock() def warn_once(message): global warned # pylint: disable=global-statement if not warned: - shared.log.warning(f'VAE: {message}') + logger.log.warning(f'VAE: {message}') warned = True diff --git a/modules/sd_samplers_diffusers.py b/modules/sd_samplers_diffusers.py index 02287cf9a..8aaffe0f6 100644 --- a/modules/sd_samplers_diffusers.py +++ b/modules/sd_samplers_diffusers.py @@ -4,11 +4,12 @@ import copy import inspect import diffusers from modules import shared, errors +from modules import logger from modules.sd_samplers_common import SamplerData, flow_models debug = os.environ.get('SD_SAMPLER_DEBUG', None) is not None -debug_log = shared.log.trace if debug else lambda *args, **kwargs: None +debug_log = logger.log.trace if debug else lambda *args, **kwargs: None # Diffusers schedulers try: @@ -44,7 +45,7 @@ try: TCDScheduler, ) except Exception as e: - shared.log.error(f'Sampler import: version={diffusers.__version__} error: {e}') + logger.log.error(f'Sampler import: version={diffusers.__version__} error: {e}') if os.environ.get('SD_SAMPLER_DEBUG', None) is not None: errors.display(e, 'Samplers') @@ -61,7 +62,7 @@ try: from modules.schedulers.scheduler_flashflow import FlashFlowMatchEulerDiscreteScheduler # pylint: disable=ungrouped-imports from modules.schedulers.perflow import PeRFlowScheduler # pylint: disable=ungrouped-imports except Exception as e: - shared.log.error(f'Sampler import: version={diffusers.__version__} error: {e}') + logger.log.error(f'Sampler import: version={diffusers.__version__} error: {e}') if os.environ.get('SD_SAMPLER_DEBUG', None) is not None: errors.display(e, 'Samplers') @@ -93,7 +94,7 @@ try: # SimpleExponentialScheduler, ) except Exception as e: - shared.log.error(f'Sampler import: version={diffusers.__version__} error: {e}') + logger.log.error(f'Sampler import: version={diffusers.__version__} error: {e}') if os.environ.get('SD_SAMPLER_DEBUG', None) is not None: errors.display(e, 'Samplers') @@ -466,7 +467,7 @@ class DiffusionSampler: try: sampler = constructor(**self.config) except Exception as e: - shared.log.error(f'Sampler: "{name}" {e}') + logger.log.error(f'Sampler: "{name}" {e}') if debug: errors.display(e, 'Samplers') self.sampler = None @@ -478,11 +479,11 @@ class DiffusionSampler: accept_scale_noise = hasattr(sampler, "scale_noise") debug_log(f'Sampler: "{name}" sigmas={accept_sigmas} timesteps={accepts_timesteps}') if ('Flux' in model.__class__.__name__) and (not accept_sigmas): - shared.log.warning(f'Sampler: "{name}" does not accept sigmas') + logger.log.warning(f'Sampler: "{name}" does not accept sigmas') self.sampler = None return if ('StableDiffusion3' in model.__class__.__name__) and (not accept_scale_noise): - shared.log.warning(f'Sampler: "{name}" does not implement scale noise') + logger.log.warning(f'Sampler: "{name}" does not implement scale noise') self.sampler = None return @@ -494,5 +495,5 @@ class DiffusionSampler: self.sampler = sampler - # shared.log.debug_log(f'Sampler: class="{self.sampler.__class__.__name__}" config={self.sampler.config}') + # logger.log.debug_log(f'Sampler: class="{self.sampler.__class__.__name__}" config={self.sampler.config}') self.sampler.name = name diff --git a/modules/sd_te_remote.py b/modules/sd_te_remote.py index cdc743e0d..47f3cae0c 100644 --- a/modules/sd_te_remote.py +++ b/modules/sd_te_remote.py @@ -4,6 +4,7 @@ import json import torch import requests from modules import devices, errors +from modules import logger def get_t5_prompt_embeds( @@ -17,7 +18,7 @@ def get_t5_prompt_embeds( dtype = dtype or devices.dtype url = os.environ.get('SD_REMOTE_T5', None) if url is None: - errors.log.error('Remote-TE: url is not set') + logger.log.error('Remote-TE: url is not set') return None try: t0 = time.time() @@ -31,9 +32,9 @@ def get_t5_prompt_embeds( shape = json.loads(response.headers["shape"]) buffer = bytearray(response.content) tensor = torch.frombuffer(buffer, dtype=dtype).reshape(shape) - errors.log.debug(f'Remote-TE: url="{url}" prompt="{prompt}" shape={shape} time={t1-t0:.3f}') + logger.log.debug(f'Remote-TE: url="{url}" prompt="{prompt}" shape={shape} time={t1-t0:.3f}') return tensor.to(device=device, dtype=dtype) except Exception as e: - errors.log.error(f'Remote-TE: {e}') + logger.log.error(f'Remote-TE: {e}') errors.display(e, 'remote-te') return None diff --git a/modules/sd_unet.py b/modules/sd_unet.py index 643d1c08e..6206764a7 100644 --- a/modules/sd_unet.py +++ b/modules/sd_unet.py @@ -1,5 +1,6 @@ import os from modules import shared, devices, files_cache, sd_models, model_quant +from modules import logger unet_dict = {} @@ -15,7 +16,7 @@ def load_unet_sdxl_nunchaku(repo_id): try: from nunchaku.models.unets.unet_sdxl import NunchakuSDXLUNet2DConditionModel except Exception: - shared.log.error(f'Load module: quant=Nunchaku module=unet repo="{repo_id}" low nunchaku version') + logger.log.error(f'Load module: quant=Nunchaku module=unet repo="{repo_id}" low nunchaku version') return None if 'turbo' in repo_id.lower(): nunchaku_repo = 'nunchaku-ai/nunchaku-sdxl-turbo/svdq-int4_r32-sdxl-turbo.safetensors' @@ -23,8 +24,8 @@ def load_unet_sdxl_nunchaku(repo_id): nunchaku_repo = 'nunchaku-ai/nunchaku-sdxl/svdq-int4_r32-sdxl.safetensors' if shared.opts.nunchaku_offload: - shared.log.warning('Load module: quant=Nunchaku module=unet offload not supported for SDXL, ignoring') - shared.log.debug(f'Load module: quant=Nunchaku module=unet repo="{nunchaku_repo}"') + logger.log.warning('Load module: quant=Nunchaku module=unet offload not supported for SDXL, ignoring') + logger.log.debug(f'Load module: quant=Nunchaku module=unet repo="{nunchaku_repo}"') unet = NunchakuSDXLUNet2DConditionModel.from_pretrained( nunchaku_repo, torch_dtype=devices.dtype, @@ -48,7 +49,7 @@ def load_unet(model, repo_id:str=None): return if shared.opts.sd_unet not in list(unet_dict): - shared.log.error(f'Load module: type=UNet not found: {shared.opts.sd_unet}') + logger.log.error(f'Load module: type=UNet not found: {shared.opts.sd_unet}') return config_file = os.path.splitext(unet_dict[shared.opts.sd_unet])[0] + '.json' @@ -76,9 +77,9 @@ def load_unet(model, repo_id:str=None): sd_models.load_diffuser() # TODO model load: force-reloading entire model as loading transformers only leads to massive memory usage else: if not hasattr(model, 'unet') or model.unet is None: - shared.log.error('Load module: type=UNET not found in current model') + logger.log.error('Load module: type=UNET not found in current model') return - shared.log.info(f'Load module: type=UNet name="{shared.opts.sd_unet}" file="{unet_dict[shared.opts.sd_unet]}" config="{config_file}"') + logger.log.info(f'Load module: type=UNet name="{shared.opts.sd_unet}" file="{unet_dict[shared.opts.sd_unet]}" config="{config_file}"') from diffusers import UNet2DConditionModel from safetensors.torch import load_file unet = UNet2DConditionModel.from_config(model.unet.config if config is None else config).to(devices.device, devices.dtype) @@ -86,7 +87,7 @@ def load_unet(model, repo_id:str=None): unet.load_state_dict(state_dict) model.unet = unet.to(devices.device, devices.dtype_unet) except Exception as e: - shared.log.error(f'Failed to load UNet model: {e}') + logger.log.error(f'Failed to load UNet model: {e}') if debug: from modules import errors errors.display(e, 'UNet load:') @@ -100,4 +101,4 @@ def refresh_unet_list(): basename = os.path.basename(file) name = os.path.splitext(basename)[0] if ".safetensors" in basename else basename unet_dict[name] = file - shared.log.info(f'Available UNets: path="{shared.opts.unet_dir}" items={len(unet_dict)}') + logger.log.info(f'Available UNets: path="{shared.opts.unet_dir}" items={len(unet_dict)}') diff --git a/modules/sd_vae.py b/modules/sd_vae.py index 9c7255493..b3aba7a6e 100644 --- a/modules/sd_vae.py +++ b/modules/sd_vae.py @@ -2,6 +2,7 @@ import os import glob import torch from modules import shared, errors, paths, devices, sd_models, sd_detect +from modules import logger vae_ignore_keys = {"model_ema.decay", "model_ema.num_updates"} @@ -38,12 +39,12 @@ def get_vae_scale_factor(model=None): elif hasattr(model, 'config') and hasattr(model.config, 'vae_scale_factor'): vae_scale_factor = model.config.vae_scale_factor else: - # shared.log.warning(f'VAE: cls={model.__class__.__name__ if model else "None"} scale=unknown') + # logger.log.warning(f'VAE: cls={model.__class__.__name__ if model else "None"} scale=unknown') vae_scale_factor = 8 if hasattr(model, 'patch_size'): patch_size = model.patch_size if debug: - shared.log.trace(f'VAE: cls={model.__class__.__name__ if model else "None"} scale={vae_scale_factor} patch={patch_size}') + logger.log.trace(f'VAE: cls={model.__class__.__name__ if model else "None"} scale={vae_scale_factor} patch={patch_size}') return vae_scale_factor * patch_size @@ -87,7 +88,7 @@ def refresh_vae_list(): vae_dict[name] = os.path.dirname(filepath) else: vae_dict[name] = filepath - shared.log.info(f'Available VAEs: path="{vae_path}" items={len(vae_dict)}') + logger.log.info(f'Available VAEs: path="{vae_path}" items={len(vae_dict)}') return vae_dict @@ -120,7 +121,7 @@ def resolve_vae(checkpoint_file): vae_from_options = vae_dict.get(shared.opts.sd_vae + '.safetensors', None) # 6th if vae_from_options is not None: return vae_from_options, 'settings' - shared.log.warning(f"VAE not found: {shared.opts.sd_vae}") + logger.log.warning(f"VAE not found: {shared.opts.sd_vae}") return None, None @@ -148,7 +149,7 @@ def load_vae_diffusers(model_file, vae_file=None, vae_source="unknown-source"): if vae_file is None: return None if not os.path.exists(vae_file): - shared.log.error(f'VAE not found: model{vae_file}') + logger.log.error(f'VAE not found: model{vae_file}') return None diffusers_load_config = { "low_cpu_mem_usage": False, @@ -168,7 +169,7 @@ def load_vae_diffusers(model_file, vae_file=None, vae_source="unknown-source"): vae_config = sd_detect.get_load_config(model_file, model_type, config_type='json') if vae_config is not None: diffusers_load_config['config'] = os.path.join(vae_config, 'vae') - shared.log.info(f'Load module: type=VAE model="{vae_file}" source={vae_source} config={diffusers_load_config}') + logger.log.info(f'Load module: type=VAE model="{vae_file}" source={vae_source} config={diffusers_load_config}') try: import diffusers if os.path.isfile(vae_file): @@ -180,7 +181,7 @@ def load_vae_diffusers(model_file, vae_file=None, vae_source="unknown-source"): vae = diffusers.AutoencoderKL.from_single_file(vae_file, **diffusers_load_config) if getattr(vae.config, 'scaling_factor', 0) == 0.18125 and shared.sd_model_type == 'sdxl': vae.config.scaling_factor = 0.13025 - shared.log.debug('Setting model: component=VAE fix scaling factor') + logger.log.debug('Setting model: component=VAE fix scaling factor') vae = vae.to(devices.dtype_vae) else: if 'consistency-decoder' in vae_file: @@ -189,12 +190,12 @@ def load_vae_diffusers(model_file, vae_file=None, vae_source="unknown-source"): vae = diffusers.AutoencoderKL.from_pretrained(vae_file, **diffusers_load_config) global loaded_vae_file # pylint: disable=global-statement loaded_vae_file = os.path.basename(vae_file) - # shared.log.debug(f'Diffusers VAE config: {vae.config}') + # logger.log.debug(f'Diffusers VAE config: {vae.config}') if shared.opts.diffusers_offload_mode == 'none': sd_models.move_model(vae, devices.device) return vae except Exception as e: - shared.log.error(f"Load VAE failed: model={vae_file} {e}") + logger.log.error(f"Load VAE failed: model={vae_file} {e}") if debug: errors.display(e, 'VAE') return None @@ -215,7 +216,7 @@ def reload_vae_weights(sd_model=None, vae_file=unspecified): if vae_file is None or vae_file == 'None': if hasattr(sd_model, 'original_vae'): sd_models.set_diffuser_options(sd_model, vae=sd_model.original_vae, op='vae') - shared.log.info("VAE restored") + logger.log.info("VAE restored") return None if loaded_vae_file == vae_file: return None diff --git a/modules/shared.py b/modules/shared.py index fc8b71a83..4b76db6df 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -8,7 +8,8 @@ import contextlib from enum import Enum from typing import TYPE_CHECKING import gradio as gr -from installer import log, print_dict # pylint: disable=unused-import +from installer import print_dict # pylint: disable=unused-import +from modules.logger import log log.debug('Initializing: shared module') import modules.memmon diff --git a/modules/shared_defaults.py b/modules/shared_defaults.py index 5c7179a0e..b228a0589 100644 --- a/modules/shared_defaults.py +++ b/modules/shared_defaults.py @@ -1,4 +1,4 @@ -from installer import log +from modules.logger import log from modules import devices diff --git a/modules/shared_helpers.py b/modules/shared_helpers.py index 4ab4a9939..997e6475e 100644 --- a/modules/shared_helpers.py +++ b/modules/shared_helpers.py @@ -1,7 +1,7 @@ import os from types import SimpleNamespace from modules import paths -from installer import log +from modules.logger import log dir_timestamps = {} diff --git a/modules/shared_items.py b/modules/shared_items.py index 3a2a81a9d..e47411b7f 100644 --- a/modules/shared_items.py +++ b/modules/shared_items.py @@ -130,13 +130,12 @@ def get_pipelines(): 'ONNX Stable Diffusion Upscale': getattr(diffusers, 'OnnxStableDiffusionUpscalePipeline', None), } except Exception as e: - from installer import log + from modules.logger import log log.error(f'ONNX initialization error: {e}') onnx_pipelines = {} pipelines.update(onnx_pipelines) for k, v in pipelines.items(): if k != 'Autodetect' and v is None: - from installer import log # pylint: disable=redefined-outer-name log.error(f'Model="{k}" diffusers={diffusers.__version__} path={diffusers.__file__} pipeline not available') return pipelines diff --git a/modules/styles.py b/modules/styles.py index bb555e616..331b09b20 100644 --- a/modules/styles.py +++ b/modules/styles.py @@ -6,6 +6,7 @@ import json import time import random from modules import files_cache, shared, infotext, sd_models, sd_vae +from modules import logger debug_enabled = os.environ.get('SD_STYLES_DEBUG', None) is not None @@ -153,11 +154,11 @@ def apply_file_wildcards(prompt, replaced = None, not_found = None, recursion=0, if '|' in choice: choice = random.choice(choice.split('|')).strip(' []{}\n') prompt = prompt.replace(f"__{wildcard}__", choice, 1) - shared.log.debug(f'Apply wildcard: select="{wildcard}" choice="{choice}" file="{file}" choices={len(lines)}') + logger.log.debug(f'Apply wildcard: select="{wildcard}" choice="{choice}" file="{file}" choices={len(lines)}') replaced.append(wildcard) return prompt, True except Exception as e: - shared.log.error(f'Wildcards: wildcard={wildcard} file={file} {e}') + logger.log.error(f'Wildcards: wildcard={wildcard} file={file} {e}') if not file_only: return prompt, False return check_wildcard_files(prompt, wildcard, files, file_only=False) @@ -207,14 +208,14 @@ def apply_wildcards_to_prompt(prompt, all_wildcards, seed=-1, silent=False): prompt = prompt.replace(what, word) replaced[what] = word except Exception as e: - shared.log.error(f'Wildcards: wildcard="{wildcard}" error={e}') + logger.log.error(f'Wildcards: wildcard="{wildcard}" error={e}') t1 = time.time() prompt, replaced_file, not_found = apply_file_wildcards(prompt, [], [], recursion=0, seed=seed) t2 = time.time() if replaced and not silent: - shared.log.debug(f'Apply wildcards: {replaced} path="{shared.opts.wildcards_dir}" type=style time={t1-t0:.2f}') + logger.log.debug(f'Apply wildcards: {replaced} path="{shared.opts.wildcards_dir}" type=style time={t1-t0:.2f}') if (len(replaced_file) > 0 or len(not_found) > 0) and not silent: - shared.log.debug(f'Apply wildcards: found={replaced_file} missing={not_found} path="{shared.opts.wildcards_dir}" type=file seed={seed} time={t2-t2:.2f}') + logger.log.debug(f'Apply wildcards: found={replaced_file} missing={not_found} path="{shared.opts.wildcards_dir}" type=file seed={seed} time={t2-t2:.2f}') if old_state is not None: random.setstate(old_state) return prompt @@ -273,11 +274,11 @@ def apply_styles_to_extra(p, style: Style): v = type(orig)(v) setattr(p, k, v) if debug_enabled: - shared.log.trace(f'Apply style param: {k}={v}') + logger.log.trace(f'Apply style param: {k}={v}') params.append(f'{k}={v}') elif shared.opts.data_labels.get(k, None) is not None: if debug_enabled: - shared.log.trace(f'Apply style setting: {k}={v}') + logger.log.trace(f'Apply style setting: {k}={v}') shared.opts.data[k] = v if k == 'sd_model_checkpoint': sd_models.reload_model_weights() @@ -286,9 +287,9 @@ def apply_styles_to_extra(p, style: Style): settings.append(f'{k}={v}') else: if debug_enabled: - shared.log.trace(f'Apply style skip: {k}={v}') + logger.log.trace(f'Apply style skip: {k}={v}') skipped.append(f'{k}={v}') - shared.log.debug(f'Apply style: name="{style.name}" params={params} settings={settings} unknown={skipped} reference={True if reference_style else False}') + logger.log.debug(f'Apply style: name="{style.name}" params={params} settings={settings} unknown={skipped} reference={True if reference_style else False}') class StyleDatabase: @@ -307,10 +308,10 @@ class StyleDatabase: try: os.makedirs(opts.styles_dir, exist_ok=True) self.save_styles(opts.styles_dir, verbose=True) - shared.log.debug(f'Migrated styles: file="{legacy_file}" folder="{opts.styles_dir}"') + logger.log.debug(f'Migrated styles: file="{legacy_file}" folder="{opts.styles_dir}"') self.reload() except Exception as e: - shared.log.error(f'styles failed to migrate: file="{legacy_file}" error={e}') + logger.log.error(f'styles failed to migrate: file="{legacy_file}" error={e}') if not os.path.isdir(opts.styles_dir): opts.styles_dir = os.path.join(paths.models_path, "styles") self.path = opts.styles_dir @@ -348,7 +349,7 @@ class StyleDatabase: ) self.styles[style["name"]] = new_style except Exception as e: - shared.log.error(f'Failed to load style: file="{fn}" error={e}') + logger.log.error(f'Failed to load style: file="{fn}" error={e}') return new_style def reload(self): @@ -376,7 +377,7 @@ class StyleDatabase: self.built_in = shared.opts.extra_networks_styles list_folder(self.path) t1 = time.time() - shared.log.info(f'Available Styles: path="{self.path}" items={len(self.styles.keys())} time={t1-t0:.2f}') + logger.log.info(f'Available Styles: path="{self.path}" items={len(self.styles.keys())} time={t1-t0:.2f}') def find_style(self, name): found = [style for style in self.styles.values() if style.name == name] @@ -386,7 +387,7 @@ class StyleDatabase: if styles is None: return [] if not isinstance(styles, list): - shared.log.error(f'Styles invalid: {styles}') + logger.log.error(f'Styles invalid: {styles}') return [] return [self.find_style(x).prompt for x in styles] @@ -394,7 +395,7 @@ class StyleDatabase: if styles is None: return [] if not isinstance(styles, list): - shared.log.error(f'Styles invalid: {styles}') + logger.log.error(f'Styles invalid: {styles}') return [] return [self.find_style(x).negative_prompt for x in styles] @@ -402,13 +403,13 @@ class StyleDatabase: if styles is None: return prompts, negatives if not isinstance(styles, list): - shared.log.error(f'Styles invalid styles: {styles}') + logger.log.error(f'Styles invalid styles: {styles}') return prompts, negatives if prompts is None or not isinstance(prompts, list): - shared.log.error(f'Styles invalid prompts: {prompts}') + logger.log.error(f'Styles invalid prompts: {prompts}') return prompts, negatives if seeds is None or not isinstance(prompts, list): - shared.log.error(f'Styles invalid seeds: {seeds}') + logger.log.error(f'Styles invalid seeds: {seeds}') return prompts, negatives jobid = shared.state.begin('Styles') parsed_positive = [] @@ -440,7 +441,7 @@ class StyleDatabase: if styles is None: return prompt if not isinstance(styles, list): - shared.log.error(f'Styles invalid: {styles}') + logger.log.error(f'Styles invalid: {styles}') return prompt prompt = apply_styles_to_prompt(prompt, [self.find_style(x).prompt for x in styles]) if wildcards: @@ -451,7 +452,7 @@ class StyleDatabase: if styles is None: return prompt if not isinstance(styles, list): - shared.log.error(f'Styles invalid: {styles}') + logger.log.error(f'Styles invalid: {styles}') return prompt prompt = apply_styles_to_prompt(prompt, [self.find_style(x).negative_prompt for x in styles]) if wildcards: @@ -467,12 +468,12 @@ class StyleDatabase: if p.styles is None: return if p.styles is None or not isinstance(p.styles, list): - shared.log.error(f'Styles invalid: {p.styles}') + logger.log.error(f'Styles invalid: {p.styles}') return for style in p.styles: s = self.find_style(style) if s == self.no_style: - shared.log.warning(f'Apply style: name="{style}" not found') + logger.log.warning(f'Apply style: name="{style}" not found') continue apply_styles_to_extra(p, s) @@ -501,12 +502,12 @@ class StyleDatabase: with open(fn, 'w', encoding='utf-8') as f: json.dump(style, f, indent=2) if verbose: - shared.log.debug(f'Saved style: name={name} file="{fn}"') + logger.log.debug(f'Saved style: name={name} file="{fn}"') except Exception as e: - shared.log.error(f'Failed to save style: name={name} file="{path}" error={e}') + logger.log.error(f'Failed to save style: name={name} file="{path}" error={e}') count = len(list(self.styles)) if count > 0: - shared.log.debug(f'Saved styles: folder="{path}" items={count}') + logger.log.debug(f'Saved styles: folder="{path}" items={count}') def load_csv(self, legacy_file): if not os.path.isfile(legacy_file): @@ -520,8 +521,8 @@ class StyleDatabase: prompt = row["prompt"] if "prompt" in row else row["text"] negative = row.get("negative_prompt", "") if "negative_prompt" in row else row.get("negative", "") self.styles[name] = Style(name, desc=name, prompt=prompt, negative_prompt=negative) - shared.log.debug(f'Migrated style: {self.styles[name].__dict__}') + logger.log.debug(f'Migrated style: {self.styles[name].__dict__}') num += 1 except Exception: - shared.log.error(f'Styles error: file="{legacy_file}" row={row}') - shared.log.info(f'Load legacy styles: file="{legacy_file}" loaded={num} created={len(list(self.styles))}') + logger.log.error(f'Styles error: file="{legacy_file}" row={row}') + logger.log.info(f'Load legacy styles: file="{legacy_file}" loaded={num} created={len(list(self.styles))}') diff --git a/modules/teacache/__init__.py b/modules/teacache/__init__.py index 56a261241..d825e5594 100644 --- a/modules/teacache/__init__.py +++ b/modules/teacache/__init__.py @@ -1,3 +1,4 @@ +from modules import logger from .teacache_flux import teacache_flux_forward from .teacache_hidream import teacache_hidream_forward from .teacache_lumina2 import teacache_lumina2_forward @@ -30,4 +31,4 @@ def apply_teacache(p): if shared.sd_model.__class__.__name__.startswith('Lumina2'): shared.sd_model.transformer.__class__.cache = {} shared.sd_model.transformer.__class__.uncond_seq_len = None - shared.log.info(f'Transformers cache: type=teacache cls={shared.sd_model.__class__.__name__} thresh={shared.opts.teacache_thresh}') + logger.log.info(f'Transformers cache: type=teacache cls={shared.sd_model.__class__.__name__} thresh={shared.opts.teacache_thresh}') diff --git a/modules/textual_inversion.py b/modules/textual_inversion.py index d01118e64..6fe7aeadd 100644 --- a/modules/textual_inversion.py +++ b/modules/textual_inversion.py @@ -4,10 +4,11 @@ import torch import safetensors.torch from modules.errorlimiter import limit_errors from modules import shared, devices, errors +from modules import logger from modules.files_cache import directory_files, directory_mtime, extension_filter -debug = shared.log.trace if os.environ.get('SD_TI_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_TI_DEBUG', None) is not None else lambda *args, **kwargs: None debug('Trace: TEXTUAL INVERSION') supported_models = ['ldm', 'sd', 'sdxl'] @@ -284,11 +285,11 @@ class EmbeddingDatabase: embedding.tokens = [] self.skipped_embeddings[embedding.name] = embedding except Exception as e: - shared.log.error(f'Load embedding invalid: name="{embedding.name}" fn="{filename}" {e}') + logger.log.error(f'Load embedding invalid: name="{embedding.name}" fn="{filename}" {e}') self.skipped_embeddings[embedding.name] = embedding elimit() if overwrite: - shared.log.info(f"Load bundled embeddings: {list(data.keys())}") + logger.log.info(f"Load bundled embeddings: {list(data.keys())}") for embedding in embeddings: if embedding.name not in self.skipped_embeddings: deref_tokenizers(embedding.tokens, tokenizers) @@ -299,14 +300,14 @@ class EmbeddingDatabase: insert_vectors(embedding, tokenizers, text_encoders, hiddensizes) self.register_embedding(embedding, shared.sd_model) except Exception as e: - shared.log.error(f'Load embedding: name="{embedding.name}" file="{embedding.filename}" {e}') + logger.log.error(f'Load embedding: name="{embedding.name}" file="{embedding.filename}" {e}') errors.display(e, f'Load embedding: name="{embedding.name}" file="{embedding.filename}"') elimit() return def load_from_dir(self, embdir): if not shared.sd_loaded: - shared.log.info('Skipping embeddings load: model not loaded') + logger.log.info('Skipping embeddings load: model not loaded') return if not os.path.isdir(embdir.path): return @@ -345,4 +346,4 @@ class EmbeddingDatabase: if self.previously_displayed_embeddings != displayed_embeddings and shared.opts.diffusers_enable_embed: self.previously_displayed_embeddings = displayed_embeddings t1 = time.time() - shared.log.info(f"Network load: type=embeddings loaded={len(self.word_embeddings)} skipped={len(self.skipped_embeddings)} time={t1-t0:.2f}") + logger.log.info(f"Network load: type=embeddings loaded={len(self.word_embeddings)} skipped={len(self.skipped_embeddings)} time={t1-t0:.2f}") diff --git a/modules/theme.py b/modules/theme.py index 0b384ac20..d0529a005 100644 --- a/modules/theme.py +++ b/modules/theme.py @@ -3,6 +3,7 @@ import json import gradio as gr import modules.shared import modules.extensions +from modules import logger gradio_theme = gr.themes.Base() @@ -21,18 +22,18 @@ def refresh_themes(no_update=False): with open(themes_file, encoding='utf8') as f: res = json.load(f) except Exception: - modules.shared.log.error('Exception loading UI themes') + modules.logger.log.error('Exception loading UI themes') if not no_update: try: - modules.shared.log.info('Refreshing UI themes') + modules.logger.log.info('Refreshing UI themes') r = modules.shared.req('https://huggingface.co/datasets/freddyaboulton/gradio-theme-subdomains/resolve/main/subdomains.json') if r.status_code == 200: res = r.json() modules.shared.writefile(res, themes_file) else: - modules.shared.log.error('Error refreshing UI themes') + modules.logger.log.error('Error refreshing UI themes') except Exception: - modules.shared.log.error('Exception refreshing UI themes') + modules.logger.log.error('Exception refreshing UI themes') return res @@ -46,12 +47,12 @@ def list_themes(): themes = ['lobe'] modules.shared.opts.data['gradio_theme'] = themes[0] modules.shared.opts.data['theme_type'] = 'None' - modules.shared.log.info('UI theme: extension="lobe"') + modules.logger.log.info('UI theme: extension="lobe"') elif 'Cozy-Nest' in extensions and modules.shared.opts.gradio_theme == 'cozy-nest': themes = ['cozy-nest'] modules.shared.opts.data['gradio_theme'] = themes[0] modules.shared.opts.data['theme_type'] = 'None' - modules.shared.log.info('UI theme: extension="cozy-nest"') + modules.logger.log.info('UI theme: extension="cozy-nest"') elif modules.shared.opts.theme_type == 'None': gradio = ["gradio/default", "gradio/base", "gradio/glass", "gradio/monochrome", "gradio/soft"] huggingface = refresh_themes(no_update=True) @@ -64,7 +65,7 @@ def list_themes(): elif modules.shared.opts.theme_type == 'Modern': ext = next((e for e in modules.extensions.extensions if e.name == 'sdnext-modernui'), None) if ext is None: - modules.shared.log.error('UI themes: ModernUI not found') + modules.logger.log.error('UI themes: ModernUI not found') builtin = list_builtin_themes() themes = sorted(builtin) modules.shared.opts.theme_type = 'Standard' @@ -79,7 +80,7 @@ def list_themes(): themes.append('modern/Default') themes = sorted(themes) else: - modules.shared.log.error(f'UI themes: type={modules.shared.opts.theme_type} unknown') + modules.logger.log.error(f'UI themes: type={modules.shared.opts.theme_type} unknown') themes = [] return themes @@ -94,7 +95,7 @@ def reload_gradio_theme(): gradio_theme = gr.themes.Base(**default_font_params) available_themes = list_themes() if theme_name not in available_themes: - # modules.shared.log.error(f'UI theme invalid: type={modules.shared.opts.theme_type} theme="{theme_name}"') + # modules.logger.log.error(f'UI theme invalid: type={modules.shared.opts.theme_type} theme="{theme_name}"') if modules.shared.opts.theme_type == 'Standard': theme_name = 'black-teal' elif modules.shared.opts.theme_type == 'Modern': @@ -106,22 +107,22 @@ def reload_gradio_theme(): theme_name = 'black-teal' modules.shared.opts.data['gradio_theme'] = theme_name - modules.shared.log.info(f'UI locale: name="{modules.shared.opts.ui_locale}"') + modules.logger.log.info(f'UI locale: name="{modules.shared.opts.ui_locale}"') if theme_name.lower() in ['lobe', 'cozy-nest']: - modules.shared.log.info(f'UI theme extension: name="{theme_name}"') + modules.logger.log.info(f'UI theme extension: name="{theme_name}"') return None elif modules.shared.opts.theme_type == 'Standard': gradio_theme = gr.themes.Base(**default_font_params) - modules.shared.log.info(f'UI theme: type={modules.shared.opts.theme_type} name="{theme_name}" available={len(available_themes)}') + modules.logger.log.info(f'UI theme: type={modules.shared.opts.theme_type} name="{theme_name}" available={len(available_themes)}') return 'sdnext.css' elif modules.shared.opts.theme_type == 'Modern': gradio_theme = gr.themes.Base(**default_font_params) - modules.shared.log.info(f'UI theme: type={modules.shared.opts.theme_type} name="{theme_name}" available={len(available_themes)}') + modules.logger.log.info(f'UI theme: type={modules.shared.opts.theme_type} name="{theme_name}" available={len(available_themes)}') return 'base.css' elif modules.shared.opts.theme_type == 'None': if theme_name.startswith('gradio/'): - modules.shared.log.warning('UI theme: using Gradio default theme which is not optimized for SD.Next') + modules.logger.log.warning('UI theme: using Gradio default theme which is not optimized for SD.Next') if theme_name == "gradio/default": gradio_theme = gr.themes.Default(**default_font_params) elif theme_name == "gradio/base": @@ -133,18 +134,18 @@ def reload_gradio_theme(): elif theme_name == "gradio/soft": gradio_theme = gr.themes.Soft(**default_font_params) else: - modules.shared.log.warning('UI theme: unknown Gradio theme') + modules.logger.log.warning('UI theme: unknown Gradio theme') theme_name = "gradio/default" gradio_theme = gr.themes.Default(**default_font_params) elif theme_name.startswith('huggingface/'): - modules.shared.log.warning('UI theme: using 3rd party theme which is not optimized for SD.Next') + modules.logger.log.warning('UI theme: using 3rd party theme which is not optimized for SD.Next') try: hf_theme_name = theme_name.replace('huggingface/', '') gradio_theme = gr.themes.ThemeClass.from_hub(hf_theme_name) except Exception as e: - modules.shared.log.error(f"UI theme: download error accessing HuggingFace {e}") + modules.logger.log.error(f"UI theme: download error accessing HuggingFace {e}") gradio_theme = gr.themes.Default(**default_font_params) - modules.shared.log.info(f'UI theme: type={modules.shared.opts.theme_type} name="{theme_name}" style={modules.shared.opts.theme_style}') + modules.logger.log.info(f'UI theme: type={modules.shared.opts.theme_type} name="{theme_name}" style={modules.shared.opts.theme_style}') return 'base.css' - modules.shared.log.error(f'UI theme: type={modules.shared.opts.theme_type} unknown') + modules.logger.log.error(f'UI theme: type={modules.shared.opts.theme_type} unknown') return None diff --git a/modules/token_merge.py b/modules/token_merge.py index f97c1fc8e..a3462f78a 100644 --- a/modules/token_merge.py +++ b/modules/token_merge.py @@ -1,3 +1,4 @@ +from modules import logger from modules import shared @@ -9,7 +10,7 @@ def apply_token_merging(sd_model): if current_tome == shared.opts.tome_ratio: return if shared.opts.hypertile_unet_enabled and not shared.cmd_opts.experimental: - shared.log.warning('Token merging not supported with HyperTile for UNet') + logger.log.warning('Token merging not supported with HyperTile for UNet') return try: import installer @@ -23,10 +24,10 @@ def apply_token_merging(sd_model): merge_crossattn=False, merge_mlp=False ) - shared.log.info(f'Applying ToMe: ratio={shared.opts.tome_ratio}') + logger.log.info(f'Applying ToMe: ratio={shared.opts.tome_ratio}') sd_model.applied_tome = shared.opts.tome_ratio except Exception: - shared.log.warning(f'Token merging not supported: pipeline={sd_model.__class__.__name__}') + logger.log.warning(f'Token merging not supported: pipeline={sd_model.__class__.__name__}') else: sd_model.applied_tome = 0 @@ -34,7 +35,7 @@ def apply_token_merging(sd_model): if current_todo == shared.opts.todo_ratio: return if shared.opts.hypertile_unet_enabled and not shared.cmd_opts.experimental: - shared.log.warning('Token merging not supported with HyperTile for UNet') + logger.log.warning('Token merging not supported with HyperTile for UNet') return try: from modules.todo.todo_utils import patch_attention_proc @@ -50,10 +51,10 @@ def apply_token_merging(sd_model): "ratio_level_2": 0.0, } patch_attention_proc(sd_model.unet, token_merge_args=token_merge_args) - shared.log.info(f'Applying ToDo: ratio={shared.opts.todo_ratio}') + logger.log.info(f'Applying ToDo: ratio={shared.opts.todo_ratio}') sd_model.applied_todo = shared.opts.todo_ratio except Exception: - shared.log.warning(f'Token merging not supported: pipeline={sd_model.__class__.__name__}') + logger.log.warning(f'Token merging not supported: pipeline={sd_model.__class__.__name__}') else: sd_model.applied_todo = 0 diff --git a/modules/transformer_cache.py b/modules/transformer_cache.py index c8615c534..7496a47d4 100644 --- a/modules/transformer_cache.py +++ b/modules/transformer_cache.py @@ -1,9 +1,10 @@ import os import diffusers from modules import shared, errors +from modules import logger -debug = shared.log.trace if os.environ.get('SD_PROCESS_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_PROCESS_DEBUG', None) is not None else lambda *args, **kwargs: None def set_cache(faster_cache=None, pyramid_attention_broadcast=None): @@ -14,7 +15,7 @@ def set_cache(faster_cache=None, pyramid_attention_broadcast=None): if (not faster_cache) and (not pyramid_attention_broadcast): return if (not hasattr(shared.sd_model.transformer, 'enable_cache')) or (not hasattr(shared.sd_model.transformer, 'disable_cache')): - shared.log.debug(f'Transformer cache: cls={shared.sd_model.transformer.__class__.__name__} fc={faster_cache} pab={pyramid_attention_broadcast} not supported') + logger.log.debug(f'Transformer cache: cls={shared.sd_model.transformer.__class__.__name__} fc={faster_cache} pab={pyramid_attention_broadcast} not supported') return try: if faster_cache: # https://github.com/huggingface/diffusers/pull/10163 @@ -31,7 +32,7 @@ def set_cache(faster_cache=None, pyramid_attention_broadcast=None): ) shared.sd_model.transformer.disable_cache() shared.sd_model.transformer.enable_cache(config) - shared.log.debug(f'Transformer cache: type={config.__class__.__name__}') + logger.log.debug(f'Transformer cache: type={config.__class__.__name__}') debug(f'Transformer cache: {vars(config)}') elif pyramid_attention_broadcast: # https://github.com/huggingface/diffusers/pull/9562 config = diffusers.PyramidAttentionBroadcastConfig( @@ -41,11 +42,11 @@ def set_cache(faster_cache=None, pyramid_attention_broadcast=None): ) shared.sd_model.transformer.disable_cache() shared.sd_model.transformer.enable_cache(config) - shared.log.debug(f'Transformer cache: type={config.__class__.__name__}') + logger.log.debug(f'Transformer cache: type={config.__class__.__name__}') debug(f'Transformer cache: {vars(config)}') else: debug('Transformer cache: not enabled') shared.sd_model.transformer.disable_cache() except Exception as e: - shared.log.error(f'Transformer cache: {e}') + logger.log.error(f'Transformer cache: {e}') errors.display(e, 'Transformer cache') diff --git a/modules/txt2img.py b/modules/txt2img.py index 021b586e5..d8074fc0e 100644 --- a/modules/txt2img.py +++ b/modules/txt2img.py @@ -1,11 +1,12 @@ import os from modules import shared, processing, scripts_manager +from modules import logger from modules.generation_parameters_copypaste import create_override_settings_dict from modules.ui_common import plaintext_to_html from modules.paths import resolve_output_path -debug = shared.log.trace if os.environ.get('SD_PROCESS_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_PROCESS_DEBUG', None) is not None else lambda *args, **kwargs: None debug('Trace: PROCESS') @@ -30,12 +31,12 @@ def txt2img(id_task, state, debug(f'txt2img: {id_task}') if shared.sd_model is None: - shared.log.warning('Aborted: op=txt model not loaded') + logger.log.warning('Aborted: op=txt model not loaded') return [], '', '', 'Error: model not loaded' override_settings = create_override_settings_dict(override_settings_texts) if sampler_index is None: - shared.log.warning('Sampler: invalid') + logger.log.warning('Sampler: invalid') sampler_index = 0 if hr_sampler_index is None: hr_sampler_index = sampler_index diff --git a/modules/ui.py b/modules/ui.py index b1c0033b6..d30bba862 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -2,6 +2,7 @@ import gradio as gr import gradio.routes import gradio.utils from modules import errors, timer, gr_hijack, shared, script_callbacks, ui_common, ui_symbols, ui_javascript, ui_sections, generation_parameters_copypaste, call_queue, scripts_manager +from modules import logger from modules.api import mime @@ -78,7 +79,7 @@ def create_ui(startup_timer = None) -> gr.Blocks: interfaces.clear() shared.opts.ui_disabled = ui_disabled if len(ui_disabled) > 0: - shared.log.warning(f'UI disabled: {ui_disabled}') + logger.log.warning(f'UI disabled: {ui_disabled}') if 'txt2img' not in ui_disabled: with gr.Blocks(analytics_enabled=False) as txt2img_interface: diff --git a/modules/ui_caption.py b/modules/ui_caption.py index 6498d463b..6ab201014 100644 --- a/modules/ui_caption.py +++ b/modules/ui_caption.py @@ -1,5 +1,6 @@ import gradio as gr from modules import shared, ui_common, generation_parameters_copypaste +from modules import logger from modules.caption import openclip @@ -146,7 +147,7 @@ def update_default_caption_type(caption_type): def create_ui(): - shared.log.debug('UI initialize: tab=caption') + logger.log.debug('UI initialize: tab=caption') with gr.Row(equal_height=False, variant='compact', elem_classes="caption", elem_id="caption_tab"): with gr.Column(variant='compact', elem_id='caption_input'): with gr.Row(): diff --git a/modules/ui_common.py b/modules/ui_common.py index 740d44385..1077f178b 100644 --- a/modules/ui_common.py +++ b/modules/ui_common.py @@ -6,10 +6,11 @@ import platform import subprocess import gradio as gr from modules import paths, call_queue, shared, errors, ui_sections, ui_symbols, ui_components, generation_parameters_copypaste, images, scripts_manager, script_callbacks, infotext, processing +from modules import logger folder_symbol = ui_symbols.folder -debug = shared.log.trace if os.environ.get('SD_PASTE_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_PASTE_DEBUG', None) is not None else lambda *args, **kwargs: None debug('Trace: PASTE') @@ -34,7 +35,7 @@ def update_generation_info(generation_info, html_info, img_index): html_info_formatted = infotext_to_html(info) return html_info, html_info_formatted except Exception as e: - shared.log.trace(f'Update info: info="{generation_info}" {e}') + logger.log.trace(f'Update info: info="{generation_info}" {e}') return html_info, html_info @@ -75,7 +76,7 @@ def delete_files(js_data, files, all_files, index): files = [files[index]] start_index = index else: - shared.log.error(f'Delete: index={index} first={first_index} files={len(files)} out of range') + logger.log.error(f'Delete: index={index} first={first_index} files={len(files)} out of range') files = [] deleted = [] all_files = [f.split('/file=')[1] if 'file=' in f else f for f in all_files] if isinstance(all_files, list) else [] @@ -85,23 +86,23 @@ def delete_files(js_data, files, all_files, index): try: fn = os.path.normpath(filedata['name']) if reference_dir in fn: - shared.log.warning(f'Delete: file="{fn}" not allowed') + logger.log.warning(f'Delete: file="{fn}" not allowed') continue if os.path.exists(fn) and os.path.isfile(fn): deleted.append(fn) os.remove(fn) if fn in all_files: all_files.remove(fn) - shared.log.info(f'Delete: image="{fn}"') + logger.log.info(f'Delete: image="{fn}"') else: - shared.log.warning(f'Delete: image="{fn}" ui mismatch') + logger.log.warning(f'Delete: image="{fn}" ui mismatch') base, _ext = os.path.splitext(fn) desc = f'{base}.txt' if os.path.exists(desc) and os.path.isfile(desc): os.remove(desc) - shared.log.info(f'Delete: text="{fn}"') + logger.log.info(f'Delete: text="{fn}"') except Exception as e: - shared.log.error(f'Delete: file="{fn}" {e}') + logger.log.error(f'Delete: file="{fn}" {e}') deleted = ', '.join(deleted) if len(deleted) > 0 else 'none' return all_files, plaintext_to_html(f"Deleted: {deleted}", ['performance']) @@ -151,7 +152,7 @@ def save_files(js_data, files, html_info, index): files = [files[index]] start_index = index else: - shared.log.error(f'Save: index={index} first={p.index_of_first_image} files={len(files)} out of range') + logger.log.error(f'Save: index={index} first={p.index_of_first_image} files={len(files)} out of range') files = [] filenames = [] fullfns = [] @@ -179,9 +180,9 @@ def save_files(js_data, files, html_info, index): if not os.path.exists(tgt_filename): try: shutil.copy(fullfn, destination) - shared.log.info(f'Copying image: file="{fullfn}" folder="{destination}"') + logger.log.info(f'Copying image: file="{fullfn}" folder="{destination}"') except Exception as e: - shared.log.error(f'Copying image: {fullfn} {e}') + logger.log.error(f'Copying image: {fullfn} {e}') if shared.opts.save_txt: try: from PIL import Image @@ -190,9 +191,9 @@ def save_files(js_data, files, html_info, index): filename_txt = f"{os.path.splitext(tgt_filename)[0]}.txt" with open(filename_txt, "w", encoding="utf8") as file: file.write(f"{info}\n") - shared.log.debug(f'Save: text="{filename_txt}"') + logger.log.debug(f'Save: text="{filename_txt}"') except Exception as e: - shared.log.warning(f'Image description save failed: {filename_txt} {e}') + logger.log.warning(f'Image description save failed: {filename_txt} {e}') script_callbacks.image_save_btn_callback(tgt_filename) else: image = generation_parameters_copypaste.image_from_url_text(filedata) @@ -209,7 +210,7 @@ def save_files(js_data, files, html_info, index): fullfn, txt_fullfn, _exif = images.save_image(image, paths.resolve_output_path(shared.opts.outdir_samples, shared.opts.outdir_save), "", seed=seed, prompt=prompt, info=info, extension=shared.opts.samples_format, grid=is_grid, p=p) except Exception as e: fullfn, txt_fullfn = None, None - shared.log.error(f'Save: image={image} i={i} seeds={p.all_seeds} prompts={p.all_prompts}') + logger.log.error(f'Save: image={image} i={i} seeds={p.all_seeds} prompts={p.all_prompts}') errors.display(e, 'save') if fullfn is None: continue @@ -238,10 +239,10 @@ def open_folder(result_gallery, gallery_index = 0): except Exception: folder = shared.opts.outdir_samples if not os.path.exists(folder): - shared.log.warning(f'Folder open: folder="{folder}" does not exist') + logger.log.warning(f'Folder open: folder="{folder}" does not exist') return elif not os.path.isdir(folder): - shared.log.warning(f'Folder open: folder="{folder}" not a folder') + logger.log.warning(f'Folder open: folder="{folder}" not a folder') return if not shared.cmd_opts.hide_ui_dir_config: @@ -385,7 +386,7 @@ def reuse_seed(seed_component: gr.Number, reuse_button: gr.Button, subseed:bool= seed = processing.processed.all_seeds[0] if not subseed else processing.processed.all_subseeds[0] else: seed = -1 - shared.log.debug(f'Reuse seed: index={selected_gallery_index} seed={seed} subseed={subseed}') + logger.log.debug(f'Reuse seed: index={selected_gallery_index} seed={seed} subseed={subseed}') return seed reuse_button.click(fn=reuse_click, _js="selected_gallery_index", inputs=[seed_component], outputs=[seed_component], show_progress='hidden') @@ -400,7 +401,7 @@ def connect_reuse_seed(seed: gr.Number, reuse_seed_btn: gr.Button, generation_in restore_strength = -1 try: gen_info = json.loads(gen_info_string) - shared.log.debug(f'Reuse: info={gen_info}') + logger.log.debug(f'Reuse: info={gen_info}') index -= gen_info.get('index_of_first_image', 0) index = int(index) if is_subseed: @@ -412,7 +413,7 @@ def connect_reuse_seed(seed: gr.Number, reuse_seed_btn: gr.Button, generation_in restore_seed = all_seeds[index if 0 <= index < len(all_seeds) else 0] except json.decoder.JSONDecodeError: if gen_info_string != '': - shared.log.error(f"Error parsing JSON generation info: {gen_info_string}") + logger.log.error(f"Error parsing JSON generation info: {gen_info_string}") if is_subseed is not None: return [restore_seed, gr_show(False), restore_strength] else: @@ -428,7 +429,7 @@ def update_token_counter(text): token_count = 0 max_length = 75 if shared.state.job_count > 0: - shared.log.debug('Tokenizer busy') + logger.log.debug('Tokenizer busy') return f"{token_count}/{max_length}" from modules import extra_networks if isinstance(text, list): diff --git a/modules/ui_control.py b/modules/ui_control.py index 2c1c74748..09a283959 100644 --- a/modules/ui_control.py +++ b/modules/ui_control.py @@ -5,6 +5,7 @@ from modules.control import unit from modules import errors, shared, progress, generation_parameters_copypaste, call_queue, scripts_manager, masking, images, processing_vae, timer # pylint: disable=ungrouped-imports from modules import ui_common, ui_sections, ui_guidance from modules import ui_control_helpers as helpers +from modules import logger import installer @@ -12,7 +13,7 @@ gr_height = 512 max_units = shared.opts.control_max_units units: list[unit.Unit] = [] # main state variable controls: list[gr.components.Component] = [] # list of gr controls -debug = shared.log.trace if os.environ.get('SD_CONTROL_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_CONTROL_DEBUG', None) is not None else lambda *args, **kwargs: None debug('Trace: CONTROL') @@ -105,9 +106,9 @@ def generate_click(job_id: str, state: str, active_tab: str, *args): progress.record_results(job_id, results) yield return_controls(results, t) except GeneratorExit: - shared.log.error("Control: generator exit") + logger.log.error("Control: generator exit") except Exception as e: - shared.log.error(f"Control exception: {e}") + logger.log.error(f"Control exception: {e}") errors.display(e, 'Control') yield [None, None, None, None, f'Control: Exception: {e}', ''] finally: @@ -132,9 +133,9 @@ def generate_click_alt(job_id: str, state: str, active_tab: str, *args): for results in control_run(state, units, helpers.input_source, helpers.input_init, helpers.input_mask, active_tab, True, *args): progress.record_results(job_id, results) except GeneratorExit: - shared.log.error("Control: generator exit") + logger.log.error("Control: generator exit") except Exception as e: - shared.log.error(f"Control exception: {e}") + logger.log.error(f"Control exception: {e}") errors.display(e, 'Control') return [None, None, None, None, f'Control: Exception: {e}', ''] finally: @@ -221,7 +222,7 @@ def create_ui(_blocks: gr.Blocks=None): input_mode = gr.Label(value='select', visible=False) with gr.Tab('Image', id='in-image') as tab_image: if (installer.version['kanvas'] == 'disabled') or (installer.version['kanvas'] == 'unavailable'): - shared.log.warning(f'Kanvas: status={installer.version["kanvas"]}') + logger.log.warning(f'Kanvas: status={installer.version["kanvas"]}') input_image = gr.Image(label="Input", show_label=False, type="pil", interactive=True, tool="editor", height=gr_height, image_mode='RGB', elem_id='control_input_select', elem_classes=['control-image']) else: input_image = gr.HTML(value='

Kanvas not initialized

', elem_id='kanvas-container') diff --git a/modules/ui_control_helpers.py b/modules/ui_control_helpers.py index cbe3c4df8..f88e9a9b2 100644 --- a/modules/ui_control_helpers.py +++ b/modules/ui_control_helpers.py @@ -3,12 +3,13 @@ import time import gradio as gr from PIL import Image from modules import shared, scripts_manager, masking, video # pylint: disable=ungrouped-imports +from modules import logger gr_height = None max_units = shared.opts.control_max_units debug = os.environ.get('SD_CONTROL_DEBUG', None) is not None -debug_log = shared.log.trace if debug else lambda *args, **kwargs: None +debug_log = logger.log.trace if debug else lambda *args, **kwargs: None # state variables busy = False # used to synchronize select_input and generate_click @@ -25,7 +26,7 @@ def initialize(): from modules.control.units import xs # vislearn ControlNet-XS from modules.control.units import lite # vislearn ControlNet-XS from modules.control.units import t2iadapter # TencentARC T2I-Adapter - shared.log.debug(f'UI initialize: tab=control models="{shared.opts.control_dir}"') + logger.log.debug(f'UI initialize: tab=control models="{shared.opts.control_dir}"') controlnet.cache_dir = os.path.join(shared.opts.control_dir, 'controlnet') xs.cache_dir = os.path.join(shared.opts.control_dir, 'xs') lite.cache_dir = os.path.join(shared.opts.control_dir, 'lite') @@ -51,13 +52,13 @@ def initialize(): def caption(): prompt = None if input_source is None or len(input_source) == 0: - shared.log.warning('Caption: no input source') + logger.log.warning('Caption: no input source') return prompt try: from modules.caption.caption import caption as caption_fn prompt = caption_fn(input_source[0]) except Exception as e: - shared.log.error(f'Caption: {e}') + logger.log.error(f'Caption: {e}') return prompt @@ -71,12 +72,12 @@ def get_video(filepath: str): return '' try: frames, fps, duration, w, h, codec, _cap = video.get_video_params(filepath) - shared.log.debug(f'Control: input video: path={filepath} frames={frames} fps={fps} size={w}x{h} codec={codec}') + logger.log.debug(f'Control: input video: path={filepath} frames={frames} fps={fps} size={w}x{h} codec={codec}') msg = f'Control input | Video | Size {w}x{h} | Frames {frames} | FPS {fps:.2f} | Duration {duration:.2f} | Codec {codec}' return msg except Exception as e: msg = f'Control: video open failed: path={filepath} {e}' - shared.log.error(msg) + logger.log.error(msg) return msg @@ -98,7 +99,7 @@ def process_kanvas(x): # only used when kanvas overrides gr.Image object mask = helpers.decode_base64_to_image(mask_data) mask = mask.convert('L') t1 = time.time() - shared.log.debug(f'Kanvas: image={image}:{image_bytes} mask={mask}:{mask_bytes} time={t1-t0:.2f}') + logger.log.debug(f'Kanvas: image={image}:{image_bytes} mask={mask}:{mask_bytes} time={t1-t0:.2f}') return image, mask except Exception: pass @@ -122,7 +123,7 @@ def process_kanvas(x): # only used when kanvas overrides gr.Image object # mask = Image.merge("RGB", [alpha, alpha, alpha]) mask = mask.convert('L') t1 = time.time() - shared.log.debug(f'Kanvas: image={image} mask={mask} time={t1-t0:.2f}') + logger.log.debug(f'Kanvas: image={image} mask={mask} time={t1-t0:.2f}') except Exception: pass return image, mask @@ -201,7 +202,7 @@ def select_input(input_mode, input_image, init_image, init_type, input_video, in elif init_type == 2: # Separate init image input_init = [init_image] t1 = time.time() - shared.log.debug(f'Select input: type={input_type} source={input_source} init={input_init} mask={input_mask} mode={input_mode} time={t1-t0:.2f}') + logger.log.debug(f'Select input: type={input_type} source={input_source} init={input_init} mask={input_mask} mode={input_mode} time={t1-t0:.2f}') busy = False return res + size @@ -222,7 +223,7 @@ def copy_input(mode_from, mode_to, input_image, input_resize, input_inpaint): elif mode_to == 'Outpaint': return [None, getimg(input_image) if mode_from == 'Image' else getimg(input_inpaint), None] else: - shared.log.error(f'Control transfer unknown input: from={mode_from} to={mode_to}') + logger.log.error(f'Control transfer unknown input: from={mode_from} to={mode_to}') return [gr.update(), gr.update(), gr.update()] diff --git a/modules/ui_docs.py b/modules/ui_docs.py index a8e824b30..2bf4deb93 100644 --- a/modules/ui_docs.py +++ b/modules/ui_docs.py @@ -2,7 +2,8 @@ import os import time import gradio as gr from modules import ui_symbols, ui_components -from installer import install, log +from installer import install +from modules.logger import log class Page: diff --git a/modules/ui_extensions.py b/modules/ui_extensions.py index 8bc30dd24..f55e8cd5f 100644 --- a/modules/ui_extensions.py +++ b/modules/ui_extensions.py @@ -7,9 +7,10 @@ import re from datetime import datetime, timezone, timedelta import gradio as gr from modules import extensions, shared, paths, errors, ui_symbols, call_queue +from modules import logger -debug = shared.log.debug if os.environ.get('SD_EXT_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.debug if os.environ.get('SD_EXT_DEBUG', None) is not None else lambda *args, **kwargs: None extensions_index = "https://vladmandic.github.io/sd-data/pages/extensions.json" hide_tags = ["localization"] exclude_extensions = ['sdnext-modernui', 'sdnext-kanvas'] @@ -43,7 +44,7 @@ def list_extensions(): global extensions_list # pylint: disable=global-statement extensions_list = shared.readfile(extensions_data_file, silent=True, as_type="list") if len(extensions_list) == 0: - shared.log.info("Extension list: No information found. Refresh required.") + logger.log.info("Extension list: No information found. Refresh required.") found = [] for ext in extensions.extensions: ext.read_info() @@ -74,9 +75,9 @@ def list_extensions(): def apply_changes(disable_list, update_list, disable_all): if shared.cmd_opts.disable_extension_access: - shared.log.error('Extension: apply changes disallowed because public access is enabled and insecure is not specified') + logger.log.error('Extension: apply changes disallowed because public access is enabled and insecure is not specified') return - shared.log.debug(f'Extensions apply: disable={disable_list} update={update_list}') + logger.log.debug(f'Extensions apply: disable={disable_list} update={update_list}') disabled = json.loads(disable_list) assert type(disabled) == list, f"wrong disable_list data for apply_changes: {disable_list}" update = json.loads(update_list) @@ -97,12 +98,12 @@ def apply_changes(disable_list, update_list, disable_all): def check_updates(_id_task, disable_list, search_text, sort_column): if shared.cmd_opts.disable_extension_access: - shared.log.error('Extension: apply changes disallowed because public access is enabled and insecure is not specified') + logger.log.error('Extension: apply changes disallowed because public access is enabled and insecure is not specified') return create_html(search_text, sort_column) disabled = json.loads(disable_list) assert type(disabled) == list, f"wrong disable_list data for apply_and_restart: {disable_list}" exts = [ext for ext in extensions.extensions if ext.remote is not None and ext.name not in disabled] - shared.log.info(f'Extensions update check: update={len(exts)} disabled={len(disable_list)}') + logger.log.info(f'Extensions update check: update={len(exts)} disabled={len(disable_list)}') shared.state.job_count = len(exts) for ext in exts: shared.state.textinfo = ext.name @@ -112,10 +113,10 @@ def check_updates(_id_task, disable_list, search_text, sort_column): ext.git_fetch() ext.read_info() commit_date = ext.commit_date or 1577836800 - shared.log.info(f'Extensions updated: {ext.name} {ext.commit_hash[:8]} {extensions.format_dt(extensions.ts2utc(commit_date), seconds=True)}') + logger.log.info(f'Extensions updated: {ext.name} {ext.commit_hash[:8]} {extensions.format_dt(extensions.ts2utc(commit_date), seconds=True)}') else: commit_date = ext.commit_date or 1577836800 - shared.log.debug(f'Extensions no update available: {ext.name} {ext.commit_hash[:8]} {extensions.format_dt(extensions.ts2utc(commit_date), seconds=True)}') + logger.log.debug(f'Extensions no update available: {ext.name} {ext.commit_hash[:8]} {extensions.format_dt(extensions.ts2utc(commit_date), seconds=True)}') except FileNotFoundError as e: if 'FETCH_HEAD' not in str(e): raise @@ -131,18 +132,18 @@ def normalize_git_url(url: str | None) -> str: def install_extension_from_url(dirname, url, branch_name, search_text, sort_column): if shared.cmd_opts.disable_extension_access: - shared.log.error('Extension: apply changes disallowed because public access is enabled and insecure is not specified') + logger.log.error('Extension: apply changes disallowed because public access is enabled and insecure is not specified') return ['', ''] url = normalize_git_url(url) if not url: - shared.log.error('Extension: url is not specified') + logger.log.error('Extension: url is not specified') return ['', ''] if not dirname: dirname = url.split('/')[-1] target_dir = os.path.join(extensions.extensions_dir, dirname) - shared.log.info(f'Installing extension: {url} into {target_dir}') + logger.log.info(f'Installing extension: {url} into {target_dir}') if os.path.exists(target_dir): - shared.log.error(f'Extension: path="{target_dir}" directory already exists') + logger.log.error(f'Extension: path="{target_dir}" directory already exists') return ['', ''] if any(normalize_git_url(x.remote) == url for x in extensions.extensions): return ['', "Extension with this URL is already installed"] @@ -162,7 +163,7 @@ def install_extension_from_url(dirname, url, branch_name, search_text, sort_colu ssh = os.environ.get('GIT_SSH_COMMAND', None) if ssh: args['env'] = {'GIT_SSH_COMMAND':ssh} - shared.log.debug(f'GIT: {args}') + logger.log.debug(f'GIT: {args}') with git.Repo.clone_from(**args) as repo: repo.remote().fetch(verbose=True) for submodule in repo.submodules: @@ -182,12 +183,12 @@ def install_extension_from_url(dirname, url, branch_name, search_text, sort_colu except Exception as e: # errors.display(e, 'GIT') shutil.rmtree(tmpdir, True) - shared.log.error(f'Error installing extension: {url} {e}') + logger.log.error(f'Error installing extension: {url} {e}') return ['', str(e).replace('\n', '
')] def install_extension(extension_to_install, search_text, sort_column): - shared.log.info(f'Extension install: {extension_to_install}') + logger.log.info(f'Extension install: {extension_to_install}') code, message = install_extension_from_url(None, extension_to_install, None, search_text, sort_column) return code, message @@ -196,9 +197,9 @@ def uninstall_extension(extension_path, search_text, sort_column): def errorRemoveReadonly(func, path, exc): import stat excvalue = exc[1] - shared.log.debug(f'Exception during cleanup: {func} {path} {excvalue.strerror}') + logger.log.debug(f'Exception during cleanup: {func} {path} {excvalue.strerror}') if func in (os.rmdir, os.remove, os.unlink) and excvalue.errno == errno.EACCES: - shared.log.debug(f'Retrying cleanup: {path}') + logger.log.debug(f'Retrying cleanup: {path}') os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) func(path) @@ -209,15 +210,15 @@ def uninstall_extension(extension_path, search_text, sort_column): shutil.rmtree(found.path, ignore_errors=False, onerror=errorRemoveReadonly) # pylint: disable=deprecated-argument # extensions.extensions = [extension for extension in extensions.extensions if os.path.abspath(found.path) != os.path.abspath(extension_path)] except Exception as e: - shared.log.warning(f'Extension uninstall failed: {found.path} {e}') + logger.log.warning(f'Extension uninstall failed: {found.path} {e}') list_extensions() global extensions_list # pylint: disable=global-statement extensions_list = [ext for ext in extensions_list if ext['name'] != found.name] - shared.log.info(f'Extension uninstalled: {found.path}') + logger.log.info(f'Extension uninstalled: {found.path}') code = create_html(search_text, sort_column) return code, f"Extension uninstalled: {found.path} | Restart required" else: - shared.log.warning(f'Extension uninstall cannot find extension: {extension_path}') + logger.log.warning(f'Extension uninstall cannot find extension: {extension_path}') code = create_html(search_text, sort_column) return code, f"Extension uninstalled failed: {extension_path}" @@ -226,7 +227,7 @@ def update_extension(extension_path, search_text, sort_column): exts = [extension for extension in extensions.extensions if os.path.abspath(extension.path) == os.path.abspath(extension_path)] shared.state.job_count = len(exts) for ext in exts: - shared.log.debug(f'Extensions update start: {ext.name} {ext.commit_hash} {ext.commit_date}') + logger.log.debug(f'Extensions update start: {ext.name} {ext.commit_hash} {ext.commit_date}') shared.state.textinfo = ext.name try: ext.check_updates() @@ -234,17 +235,17 @@ def update_extension(extension_path, search_text, sort_column): ext.git_fetch() ext.read_info() commit_date = ext.commit_date or 1577836800 - shared.log.info(f'Extensions updated: {ext.name} {ext.commit_hash[:8]} {extensions.format_dt(extensions.ts2utc(commit_date), seconds=True)}') + logger.log.info(f'Extensions updated: {ext.name} {ext.commit_hash[:8]} {extensions.format_dt(extensions.ts2utc(commit_date), seconds=True)}') else: commit_date = ext.commit_date or 1577836800 - shared.log.info(f'Extensions no update available: {ext.name} {ext.commit_hash[:8]} {extensions.format_dt(extensions.ts2utc(commit_date), seconds=True)}') + logger.log.info(f'Extensions no update available: {ext.name} {ext.commit_hash[:8]} {extensions.format_dt(extensions.ts2utc(commit_date), seconds=True)}') except FileNotFoundError as e: if 'FETCH_HEAD' not in str(e): raise except Exception as e: - shared.log.error(f'Extensions update failed: {ext.name}') + logger.log.error(f'Extensions update failed: {ext.name}') errors.display(e, f'extensions check update: {ext.name}') - shared.log.debug(f'Extensions update finish: {ext.name} {ext.commit_hash} {ext.commit_date}') + logger.log.debug(f'Extensions update finish: {ext.name} {ext.commit_hash} {ext.commit_date}') shared.state.nextjob() return create_html(search_text, sort_column), f"Extension updated | {extension_path} | Restart required" @@ -254,7 +255,7 @@ def refresh_extensions_list(search_text, sort_column): import ssl import urllib.request try: - shared.log.debug(f'Updating extensions list: url={extensions_index}') + logger.log.debug(f'Updating extensions list: url={extensions_index}') context = ssl._create_unverified_context() # pylint: disable=protected-access with urllib.request.urlopen(extensions_index, timeout=3.0, context=context) as response: text = response.read() @@ -262,9 +263,9 @@ def refresh_extensions_list(search_text, sort_column): with open(extensions_data_file, "w", encoding="utf-8") as outfile: json_object = json.dumps(extensions_list, indent=2) outfile.write(json_object) - shared.log.info(f'Updated extensions list: items={len(extensions_list)} url={extensions_index}') + logger.log.info(f'Updated extensions list: items={len(extensions_list)} url={extensions_index}') except Exception as e: - shared.log.warning(f'Updated extensions list failed: {extensions_index} {e}') + logger.log.warning(f'Updated extensions list failed: {extensions_index} {e}') list_extensions() code = create_html(search_text, sort_column) return code, f'Extensions | {len(extensions.extensions)} registered | {len(extensions_list)} available' @@ -282,7 +283,7 @@ def make_wrappable_html(text: str) -> str: def create_html(search_text, sort_column): - # shared.log.debug(f'Extensions manager: refresh list search="{search_text}" sort="{sort_column}"') + # logger.log.debug(f'Extensions manager: refresh list search="{search_text}" sort="{sort_column}"') code = """
@@ -429,12 +430,12 @@ def create_html(search_text, sort_column): """ code += "
{install_code}
" - shared.log.debug(f'Extension list: processed={stats["processed"]} installed={stats["installed"]} enabled={stats["enabled"]} disabled={stats["installed"] - stats["enabled"]} visible={stats["processed"] - stats["hidden"]} hidden={stats["hidden"]}') + logger.log.debug(f'Extension list: processed={stats["processed"]} installed={stats["installed"]} enabled={stats["enabled"]} disabled={stats["installed"] - stats["enabled"]} visible={stats["processed"] - stats["hidden"]} hidden={stats["hidden"]}') return code def create_ui(): - shared.log.debug('UI initialize: tab=extensions') + logger.log.debug('UI initialize: tab=extensions') extensions_disable_all = gr.Radio(label="Disable all extensions", choices=["none", "user", "all"], value=shared.opts.disable_all_extensions, elem_id="extensions_disable_all", visible=False) extensions_disabled_list = gr.Textbox(elem_id="extensions_disabled_list", visible=False, container=False) extensions_update_list = gr.Textbox(elem_id="extensions_update_list", visible=False, container=False) diff --git a/modules/ui_extra_networks.py b/modules/ui_extra_networks.py index 063580f51..96f6156f0 100644 --- a/modules/ui_extra_networks.py +++ b/modules/ui_extra_networks.py @@ -17,12 +17,13 @@ import gradio as gr from PIL import Image from starlette.responses import FileResponse, JSONResponse from modules import paths, shared, files_cache, errors, infotext, ui_symbols, ui_components, modelstats +from modules import logger allowed_dirs = [] refresh_time = 0 extra_pages = shared.extra_networks -debug = shared.log.trace if os.environ.get('SD_EN_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_EN_DEBUG', None) is not None else lambda *args, **kwargs: None debug('Trace: EN') card_full = '''
@@ -77,7 +78,7 @@ def init_api(): metadata = page_dict.metadata.get(item, 'none') if metadata is None: metadata = '' - # shared.log.debug(f"Networks metadata: page='{page}' item={item} len={len(metadata)}") + # logger.log.debug(f"Networks metadata: page='{page}' item={item} len={len(metadata)}") return JSONResponse({"metadata": metadata}) def get_info(page: str = "", item: str = ""): @@ -90,7 +91,7 @@ def init_api(): info = page_dict.find_info(item_dict.get('filename', None) or item_dict.get('name', None)) if info is None: info = {} - # shared.log.debug(f"Networks info: page='{page.name}' item={item['name']} len={len(info)}") + # logger.log.debug(f"Networks info: page='{page.name}' item={item['name']} len={len(info)}") return JSONResponse({"info": info}) def get_desc(page: str = "", item: str = ""): @@ -103,7 +104,7 @@ def init_api(): desc = page_dict.find_description(item_dict.get('filename', None) or item_dict.get('name', None)) if desc is None: desc = '' - # shared.log.debug(f"Networks desc: page='{page.name}' item={item['name']} len={len(desc)}") + # logger.log.debug(f"Networks desc: page='{page.name}' item={item['name']} len={len(desc)}") return JSONResponse({"description": desc}) def get_network(page: str = "", item: str = ""): @@ -235,7 +236,7 @@ class ExtraNetworksPage: img.load() except Exception as e: img = None - shared.log.warning(f'Network removing invalid: image={f} {e}') + logger.log.warning(f'Network removing invalid: image={f} {e}') try: if img is None: img = None @@ -248,10 +249,10 @@ class ExtraNetworksPage: img.close() created += 1 except Exception as e: - shared.log.warning(f'Network create thumbnail={f} {e}') + logger.log.warning(f'Network create thumbnail={f} {e}') errors.display(e, 'thumbnail') if created > 0: - shared.log.info(f'Network thumbnails: type={self.name} created={created}') + logger.log.info(f'Network thumbnails: type={self.name} created={created}') self.missing_thumbs.clear() def create_items(self, tabname): @@ -263,7 +264,7 @@ class ExtraNetworksPage: self.refresh_time = time.time() except Exception as e: self.items = [] - shared.log.error(f'Networks: listing items class={self.__class__.__name__} tab={tabname} {e}') + logger.log.error(f'Networks: listing items class={self.__class__.__name__} tab={tabname} {e}') if os.environ.get('SD_EN_DEBUG', None): errors.display(e, f'Networks: listing items: class={self.__class__.__name__} tab={tabname}') for item in self.items: @@ -375,7 +376,7 @@ class ExtraNetworksPage: self.html += ''.join(htmls) self.page_time = time.time() self.html = f"""
{subdirs_html}{versions_html}
{self.html}
""" - shared.log.debug(f'Networks: type="{self.name}" items={len(self.items)} subfolders={len(subdirs)} tab={tabname} folders={self.allowed_directories_for_previews()} list={self.list_time:.2f} thumb={self.preview_time:.2f} desc={self.desc_time:.2f} info={self.info_time:.2f} workers={shared.max_workers}') + logger.log.debug(f'Networks: type="{self.name}" items={len(self.items)} subfolders={len(subdirs)} tab={tabname} folders={self.allowed_directories_for_previews()} list={self.list_time:.2f} thumb={self.preview_time:.2f} desc={self.desc_time:.2f} info={self.info_time:.2f} workers={shared.max_workers}') if len(self.missing_thumbs) > 0: threading.Thread(target=self.create_thumb).start() return self.patch(self.html, tabname) @@ -422,7 +423,7 @@ class ExtraNetworksPage: # args['title'] += f'\nAlias: {alias}' return self.card.format(**args) except Exception as e: - shared.log.error(f'Networks: item error: page={tabname} item={item["name"]} {e}') + logger.log.error(f'Networks: item error: page={tabname} item={item["name"]} {e}') if os.environ.get('SD_EN_DEBUG', None) is not None: errors.display(e, 'Networks') return "" @@ -680,10 +681,10 @@ def create_ui(container, button_parent, tabname, skip_indexing = False): nonlocal state state = SimpleNamespace(**json.loads(state_text)) except Exception as e: - shared.log.error(f'Networks: state error: {e}') + logger.log.error(f'Networks: state error: {e}') return _page, _item = get_item(state) - # shared.log.debug(f'Extra network: op={state.op} page={page.title if page is not None else None} item={item.filename if item is not None else None}') + # logger.log.debug(f'Extra network: op={state.op} page={page.title if page is not None else None} item={item.filename if item is not None else None}') def toggle_visibility(is_visible): is_visible = not is_visible @@ -779,13 +780,13 @@ def create_ui(container, button_parent, tabname, skip_indexing = False): if ui.gallery is not None: images = list(ui.gallery.temp_files) # gallery cannot be used as input component so looking at most recently registered temp files if len(images) < 1: - shared.log.warning(f'Network no image: item="{ui.last_item.name}"') + logger.log.warning(f'Network no image: item="{ui.last_item.name}"') return 'html/missing.png' try: images.sort(key=lambda f: os.path.getmtime(f), reverse=True) image = Image.open(images[0]) except Exception as e: - shared.log.error(f'Network error opening image: item="{ui.last_item.name}" {e}') + logger.log.error(f'Network error opening image: item="{ui.last_item.name}" {e}') return 'html/missing.png' fn_delete_img(image) if image.width > 512 or image.height > 512: @@ -793,9 +794,9 @@ def create_ui(container, button_parent, tabname, skip_indexing = False): image.thumbnail((512, 512), Image.Resampling.HAMMING) try: image.save(ui.last_item.local_preview, quality=50) - shared.log.debug(f'Networks save image: item="{ui.last_item.name}" filename="{ui.last_item.local_preview}"') + logger.log.debug(f'Networks save image: item="{ui.last_item.name}" filename="{ui.last_item.local_preview}"') except Exception as e: - shared.log.error(f'Network save image: item="{ui.last_item.name}" filename="{ui.last_item.local_preview}" {e}') + logger.log.error(f'Network save image: item="{ui.last_item.name}" filename="{ui.last_item.local_preview}" {e}') return image def fn_delete_img(_image): @@ -804,7 +805,7 @@ def create_ui(container, button_parent, tabname, skip_indexing = False): for file in [f'{fn}{mid}{ext}' for ext in preview_extensions for mid in ['.thumb.', '.preview.', '.']]: if os.path.exists(file): os.remove(file) - shared.log.debug(f'Network delete image: item="{ui.last_item.name}" filename="{file}"') + logger.log.debug(f'Network delete image: item="{ui.last_item.name}" filename="{file}"') return 'html/missing.png' def fn_save_desc(desc): @@ -816,7 +817,7 @@ def create_ui(container, button_parent, tabname, skip_indexing = False): fn = os.path.splitext(ui.last_item.filename)[0] + '.txt' with open(fn, 'w', encoding='utf-8') as f: f.write(desc) - shared.log.debug(f'Network save desc: item="{ui.last_item.name}" filename="{fn}"') + logger.log.debug(f'Network save desc: item="{ui.last_item.name}" filename="{fn}"') return desc def fn_delete_network(desc): @@ -830,7 +831,7 @@ def create_ui(container, button_parent, tabname, skip_indexing = False): if os.path.exists(fn) and os.path.isfile(fn): candidates.append(fn) msg = f'Network delete: item="{ui.last_item.name}" files={candidates}' - shared.log.debug(msg) + logger.log.debug(msg) for fn in candidates: os.remove(fn) return msg @@ -838,12 +839,12 @@ def create_ui(container, button_parent, tabname, skip_indexing = False): def fn_save_info(info): fn = os.path.splitext(ui.last_item.filename)[0] + '.json' shared.writefile(info, fn, silent=True) - shared.log.debug(f'Network save info: item="{ui.last_item.name}" filename="{fn}"') + logger.log.debug(f'Network save info: item="{ui.last_item.name}" filename="{fn}"') return info def fn_save_style(info, description, prompt, negative, extra, wildcards): if not isinstance(info, dict) or isinstance(info, list): - shared.log.warning(f'Network save style skip: item="{ui.last_item.name}" not a dict: {type(info)}') + logger.log.warning(f'Network save style skip: item="{ui.last_item.name}" not a dict: {type(info)}') return info if ui.last_item is None: return info @@ -851,7 +852,7 @@ def create_ui(container, button_parent, tabname, skip_indexing = False): if hasattr(ui.last_item, 'type') and ui.last_item.type == 'Style': info.update(**{ 'description': description, 'prompt': prompt, 'negative': negative, 'extra': extra, 'wildcards': wildcards }) shared.writefile(info, fn, silent=True) - shared.log.debug(f'Network save style: item="{ui.last_item.name}" filename="{fn}"') + logger.log.debug(f'Network save style: item="{ui.last_item.name}" filename="{fn}"') return info def fn_delete_style(info): @@ -859,7 +860,7 @@ def create_ui(container, button_parent, tabname, skip_indexing = False): return info fn = os.path.splitext(ui.last_item.filename)[0] + '.json' if os.path.exists(fn): - shared.log.debug(f'Network delete style: item="{ui.last_item.name}" filename="{fn}"') + logger.log.debug(f'Network delete style: item="{ui.last_item.name}" filename="{fn}"') os.remove(fn) return {} return info @@ -894,7 +895,7 @@ def create_ui(container, button_parent, tabname, skip_indexing = False): info = fullinfo if isinstance(info, list): item.filename = None - shared.log.warning('Network: show details not supported for compound item') + logger.log.warning('Network: show details not supported for compound item') info = None if prompt is not None and len(prompt) > 0: item.prompt = prompt @@ -1018,7 +1019,7 @@ def create_ui(container, button_parent, tabname, skip_indexing = False): page.refresh_time = 0 page.refresh() page.create_page(ui.tabname) - shared.log.debug(f'Networks: refresh page="{page.title}" items={len(page.items)} tab={ui.tabname}') + logger.log.debug(f'Networks: refresh page="{page.title}" items={len(page.items)} tab={ui.tabname}') pages.append(page.html) ui.search.update(title) return pages @@ -1027,7 +1028,7 @@ def create_ui(container, button_parent, tabname, skip_indexing = False): pages = [] for page in get_pages(): page.switch_view(ui.tabname) - shared.log.debug(f'Networks: refresh page="{page.title}" items={len(page.items)} tab={ui.tabname} view={page.view}') + logger.log.debug(f'Networks: refresh page="{page.title}" items={len(page.items)} tab={ui.tabname} view={page.view}') pages.append(page.html) ui.search.update(title) return pages @@ -1055,7 +1056,7 @@ def create_ui(container, button_parent, tabname, skip_indexing = False): def ui_quicksave_click(name): if name is None or len(name) < 1: - shared.log.warning("Network quick save style: no name provided") + logger.log.warning("Network quick save style: no name provided") return from modules.processing_info import get_last_args params, text = get_last_args() @@ -1078,9 +1079,9 @@ def create_ui(container, button_parent, tabname, skip_indexing = False): } shared.writefile(item, fn, silent=True) if len(prompt) > 0: - shared.log.debug(f'Networks type=style quicksave style: item="{name}" filename="{fn}" prompt="{prompt}"') + logger.log.debug(f'Networks type=style quicksave style: item="{name}" filename="{fn}" prompt="{prompt}"') else: - shared.log.warning(f'Networks type=style quicksave model: item="{name}" filename="{fn}" prompt is empty') + logger.log.warning(f'Networks type=style quicksave model: item="{name}" filename="{fn}" prompt is empty') def ui_sort_cards(sort_order): if shared.opts.extra_networks_sort != sort_order: diff --git a/modules/ui_extra_networks_checkpoints.py b/modules/ui_extra_networks_checkpoints.py index 65078ef97..e88393da0 100644 --- a/modules/ui_extra_networks_checkpoints.py +++ b/modules/ui_extra_networks_checkpoints.py @@ -4,6 +4,7 @@ import json import concurrent from datetime import datetime from modules import shared, ui_extra_networks, sd_models, modelstats, paths, devices +from modules import logger from modules.json_helpers import readfile @@ -39,7 +40,7 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage): return any(model.endswith(url) for model in existing) if not shared.opts.sd_checkpoint_autodownload or not shared.opts.extra_network_reference_enable: - shared.log.debug(f'Networks: type="reference" autodownload={shared.opts.sd_checkpoint_autodownload} enable={shared.opts.extra_network_reference_enable}') + logger.log.debug(f'Networks: type="reference" autodownload={shared.opts.sd_checkpoint_autodownload} enable={shared.opts.extra_network_reference_enable}') return [] count = { 'total': 0, 'ready': 0, 'hidden': 0, 'experimental': 0, 'base': 0 } @@ -66,7 +67,7 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage): experimental = v.get('experimental', False) if experimental: if shared.cmd_opts.experimental: - shared.log.debug(f'Networks: experimental model="{k}"') + logger.log.debug(f'Networks: experimental model="{k}"') count['experimental'] += 1 else: continue @@ -125,7 +126,7 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage): "version": version, "tags": tag, } - shared.log.debug(f'Networks: type="reference" {count}') + logger.log.debug(f'Networks: type="reference" {count}') def create_item(self, name): record = None @@ -155,7 +156,7 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage): record['version'] = version_map.get(record['version'], record['version']) except Exception as e: - shared.log.debug(f'Networks error: type=model file="{name}" {e}') + logger.log.debug(f'Networks error: type=model file="{name}" {e}') return record def list_items(self): diff --git a/modules/ui_extra_networks_history.py b/modules/ui_extra_networks_history.py index 44a9df050..42911000a 100644 --- a/modules/ui_extra_networks_history.py +++ b/modules/ui_extra_networks_history.py @@ -2,23 +2,24 @@ import time import json import html from modules import shared, ui_extra_networks +from modules import logger class ExtraNetworksPageHistory(ui_extra_networks.ExtraNetworksPage): def __init__(self): - # shared.log.trace('History init') + # logger.log.trace('History init') super().__init__('History') self.last_refresh = 0 def refresh(self): - # shared.log.trace('History refresh') + # logger.log.trace('History refresh') self.last_refresh = time.time() self.html = '

buttons

' for ts in shared.history.list: self.html += '

' + str(ts) + '

' def list_items(self): - # shared.log.trace('History list') + # logger.log.trace('History list') for item in shared.history.latents: title = ', '.join(list(set(item.ops))) + '
' + item.name yield { diff --git a/modules/ui_extra_networks_lora.py b/modules/ui_extra_networks_lora.py index 5a11f85ab..3e6b72ebd 100644 --- a/modules/ui_extra_networks_lora.py +++ b/modules/ui_extra_networks_lora.py @@ -2,6 +2,7 @@ import os import json import concurrent from modules import shared, ui_extra_networks, modelstats +from modules import logger from modules.lora import lora_load @@ -72,7 +73,7 @@ class ExtraNetworksPageLora(ui_extra_networks.ExtraNetworksPage): def create_item(self, name): l = lora_load.available_networks.get(name) if l is None: - shared.log.warning(f'Networks: type=lora registered={len(list(lora_load.available_networks))} file="{name}" not registered') + logger.log.warning(f'Networks: type=lora registered={len(list(lora_load.available_networks))} file="{name}" not registered') return None try: # path, _ext = os.path.splitext(l.filename) @@ -97,7 +98,7 @@ class ExtraNetworksPageLora(ui_extra_networks.ExtraNetworksPage): } return item except Exception as e: - shared.log.error(f'Networks: type=lora file="{name}" {e}') + logger.log.error(f'Networks: type=lora file="{name}" {e}') if debug: from modules import errors errors.display(e, 'Lora') diff --git a/modules/ui_extra_networks_styles.py b/modules/ui_extra_networks_styles.py index 7c9bc40dd..8426b540c 100644 --- a/modules/ui_extra_networks_styles.py +++ b/modules/ui_extra_networks_styles.py @@ -3,6 +3,7 @@ import html import json from datetime import datetime from modules import shared, extra_networks, ui_extra_networks, styles +from modules import logger class ExtraNetworksPageStyles(ui_extra_networks.ExtraNetworksPage): @@ -95,7 +96,7 @@ class ExtraNetworksPageStyles(ui_extra_networks.ExtraNetworksPage): "size": os.path.getsize(style.filename), } except Exception as e: - shared.log.debug(f'Networks error: type=style file="{k}" {e}') + logger.log.debug(f'Networks error: type=style file="{k}" {e}') return item def list_items(self): diff --git a/modules/ui_extra_networks_textual_inversion.py b/modules/ui_extra_networks_textual_inversion.py index 6857447f2..ca8e6d571 100644 --- a/modules/ui_extra_networks_textual_inversion.py +++ b/modules/ui_extra_networks_textual_inversion.py @@ -1,6 +1,7 @@ import json import os from modules import shared, sd_models, ui_extra_networks, files_cache, modelstats +from modules import logger from modules.textual_inversion import Embedding @@ -38,7 +39,7 @@ class ExtraNetworksPageTextualInversion(ui_extra_networks.ExtraNetworksPage): "description": self.find_description(embedding.filename, info), } except Exception as e: - shared.log.debug(f'Networks error: type=embedding file="{embedding.filename}" {e}') + logger.log.debug(f'Networks error: type=embedding file="{embedding.filename}" {e}') return record def list_items(self): diff --git a/modules/ui_extra_networks_vae.py b/modules/ui_extra_networks_vae.py index c62f7b3ab..e19babf74 100644 --- a/modules/ui_extra_networks_vae.py +++ b/modules/ui_extra_networks_vae.py @@ -2,6 +2,7 @@ import html import json import os from modules import shared, ui_extra_networks, sd_vae, hashes, modelstats +from modules import logger class ExtraNetworksPageVAEs(ui_extra_networks.ExtraNetworksPage): @@ -36,7 +37,7 @@ class ExtraNetworksPageVAEs(ui_extra_networks.ExtraNetworksPage): } yield record except Exception as e: - shared.log.debug(f'Networks error: type=vae file="{filename}" {e}') + logger.log.debug(f'Networks error: type=vae file="{filename}" {e}') def allowed_directories_for_previews(self): return [v for v in [shared.opts.vae_dir] if v is not None] diff --git a/modules/ui_extra_networks_wildcards.py b/modules/ui_extra_networks_wildcards.py index a139e7e0d..5f9adeab6 100644 --- a/modules/ui_extra_networks_wildcards.py +++ b/modules/ui_extra_networks_wildcards.py @@ -1,6 +1,7 @@ import os import json from modules import shared, ui_extra_networks, modelstats, files_cache +from modules import logger wildcards_list = [] @@ -44,7 +45,7 @@ class ExtraNetworksPageWildcards(ui_extra_networks.ExtraNetworksPage): } yield record except Exception as e: - shared.log.debug(f'Networks error: type=wildcard file="{filename}" {e}') + logger.log.debug(f'Networks error: type=wildcard file="{filename}" {e}') def allowed_directories_for_previews(self): return [v for v in [shared.opts.wildcards_dir] if v is not None] diff --git a/modules/ui_gallery.py b/modules/ui_gallery.py index f22bc1a1a..0729bf80f 100644 --- a/modules/ui_gallery.py +++ b/modules/ui_gallery.py @@ -3,13 +3,14 @@ from urllib.parse import unquote import gradio as gr from PIL import Image from modules import shared, ui_symbols, ui_common, images, video, modelstats +from modules import logger from modules.ui_components import ToolButton def read_media(fn): fn = unquote(fn).replace('%3A', ':') if not os.path.isfile(fn): - shared.log.error(f'Gallery not found: file="{fn}"') + logger.log.error(f'Gallery not found: file="{fn}"') return [[], None, '', '', f'Media not found: {fn}'] stat_size, stat_mtime = modelstats.stat(fn) # Treat common containers as video for preview; Gradio/HTML5 will handle codec support. @@ -28,7 +29,7 @@ def read_media(fn): | Modified {stat_mtime}


''' except Exception as e: # keep preview even if probing fails - shared.log.warning(f'Video probe failed: file="{fn}" {e}') + logger.log.warning(f'Video probe failed: file="{fn}" {e}') log = f'''

Video | Size {stat_size:,} @@ -54,7 +55,7 @@ def read_media(fn): def create_ui(): - shared.log.debug('UI initialize: tab=gallery') + logger.log.debug('UI initialize: tab=gallery') with gr.Blocks() as tab: with gr.Row(elem_id='tab-gallery-sort-buttons'): sort_buttons = [] diff --git a/modules/ui_img2img.py b/modules/ui_img2img.py index 7828bc8ab..add0897ff 100644 --- a/modules/ui_img2img.py +++ b/modules/ui_img2img.py @@ -1,6 +1,7 @@ import gradio as gr from modules import timer, shared, call_queue, generation_parameters_copypaste, processing_vae from modules import ui_common, ui_sections, ui_guidance +from modules import logger def process_caption(mode, ii_input_files, ii_input_dir, ii_output_dir, *ii_singles): @@ -17,7 +18,7 @@ def process_caption(mode, ii_input_files, ii_input_dir, ii_output_dir, *ii_singl images = [f.name for f in ii_input_files] else: if not os.path.isdir(ii_input_dir): - shared.log.error(f"Caption: Input directory not found: {ii_input_dir}") + logger.log.error(f"Caption: Input directory not found: {ii_input_dir}") return [gr.update(), None] images = os.listdir(ii_input_dir) if ii_output_dir != "": @@ -33,7 +34,7 @@ def process_caption(mode, ii_input_files, ii_input_dir, ii_output_dir, *ii_singl def create_ui(): - shared.log.debug('UI initialize: tab=img2img') + logger.log.debug('UI initialize: tab=img2img') import modules.img2img # pylint: disable=redefined-outer-name modules.scripts_manager.scripts_current = modules.scripts_manager.scripts_img2img modules.scripts_manager.scripts_img2img.initialize_scripts(is_img2img=True, is_control=False) diff --git a/modules/ui_javascript.py b/modules/ui_javascript.py index 5c5f966a8..e2ae619ef 100644 --- a/modules/ui_javascript.py +++ b/modules/ui_javascript.py @@ -4,6 +4,7 @@ import gradio.utils from modules import shared, theme from modules.paths import script_path, data_path import modules.scripts_manager +from modules import logger def webpath(fn): @@ -81,17 +82,17 @@ def html_css(css: list[str]): themecss = os.path.join(script_path, "javascript", f"{modules.shared.opts.gradio_theme}.css") if os.path.exists(themecss): head += stylesheet(themecss) - modules.shared.log.debug(f'UI theme: css="{themecss}" base="{css}" user="{usercss}"') + modules.logger.log.debug(f'UI theme: css="{themecss}" base="{css}" user="{usercss}"') else: - modules.shared.log.error(f'UI theme: css="{themecss}" not found') + modules.logger.log.error(f'UI theme: css="{themecss}" not found') elif modules.shared.opts.theme_type == 'Modern': theme_folder = next((e.path for e in modules.extensions.extensions if e.name == 'sdnext-modernui'), None) themecss = os.path.join(theme_folder or '', 'themes', f'{modules.shared.opts.gradio_theme}.css') if os.path.exists(themecss): head += stylesheet(themecss) - modules.shared.log.debug(f'UI theme: css="{themecss}" base="{css}" user="{usercss}"') + modules.logger.log.debug(f'UI theme: css="{themecss}" base="{css}" user="{usercss}"') else: - modules.shared.log.error(f'UI theme: css="{themecss}" not found') + modules.logger.log.error(f'UI theme: css="{themecss}" not found') if usercss is not None: head += stylesheet(usercss) return head diff --git a/modules/ui_loadsave.py b/modules/ui_loadsave.py index ff054f686..3b508418c 100644 --- a/modules/ui_loadsave.py +++ b/modules/ui_loadsave.py @@ -2,6 +2,7 @@ from typing import TYPE_CHECKING, cast import os import gradio as gr from modules import errors +from modules import logger from modules.ui_components import ToolButton @@ -46,7 +47,7 @@ class UiLoadsave: if init_field is not None: init_field(saved_value) if debug_ui and key in self.component_mapping and not key.startswith('customscript'): - errors.log.warning(f'UI duplicate: key="{key}" id={getattr(obj, "elem_id", None)} class={getattr(obj, "elem_classes", None)}') + logger.log.warning(f'UI duplicate: key="{key}" id={getattr(obj, "elem_id", None)} class={getattr(obj, "elem_classes", None)}') if hasattr(obj, 'skip'): pass if (field == 'value') and (key not in self.component_mapping): @@ -81,7 +82,7 @@ class UiLoadsave: if type(x) == gr.Dropdown: def check_dropdown(val): if x.choices is None: - errors.log.warning(f'UI: path={path} value={getattr(x, "value", None)}, choices={getattr(x, "choices", None)}') + logger.log.warning(f'UI: path={path} value={getattr(x, "value", None)}, choices={getattr(x, "choices", None)}') return False choices = [c[0] for c in x.choices] if type(x.choices) == list and len(x.choices) > 0 and type(x.choices[0]) == tuple else x.choices if getattr(x, 'multiselect', False): @@ -232,7 +233,7 @@ class UiLoadsave: else: name, old_value, new_value, default_value = x component = self.component_mapping[name] - errors.log.debug(f'Settings: name={name} component={component} old={old_value} default={default_value} new={new_value}') + logger.log.debug(f'Settings: name={name} component={component} old={old_value} default={default_value} new={new_value}') num_changed += 1 current_ui_settings[name] = new_value # what = name.split('/')[-1] @@ -240,7 +241,7 @@ class UiLoadsave: if num_changed == 0: return "No changes" self.write_to_file(current_ui_settings) - errors.log.info(f'UI defaults saved: {self.filename} changes={num_changed} unchanged={num_unchanged}') + logger.log.info(f'UI defaults saved: {self.filename} changes={num_changed} unchanged={num_unchanged}') return f"Wrote {num_changed} changes" def ui_submenu_apply(self, items): @@ -266,21 +267,21 @@ class UiLoadsave: num_changed = 0 current_ui_settings = self.read_from_file() for name, _old_value, new_value, default_value in self.iter_menus(): - errors.log.debug(f'Settings: name={name} default={default_value} new={new_value}') + logger.log.debug(f'Settings: name={name} default={default_value} new={new_value}') num_changed += 1 current_ui_settings[name] = new_value if num_changed == 0: text += '
No changes' else: self.write_to_file(current_ui_settings) - errors.log.info(f'UI defaults saved: {self.filename}') + logger.log.info(f'UI defaults saved: {self.filename}') text += f'
Changes: {num_changed}' return text def ui_restore(self): if os.path.exists(self.filename): os.remove(self.filename) - errors.log.info(f'UI defaults reset: {self.filename}') + logger.log.info(f'UI defaults reset: {self.filename}') return "Restored system defaults for user interface" def create_ui(self): diff --git a/modules/ui_models_load.py b/modules/ui_models_load.py index d63a63d20..10386e499 100644 --- a/modules/ui_models_load.py +++ b/modules/ui_models_load.py @@ -6,24 +6,25 @@ import torch import diffusers from huggingface_hub import hf_hub_download from modules import shared, errors, shared_items, sd_models, sd_checkpoint, devices, model_quant, modelloader +from modules import logger debug_enabled = os.environ.get('SD_LOAD_DEBUG', None) -debug_log = shared.log.trace if debug_enabled else lambda *args, **kwargs: None +debug_log = logger.log.trace if debug_enabled else lambda *args, **kwargs: None components = [] def load_model(model: str, cls: str, repo: str, dataframes: list): if cls is None: - shared.log.error('Model load: class is None') + logger.log.error('Model load: class is None') return 'Model load: class is None' if repo is None: - shared.log.error('Model load: repo is None') + logger.log.error('Model load: repo is None') return 'Model load: repo is None' cls = getattr(diffusers, cls, None) if cls is None: cls = diffusers.AutoPipelineForText2Image - shared.log.info(f'Model load: name="{model}" cls={cls.__name__} repo="{repo}"') + logger.log.info(f'Model load: name="{model}" cls={cls.__name__} repo="{repo}"') kwargs = {} for df in dataframes: c = [x for x in components if x.id == df[0]] @@ -43,8 +44,8 @@ def load_model(model: str, cls: str, repo: str, dataframes: list): instance = c.load() if instance is not None: kwargs[c.name] = instance - shared.log.info(f'Model component: instance={instance.__class__.__name__}') - shared.log.info(f'Model load: name="{model}" cls={cls.__name__} repo="{repo}" preload={kwargs.keys()}') + logger.log.info(f'Model component: instance={instance.__class__.__name__}') + logger.log.info(f'Model load: name="{model}" cls={cls.__name__} repo="{repo}" preload={kwargs.keys()}') pipe = None if model == 'Current': for k, v in kwargs.items(): @@ -61,11 +62,11 @@ def load_model(model: str, cls: str, repo: str, dataframes: list): **kwargs, ) except Exception as e: - shared.log.error(f'Model load: name="{model}" {e}') + logger.log.error(f'Model load: name="{model}" {e}') errors.display(e, 'Model load') return f'Model load failed: {e}' if pipe is not None: - shared.log.info(f'Model load: name="{model}" cls={cls.__name__} repo="{repo}" instance={pipe.__class__.__name__}') + logger.log.info(f'Model load: name="{model}" cls={cls.__name__} repo="{repo}" instance={pipe.__class__.__name__}') shared.sd_model = pipe shared.sd_model.sd_checkpoint_info = sd_checkpoint.CheckpointInfo(repo) shared.sd_model.sd_model_hash = None @@ -206,7 +207,7 @@ class Component: debug_log(f'Model load component: name="{self.name}" cls={self.cls} no handler') return None except Exception as e: - shared.log.error(f'Model load component: name="{self.name}" {e}') + logger.log.error(f'Model load component: name="{self.name}" {e}') errors.display(e, 'Model load component') return None @@ -237,7 +238,7 @@ def create_ui(gr_status, gr_file): link = f'Link

{repo}' if repo else '' get_components(cls) dataframes = [c.dataframe() for c in components] - shared.log.debug(f'Model select: name="{model}" cls={name} repo="{repo}" link={link} components={len(components)}') + logger.log.debug(f'Model select: name="{model}" cls={name} repo="{repo}" link={link} components={len(components)}') return [name, repo, link, dataframes] def update_component(dataframes): @@ -257,7 +258,7 @@ def create_ui(gr_status, gr_file): def load_receipe(file_select): if file_select is not None and 'name' in file_select: fn = file_select['name'] - shared.log.debug(f'Load receipe: fn={fn}') + logger.log.debug(f'Load receipe: fn={fn}') return ['Load receipe not implemented yet', gr.update(label='Receipe .json file', file_types=['json'], visible=True)] # TODO loader: save receipe diff --git a/modules/ui_postprocessing.py b/modules/ui_postprocessing.py index 92c80697e..65aafa590 100644 --- a/modules/ui_postprocessing.py +++ b/modules/ui_postprocessing.py @@ -1,5 +1,6 @@ import gradio as gr from modules import scripts_manager, shared, ui_common, postprocessing, call_queue, generation_parameters_copypaste +from modules import logger def submit_info(image): @@ -18,7 +19,7 @@ def submit_process(tab_index, extras_image, image_batch, extras_batch_input_dir, def create_ui(): - shared.log.debug('UI initialize: tab=process') + logger.log.debug('UI initialize: tab=process') tab_index = gr.State(value=0) # pylint: disable=abstract-class-instantiated with gr.Row(equal_height=False, variant='compact', elem_classes="extras", elem_id="extras_tab"): with gr.Column(variant='compact'): diff --git a/modules/ui_sections.py b/modules/ui_sections.py index 4930446f2..635ed47ef 100644 --- a/modules/ui_sections.py +++ b/modules/ui_sections.py @@ -1,5 +1,6 @@ import gradio as gr from modules import shared, modelloader, ui_symbols, ui_common, sd_samplers +from modules import logger from modules.ui_components import ToolButton from modules.caption import caption @@ -69,7 +70,7 @@ def ar_change(ar, width, height): try: (w, h) = [float(x) for x in ar.split(':')] except Exception as e: - shared.log.warning(f"Invalid aspect ratio: {ar} {e}") + logger.log.warning(f"Invalid aspect ratio: {ar} {e}") return gr.update(), gr.update() if w > h: return gr.update(), gr.update(value=int(width * h / w)) @@ -199,48 +200,48 @@ def create_sampler_options(tabname): shared.opts.data['schedulers_use_thresholding'] = 'thresholding' in sampler_options shared.opts.data['schedulers_use_loworder'] = 'low order' in sampler_options shared.opts.data['schedulers_rescale_betas'] = 'rescale' in sampler_options - shared.log.debug(f'Sampler set options: {sampler_options}') + logger.log.debug(f'Sampler set options: {sampler_options}') shared.opts.save(silent=True) def set_sampler_timesteps(timesteps): - shared.log.debug(f'Sampler set options: timesteps={timesteps}') + logger.log.debug(f'Sampler set options: timesteps={timesteps}') shared.opts.schedulers_timesteps = timesteps shared.opts.save(silent=True) def set_sampler_spacing(spacing): - shared.log.debug(f'Sampler set options: spacing={spacing}') + logger.log.debug(f'Sampler set options: spacing={spacing}') shared.opts.schedulers_timestep_spacing = spacing shared.opts.save(silent=True) def set_sampler_sigma(sampler_sigma): - shared.log.debug(f'Sampler set options: sigma={sampler_sigma}') + logger.log.debug(f'Sampler set options: sigma={sampler_sigma}') shared.opts.schedulers_sigma = sampler_sigma shared.opts.save(silent=True) def set_sampler_order(sampler_order): - shared.log.debug(f'Sampler set options: order={sampler_order}') + logger.log.debug(f'Sampler set options: order={sampler_order}') shared.opts.schedulers_solver_order = sampler_order shared.opts.save(silent=True) def set_sampler_prediction(sampler_prediction): - shared.log.debug(f'Sampler set options: prediction={sampler_prediction}') + logger.log.debug(f'Sampler set options: prediction={sampler_prediction}') shared.opts.schedulers_prediction_type = sampler_prediction shared.opts.save(silent=True) def set_sampler_beta(sampler_beta): - shared.log.debug(f'Sampler set options: beta={sampler_beta}') + logger.log.debug(f'Sampler set options: beta={sampler_beta}') shared.opts.schedulers_beta_schedule = sampler_beta shared.opts.save(silent=True) def set_sampler_shift(sampler_shift, sampler_base_shift, sampler_max_shift): - shared.log.debug(f'Sampler set options: shift={sampler_shift} base={sampler_base_shift} max={sampler_max_shift}') + logger.log.debug(f'Sampler set options: shift={sampler_shift} base={sampler_base_shift} max={sampler_max_shift}') shared.opts.schedulers_shift = sampler_shift shared.opts.schedulers_base_shift = sampler_base_shift shared.opts.schedulers_max_shift = sampler_max_shift shared.opts.save(silent=True) def set_sigma_adjust(val, start, end): - shared.log.debug(f'Sampler set options: sigma={val} min={start} max={end}') + logger.log.debug(f'Sampler set options: sigma={val} min={start} max={end}') shared.opts.schedulers_sigma_adjust = val shared.opts.schedulers_sigma_adjust_min = start shared.opts.schedulers_sigma_adjust_max = end diff --git a/modules/ui_settings.py b/modules/ui_settings.py index 247325b3f..a64a3a6f0 100644 --- a/modules/ui_settings.py +++ b/modules/ui_settings.py @@ -2,6 +2,7 @@ import os import gradio as gr from modules import timer, shared, paths, theme, sd_models, modelloader, generation_parameters_copypaste, call_queue, script_callbacks from modules import ui_common, ui_loadsave, ui_history, ui_components, ui_symbols +from modules import logger text_settings = None # holds json of entire shared.opts @@ -91,14 +92,14 @@ def create_setting_component(key, is_quicksettings=False): try: res = comp(label=info.label, value=fun(), elem_id=elem_id, **args) except Exception as e: - shared.log.error(f'Error creating setting: {key} {e}') + logger.log.error(f'Error creating setting: {key} {e}') res = None if res is not None and not is_quicksettings: try: res.change(fn=None, inputs=res, _js=f'(val) => markIfModified("{key}", val)') except Exception as e: - shared.log.error(f'Quicksetting: component={res} {e}') + logger.log.error(f'Quicksetting: component={res} {e}') if dirty_indicator is not None: dirty_indicator.click(fn=lambda: shared.opts.get_default(key), outputs=[res], show_progress='hidden') dirtyable_setting.__exit__() @@ -108,7 +109,7 @@ def create_setting_component(key, is_quicksettings=False): def create_dirty_indicator(key, keys_to_reset, **kwargs): def get_default_values(): values = [shared.opts.get_default(key) for key in keys_to_reset] - shared.log.debug(f'Settings restore: section={key} keys={keys_to_reset} values={values}') + logger.log.debug(f'Settings restore: section={key} keys={keys_to_reset} values={values}') return values elements_to_reset = [shared.settings_components[_key] for _key in keys_to_reset if shared.settings_components[_key] is not None] @@ -123,10 +124,10 @@ def run_settings(*args): if comp == dummy_component or value=='dummy': # or getattr(comp, 'visible', True) is False or key in hidden_list: # actual = shared.opts.data.get(key, None) # ensure the key is in data # default = shared.opts.data_labels[key].default - # shared.log.warning(f'Setting skip: key={key} value={value} actual={actual} default={default} comp={comp}') + # logger.log.warning(f'Setting skip: key={key} value={value} actual={actual} default={default} comp={comp}') continue if not shared.opts.same_type(value, shared.opts.data_labels[key].default): - shared.log.error(f'Setting bad value: {key}={value} expecting={type(shared.opts.data_labels[key].default).__name__}') + logger.log.error(f'Setting bad value: {key}={value} expecting={type(shared.opts.data_labels[key].default).__name__}') continue if shared.opts.set(key, value): changed.append(key) @@ -139,20 +140,20 @@ def run_settings(*args): directml_override_opts() if shared.cmd_opts.use_openvino: if "Model" not in shared.opts.cuda_compile: - shared.log.warning("OpenVINO: Enabling Torch Compile Model") + logger.log.warning("OpenVINO: Enabling Torch Compile Model") shared.opts.cuda_compile.append("Model") if shared.opts.cuda_compile_backend != "openvino_fx": - shared.log.warning("OpenVINO: Setting Torch Compiler backend to OpenVINO FX") + logger.log.warning("OpenVINO: Setting Torch Compiler backend to OpenVINO FX") shared.opts.cuda_compile_backend = "openvino_fx" if shared.opts.sd_backend != "diffusers": - shared.log.error('Legacy option: backend=original is no longer supported') + logger.log.error('Legacy option: backend=original is no longer supported') shared.opts.sd_backend = "diffusers" try: if len(changed) > 0: shared.opts.save() - shared.log.info(f'Settings: changed={len(changed)} {changed}') + logger.log.info(f'Settings: changed={len(changed)} {changed}') except RuntimeError: - shared.log.error(f'Settings failed: change={len(changed)} {changed}') + logger.log.error(f'Settings failed: change={len(changed)} {changed}') return shared.opts.dumpjson(), f'{len(changed)} Settings changed without save: {", ".join(changed)}' return shared.opts.dumpjson(), f'{len(changed)} Settings changed{": " if len(changed) > 0 else ""}{", ".join(changed)}' @@ -169,14 +170,14 @@ def run_settings_single(value, key, progress=False): directml_override_opts() shared.opts.save() if key not in ['sd_model_checkpoint', 'sd_model_refiner', 'sd_vae', 'sd_te', 'sd_unet']: - shared.log.debug(f'Setting changed: {key}={value} progress={progress}') + logger.log.debug(f'Setting changed: {key}={value} progress={progress}') return get_value_for_setting(key), shared.opts.dumpjson() def create_ui(disabled_tabs=None): if disabled_tabs is None: disabled_tabs = [] - shared.log.debug('UI initialize: tab=settings') + logger.log.debug('UI initialize: tab=settings') global text_settings # pylint: disable=global-statement text_settings = gr.Textbox(elem_id="settings_json", elem_classes=["settings_json"], value=lambda: shared.opts.dumpjson(), visible=False) @@ -189,7 +190,7 @@ def create_ui(disabled_tabs=None): def switch_profiling(): shared.cmd_opts.profile = not shared.cmd_opts.profile - shared.log.warning(f'Profiling: {shared.cmd_opts.profile}') + logger.log.warning(f'Profiling: {shared.cmd_opts.profile}') return 'Stop profiling' if shared.cmd_opts.profile else 'Start profiling' if 'system' not in disabled_tabs: @@ -236,7 +237,7 @@ def create_ui(disabled_tabs=None): for (section_id, section_text) in sections: items = [item for item in shared.opts.data_labels.items() if item[1].section[0] == section_id] # find all items in this section hidden = section_id is None or 'hidden' in section_id.lower() or 'hidden' in section_text.lower() - # shared.log.trace(f'Settings: section="{section_id}" title="{section_text}" items={len(items)} hidden={hidden}') + # logger.log.trace(f'Settings: section="{section_id}" title="{section_text}" items={len(items)} hidden={hidden}') if hidden: for (key, _item) in items: hidden_list.append(key) @@ -257,13 +258,13 @@ def create_ui(disabled_tabs=None): create_dirty_indicator(section_id, current_items) components_count = len(components) if components_count != options_count: - shared.log.error(f'Settings: count mismatch: options={options_count} components={components_count}') + logger.log.error(f'Settings: count mismatch: options={options_count} components={components_count}') with gr.TabItem("Show all pages", elem_id="settings_show_all_pages"): create_dirty_indicator("show_all_pages", []) request_notifications = gr.Button(value='Request browser notifications', elem_id="request_notifications", visible=False) - shared.log.debug(f'Settings: sections={len(sections)} settings={len(shared.opts.list())}/{len(list(shared.opts.data_labels))} quicksettings={len(quicksettings_list)}') + logger.log.debug(f'Settings: sections={len(sections)} settings={len(shared.opts.list())}/{len(list(shared.opts.data_labels))} quicksettings={len(quicksettings_list)}') if 'update' not in disabled_tabs: with gr.TabItem("Update", id="system_update", elem_id="tab_update"): @@ -316,7 +317,7 @@ def reset_quicksettings(quick_components): quick_components = quick_components.split(',') updates = [] for key in quick_components: - shared.log.warning(f'Reset: setting={key}') + logger.log.warning(f'Reset: setting={key}') updates.append(gr.update(value=shared.opts.get_default(key))) return updates diff --git a/modules/ui_txt2img.py b/modules/ui_txt2img.py index aea99fa1e..3a2ba43b7 100644 --- a/modules/ui_txt2img.py +++ b/modules/ui_txt2img.py @@ -1,10 +1,11 @@ import gradio as gr from modules import timer, shared, call_queue, generation_parameters_copypaste, processing_vae, images from modules import ui_common, ui_sections, ui_guidance +from modules import logger def create_ui(): - shared.log.debug('UI initialize: tab=txt2img') + logger.log.debug('UI initialize: tab=txt2img') import modules.txt2img # pylint: disable=redefined-outer-name modules.scripts_manager.scripts_current = modules.scripts_manager.scripts_txt2img modules.scripts_manager.scripts_txt2img.initialize_scripts(is_img2img=False, is_control=False) diff --git a/modules/ui_video.py b/modules/ui_video.py index 77fda42c7..bc388819e 100644 --- a/modules/ui_video.py +++ b/modules/ui_video.py @@ -1,13 +1,14 @@ import os import gradio as gr from modules import shared, timer, images, ui_common, ui_sections, generation_parameters_copypaste +from modules import logger -debug = shared.log.trace if os.environ.get('SD_VIDEO_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_VIDEO_DEBUG', None) is not None else lambda *args, **kwargs: None def create_ui(): - shared.log.debug('UI initialize: tab=video') + logger.log.debug('UI initialize: tab=video') with gr.Blocks(analytics_enabled=False) as _video_interface: prompt, styles, negative, generate_btn, _reprocess, paste, networks_button, _token_counter, _token_button, _token_counter_negative, _token_button_negative = ui_sections.create_toprow( is_img2img=False, diff --git a/modules/ui_video_vlm.py b/modules/ui_video_vlm.py index b39ba4fe3..88dc5acad 100644 --- a/modules/ui_video_vlm.py +++ b/modules/ui_video_vlm.py @@ -1,6 +1,7 @@ import gradio as gr from PIL import Image from modules import shared +from modules import logger models = [ @@ -45,9 +46,9 @@ def enhance_prompt(enable:bool, model:str=None, image=None, prompt:str='', syste system_prompt = f"{system_prompts['prefix']} {core_prompt} {system_prompts['desc']}' " system_prompt += system_prompts['nsfw_ok'] if nsfw else system_prompts['nsfw_no'] system_prompt += f" {system_prompts['suffix']} {system_prompts['example']}" - shared.log.debug(f'Video prompt enhance: model="{model}" image={image} nsfw={nsfw} prompt="{prompt}"') + logger.log.debug(f'Video prompt enhance: model="{model}" image={image} nsfw={nsfw} prompt="{prompt}"') answer = vqa.caption(question='', prompt=prompt, system_prompt=system_prompt, image=image, model_name=model, quiet=False) - shared.log.debug(f'Video prompt enhance: answer="{answer}"') + logger.log.debug(f'Video prompt enhance: answer="{answer}"') return answer diff --git a/modules/upscaler.py b/modules/upscaler.py index 10e816569..c1bdd22c8 100644 --- a/modules/upscaler.py +++ b/modules/upscaler.py @@ -2,6 +2,7 @@ import os from abc import abstractmethod from PIL import Image from modules import modelloader, shared, paths +from modules import logger models = None @@ -37,7 +38,7 @@ class Upscaler: self.mod_scale = None self.model_download_path = None if self.user_path is not None and len(self.user_path) > 0 and not os.path.exists(self.user_path): - shared.log.info(f'Upscaler create: folder="{self.user_path}"') + logger.log.info(f'Upscaler create: folder="{self.user_path}"') if self.model_path is None and self.name: self.model_path = os.path.join(paths.models_path, self.name) try: @@ -64,7 +65,7 @@ class Upscaler: scaler.custom = True scalers.append(scaler) loaded.append(file_name) - # shared.log.debug(f'Upscaler type={self.name} folder="{folder}" model="{model_name}" path="{file_name}"') + # logger.log.debug(f'Upscaler type={self.name} folder="{folder}" model="{model_name}" path="{file_name}"') def find_scalers(self): scalers = [] @@ -81,7 +82,7 @@ class Upscaler: scaler = UpscalerData(name=f'{k} {model[0]}', path=model_path, upscaler=self) scalers.append(scaler) loaded.append(model_path) - # shared.log.debug(f'Upscaler type={self.name} folder="{self.user_path}" model="{model[0]}" path="{model_path}"') + # logger.log.debug(f'Upscaler type={self.name} folder="{self.user_path}" model="{model[0]}" path="{model_path}"') if self.user_path is None or not os.path.exists(self.user_path): return scalers self.find_folder(self.user_path, scalers, loaded) @@ -124,7 +125,7 @@ class Upscaler: return modelloader.load_models(model_path=self.model_path, model_url=self.model_url, command_path=self.user_path) def update_status(self, prompt): - shared.log.info(f'Upscaler: type={self.name} model="{prompt}"') + logger.log.info(f'Upscaler: type={self.name} model="{prompt}"') def find_model(self, path): info = None @@ -133,13 +134,13 @@ class Upscaler: info = scaler break if info is None: - shared.log.error(f'Upscaler cannot match model: type={self.name} model="{path}"') + logger.log.error(f'Upscaler cannot match model: type={self.name} model="{path}"') return None if info.local_data_path.startswith("http"): from modules.modelloader import load_file_from_url info.local_data_path = load_file_from_url(url=info.data_path, model_dir=self.model_download_path, progress=True) if not os.path.isfile(info.local_data_path): - shared.log.error(f'Upscaler cannot find model: type={self.name} model="{info.local_data_path}"') + logger.log.error(f'Upscaler cannot find model: type={self.name} model="{info.local_data_path}"') return None return info @@ -167,12 +168,12 @@ def compile_upscaler(model): from modules.sd_models_compile import ipex_optimize model = ipex_optimize(model, apply_to_components=False, op="Upscaler") except Exception as e: - shared.log.warning(f"Upscaler IPEX Optimize: error: {e}") + logger.log.warning(f"Upscaler IPEX Optimize: error: {e}") if "Upscaler" in shared.opts.cuda_compile: try: from modules.sd_models_compile import compile_torch model = compile_torch(model, apply_to_components=False, op="Upscaler") except Exception as e: - shared.log.warning(f"Upscaler compile error: {e}") + logger.log.warning(f"Upscaler compile error: {e}") return model diff --git a/modules/upscaler_vae.py b/modules/upscaler_vae.py index 871118c42..44b49e9ff 100644 --- a/modules/upscaler_vae.py +++ b/modules/upscaler_vae.py @@ -1,3 +1,4 @@ +from modules import logger import time from PIL import Image from modules.upscaler import Upscaler, UpscalerData @@ -30,7 +31,7 @@ class UpscalerAsymmetricVAE(Upscaler): self.vae = self.vae.to(device=devices.device, dtype=devices.dtype) self.vae.eval() self.selected = selected_model - shared.log.debug(f'Upscaler load: selected="{self.selected}" vae="{repo_id}"') + logger.log.debug(f'Upscaler load: selected="{self.selected}" vae="{repo_id}"') t0 = time.time() img = sharpfin.resize(img, (8 * (img.width // 8), 8 * (img.height // 8))).convert('RGB') tensor = convert.to_tensor(img).unsqueeze(0).to(device=devices.device, dtype=devices.dtype) @@ -39,7 +40,7 @@ class UpscalerAsymmetricVAE(Upscaler): upscaled = convert.to_pil(tensor.squeeze().clamp(0.0, 1.0).float().cpu()) self.vae = self.vae.to(device=devices.cpu) t1 = time.time() - shared.log.debug(f'Upscale: name="{self.selected}" input={img.size} output={upscaled.size} time={t1 - t0:.2f}') + logger.log.debug(f'Upscale: name="{self.selected}" input={img.size} output={upscaled.size} time={t1 - t0:.2f}') return upscaled @@ -75,7 +76,7 @@ class UpscalerWanUpscale(Upscaler): self.vae_decode = self.vae_decode.to(device=devices.device, dtype=devices.dtype) self.vae_decode.eval() self.selected = selected_model - shared.log.debug(f'Upscaler load: selected="{self.selected}" encode="{repo_encode}" decode="{repo_decode}"') + logger.log.debug(f'Upscaler load: selected="{self.selected}" encode="{repo_encode}" decode="{repo_decode}"') t0 = time.time() self.vae_encode = self.vae_encode.to(device=devices.device) @@ -90,5 +91,5 @@ class UpscalerWanUpscale(Upscaler): upscaled = convert.to_pil(tensor.squeeze().clamp(0.0, 1.0).float().cpu()) t1 = time.time() - shared.log.debug(f'Upscale: name="{self.selected}" input={img.size} output={upscaled.size} time={t1 - t0:.2f}') + logger.log.debug(f'Upscale: name="{self.selected}" input={img.size} output={upscaled.size} time={t1 - t0:.2f}') return upscaled diff --git a/modules/vae/sd_vae_approx.py b/modules/vae/sd_vae_approx.py index 78fe8f08b..ade40c6f3 100644 --- a/modules/vae/sd_vae_approx.py +++ b/modules/vae/sd_vae_approx.py @@ -2,6 +2,7 @@ import os import torch from torch import nn from modules import devices, paths, shared +from modules import logger sd_vae_approx_model = None @@ -46,7 +47,7 @@ def nn_approximation(sample): # Approximate NN sd_vae_approx_model.load_state_dict(approx_weights) sd_vae_approx_model.eval() sd_vae_approx_model.to(device, dtype) - shared.log.debug(f'VAE load: type=approximate model="{model_path}"') + logger.log.debug(f'VAE load: type=approximate model="{model_path}"') try: in_sample = sample.to(device, dtype).unsqueeze(0) sd_vae_approx_model.to(device, dtype) @@ -54,7 +55,7 @@ def nn_approximation(sample): # Approximate NN x_sample = x_sample[0].to(torch.float32).detach().cpu() return x_sample except Exception as e: - shared.log.error(f'VAE decode approximate: {e}') + logger.log.error(f'VAE decode approximate: {e}') return sample @@ -80,5 +81,5 @@ def cheap_approximation(sample): # Approximate simple x_sample = nn.functional.conv2d(sample, weights, bias) # pylint: disable=not-callable return x_sample except Exception as e: - shared.log.error(f'VAE decode simple: {e}') + logger.log.error(f'VAE decode simple: {e}') return sample diff --git a/modules/vae/sd_vae_fal.py b/modules/vae/sd_vae_fal.py index 0f0e5b3bb..8f94fcea2 100644 --- a/modules/vae/sd_vae_fal.py +++ b/modules/vae/sd_vae_fal.py @@ -6,6 +6,7 @@ from diffusers.models.autoencoders.vae import EncoderOutput, DecoderOutput from diffusers.configuration_utils import ConfigMixin, register_to_config from modules import shared, devices +from modules import logger repo_id = "fal/FLUX.2-Tiny-AutoEncoder" @@ -29,7 +30,7 @@ def load_fal_vae(): if prev_vae is None: prev_vae = shared.sd_model.vae shared.sd_model.vae = tiny_vae - shared.log.info(f'VAE load: cls={tiny_vae.__class__.__name__} repo_id={repo_id}') + logger.log.info(f'VAE load: cls={tiny_vae.__class__.__name__} repo_id={repo_id}') def unload_fal_vae(): @@ -39,7 +40,7 @@ def unload_fal_vae(): if prev_vae is not None: shared.sd_model.vae = prev_vae prev_vae = None - shared.log.info(f'VAE restore: cls={prev_vae.__class__.__name__}') + logger.log.info(f'VAE restore: cls={prev_vae.__class__.__name__}') class Flux2TinyAutoEncoder(ModelMixin, ConfigMixin): diff --git a/modules/vae/sd_vae_natten.py b/modules/vae/sd_vae_natten.py index 246816c8d..a2f43bd6b 100644 --- a/modules/vae/sd_vae_natten.py +++ b/modules/vae/sd_vae_natten.py @@ -5,7 +5,8 @@ from diffusers.models.attention import Attention import torch from torch.nn import Linear from einops import rearrange -from installer import install, log +from installer import install +from modules.logger import log def init(): diff --git a/modules/vae/sd_vae_ostris.py b/modules/vae/sd_vae_ostris.py index 70542e9f5..d25c9a5ef 100644 --- a/modules/vae/sd_vae_ostris.py +++ b/modules/vae/sd_vae_ostris.py @@ -4,6 +4,7 @@ import diffusers from huggingface_hub import hf_hub_download from safetensors.torch import load_file from modules import shared, devices +from modules import logger decoder_id = "ostris/vae-kl-f8-d16" @@ -16,7 +17,7 @@ def load_vae(pipe): elif shared.sd_model_type == 'sdxl': adapter_file = "16ch-VAE-Adapter-SDXL-alpha_v02.safetensors" else: - shared.log.error('VAE: type=osiris unsupported model type') + logger.log.error('VAE: type=osiris unsupported model type') return t0 = time.time() ckpt_file = hf_hub_download(adapter_id, adapter_file, cache_dir=shared.opts.hfcache_dir) @@ -38,4 +39,4 @@ def load_vae(pipe): pipe.vae = diffusers.AutoencoderKL.from_pretrained(decoder_id, torch_dtype=devices.dtype, cache_dir=shared.opts.hfcache_dir) t1 = time.time() - shared.log.info(f'VAE load: type=osiris decoder="{decoder_id}" adapter="{adapter_id}" time={t1-t0:.2f}s') + logger.log.info(f'VAE load: type=osiris decoder="{decoder_id}" adapter="{adapter_id}" time={t1-t0:.2f}s') diff --git a/modules/vae/sd_vae_remote.py b/modules/vae/sd_vae_remote.py index 7a03bf383..4002bb9a8 100644 --- a/modules/vae/sd_vae_remote.py +++ b/modules/vae/sd_vae_remote.py @@ -1,3 +1,4 @@ +from modules import logger import io import time import json @@ -53,7 +54,7 @@ def remote_decode(latents: torch.Tensor, width: int = 0, height: int = 0, model_ model_type = model_type or shared.sd_model_type url = hf_decode_endpoints.get(model_type, None) if url is None: - shared.log.error(f'Decode: type="remote" type={model_type} unsuppported') + logger.log.error(f'Decode: type="remote" type={model_type} unsuppported') return tensors t0 = time.time() modelloader.hf_login() @@ -106,7 +107,7 @@ def remote_decode(latents: torch.Tensor, width: int = 0, height: int = 0, model_ timeout=300, ) if not response.ok: - shared.log.error(f'Decode: type="remote" model={model_type} code={response.status_code} shape={latent.shape} url="{url}" args={params} headers={response.headers} response={response.json()}') + logger.log.error(f'Decode: type="remote" model={model_type} code={response.status_code} shape={latent.shape} url="{url}" args={params} headers={response.headers} response={response.json()}') else: content += len(response.content) if shared.opts.remote_vae_type == 'raw' or 'video' in model_type: @@ -118,12 +119,12 @@ def remote_decode(latents: torch.Tensor, width: int = 0, height: int = 0, model_ image = Image.open(io.BytesIO(response.content)).convert("RGB") tensors.append(image) except Exception as e: - shared.log.error(f'Decode: type="remote" model={model_type} {e}') + logger.log.error(f'Decode: type="remote" model={model_type} {e}') errors.display(e, 'VAE') if len(tensors) > 0 and shared.opts.remote_vae_type == 'raw': tensors = torch.cat(tensors, dim=0) t1 = time.time() - shared.log.debug(f'Decode: type="remote" model={model_type} mode={shared.opts.remote_vae_type} args={params} bytes={content} time={t1-t0:.3f}s') + logger.log.debug(f'Decode: type="remote" model={model_type} mode={shared.opts.remote_vae_type} args={params} bytes={content} time={t1-t0:.3f}s') return tensors @@ -136,7 +137,7 @@ def remote_encode(images: list[Image.Image], model_type: str | None = None): model_type = model_type or shared.sd_model_type url = hf_encode_endpoints.get(model_type, None) if url is None: - shared.log.error(f'Decode: type="remote" type={model_type} unsuppported') + logger.log.error(f'Decode: type="remote" type={model_type} unsuppported') return images t0 = time.time() modelloader.hf_login() @@ -153,7 +154,7 @@ def remote_encode(images: list[Image.Image], model_type: str | None = None): ) tensors.append(init_latent) except Exception as e: - shared.log.error(f'Encode: type="remote" model={model_type} {e}') + logger.log.error(f'Encode: type="remote" model={model_type} {e}') errors.display(e, 'VAE') if len(tensors) > 0 and torch.is_tensor(tensors[0]): @@ -162,5 +163,5 @@ def remote_encode(images: list[Image.Image], model_type: str | None = None): else: return images t1 = time.time() - shared.log.debug(f'Encode: type="remote" model={model_type} mode={shared.opts.remote_vae_type} image={images} latent={tensors.shape} time={t1-t0:.3f}s') + logger.log.debug(f'Encode: type="remote" model={model_type} mode={shared.opts.remote_vae_type} image={images} latent={tensors.shape} time={t1-t0:.3f}s') return tensors diff --git a/modules/vae/sd_vae_repa.py b/modules/vae/sd_vae_repa.py index 7dce4c1ce..a2d661643 100644 --- a/modules/vae/sd_vae_repa.py +++ b/modules/vae/sd_vae_repa.py @@ -1,5 +1,6 @@ import diffusers from modules import shared +from modules import logger models = { @@ -17,12 +18,12 @@ def repa_load(latents): global loaded_cls, loaded_vae # pylint: disable=global-statement config = models.get(shared.sd_model_type, None) if config is None: - shared.log.error(f'Decode: type="repa" model={shared.sd_model_type} not supported') + logger.log.error(f'Decode: type="repa" model={shared.sd_model_type} not supported') return latents cls = getattr(diffusers, config['cls']) if (cls != loaded_cls) or (loaded_vae is None): - shared.log.info(f'RePA VAE load: {config["repo_id"]} cls={config["cls"]}') + logger.log.info(f'RePA VAE load: {config["repo_id"]} cls={config["cls"]}') loaded_vae = cls.from_pretrained( config['repo_id'], torch_dtype=latents.dtype, diff --git a/modules/vae/sd_vae_stablecascade.py b/modules/vae/sd_vae_stablecascade.py index 198606e7d..09aadd20a 100644 --- a/modules/vae/sd_vae_stablecascade.py +++ b/modules/vae/sd_vae_stablecascade.py @@ -2,6 +2,7 @@ import os from torch import nn import safetensors from modules import devices, paths +from modules import logger preview_model = None dtype = devices.dtype_vae @@ -55,7 +56,7 @@ def download_model(model_path): model_url = 'https://huggingface.co/stabilityai/stable-cascade/resolve/main/previewer.safetensors?download=true' if not os.path.exists(model_path): import torch - from installer import log + from modules.logger import log os.makedirs(os.path.dirname(model_path), exist_ok=True) log.info(f'Downloading Stable Cascade previewer: {model_path}') torch.hub.download_url_to_file(model_url, model_path) @@ -79,12 +80,12 @@ def decode(latents): preview_model.load_state_dict(previewer_checkpoint if 'state_dict' not in previewer_checkpoint else previewer_checkpoint['state_dict']) preview_model.eval().requires_grad_(False).to(devices.device, dtype) del previewer_checkpoint - shared.log.info(f"Load Stable Cascade previewer: model={model_path}") + logger.log.info(f"Load Stable Cascade previewer: model={model_path}") try: with devices.inference_context(): latents = latents.detach().clone().unsqueeze(0).to(devices.device, dtype) image = preview_model(latents)[0].clamp(0, 1).float() return image except Exception as e: - shared.log.error(f'Stable Cascade previewer: {e}') + logger.log.error(f'Stable Cascade previewer: {e}') return latents diff --git a/modules/vae/sd_vae_taesd.py b/modules/vae/sd_vae_taesd.py index c8fc3ef47..54571825e 100644 --- a/modules/vae/sd_vae_taesd.py +++ b/modules/vae/sd_vae_taesd.py @@ -10,6 +10,7 @@ import threading from PIL import Image import torch from modules import devices, paths, shared +from modules import logger debug = os.environ.get('SD_PREVIEW_DEBUG', None) is not None @@ -52,7 +53,7 @@ def warn_once(msg, variant=None): global prev_warnings # pylint: disable=global-statement if not prev_warnings: prev_warnings = True - shared.log.warning(f'Decode: type="taesd" variant="{variant}": {msg}') + logger.log.warning(f'Decode: type="taesd" variant="{variant}": {msg}') return Image.new('RGB', (8, 8), color = (0, 0, 0)) @@ -93,16 +94,16 @@ def get_model(model_type = 'decoder', variant = None): uri += '/tae' + model_cls + '_' + model_type + '.pth' try: torch.hub.download_url_to_file(uri, fn) - shared.log.print() # new line - shared.log.info(f'Decode: type="taesd" variant="{variant}": uri="{uri}" fn="{fn}" download') + logger.log.print() # new line + logger.log.info(f'Decode: type="taesd" variant="{variant}": uri="{uri}" fn="{fn}" download') except Exception as e: warn_once(f'download uri={uri} {e}', variant=variant) if os.path.exists(fn): prev_cls = model_cls prev_type = model_type prev_model = variant - shared.log.print() # new line - shared.log.debug(f'Decode: type="taesd" variant="{variant}" fn="{fn}" layers={shared.opts.taesd_layers} load') + logger.log.print() # new line + logger.log.debug(f'Decode: type="taesd" variant="{variant}" fn="{fn}" layers={shared.opts.taesd_layers} load') vae = None if 'TAE HunyuanVideo' in variant: from modules.taesd.taehv import TAEHV @@ -132,7 +133,7 @@ def get_model(model_type = 'decoder', variant = None): prev_cls = model_cls prev_type = model_type prev_model = variant - shared.log.debug(f'Decode: type="taesd" variant="{variant}" id="{repo}" load') + logger.log.debug(f'Decode: type="taesd" variant="{variant}" id="{repo}" load') if 'tiny' in repo: from diffusers.models import AutoencoderTiny vae = AutoencoderTiny.from_pretrained(repo, cache_dir=shared.opts.hfcache_dir, torch_dtype=dtype) @@ -162,7 +163,7 @@ def decode(latents): tensor = latents.unsqueeze(0) if len(latents.shape) == 3 else latents tensor = tensor.detach().clone().to(devices.device, dtype=dtype) if debug: - shared.log.debug(f'Decode: type="taesd" variant="{variant}" input={latents.shape} tensor={tensor.shape}') + logger.log.debug(f'Decode: type="taesd" variant="{variant}" input={latents.shape} tensor={tensor.shape}') # Fallback: reshape packed 128-channel latents to 32 channels if not already unpacked if (variant == 'TAE FLUX.2') and (len(tensor.shape) == 4) and (tensor.shape[1] == 128): b, _c, h, w = tensor.shape @@ -175,7 +176,7 @@ def decode(latents): image = (image / 2.0 + 0.5).clamp(0, 1).detach() t1 = time.time() if (t1 - t0) > 3.0 and not first_run: - shared.log.warning(f'Decode: type="taesd" variant="{variant}" long decode time={t1 - t0:.2f}') + logger.log.warning(f'Decode: type="taesd" variant="{variant}" long decode time={t1 - t0:.2f}') first_run = False return image except Exception as e: diff --git a/modules/video.py b/modules/video.py index 17d51eb38..969160581 100644 --- a/modules/video.py +++ b/modules/video.py @@ -3,6 +3,7 @@ import threading import numpy as np from PIL import Image from modules import shared, errors +from modules import logger from modules.image.namegen import FilenameGenerator # pylint: disable=unused-import @@ -18,7 +19,7 @@ def interpolate_frames(images, count: int = 0, scale: float = 1.0, pad: int = 1, if len(frames) > 0: images = frames except Exception as e: - shared.log.error(f'RIFE interpolation: {e}') + logger.log.error(f'RIFE interpolation: {e}') errors.display(e, 'RIFE interpolation') return [np.array(image) for image in images] @@ -27,7 +28,7 @@ def save_video_atomic(images, filename, video_type: str = 'none', duration: floa try: import cv2 except Exception as e: - shared.log.error(f'Save video: cv2: {e}') + logger.log.error(f'Save video: cv2: {e}') return savejob = shared.state.begin('Save video') os.makedirs(os.path.dirname(filename), exist_ok=True) @@ -46,7 +47,7 @@ def save_video_atomic(images, filename, video_type: str = 'none', duration: floa loop = 0 if loop else 1, ) size = os.path.getsize(filename) - shared.log.info(f'Save video: file="{filename}" frames={len(append) + 1} duration={duration} loop={loop} size={size}') + logger.log.info(f'Save video: file="{filename}" frames={len(append) + 1} duration={duration} loop={loop} size={size}') elif video_type.lower() != 'none': frames = interpolate_frames(images, count=interpolate, scale=scale, pad=pad, change=change) fourcc = "mp4v" @@ -56,7 +57,7 @@ def save_video_atomic(images, filename, video_type: str = 'none', duration: floa img = cv2.cvtColor(frames[i], cv2.COLOR_RGB2BGR) video_writer.write(img) size = os.path.getsize(filename) - shared.log.info(f'Save video: file="{filename}" frames={len(frames)} duration={duration} fourcc={fourcc} size={size}') + logger.log.info(f'Save video: file="{filename}" frames={len(frames)} duration={duration} fourcc={fourcc} size={size}') shared.state.end(savejob) @@ -95,7 +96,7 @@ def get_video_params(filepath: str, capture: bool = False): video = cv2.VideoCapture(filepath) if not video.isOpened(): msg = f'Video open failed: path="{filepath}"' - shared.log.error(msg) + logger.log.error(msg) raise RuntimeError(msg) frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT)) fps = round(video.get(cv2.CAP_PROP_FPS), 2) diff --git a/modules/video_models/google_veo.py b/modules/video_models/google_veo.py index 49893b260..7fcaf9fb0 100644 --- a/modules/video_models/google_veo.py +++ b/modules/video_models/google_veo.py @@ -6,7 +6,8 @@ import sys sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))) from PIL import Image -from installer import install, reload, log +from installer import install, reload +from modules.logger import log image_size_buckets = { diff --git a/modules/video_models/models_def.py b/modules/video_models/models_def.py index 351d1c33a..02aa3bec2 100644 --- a/modules/video_models/models_def.py +++ b/modules/video_models/models_def.py @@ -2,7 +2,7 @@ from dataclasses import dataclass import time import diffusers import transformers -from installer import log +from modules.logger import log @dataclass diff --git a/modules/video_models/video_cache.py b/modules/video_models/video_cache.py index b4b0d1472..c4d6e6278 100644 --- a/modules/video_models/video_cache.py +++ b/modules/video_models/video_cache.py @@ -1,11 +1,12 @@ import diffusers from modules import shared +from modules import logger def apply_teacache_patch(cls): if shared.opts.teacache_enabled and cls is not None: from modules import teacache - shared.log.debug(f'Transformers cache: type=teacache patch=forward cls={cls.__name__}') + logger.log.debug(f'Transformers cache: type=teacache patch=forward cls={cls.__name__}') if cls.__name__ == 'LTXVideoTransformer3DModel': cls.forward = teacache.teacache_ltx_forward elif cls.__name__ == 'MochiTransformer3DModel': diff --git a/modules/video_models/video_load.py b/modules/video_models/video_load.py index e60463368..e6fc71b66 100644 --- a/modules/video_models/video_load.py +++ b/modules/video_models/video_load.py @@ -4,6 +4,7 @@ import copy import time import diffusers from modules import shared, errors, sd_models, sd_checkpoint, model_quant, devices, sd_hijack_te, sd_hijack_vae +from modules import logger from modules.video_models import models_def, video_utils, video_overrides, video_cache @@ -20,7 +21,7 @@ loaded_model = None def load_custom(model_name: str): - shared.log.debug(f'Video load: module=pipe repo="{model_name}" cls=Custom') + logger.log.debug(f'Video load: module=pipe repo="{model_name}" cls=Custom') if 'veo-3.1' in model_name: from modules.video_models.google_veo import load_veo pipe = load_veo(model_name) @@ -81,7 +82,7 @@ def load_model(selected: models_def.Model): selected.te_folder = 'text_encoder' selected.te_revision = None - shared.log.debug(f'Video load: module=te repo="{selected.te or selected.repo}" folder="{selected.te_folder}" cls={selected.te_cls.__name__} quant={model_quant.get_quant_type(quant_args)} loader={_loader("transformers")}') + logger.log.debug(f'Video load: module=te repo="{selected.te or selected.repo}" folder="{selected.te_folder}" cls={selected.te_cls.__name__} quant={model_quant.get_quant_type(quant_args)} loader={_loader("transformers")}') kwargs["text_encoder"] = selected.te_cls.from_pretrained( pretrained_model_name_or_path=selected.te or selected.repo, subfolder=selected.te_folder, @@ -92,7 +93,7 @@ def load_model(selected: models_def.Model): **offline_args, ) except Exception as e: - shared.log.error(f'video load: module=te cls={selected.te_cls.__name__} {e}') + logger.log.error(f'video load: module=te cls={selected.te_cls.__name__} {e}') errors.display(e, 'video') # transformer @@ -102,7 +103,7 @@ def load_model(selected: models_def.Model): if dit_folder is not None and dit_folder not in kwargs: # get a new quant arg on every loop to prevent the quant config classes getting entangled load_args, quant_args = model_quant.get_dit_args({}, module='Model', device_map=True) - shared.log.debug(f'Video load: module=transformer repo="{selected.dit or selected.repo}" module="{dit_folder}" folder="{dit_folder}" cls={selected.dit_cls.__name__} quant={model_quant.get_quant_type(quant_args)} loader={_loader("diffusers")}') + logger.log.debug(f'Video load: module=transformer repo="{selected.dit or selected.repo}" module="{dit_folder}" folder="{dit_folder}" cls={selected.dit_cls.__name__} quant={model_quant.get_quant_type(quant_args)} loader={_loader("diffusers")}') kwargs[dit_folder] = selected.dit_cls.from_pretrained( pretrained_model_name_or_path=selected.dit or selected.repo, subfolder=dit_folder, @@ -113,7 +114,7 @@ def load_model(selected: models_def.Model): **offline_args, ) else: - shared.log.debug(f'Video load: module=transformer repo="{selected.dit or selected.repo}" module="{dit_folder}" folder="{dit_folder}" cls={selected.dit_cls.__name__} loader={_loader("diffusers")} skip') + logger.log.debug(f'Video load: module=transformer repo="{selected.dit or selected.repo}" module="{dit_folder}" folder="{dit_folder}" cls={selected.dit_cls.__name__} loader={_loader("diffusers")} skip') if selected.dit_folder is None: selected.dit_folder = ['transformer'] @@ -123,7 +124,7 @@ def load_model(selected: models_def.Model): else: load_dit_folder(selected.dit_folder) except Exception as e: - shared.log.error(f'video load: module=transformer cls={selected.dit_cls.__name__} {e}') + logger.log.error(f'video load: module=transformer cls={selected.dit_cls.__name__} {e}') errors.display(e, 'video') # model @@ -131,7 +132,7 @@ def load_model(selected: models_def.Model): if selected.repo_cls is None: shared.sd_model = load_custom(selected.repo) else: - shared.log.debug(f'Video load: module=pipe repo="{selected.repo}" cls={selected.repo_cls.__name__}') + logger.log.debug(f'Video load: module=pipe repo="{selected.repo}" cls={selected.repo_cls.__name__}') shared.sd_model = selected.repo_cls.from_pretrained( pretrained_model_name_or_path=selected.repo, revision=selected.repo_revision, @@ -141,12 +142,12 @@ def load_model(selected: models_def.Model): **offline_args, ) except Exception as e: - shared.log.error(f'video load: module=pipe repo="{selected.repo}" cls={selected.repo_cls.__name__} {e}') + logger.log.error(f'video load: module=pipe repo="{selected.repo}" cls={selected.repo_cls.__name__} {e}') errors.display(e, 'video') if shared.sd_model is None: msg = f'Video load: model="{selected.name}" failed' - shared.log.error(msg) + logger.log.error(msg) return msg t1 = time.time() @@ -185,8 +186,8 @@ def load_model(selected: models_def.Model): loaded_model = selected.name msg = f'Video load: cls={shared.sd_model.__class__.__name__} model="{selected.name}" time={t1-t0:.2f}' - shared.log.info(msg) - shared.log.debug(f'Video hijacks: decode={decode} text={text} image={image} slicing={slicing} tiling={tiling} framewise={framewise}') + logger.log.info(msg) + logger.log.debug(f'Video hijacks: decode={decode} text={text} image={image} slicing={slicing} tiling={tiling} framewise={framewise}') shared.state.end(jobid) return msg @@ -197,7 +198,7 @@ def load_upscale_vae(): if hasattr(shared.sd_model.vae, '_asymmetric_upscale_vae'): return # already loaded if shared.sd_model.vae.__class__.__name__ != 'AutoencoderKLWan': - shared.log.warning('Video decode: upscale VAE unsupported') + logger.log.warning('Video decode: upscale VAE unsupported') return repo_id = 'spacepxl/Wan2.1-VAE-upscale2x' @@ -206,7 +207,7 @@ def load_upscale_vae(): vae_decode.requires_grad_(False) vae_decode = vae_decode.to(device=devices.device, dtype=devices.dtype) vae_decode.eval() - shared.log.debug(f'Decode: load="{repo_id}"') + logger.log.debug(f'Decode: load="{repo_id}"') shared.sd_model.orig_vae = shared.sd_model.vae shared.sd_model.vae = vae_decode shared.sd_model.vae._asymmetric_upscale_vae = True # pylint: disable=protected-access diff --git a/modules/video_models/video_overrides.py b/modules/video_models/video_overrides.py index 55b3ad850..60774a407 100644 --- a/modules/video_models/video_overrides.py +++ b/modules/video_models/video_overrides.py @@ -2,10 +2,11 @@ import os import torch import diffusers from modules import shared, processing +from modules import logger from modules.video_models.models_def import Model -debug = shared.log.trace if os.environ.get('SD_VIDEO_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_VIDEO_DEBUG', None) is not None else lambda *args, **kwargs: None def load_override(selected: Model, **load_args): diff --git a/modules/video_models/video_run.py b/modules/video_models/video_run.py index a8603679a..0fc2386bc 100644 --- a/modules/video_models/video_run.py +++ b/modules/video_models/video_run.py @@ -2,11 +2,12 @@ import os import copy import time from modules import shared, errors, sd_models, processing, devices, images, ui_common +from modules import logger from modules.video_models import models_def, video_utils, video_load, video_vae, video_overrides, video_save, video_prompt from modules.paths import resolve_output_path -debug = shared.log.trace if os.environ.get('SD_VIDEO_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_VIDEO_DEBUG', None) is not None else lambda *args, **kwargs: None def generate(*args, **kwargs): @@ -51,7 +52,7 @@ def generate(*args, **kwargs): override_settings=override_settings, ) if p.vae_type == 'Remote' and not selected.vae_remote: - shared.log.warning(f'Video: model={selected.name} remote vae not supported') + logger.log.warning(f'Video: model={selected.name} remote vae not supported') p.vae_type = 'Default' p.scripts = None p.script_args = None @@ -61,12 +62,12 @@ def generate(*args, **kwargs): p.outpath_samples = resolve_output_path(shared.opts.outdir_samples, shared.opts.outdir_video) if 'T2V' in model: if init_image is not None: - shared.log.warning('Video: op=T2V init image not supported') + logger.log.warning('Video: op=T2V init image not supported') elif 'I2V' in model: if init_image is None: return video_utils.queue_err('init image not set') p.task_args['image'] = images.resize_image(resize_mode=2, im=init_image, width=p.width, height=p.height, upscaler_name=None, output_type='pil') - shared.log.debug(f'Video: op=I2V init={init_image} resized={p.task_args["image"]}') + logger.log.debug(f'Video: op=I2V init={init_image} resized={p.task_args["image"]}') elif 'FLF2V' in model: if init_image is None: return video_utils.queue_err('init image not set') @@ -74,11 +75,11 @@ def generate(*args, **kwargs): return video_utils.queue_err('last image not set') p.task_args['image'] = images.resize_image(resize_mode=2, im=init_image, width=p.width, height=p.height, upscaler_name=None, output_type='pil') p.task_args['last_image'] = images.resize_image(resize_mode=2, im=last_image, width=p.width, height=p.height, upscaler_name=None, output_type='pil') - shared.log.debug(f'Video: op=FLF2V init={init_image} last={last_image} resized={p.task_args["image"]}') + logger.log.debug(f'Video: op=FLF2V init={init_image} last={last_image} resized={p.task_args["image"]}') elif 'VACE' in model: if init_image is not None: p.task_args['reference_images'] = [images.resize_image(resize_mode=2, im=init_image, width=p.width, height=p.height, upscaler_name=None, output_type='pil')] - shared.log.debug(f'Video: op=VACE reference={init_image} resized={p.task_args["reference_images"]}') + logger.log.debug(f'Video: op=VACE reference={init_image} resized={p.task_args["reference_images"]}') elif 'Animate' in model: if init_image is None: return video_utils.queue_err('init image not set') @@ -86,9 +87,9 @@ def generate(*args, **kwargs): p.task_args['mode'] = 'animate' p.task_args['pose_video'] = [] # input pose video to condition the generation on. must be a list of PIL images. p.task_args['face_video'] = [] # input face video to condition the generation on. must be a list of PIL images. - shared.log.debug(f'Video: op=Animate init={p.task_args["image"]} pose={p.task_args["pose_video"]} face={p.task_args["face_video"]}') + logger.log.debug(f'Video: op=Animate init={p.task_args["image"]} pose={p.task_args["pose_video"]} face={p.task_args["face_video"]}') else: - shared.log.warning(f'Video: unknown model type "{model}"') + logger.log.warning(f'Video: unknown model type "{model}"') # cleanup memory shared.sd_model = sd_models.apply_balanced_offload(shared.sd_model) @@ -130,7 +131,7 @@ def generate(*args, **kwargs): # run processing shared.state.disable_preview = True - shared.log.debug(f'Video: cls={shared.sd_model.__class__.__name__} width={p.width} height={p.height} frames={p.frames} steps={p.steps}') + logger.log.debug(f'Video: cls={shared.sd_model.__class__.__name__} width={p.width} height={p.height} frames={p.frames} steps={p.steps}') err = None t0 = time.time() processed = None @@ -150,7 +151,7 @@ def generate(*args, **kwargs): return video_utils.queue_err(err) if processed is None or (len(processed.images) == 0 and processed.bytes is None): return video_utils.queue_err('processing failed') - shared.log.info(f'Video: name="{selected.name}" cls={shared.sd_model.__class__.__name__} frames={len(processed.images)} time={t1-t0:.2f}') + logger.log.info(f'Video: name="{selected.name}" cls={shared.sd_model.__class__.__name__} frames={len(processed.images)} time={t1-t0:.2f}') if hasattr(processed, 'images') and processed.images is not None: pixels = video_save.images_to_tensor(processed.images) diff --git a/modules/video_models/video_save.py b/modules/video_models/video_save.py index 9f75df9c4..27d3ecd79 100644 --- a/modules/video_models/video_save.py +++ b/modules/video_models/video_save.py @@ -7,6 +7,7 @@ import torch import einops from PIL import Image from modules import shared, errors ,timer, rife, processing +from modules import logger from modules.video_models.video_utils import check_av @@ -60,7 +61,7 @@ def images_to_tensor(images): tensor = tensor.unsqueeze(0) # 1, n, h, w, c tensor = tensor.permute(0, 4, 1, 2, 3).contiguous() # 1, c, n, h, w tensor = (tensor.float() / 127.5) - 1.0 # from [0,255] to [-1,1] - # shared.log.debug(f'Video output: images={len(images)} tensor={tensor.shape}') + # logger.log.debug(f'Video output: images={len(images)} tensor={tensor.shape}') return tensor @@ -73,7 +74,7 @@ def numpy_to_tensor(images): tensor = tensor.unsqueeze(0) # 1, n, h, w, c tensor = tensor.permute(0, 4, 1, 2, 3).contiguous() # 1, c, n, h, w # tensor = (tensor.float() / 127.5) - 1.0 # from [0,255] to [-1,1] - # shared.log.debug(f'Video output: images={len(images)} tensor={tensor.shape}') + # logger.log.debug(f'Video output: images={len(images)} tensor={tensor.shape}') return tensor @@ -91,7 +92,7 @@ def write_audio( audio_stream.codec_context.format = "fltp" audio_stream.codec_context.time_base = Fraction(1, audio_sample_rate) # audio_stream.time_base = audio_stream.codec_context.time_base # TODO audio set time-base - shared.log.debug(f'Audio: codec={audio_stream.codec_context.name} rate={audio_stream.codec_context.sample_rate} layout={audio_stream.codec_context.layout} format={audio_stream.codec_context.format} base={audio_stream.codec_context.time_base}') + logger.log.debug(f'Audio: codec={audio_stream.codec_context.name} rate={audio_stream.codec_context.sample_rate} layout={audio_stream.codec_context.layout} format={audio_stream.codec_context.format} base={audio_stream.codec_context.time_base}') # init input samples if samples.ndim == 1: samples = samples[:, None] @@ -143,7 +144,7 @@ def atomic_save_video(filename: str, metadata = {} av = check_av() if av is None or av is False: - shared.log.error('Video: ffmpeg/av not available') + logger.log.error('Video: ffmpeg/av not available') return savejob = shared.state.begin('Save video') @@ -159,7 +160,7 @@ def atomic_save_video(filename: str, else: continue options[key.strip()] = value.strip() - shared.log.info(f'Video: file="{filename}" codec={codec} frames={frames} width={width} height={height} fps={rate} audio={audio is not None} aac={aac} options={options}') + logger.log.info(f'Video: file="{filename}" codec={codec} frames={frames} width={width} height={height} fps={rate} audio={audio is not None} aac={aac} options={options}') video_array = torch.as_tensor(tensor, dtype=torch.uint8).numpy(force=True) task = pbar.add_task('encoding', total=frames) if pbar is not None else None @@ -185,7 +186,7 @@ def atomic_save_video(filename: str, try: write_audio(container, audio, aac) except Exception as e: - shared.log.error(f'Video audio encoding: {e}') + logger.log.error(f'Video audio encoding: {e}') errors.display(e, 'Audio') shared.state.outputs(filename) @@ -221,12 +222,12 @@ def save_video( try: with open(output_video, 'wb') as f: f.write(binary) - shared.log.info(f'Video output: file="{output_video}" size={len(binary)}') + logger.log.info(f'Video output: file="{output_video}" size={len(binary)}') shared.state.outputs(output_video) except Exception as e: - shared.log.error(f'Video output: file="{output_video}" {e}') + logger.log.error(f'Video output: file="{output_video}" {e}') except Exception as e: - shared.log.error(f'Video output: file="{output_video}" write error {e}') + logger.log.error(f'Video output: file="{output_video}" write error {e}') errors.display(e, 'video') return 0, output_video @@ -237,13 +238,13 @@ def save_video( if isinstance(pixels, list) and isinstance(pixels[0], Image.Image): pixels = images_to_tensor(pixels) if not torch.is_tensor(pixels): - shared.log.error(f'Video: type={type(pixels)} not a tensor') + logger.log.error(f'Video: type={type(pixels)} not a tensor') return 0, output_video t_save = time.time() n, _c, t, h, w = pixels.shape size = pixels.element_size() * pixels.numel() - shared.log.debug(f'Video: video={mp4_video} export={mp4_frames} safetensors={mp4_sf} interpolate={mp4_interpolate}') - shared.log.debug(f'Video: encode={t} raw={size} latent={pixels.shape} audio={audio.shape if audio is not None else None} fps={mp4_fps} codec={mp4_codec} ext={mp4_ext} options="{mp4_opt}"') + logger.log.debug(f'Video: video={mp4_video} export={mp4_frames} safetensors={mp4_sf} interpolate={mp4_interpolate}') + logger.log.debug(f'Video: encode={t} raw={size} latent={pixels.shape} audio={audio.shape if audio is not None else None} fps={mp4_fps} codec={mp4_codec} ext={mp4_ext} options="{mp4_opt}"') try: preparejob = shared.state.begin('Prepare video') if stream is not None: @@ -267,13 +268,13 @@ def save_video( if mp4_sf: fn = f'{output_filename}.safetensors' - shared.log.info(f'Video export: file="{fn}" type=savetensors shape={x.shape}') + logger.log.info(f'Video export: file="{fn}" type=savetensors shape={x.shape}') from safetensors.torch import save_file shared.state.outputs(fn) save_file({ 'frames': x }, fn, metadata={'format': 'video', 'frames': str(t), 'width': str(w), 'height': str(h), 'fps': str(mp4_fps), 'codec': mp4_codec, 'options': mp4_opt, 'ext': mp4_ext, 'interpolate': str(mp4_interpolate)}) if mp4_frames: - shared.log.info(f'Video frames: files="{output_filename}-00000.jpg" frames={t} width={w} height={h}') + logger.log.info(f'Video frames: files="{output_filename}-00000.jpg" frames={t} width={w} height={h}') for i in range(t): image = cv2.cvtColor(x[i].numpy(), cv2.COLOR_RGB2BGR) fn = f'{output_filename}-{i:05d}.jpg' @@ -293,7 +294,7 @@ def save_video( stream.output_queue.push(('progress', (None, ''))) except Exception as e: - shared.log.error(f'Video save: raw={size} {e}') + logger.log.error(f'Video save: raw={size} {e}') errors.display(e, 'video') timer.process.add('save', time.time()-t_save) return t, output_video diff --git a/modules/video_models/video_ui.py b/modules/video_models/video_ui.py index f822c31a8..34c3ee2dc 100644 --- a/modules/video_models/video_ui.py +++ b/modules/video_models/video_ui.py @@ -1,12 +1,13 @@ import os import gradio as gr from modules import shared, sd_models, ui_common, ui_sections, ui_symbols, ui_video_vlm, call_queue +from modules import logger from modules.ui_components import ToolButton from modules.video_models import models_def, video_utils from modules.video_models import video_run -debug = shared.log.trace if os.environ.get('SD_VIDEO_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_VIDEO_DEBUG', None) is not None else lambda *args, **kwargs: None def engine_change(engine): diff --git a/modules/video_models/video_utils.py b/modules/video_models/video_utils.py index f29c43906..1074db45c 100644 --- a/modules/video_models/video_utils.py +++ b/modules/video_models/video_utils.py @@ -4,13 +4,14 @@ import time from PIL import Image from installer import install from modules import shared, sd_models, timer, errors, devices +from modules import logger -debug = shared.log.trace if os.environ.get('SD_VIDEO_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_VIDEO_DEBUG', None) is not None else lambda *args, **kwargs: None def queue_err(msg): - shared.log.error(f'Video: {msg}') + logger.log.error(f'Video: {msg}') return [], None, '', '', f'Error: {msg}' @@ -24,7 +25,7 @@ def check_av(): import av av.logging.set_level(av.logging.ERROR) # pylint: disable=c-extension-no-member except Exception as e: - shared.log.error(f'av package: {e}') + logger.log.error(f'av package: {e}') return False return av @@ -44,7 +45,7 @@ def hijack_encode_image(*args, **kwargs): sd_models.move_model(shared.sd_model.image_encoder, devices.device) res = shared.sd_model.orig_encode_image(*args, **kwargs) except Exception as e: - shared.log.error(f'Video encode image: {e}') + logger.log.error(f'Video encode image: {e}') errors.display(e, 'Video encode image') res = None t1 = time.time() @@ -69,11 +70,11 @@ def get_codecs(): pass hw_codecs = [c for c in codecs if (c.capabilities & 0x40000 > 0) or (c.capabilities & 0x80000 > 0)] sw_codecs = [c for c in codecs if c not in hw_codecs] - shared.log.debug(f'Video codecs: hardware={len(hw_codecs)} software={len(sw_codecs)}') + logger.log.debug(f'Video codecs: hardware={len(hw_codecs)} software={len(sw_codecs)}') # for c in hw_codecs: - # shared.log.trace(f'codec={c.name} cname="{c.canonical_name}" decs="{c.long_name}" intra={c.intra_only} lossy={c.lossy} lossless={c.lossless} capabilities={c.capabilities} hw=True') + # logger.log.trace(f'codec={c.name} cname="{c.canonical_name}" decs="{c.long_name}" intra={c.intra_only} lossy={c.lossy} lossless={c.lossless} capabilities={c.capabilities} hw=True') # for c in sw_codecs: - # shared.log.trace(f'codec={c.name} cname="{c.canonical_name}" decs="{c.long_name}" intra={c.intra_only} lossy={c.lossy} lossless={c.lossless} capabilities={c.capabilities} hw=False') + # logger.log.trace(f'codec={c.name} cname="{c.canonical_name}" decs="{c.long_name}" intra={c.intra_only} lossy={c.lossy} lossless={c.lossless} capabilities={c.capabilities} hw=False') return ['none'] + [c.name for c in hw_codecs + sw_codecs] @@ -112,8 +113,8 @@ def get_video_frames(fn: str, num_frames: int = -1, skip_frames: int = 0): if len(frames) >= num_frames > 0: break video.release() - shared.log.debug(f'Video open: file="{fn}" frames={len(frames)} total={frame_count} skip={skip} fps={fps} size={w}x{h} codec={codec}') + logger.log.debug(f'Video open: file="{fn}" frames={len(frames)} total={frame_count} skip={skip} fps={fps} size={w}x{h} codec={codec}') except Exception as e: - shared.log.error(f'Video open: file="{fn}" {e}') + logger.log.error(f'Video open: file="{fn}" {e}') return frames return frames diff --git a/modules/video_models/video_vae.py b/modules/video_models/video_vae.py index dd8ba233f..69b21fe62 100644 --- a/modules/video_models/video_vae.py +++ b/modules/video_models/video_vae.py @@ -1,8 +1,9 @@ import os from modules import shared, devices +from modules import logger -debug = shared.log.trace if os.environ.get('SD_VIDEO_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_VIDEO_DEBUG', None) is not None else lambda *args, **kwargs: None vae_type = None @@ -39,13 +40,13 @@ def vae_decode_tiny(latents): elif 'Kandinsky' in shared.sd_model.__class__.__name__: variant = 'TAE HunyuanVideo' else: - shared.log.warning(f'Decode: type=Tiny cls={shared.sd_model.__class__.__name__} not supported') + logger.log.warning(f'Decode: type=Tiny cls={shared.sd_model.__class__.__name__} not supported') return None from modules.vae import sd_vae_taesd vae, variant = sd_vae_taesd.get_model(variant=variant) if vae is None: return None - shared.log.debug(f'Decode: type=Tiny cls={vae.__class__.__name__} variant="{variant}" latents={latents.shape}') + logger.log.debug(f'Decode: type=Tiny cls={vae.__class__.__name__} variant="{variant}" latents={latents.shape}') vae = vae.to(device=devices.device, dtype=devices.dtype) latents = latents.transpose(1, 2).to(device=devices.device, dtype=devices.dtype) images = vae.decode_video(latents, parallel=False).transpose(1, 2).mul_(2).sub_(1) diff --git a/modules/zluda.py b/modules/zluda.py index 258958cc7..3afe100f4 100644 --- a/modules/zluda.py +++ b/modules/zluda.py @@ -21,7 +21,7 @@ def test(device) -> Exception | None: def zluda_init(): try: import torch - from installer import log + from modules.logger import log from modules import devices, zluda_installer from modules.shared import cmd_opts from modules.rocm_triton_windows import apply_triton_patches diff --git a/modules/zluda_installer.py b/modules/zluda_installer.py index 5326588eb..1d9a18890 100644 --- a/modules/zluda_installer.py +++ b/modules/zluda_installer.py @@ -6,7 +6,8 @@ import ctypes import shutil import zipfile import urllib.request -from installer import args, log +from installer import args +from modules.logger import log from modules import rocm diff --git a/pipelines/flux/flux_legacy_loader.py b/pipelines/flux/flux_legacy_loader.py index cb3dad3c1..d36be3098 100644 --- a/pipelines/flux/flux_legacy_loader.py +++ b/pipelines/flux/flux_legacy_loader.py @@ -6,9 +6,10 @@ import transformers from safetensors.torch import load_file from huggingface_hub import hf_hub_download from modules import shared, errors, devices, sd_models, sd_unet, model_te, model_quant, sd_hijack_te +from modules import logger -debug = shared.log.trace if os.environ.get('SD_LOAD_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_LOAD_DEBUG', None) is not None else lambda *args, **kwargs: None def load_flux_quanto(checkpoint_info): @@ -38,9 +39,9 @@ def load_flux_quanto(checkpoint_info): try: transformer = transformer.to(dtype=devices.dtype) except Exception: - shared.log.error(f"Load model: type=FLUX Failed to cast transformer to {devices.dtype}, set dtype to {transformer_dtype}") + logger.log.error(f"Load model: type=FLUX Failed to cast transformer to {devices.dtype}, set dtype to {transformer_dtype}") except Exception as e: - shared.log.error(f"Load model: type=FLUX failed to load Quanto transformer: {e}") + logger.log.error(f"Load model: type=FLUX failed to load Quanto transformer: {e}") if debug: errors.display(e, 'FLUX Quanto:') @@ -64,9 +65,9 @@ def load_flux_quanto(checkpoint_info): try: text_encoder_2 = text_encoder_2.to(dtype=devices.dtype) except Exception: - shared.log.error(f"Load model: type=FLUX Failed to cast text encoder to {devices.dtype}, set dtype to {text_encoder_2_dtype}") + logger.log.error(f"Load model: type=FLUX Failed to cast text encoder to {devices.dtype}, set dtype to {text_encoder_2_dtype}") except Exception as e: - shared.log.error(f"Load model: type=FLUX failed to load Quanto text encoder: {e}") + logger.log.error(f"Load model: type=FLUX failed to load Quanto text encoder: {e}") if debug: errors.display(e, 'FLUX Quanto:') @@ -97,7 +98,7 @@ def load_flux_bnb(checkpoint_info, diffusers_load_config): # pylint: disable=unu else: transformer = diffusers.FluxTransformer2DModel.from_single_file(repo_path, **diffusers_load_config) except Exception as e: - shared.log.error(f"Load model: type=FLUX failed to load BnB transformer: {e}") + logger.log.error(f"Load model: type=FLUX failed to load BnB transformer: {e}") transformer, text_encoder_2 = None, None if debug: errors.display(e, 'FLUX:') @@ -127,9 +128,9 @@ def load_quants(kwargs, repo_id, cache_dir, allow_quant): # pylint: disable=unus elif 'shuttle' in repo_id.lower(): nunchaku_repo = f"mit-han-lab/nunchaku-shuttle-jaguar/svdq-{nunchaku_precision}_r32-shuttle-jaguar.safetensors" else: - shared.log.error(f'Load module: quant=Nunchaku module=transformer repo="{repo_id}" unsupported') + logger.log.error(f'Load module: quant=Nunchaku module=transformer repo="{repo_id}" unsupported') if nunchaku_repo is not None: - shared.log.debug(f'Load module: quant=Nunchaku module=transformer repo="{nunchaku_repo}" precision={nunchaku_precision} offload={shared.opts.nunchaku_offload} attention={shared.opts.nunchaku_attention}') + logger.log.debug(f'Load module: quant=Nunchaku module=transformer repo="{nunchaku_repo}" precision={nunchaku_precision} offload={shared.opts.nunchaku_offload} attention={shared.opts.nunchaku_attention}') kwargs['transformer'] = nunchaku.NunchakuFluxTransformer2dModel.from_pretrained(nunchaku_repo, offload=shared.opts.nunchaku_offload, torch_dtype=devices.dtype, cache_dir=cache_dir) kwargs['transformer'].quantization_method = 'SVDQuant' if shared.opts.nunchaku_attention: @@ -141,14 +142,14 @@ def load_quants(kwargs, repo_id, cache_dir, allow_quant): # pylint: disable=unus import nunchaku nunchaku_precision = nunchaku.utils.get_precision() nunchaku_repo = 'mit-han-lab/nunchaku-t5/awq-int4-flux.1-t5xxl.safetensors' - shared.log.debug(f'Load module: quant=Nunchaku module=t5 repo="{nunchaku_repo}" precision={nunchaku_precision}') + logger.log.debug(f'Load module: quant=Nunchaku module=t5 repo="{nunchaku_repo}" precision={nunchaku_precision}') kwargs['text_encoder_2'] = nunchaku.NunchakuT5EncoderModel.from_pretrained(nunchaku_repo, torch_dtype=devices.dtype, cache_dir=cache_dir) kwargs['text_encoder_2'].quantization_method = 'SVDQuant' if 'text_encoder_2' not in kwargs and model_quant.check_quant('TE'): load_args, quant_args = model_quant.get_dit_args(diffusers_load_config, module='TE', device_map=True) kwargs['text_encoder_2'] = transformers.T5EncoderModel.from_pretrained(repo_id, subfolder="text_encoder_2", **load_args, **quant_args) except Exception as e: - shared.log.error(f'Quantization: {e}') + logger.log.error(f'Quantization: {e}') errors.display(e, 'Quantization:') return kwargs @@ -163,7 +164,7 @@ def load_transformer(file_path): # triggered by opts.sd_unet change "cache_dir": shared.opts.hfcache_dir, } if quant is not None and quant != 'none': - shared.log.info(f'Load module: type=UNet/Transformer file="{file_path}" offload={shared.opts.diffusers_offload_mode} prequant={quant} dtype={devices.dtype}') + logger.log.info(f'Load module: type=UNet/Transformer file="{file_path}" offload={shared.opts.diffusers_offload_mode} prequant={quant} dtype={devices.dtype}') if 'gguf' in file_path.lower(): from modules import ggml _transformer = ggml.load_gguf(file_path, cls=diffusers.FluxTransformer2DModel, compute_dtype=devices.dtype) @@ -189,16 +190,16 @@ def load_transformer(file_path): # triggered by opts.sd_unet change else: quant_args = model_quant.create_bnb_config({}) if quant_args: - shared.log.info(f'Load module: type=Flux transformer file="{file_path}" offload={shared.opts.diffusers_offload_mode} quant=bnb dtype={devices.dtype}') + logger.log.info(f'Load module: type=Flux transformer file="{file_path}" offload={shared.opts.diffusers_offload_mode} quant=bnb dtype={devices.dtype}') from pipelines.flux.flux_nf4 import load_flux_nf4 transformer, _text_encoder_2 = load_flux_nf4(file_path, prequantized=False) if transformer is not None: return transformer load_args, quant_args = model_quant.get_dit_args(diffusers_load_config, module='Model', device_map=True) - shared.log.debug(f'Load model: type=Flux transformer file="{file_path}" offload={shared.opts.diffusers_offload_mode} args={load_args}') + logger.log.debug(f'Load model: type=Flux transformer file="{file_path}" offload={shared.opts.diffusers_offload_mode} args={load_args}') transformer = diffusers.FluxTransformer2DModel.from_single_file(file_path, **load_args, **quant_args) if transformer is None: - shared.log.error('Failed to load UNet model') + logger.log.error('Failed to load UNet model') shared.opts.sd_unet = 'Default' return transformer @@ -209,7 +210,7 @@ def load_flux(checkpoint_info, diffusers_load_config): # triggered by opts.sd_ch allow_post_quant = False prequantized = model_quant.get_quant(checkpoint_info.path) - shared.log.debug(f'Load model: type=FLUX model="{checkpoint_info.name}" repo="{repo_id}" unet="{shared.opts.sd_unet}" te="{shared.opts.sd_text_encoder}" vae="{shared.opts.sd_vae}" quant={prequantized} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype}') + logger.log.debug(f'Load model: type=FLUX model="{checkpoint_info.name}" repo="{repo_id}" unet="{shared.opts.sd_unet}" te="{shared.opts.sd_text_encoder}" vae="{shared.opts.sd_vae}" quant={prequantized} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype}') debug(f'Load model: type=FLUX config={diffusers_load_config}') transformer = None @@ -224,7 +225,7 @@ def load_flux(checkpoint_info, diffusers_load_config): # triggered by opts.sd_ch if shared.opts.teacache_enabled: from modules import teacache - shared.log.debug(f'Transformers cache: type=teacache patch=forward cls={diffusers.FluxTransformer2DModel.__name__}') + logger.log.debug(f'Transformers cache: type=teacache patch=forward cls={diffusers.FluxTransformer2DModel.__name__}') diffusers.FluxTransformer2DModel.forward = teacache.teacache_flux_forward # patch must be done before transformer is loaded # load overrides if any @@ -236,7 +237,7 @@ def load_flux(checkpoint_info, diffusers_load_config): # triggered by opts.sd_ch shared.opts.sd_unet = 'Default' sd_unet.failed_unet.append(shared.opts.sd_unet) except Exception as e: - shared.log.error(f"Load model: type=FLUX failed to load UNet: {e}") + logger.log.error(f"Load model: type=FLUX failed to load UNet: {e}") shared.opts.sd_unet = 'Default' if debug: errors.display(e, 'FLUX UNet:') @@ -249,7 +250,7 @@ def load_flux(checkpoint_info, diffusers_load_config): # triggered by opts.sd_ch else: text_encoder_2 = load_t5(name=shared.opts.sd_text_encoder, cache_dir=shared.opts.diffusers_dir) except Exception as e: - shared.log.error(f"Load model: type=FLUX failed to load T5: {e}") + logger.log.error(f"Load model: type=FLUX failed to load T5: {e}") shared.opts.sd_text_encoder = 'Default' if debug: errors.display(e, 'FLUX T5:') @@ -263,7 +264,7 @@ def load_flux(checkpoint_info, diffusers_load_config): # triggered by opts.sd_ch vae_config = os.path.join('configs', 'flux', 'vae', 'config.json') vae = diffusers.AutoencoderKL.from_single_file(vae_file, config=vae_config, **diffusers_load_config) except Exception as e: - shared.log.error(f"Load model: type=FLUX failed to load VAE: {e}") + logger.log.error(f"Load model: type=FLUX failed to load VAE: {e}") shared.opts.sd_vae = 'Default' if debug: errors.display(e, 'FLUX VAE:') @@ -278,7 +279,7 @@ def load_flux(checkpoint_info, diffusers_load_config): # triggered by opts.sd_ch if _text_encoder is not None: text_encoder_2 = _text_encoder except Exception as e: - shared.log.error(f"Load model: type=FLUX failed to load NF4 components: {e}") + logger.log.error(f"Load model: type=FLUX failed to load NF4 components: {e}") if debug: errors.display(e, 'FLUX NF4:') if prequantized == 'qint8' or prequantized == 'qint4': @@ -289,7 +290,7 @@ def load_flux(checkpoint_info, diffusers_load_config): # triggered by opts.sd_ch if _text_encoder is not None: text_encoder_2 = _text_encoder except Exception as e: - shared.log.error(f"Load model: type=FLUX failed to load Quanto components: {e}") + logger.log.error(f"Load model: type=FLUX failed to load Quanto components: {e}") if debug: errors.display(e, 'FLUX Quanto:') @@ -323,14 +324,14 @@ def load_flux(checkpoint_info, diffusers_load_config): # triggered by opts.sd_ch else: cls = diffusers.FluxPipeline - shared.log.debug(f'Load model: type=FLUX cls={cls.__name__} preloaded={list(kwargs)} revision={diffusers_load_config.get("revision", None)}') + logger.log.debug(f'Load model: type=FLUX cls={cls.__name__} preloaded={list(kwargs)} revision={diffusers_load_config.get("revision", None)}') for c in kwargs: if getattr(kwargs[c], 'quantization_method', None) is not None or getattr(kwargs[c], 'gguf', None) is not None: - shared.log.debug(f'Load model: type=FLUX component={c} dtype={kwargs[c].dtype} quant={getattr(kwargs[c], "quantization_method", None) or getattr(kwargs[c], "gguf", None)}') + logger.log.debug(f'Load model: type=FLUX component={c} dtype={kwargs[c].dtype} quant={getattr(kwargs[c], "quantization_method", None) or getattr(kwargs[c], "gguf", None)}') if kwargs[c].dtype == torch.float32 and devices.dtype != torch.float32: try: kwargs[c] = kwargs[c].to(dtype=devices.dtype) - shared.log.warning(f'Load model: type=FLUX component={c} dtype={kwargs[c].dtype} cast dtype={devices.dtype} recast') + logger.log.warning(f'Load model: type=FLUX component={c} dtype={kwargs[c].dtype} cast dtype={devices.dtype} recast') except Exception: pass diff --git a/pipelines/flux/flux_nf4.py b/pipelines/flux/flux_nf4.py index 94c99e422..b6cb86f24 100644 --- a/pipelines/flux/flux_nf4.py +++ b/pipelines/flux/flux_nf4.py @@ -12,6 +12,7 @@ from accelerate.utils import set_module_tensor_to_device from diffusers.loaders.single_file_utils import convert_flux_transformer_checkpoint_to_diffusers import safetensors.torch from modules import shared, devices, model_quant +from modules import logger debug = os.environ.get('SD_LOAD_DEBUG', None) is not None @@ -163,7 +164,7 @@ def load_flux_nf4(checkpoint_info, prequantized: bool = True): try: converted_state_dict = convert_flux_transformer_checkpoint_to_diffusers(original_state_dict) except Exception as e: - shared.log.error(f"Load model: type=FLUX Failed to convert UNET: {e}") + logger.log.error(f"Load model: type=FLUX Failed to convert UNET: {e}") if debug: from modules import errors errors.display(e, 'FLUX convert:') @@ -190,7 +191,7 @@ def load_flux_nf4(checkpoint_info, prequantized: bool = True): create_quantized_param(transformer, param, param_name, target_device=0, state_dict=original_state_dict, pre_quantized=prequantized) except Exception as e: transformer, text_encoder_2 = None, None - shared.log.error(f"Load model: type=FLUX failed to load UNET: {e}") + logger.log.error(f"Load model: type=FLUX failed to load UNET: {e}") if debug: from modules import errors errors.display(e, 'FLUX:') diff --git a/pipelines/flux/flux_nunchaku.py b/pipelines/flux/flux_nunchaku.py index d8761e186..0d3cc35cd 100644 --- a/pipelines/flux/flux_nunchaku.py +++ b/pipelines/flux/flux_nunchaku.py @@ -1,3 +1,4 @@ +from modules import logger from modules import shared, devices @@ -23,9 +24,9 @@ def load_flux_nunchaku(repo_id): elif 'shuttle' in repo_id.lower(): nunchaku_repo = f"nunchaku-ai/nunchaku-shuttle-jaguar/svdq-{nunchaku_precision}-shuttle-jaguar.safetensors" else: - shared.log.error(f'Load module: quant=Nunchaku module=transformer repo="{repo_id}" unsupported') + logger.log.error(f'Load module: quant=Nunchaku module=transformer repo="{repo_id}" unsupported') if nunchaku_repo is not None: - shared.log.debug(f'Load module: quant=Nunchaku module=transformer repo="{nunchaku_repo}" precision={nunchaku_precision} offload={shared.opts.nunchaku_offload} attention={shared.opts.nunchaku_attention}') + logger.log.debug(f'Load module: quant=Nunchaku module=transformer repo="{nunchaku_repo}" precision={nunchaku_precision} offload={shared.opts.nunchaku_offload} attention={shared.opts.nunchaku_attention}') transformer = nunchaku.NunchakuFluxTransformer2dModel.from_pretrained( nunchaku_repo, offload=shared.opts.nunchaku_offload, diff --git a/pipelines/flux/flux_quanto.py b/pipelines/flux/flux_quanto.py index 11e604b62..1e8f71060 100644 --- a/pipelines/flux/flux_quanto.py +++ b/pipelines/flux/flux_quanto.py @@ -6,9 +6,10 @@ import transformers from safetensors.torch import load_file from huggingface_hub import hf_hub_download from modules import shared, errors, devices, sd_models, model_quant +from modules import logger -debug = shared.log.trace if os.environ.get('SD_LOAD_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_LOAD_DEBUG', None) is not None else lambda *args, **kwargs: None def load_flux_quanto(checkpoint_info): @@ -38,9 +39,9 @@ def load_flux_quanto(checkpoint_info): try: transformer = transformer.to(dtype=devices.dtype) except Exception: - shared.log.error(f"Load model: type=FLUX Failed to cast transformer to {devices.dtype}, set dtype to {transformer_dtype}") + logger.log.error(f"Load model: type=FLUX Failed to cast transformer to {devices.dtype}, set dtype to {transformer_dtype}") except Exception as e: - shared.log.error(f"Load model: type=FLUX failed to load Quanto transformer: {e}") + logger.log.error(f"Load model: type=FLUX failed to load Quanto transformer: {e}") if debug: errors.display(e, 'FLUX Quanto:') @@ -64,9 +65,9 @@ def load_flux_quanto(checkpoint_info): try: text_encoder_2 = text_encoder_2.to(dtype=devices.dtype) except Exception: - shared.log.error(f"Load model: type=FLUX Failed to cast text encoder to {devices.dtype}, set dtype to {text_encoder_2_dtype}") + logger.log.error(f"Load model: type=FLUX Failed to cast text encoder to {devices.dtype}, set dtype to {text_encoder_2_dtype}") except Exception as e: - shared.log.error(f"Load model: type=FLUX failed to load Quanto text encoder: {e}") + logger.log.error(f"Load model: type=FLUX failed to load Quanto text encoder: {e}") if debug: errors.display(e, 'FLUX Quanto:') diff --git a/pipelines/generic.py b/pipelines/generic.py index 3b1b4bc66..f5a8858b2 100644 --- a/pipelines/generic.py +++ b/pipelines/generic.py @@ -4,6 +4,7 @@ import json import diffusers import transformers from modules import shared, devices, errors, sd_models, model_quant +from modules import logger debug = os.environ.get('SD_LOAD_DEBUG', None) is not None @@ -36,12 +37,12 @@ def load_transformer(repo_id, cls_name, load_config=None, subfolder="transformer if shared.opts.sd_unet is not None and shared.opts.sd_unet != 'Default': from modules import sd_unet if shared.opts.sd_unet not in list(sd_unet.unet_dict): - shared.log.error(f'Load module: type=transformer file="{shared.opts.sd_unet}" not found') + logger.log.error(f'Load module: type=transformer file="{shared.opts.sd_unet}" not found') elif os.path.exists(sd_unet.unet_dict[shared.opts.sd_unet]): local_file = sd_unet.unet_dict[shared.opts.sd_unet] if local_file is not None and local_file.lower().endswith('.gguf'): - shared.log.debug(f'Load model: transformer="{local_file}" cls={cls_name.__name__} quant="{quant_type}" loader={_loader("diffusers")} args={load_args}') + logger.log.debug(f'Load model: transformer="{local_file}" cls={cls_name.__name__} quant="{quant_type}" loader={_loader("diffusers")} args={load_args}') from modules import ggml ggml.install_gguf() loader = cls_name.from_single_file if hasattr(cls_name, 'from_single_file') else cls_name.from_pretrained @@ -53,7 +54,7 @@ def load_transformer(repo_id, cls_name, load_config=None, subfolder="transformer ) transformer = model_quant.do_post_load_quant(transformer, allow=quant_type is not None) elif local_file is not None and local_file.lower().endswith('.safetensors'): - shared.log.debug(f'Load model: transformer="{local_file}" cls={cls_name.__name__} quant="{quant_type}" loader={_loader("diffusers")} args={load_args}') + logger.log.debug(f'Load model: transformer="{local_file}" cls={cls_name.__name__} quant="{quant_type}" loader={_loader("diffusers")} args={load_args}') if dtype is not None: load_args['torch_dtype'] = dtype load_args.pop('device_map', None) # single-file uses different syntax @@ -65,7 +66,7 @@ def load_transformer(repo_id, cls_name, load_config=None, subfolder="transformer **quant_args, ) else: - shared.log.debug(f'Load model: transformer="{repo_id}" cls={cls_name.__name__} subfolder={subfolder} quant="{quant_type}" loader={_loader("diffusers")} args={load_args}') + logger.log.debug(f'Load model: transformer="{repo_id}" cls={cls_name.__name__} subfolder={subfolder} quant="{quant_type}" loader={_loader("diffusers")} args={load_args}') if 'sdnq-' in repo_id.lower(): quant_args = {} if dtype is not None: @@ -91,7 +92,7 @@ def load_transformer(repo_id, cls_name, load_config=None, subfolder="transformer elif (quant_type is not None) and (quant_args.get('quantization_config', None) is not None): transformer.quantization_config = quant_args.get('quantization_config', None) except Exception as e: - shared.log.error(f'Load model: transformer="{repo_id}" cls={cls_name.__name__} {e}') + logger.log.error(f'Load model: transformer="{repo_id}" cls={cls_name.__name__} {e}') errors.display(e, 'Load') raise devices.torch_gc() @@ -120,13 +121,13 @@ def load_text_encoder(repo_id, cls_name, load_config=None, subfolder="text_encod if shared.opts.sd_text_encoder is not None and shared.opts.sd_text_encoder != 'Default': from modules import model_te if shared.opts.sd_text_encoder not in list(model_te.te_dict): - shared.log.error(f'Load module: type=te file="{shared.opts.sd_text_encoder}" not found') + logger.log.error(f'Load module: type=te file="{shared.opts.sd_text_encoder}" not found') elif os.path.exists(model_te.te_dict[shared.opts.sd_text_encoder]): local_file = model_te.te_dict[shared.opts.sd_text_encoder] # load from local file gguf if local_file is not None and local_file.lower().endswith('.gguf'): - shared.log.debug(f'Load model: text_encoder="{local_file}" cls={cls_name.__name__} quant="{quant_type}" loader={_loader("transformers")}') + logger.log.debug(f'Load model: text_encoder="{local_file}" cls={cls_name.__name__} quant="{quant_type}" loader={_loader("transformers")}') """ from modules import ggml ggml.install_gguf() @@ -143,7 +144,7 @@ def load_text_encoder(repo_id, cls_name, load_config=None, subfolder="text_encod # load from local file safetensors elif local_file is not None and local_file.lower().endswith('.safetensors'): - shared.log.debug(f'Load model: text_encoder="{local_file}" cls={cls_name.__name__} quant="{quant_type}" loader={_loader("transformers")}') + logger.log.debug(f'Load model: text_encoder="{local_file}" cls={cls_name.__name__} quant="{quant_type}" loader={_loader("transformers")}') from modules import model_te text_encoder = model_te.load_t5(local_file) text_encoder = model_quant.do_post_load_quant(text_encoder, allow=quant_type is not None) @@ -154,7 +155,7 @@ def load_text_encoder(repo_id, cls_name, load_config=None, subfolder="text_encod import nunchaku repo_id = 'nunchaku-ai/nunchaku-t5/awq-int4-flux.1-t5xxl.safetensors' cls_name = nunchaku.NunchakuT5EncoderModel - shared.log.debug(f'Load model: text_encoder="{repo_id}" cls={cls_name.__name__} quant="SVDQuant" loader={_loader("transformers")}') + logger.log.debug(f'Load model: text_encoder="{repo_id}" cls={cls_name.__name__} quant="SVDQuant" loader={_loader("transformers")}') text_encoder = nunchaku.NunchakuT5EncoderModel.from_pretrained( repo_id, torch_dtype=dtype, @@ -168,7 +169,7 @@ def load_text_encoder(repo_id, cls_name, load_config=None, subfolder="text_encod repo_id = 'Disty0/t5-xxl' with open(os.path.join('configs', 'flux', 'text_encoder_2', 'config.json'), encoding='utf8') as f: load_args['config'] = transformers.T5Config(**json.load(f)) - shared.log.debug(f'Load model: text_encoder="{repo_id}" cls={cls_name.__name__} quant="{quant_type}" loader={_loader("transformers")} shared={shared.opts.te_shared_t5}') + logger.log.debug(f'Load model: text_encoder="{repo_id}" cls={cls_name.__name__} quant="{quant_type}" loader={_loader("transformers")} shared={shared.opts.te_shared_t5}') text_encoder = cls_name.from_pretrained( repo_id, cache_dir=shared.opts.hfcache_dir, @@ -181,7 +182,7 @@ def load_text_encoder(repo_id, cls_name, load_config=None, subfolder="text_encod else: repo_id = 'Wan-AI/Wan2.1-T2V-1.3B-Diffusers' subfolder = 'text_encoder' - shared.log.debug(f'Load model: text_encoder="{repo_id}" cls={cls_name.__name__} quant="{quant_type}" loader={_loader("transformers")} shared={shared.opts.te_shared_t5}') + logger.log.debug(f'Load model: text_encoder="{repo_id}" cls={cls_name.__name__} quant="{quant_type}" loader={_loader("transformers")} shared={shared.opts.te_shared_t5}') text_encoder = cls_name.from_pretrained( repo_id, cache_dir=shared.opts.hfcache_dir, @@ -192,7 +193,7 @@ def load_text_encoder(repo_id, cls_name, load_config=None, subfolder="text_encod elif cls_name == transformers.Qwen2_5_VLForConditionalGeneration and allow_shared and shared.opts.te_shared_t5: repo_id = 'hunyuanvideo-community/HunyuanImage-2.1-Diffusers' subfolder = 'text_encoder' - shared.log.debug(f'Load model: text_encoder="{repo_id}" cls={cls_name.__name__} quant="{quant_type}" loader={_loader("transformers")} shared={shared.opts.te_shared_t5}') + logger.log.debug(f'Load model: text_encoder="{repo_id}" cls={cls_name.__name__} quant="{quant_type}" loader={_loader("transformers")} shared={shared.opts.te_shared_t5}') text_encoder = cls_name.from_pretrained( repo_id, cache_dir=shared.opts.hfcache_dir, @@ -210,7 +211,7 @@ def load_text_encoder(repo_id, cls_name, load_config=None, subfolder="text_encod else: shared_repo = 'Tongyi-MAI/Z-Image-Turbo' # 4B variants and Z-Image use Qwen3-4B subfolder = 'text_encoder' - shared.log.debug(f'Load model: text_encoder="{shared_repo}" cls={cls_name.__name__} quant="{quant_type}" loader={_loader("transformers")} shared={shared.opts.te_shared_t5}') + logger.log.debug(f'Load model: text_encoder="{shared_repo}" cls={cls_name.__name__} quant="{quant_type}" loader={_loader("transformers")} shared={shared.opts.te_shared_t5}') text_encoder = cls_name.from_pretrained( shared_repo, cache_dir=shared.opts.hfcache_dir, @@ -221,7 +222,7 @@ def load_text_encoder(repo_id, cls_name, load_config=None, subfolder="text_encod # load from repo if text_encoder is None: - shared.log.debug(f'Load model: text_encoder="{repo_id}" cls={cls_name.__name__} quant="{quant_type}" loader={_loader("transformers")} shared={shared.opts.te_shared_t5}') + logger.log.debug(f'Load model: text_encoder="{repo_id}" cls={cls_name.__name__} quant="{quant_type}" loader={_loader("transformers")} shared={shared.opts.te_shared_t5}') if subfolder is not None: load_args['subfolder'] = subfolder if variant is not None: @@ -243,7 +244,7 @@ def load_text_encoder(repo_id, cls_name, load_config=None, subfolder="text_encod elif (quant_type is not None) and (quant_args.get('quantization_config', None) is not None): text_encoder.quantization_config = quant_args.get('quantization_config', None) except Exception as e: - shared.log.error(f'Load model: text_encoder="{repo_id}" cls={cls_name.__name__} {e}') + logger.log.error(f'Load model: text_encoder="{repo_id}" cls={cls_name.__name__} {e}') errors.display(e, 'Load') raise devices.torch_gc() diff --git a/pipelines/model_anima.py b/pipelines/model_anima.py index 2937cd7e3..c9fa1457b 100644 --- a/pipelines/model_anima.py +++ b/pipelines/model_anima.py @@ -4,6 +4,7 @@ import transformers import diffusers import huggingface_hub as hf from modules import shared, devices, sd_models, model_quant, sd_hijack_te, sd_hijack_vae +from modules import logger from pipelines import generic @@ -21,14 +22,14 @@ def load_anima(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False) - shared.log.debug(f'Load model: type=Anima repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=Anima repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') # download custom pipeline modules from repo try: pipeline_file = hf.hf_hub_download(repo_id, filename='pipeline.py', cache_dir=shared.opts.diffusers_dir) adapter_file = hf.hf_hub_download(repo_id, filename='llm_adapter/modeling_llm_adapter.py', cache_dir=shared.opts.diffusers_dir) except Exception as e: - shared.log.error(f'Load model: type=Anima failed to download custom modules: {e}') + logger.log.error(f'Load model: type=Anima failed to download custom modules: {e}') return None # dynamically import custom classes and register in sys.modules so @@ -53,7 +54,7 @@ def load_anima(checkpoint_info, diffusers_load_config=None): torch_dtype=devices.dtype, ) except Exception as e: - shared.log.error(f'Load model: type=Anima adapter: {e}') + logger.log.error(f'Load model: type=Anima adapter: {e}') return None finally: shared.state.end() diff --git a/pipelines/model_auraflow.py b/pipelines/model_auraflow.py index ee9e1b633..dd45ec187 100644 --- a/pipelines/model_auraflow.py +++ b/pipelines/model_auraflow.py @@ -1,6 +1,7 @@ import transformers import diffusers from modules import shared, sd_models, devices, model_quant, sd_hijack_te +from modules import logger from pipelines import generic @@ -11,7 +12,7 @@ def load_auraflow(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config) - shared.log.debug(f'Load model: type=AuraFlow repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=AuraFlow repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') transformer = generic.load_transformer(repo_id, cls_name=diffusers.AuraFlowTransformer2DModel, load_config=diffusers_load_config) text_encoder = generic.load_text_encoder(repo_id, cls_name=transformers.UMT5EncoderModel, load_config=diffusers_load_config, allow_shared=False) # auraflow uses EleutherAI/pile-t5-xl diff --git a/pipelines/model_bria.py b/pipelines/model_bria.py index dd68f4070..a24f500d3 100644 --- a/pipelines/model_bria.py +++ b/pipelines/model_bria.py @@ -3,6 +3,7 @@ import sys import transformers import diffusers from modules import shared, devices, sd_models, model_quant, sd_hijack_te, sd_hijack_vae +from modules import logger from pipelines import generic @@ -19,7 +20,7 @@ def load_bria(checkpoint_info, diffusers_load_config=None): diffusers.BriaTransformer2DModel = BriaTransformer2DModel load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False) - shared.log.debug(f'Load model: type=Bria repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=Bria repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') transformer = generic.load_transformer(repo_id, cls_name=BriaTransformer2DModel, load_config=diffusers_load_config) text_encoder = generic.load_text_encoder(repo_id, cls_name=transformers.T5EncoderModel, load_config=diffusers_load_config) diff --git a/pipelines/model_chroma.py b/pipelines/model_chroma.py index bcb2cdcd5..e36d412cf 100644 --- a/pipelines/model_chroma.py +++ b/pipelines/model_chroma.py @@ -1,6 +1,7 @@ import diffusers import transformers from modules import shared, devices, sd_models, model_quant, sd_hijack_te +from modules import logger from pipelines import generic @@ -11,7 +12,7 @@ def load_chroma(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False) - shared.log.debug(f'Load model: type=Chroma repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=Chroma repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') transformer = generic.load_transformer(repo_id, cls_name=diffusers.ChromaTransformer2DModel, load_config=diffusers_load_config, modules_to_not_convert=["distilled_guidance_layer"]) text_encoder = generic.load_text_encoder(repo_id, cls_name=transformers.T5EncoderModel, load_config=diffusers_load_config) diff --git a/pipelines/model_chrono.py b/pipelines/model_chrono.py index 2c66df916..884ee9c16 100644 --- a/pipelines/model_chrono.py +++ b/pipelines/model_chrono.py @@ -1,11 +1,12 @@ import diffusers import transformers from modules import shared, devices, sd_models, model_quant, sd_hijack_te, sd_hijack_vae +from modules import logger from pipelines import generic def postprocess(p, result): # pylint: disable=unused-argument - shared.log.debug('Postprocess: model=ChronoEdit') + logger.log.debug('Postprocess: model=ChronoEdit') if result is not None and hasattr(result, 'images'): result.images = result.images[-1] return result @@ -18,7 +19,7 @@ def load_chrono(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False) - shared.log.debug(f'Load model: type=ChronoEdit repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=ChronoEdit repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') transformer = generic.load_transformer(repo_id, cls_name=diffusers.ChronoEditTransformer3DModel, load_config=diffusers_load_config, subfolder="transformer") text_encoder = generic.load_text_encoder(repo_id, cls_name=transformers.UMT5EncoderModel, load_config=diffusers_load_config, subfolder="text_encoder") diff --git a/pipelines/model_cogview.py b/pipelines/model_cogview.py index ae011ca95..3b96bfd3e 100644 --- a/pipelines/model_cogview.py +++ b/pipelines/model_cogview.py @@ -1,6 +1,7 @@ import transformers import diffusers from modules import shared, devices, sd_models, model_quant, sd_hijack_te +from modules import logger from pipelines import generic @@ -11,7 +12,7 @@ def load_cogview3(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config) - shared.log.debug(f'Load model: type=CogView3 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=CogView3 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') transformer = generic.load_transformer(repo_id, cls_name=diffusers.CogView3PlusTransformer2DModel, load_config=diffusers_load_config, subfolder="transformer") text_encoder = generic.load_text_encoder(repo_id, cls_name=transformers.T5EncoderModel, load_config=diffusers_load_config, subfolder="text_encoder") @@ -37,7 +38,7 @@ def load_cogview4(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config) - shared.log.debug(f'Load model: type=CogView4 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=CogView4 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') transformer = generic.load_transformer(repo_id, cls_name=diffusers.CogView4Transformer2DModel, load_config=diffusers_load_config, subfolder="transformer") text_encoder = generic.load_text_encoder(repo_id, cls_name=transformers.GlmModel, load_config=diffusers_load_config, subfolder="text_encoder", allow_quant=True) diff --git a/pipelines/model_cosmos.py b/pipelines/model_cosmos.py index 4c7430639..2ab5a5486 100644 --- a/pipelines/model_cosmos.py +++ b/pipelines/model_cosmos.py @@ -1,6 +1,7 @@ import transformers import diffusers from modules import shared, devices, sd_models, model_quant, sd_hijack_te, sd_hijack_vae +from modules import logger from pipelines import generic @@ -11,7 +12,7 @@ def load_cosmos_t2i(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False) - shared.log.debug(f'Load model: type=Cosmos repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=Cosmos repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') transformer = generic.load_transformer(repo_id, cls_name=diffusers.CosmosTransformer3DModel, load_config=diffusers_load_config, subfolder="transformer") repo_te = 'nvidia/Cosmos-Predict2-2B-Text2Image' if 'Cosmos-Predict2-14B-Text2Image' in repo_id else repo_id diff --git a/pipelines/model_flex.py b/pipelines/model_flex.py index 097da2fec..c87004484 100644 --- a/pipelines/model_flex.py +++ b/pipelines/model_flex.py @@ -1,6 +1,7 @@ import transformers import diffusers from modules import shared, devices, sd_models, model_quant, sd_hijack_te +from modules import logger from pipelines import generic @@ -11,7 +12,7 @@ def load_flex(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False) - shared.log.debug(f'Load model: type=Flex repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=Flex repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') transformer = generic.load_transformer(repo_id, cls_name=diffusers.FluxTransformer2DModel, load_config=diffusers_load_config) text_encoder_2 = generic.load_text_encoder(repo_id, cls_name=transformers.T5EncoderModel, load_config=diffusers_load_config, subfolder="text_encoder_2") diff --git a/pipelines/model_flite.py b/pipelines/model_flite.py index 66199981e..7bb93b131 100644 --- a/pipelines/model_flite.py +++ b/pipelines/model_flite.py @@ -2,6 +2,7 @@ import sys import diffusers import transformers from modules import shared, devices, sd_models, model_quant, sd_hijack_te +from modules import logger from pipelines import generic @@ -12,7 +13,7 @@ def load_flite(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False) - shared.log.debug(f'Load model: type=FLite repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=FLite repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') from pipelines import f_lite diffusers.FLitePipeline = f_lite.FLitePipeline diff --git a/pipelines/model_flux.py b/pipelines/model_flux.py index 142978455..d70f728a1 100644 --- a/pipelines/model_flux.py +++ b/pipelines/model_flux.py @@ -2,6 +2,7 @@ import os import diffusers import transformers from modules import shared, devices, sd_models, model_quant, sd_hijack_te +from modules import logger from pipelines import generic @@ -29,12 +30,12 @@ def load_flux(checkpoint_info, diffusers_load_config=None): flux_lora.apply_patch() load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False) - shared.log.debug(f'Load model: type=Flux repo="{repo_id}" cls={cls_name.__name__} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=Flux repo="{repo_id}" cls={cls_name.__name__} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') # optional teacache patch if shared.opts.teacache_enabled and not model_quant.check_nunchaku('Model'): from modules import teacache - shared.log.debug(f'Transformers cache: type=teacache patch=forward cls={diffusers.FluxTransformer2DModel.__name__}') + logger.log.debug(f'Transformers cache: type=teacache patch=forward cls={diffusers.FluxTransformer2DModel.__name__}') diffusers.FluxTransformer2DModel.forward = teacache.teacache_flux_forward # patch must be done before transformer is loaded transformer = None @@ -73,7 +74,7 @@ def load_flux(checkpoint_info, diffusers_load_config=None): if os.environ.get('SD_REMOTE_T5', None) is not None: from modules import sd_te_remote - shared.log.warning('Remote-TE: applying patch') + logger.log.warning('Remote-TE: applying patch') pipe._get_t5_prompt_embeds = sd_te_remote.get_t5_prompt_embeds # pylint: disable=protected-access pipe.text_encoder_2 = None diff --git a/pipelines/model_flux2.py b/pipelines/model_flux2.py index 5119f5588..068088091 100644 --- a/pipelines/model_flux2.py +++ b/pipelines/model_flux2.py @@ -1,6 +1,7 @@ import transformers import diffusers from modules import shared, devices, sd_models, model_quant, sd_hijack_te, sd_hijack_vae +from modules import logger from pipelines import generic @@ -11,7 +12,7 @@ def load_flux2(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False) - shared.log.debug(f'Load model: type=Flux2 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=Flux2 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') transformer = generic.load_transformer(repo_id, cls_name=diffusers.Flux2Transformer2DModel, load_config=diffusers_load_config) text_encoder = generic.load_text_encoder(repo_id, cls_name=transformers.Mistral3ForConditionalGeneration, load_config=diffusers_load_config) diff --git a/pipelines/model_flux2_klein.py b/pipelines/model_flux2_klein.py index d810821d9..119d46885 100644 --- a/pipelines/model_flux2_klein.py +++ b/pipelines/model_flux2_klein.py @@ -1,6 +1,7 @@ import transformers import diffusers from modules import shared, devices, sd_models, model_quant, sd_hijack_te, sd_hijack_vae +from modules import logger from pipelines import generic @@ -11,7 +12,7 @@ def load_flux2_klein(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False) - shared.log.debug(f'Load model: type=Flux2Klein repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=Flux2Klein repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') # Load transformer - Klein uses Flux2Transformer2DModel (same class as Flux2, different size) transformer = generic.load_transformer(repo_id, cls_name=diffusers.Flux2Transformer2DModel, load_config=diffusers_load_config) diff --git a/pipelines/model_glm.py b/pipelines/model_glm.py index d849ebb19..2c04417c8 100644 --- a/pipelines/model_glm.py +++ b/pipelines/model_glm.py @@ -3,6 +3,7 @@ import rich.progress as rp import transformers import diffusers from modules import shared, devices, sd_models, model_quant, sd_hijack_te +from modules import logger from pipelines import generic @@ -33,7 +34,7 @@ class GLMTokenProgressProcessor(transformers.LogitsProcessor): rp.MofNCompleteColumn(), rp.TimeElapsedColumn(), rp.TimeRemainingColumn(), - console=shared.console, + console=logger.console, ) self.pbar.start() self.pbar_task = self.pbar.add_task(description='', total=self.total_tokens, speed='') @@ -87,11 +88,11 @@ def load_glm_image(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) if not hasattr(transformers, 'GlmImageForConditionalGeneration'): - shared.log.error(f'Load model: type=GLM-Image repo="{repo_id}" transformers={transformers.__version__} not supported') + logger.log.error(f'Load model: type=GLM-Image repo="{repo_id}" transformers={transformers.__version__} not supported') return None load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False) - shared.log.debug(f'Load model: type=GLM-Image repo="{repo_id}" offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=GLM-Image repo="{repo_id}" offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') # Load transformer (DiT decoder - 7B) with quantization support transformer = generic.load_transformer( diff --git a/pipelines/model_google.py b/pipelines/model_google.py index 9c0637cf2..16738102d 100644 --- a/pipelines/model_google.py +++ b/pipelines/model_google.py @@ -2,7 +2,8 @@ import io import os import time from PIL import Image -from installer import install, reload, log +from installer import install, reload +from modules.logger import log image_size_buckets = { diff --git a/pipelines/model_hdm.py b/pipelines/model_hdm.py index 2d17da0a5..f6e456a30 100644 --- a/pipelines/model_hdm.py +++ b/pipelines/model_hdm.py @@ -2,6 +2,7 @@ import sys import torch import diffusers from modules import shared, devices, sd_models, errors +from modules import logger def load_hdm(checkpoint_info, diffusers_load_config=None): # pylint: disable=unused-argument @@ -25,7 +26,7 @@ def load_hdm(checkpoint_info, diffusers_load_config=None): # pylint: disable=unu **diffusers_load_config, ).to(devices.device) except Exception as e: - shared.log.error(f'Load HDM-XUT: path="{checkpoint_info.path}" {e}') + logger.log.error(f'Load HDM-XUT: path="{checkpoint_info.path}" {e}') errors.display(e, 'hdm') return None diff --git a/pipelines/model_hidream.py b/pipelines/model_hidream.py index efb748502..9bc6d6da5 100644 --- a/pipelines/model_hidream.py +++ b/pipelines/model_hidream.py @@ -1,6 +1,7 @@ import transformers import diffusers from modules import shared, devices, sd_models, model_quant, sd_hijack_te, sd_hijack_vae +from modules import logger from pipelines import generic @@ -9,7 +10,7 @@ def load_llama(diffusers_load_config=None): diffusers_load_config = {} load_args, quant_args = model_quant.get_dit_args(diffusers_load_config, module='TE', device_map=True) llama_repo = shared.opts.model_h1_llama_repo if shared.opts.model_h1_llama_repo != 'Default' else 'meta-llama/Meta-Llama-3.1-8B-Instruct' - shared.log.debug(f'Load model: type=HiDream te4="{llama_repo}" quant="{model_quant.get_quant_type(quant_args)}" args={load_args}') + logger.log.debug(f'Load model: type=HiDream te4="{llama_repo}" quant="{model_quant.get_quant_type(quant_args)}" args={load_args}') sd_models.hf_auth_check(llama_repo) text_encoder_4 = transformers.LlamaForCausalLM.from_pretrained( @@ -37,7 +38,7 @@ def load_hidream(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False) - shared.log.debug(f'Load model: type=HiDream repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=HiDream repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') transformer = generic.load_transformer(repo_id, cls_name=diffusers.HiDreamImageTransformer2DModel, load_config=diffusers_load_config, subfolder="transformer") text_encoder_3 = generic.load_text_encoder(repo_id, cls_name=transformers.T5EncoderModel, load_config=diffusers_load_config, subfolder="text_encoder_3") @@ -45,7 +46,7 @@ def load_hidream(checkpoint_info, diffusers_load_config=None): if shared.opts.teacache_enabled: from modules import teacache - shared.log.debug(f'Transformers cache: type=teacache patch=forward cls={diffusers.HiDreamImageTransformer2DModel.__name__}') + logger.log.debug(f'Transformers cache: type=teacache patch=forward cls={diffusers.HiDreamImageTransformer2DModel.__name__}') diffusers.HiDreamImageTransformer2DModel.forward = teacache.teacache_hidream_forward # patch must be done before transformer is loaded if 'I1' in repo_id: @@ -61,7 +62,7 @@ def load_hidream(checkpoint_info, diffusers_load_config=None): elif transformer and 'E1' in repo_id: transformer.max_seq = 4608 else: - shared.log.error(f'Load model: type=HiDream model="{checkpoint_info.name}" repo="{repo_id}" not recognized') + logger.log.error(f'Load model: type=HiDream model="{checkpoint_info.name}" repo="{repo_id}" not recognized') return False pipe = cls.from_pretrained( diff --git a/pipelines/model_hunyuandit.py b/pipelines/model_hunyuandit.py index 10863e9d9..758fe7b7d 100644 --- a/pipelines/model_hunyuandit.py +++ b/pipelines/model_hunyuandit.py @@ -1,6 +1,7 @@ import transformers import diffusers from modules import shared, sd_models, devices, model_quant +from modules import logger from pipelines import generic @@ -16,7 +17,7 @@ def load_hunyuandit(checkpoint_info, diffusers_load_config=None): # devices.dtype_unet = torch.float16 # diffusers_load_config['torch_dtype'] = devices.dtype load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config) - shared.log.debug(f'Load model: type=HunyuanDiT repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=HunyuanDiT repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') transformer = generic.load_transformer(repo_id, cls_name=diffusers.HunyuanDiT2DModel, load_config=diffusers_load_config) repo_te = 'Tencent-Hunyuan/HunyuanDiT-v1.2-Diffusers' if 'HunyuanDiT-v1' in repo_id else repo_id diff --git a/pipelines/model_hyimage.py b/pipelines/model_hyimage.py index 28458bc86..6e12036b4 100644 --- a/pipelines/model_hyimage.py +++ b/pipelines/model_hyimage.py @@ -3,6 +3,7 @@ import torch import transformers import diffusers from modules import shared, sd_models, devices, model_quant, sd_hijack_te, sd_hijack_vae +from modules import logger from pipelines import generic @@ -13,7 +14,7 @@ def load_hyimage(checkpoint_info, diffusers_load_config=None): # pylint: disable sd_models.hf_auth_check(checkpoint_info) load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config) - shared.log.debug(f'Load model: type=HunyuanImage21 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=HunyuanImage21 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') transformer = generic.load_transformer(repo_id, cls_name=diffusers.HunyuanImageTransformer2DModel, load_config=diffusers_load_config, subfolder="transformer") text_encoder = generic.load_text_encoder(repo_id, cls_name=transformers.Qwen2_5_VLForConditionalGeneration, load_config=diffusers_load_config, subfolder="text_encoder") @@ -46,7 +47,7 @@ def load_hyimage3(checkpoint_info, diffusers_load_config=None): # pylint: disabl diffusers_load_config = {} repo_id = sd_models.path_to_repo(checkpoint_info) sd_models.hf_auth_check(checkpoint_info) - shared.log.debug(f'Load model: type=HunyuanImage3 repo="{repo_id}" offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype}') + logger.log.debug(f'Load model: type=HunyuanImage3 repo="{repo_id}" offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype}') allow_quant = True if 'sdnq-' in repo_id.lower(): diff --git a/pipelines/model_kandinsky.py b/pipelines/model_kandinsky.py index b2545e8fc..54c826270 100644 --- a/pipelines/model_kandinsky.py +++ b/pipelines/model_kandinsky.py @@ -1,6 +1,7 @@ import transformers import diffusers from modules import shared, sd_models, devices, model_quant, sd_hijack_te, sd_hijack_vae +from modules import logger from pipelines import generic @@ -11,7 +12,7 @@ def load_kandinsky21(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config) - shared.log.debug(f'Load model: type=Kandinsky21 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=Kandinsky21 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') pipe = diffusers.KandinskyCombinedPipeline.from_pretrained( repo_id, cache_dir=shared.opts.diffusers_dir, @@ -29,7 +30,7 @@ def load_kandinsky22(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config) - shared.log.debug(f'Load model: type=Kandinsky22 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=Kandinsky22 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') pipe = diffusers.KandinskyV22CombinedPipeline.from_pretrained( repo_id, cache_dir=shared.opts.diffusers_dir, @@ -47,7 +48,7 @@ def load_kandinsky3(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config) - shared.log.debug(f'Load model: type=Kandinsky30 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=Kandinsky30 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') unet = generic.load_transformer(repo_id, cls_name=diffusers.Kandinsky3UNet, load_config=diffusers_load_config, subfolder="unet", variant="fp16") text_encoder = generic.load_text_encoder(repo_id, cls_name=transformers.T5EncoderModel, load_config=diffusers_load_config, subfolder="text_encoder", variant="fp16", allow_shared=False) @@ -80,7 +81,7 @@ def load_kandinsky5(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config) - shared.log.debug(f'Load model: type=Kandinsky50 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=Kandinsky50 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') transformer = generic.load_transformer(repo_id, cls_name=diffusers.Kandinsky5Transformer3DModel, load_config=diffusers_load_config) text_encoder = generic.load_text_encoder(repo_id, cls_name=transformers.Qwen2_5_VLForConditionalGeneration, load_config=diffusers_load_config) diff --git a/pipelines/model_kolors.py b/pipelines/model_kolors.py index 977b68320..4dfa7c507 100644 --- a/pipelines/model_kolors.py +++ b/pipelines/model_kolors.py @@ -1,6 +1,7 @@ import torch import diffusers from modules import shared, devices, sd_models, sd_hijack_te +from modules import logger def load_kolors(checkpoint_info, diffusers_load_config=None): @@ -13,7 +14,7 @@ def load_kolors(checkpoint_info, diffusers_load_config=None): if 'torch_dtype' not in diffusers_load_config: diffusers_load_config['torch_dtype'] = torch.float16 - shared.log.debug(f'Load model: type=Kolors repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={diffusers_load_config}') + logger.log.debug(f'Load model: type=Kolors repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={diffusers_load_config}') pipe = diffusers.KolorsPipeline.from_pretrained( repo_id, cache_dir = shared.opts.diffusers_dir, diff --git a/pipelines/model_longcat.py b/pipelines/model_longcat.py index d8dd7ece4..5b9166232 100644 --- a/pipelines/model_longcat.py +++ b/pipelines/model_longcat.py @@ -1,6 +1,7 @@ import transformers import diffusers from modules import shared, devices, sd_models, model_quant, sd_hijack_te +from modules import logger from pipelines import generic @@ -11,7 +12,7 @@ def load_longcat(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False) - shared.log.debug(f'Load model: type=LongCat repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={diffusers_load_config}') + logger.log.debug(f'Load model: type=LongCat repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={diffusers_load_config}') transformer = generic.load_transformer(repo_id, cls_name=diffusers.LongCatImageTransformer2DModel, load_config=diffusers_load_config) text_encoder = generic.load_text_encoder(repo_id, cls_name=transformers.Qwen2_5_VLForConditionalGeneration, load_config=diffusers_load_config) diff --git a/pipelines/model_lumina.py b/pipelines/model_lumina.py index 84607407e..2bba3c626 100644 --- a/pipelines/model_lumina.py +++ b/pipelines/model_lumina.py @@ -1,6 +1,7 @@ import transformers import diffusers from modules import shared, sd_models, sd_hijack_te, devices, model_quant +from modules import logger from pipelines import generic @@ -11,7 +12,7 @@ def load_lumina(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) load_config, _quant_config = model_quant.get_dit_args(diffusers_load_config, allow_quant=False) - shared.log.debug(f'Load model: type=LuminaSFT repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={diffusers_load_config}') + logger.log.debug(f'Load model: type=LuminaSFT repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={diffusers_load_config}') pipe = diffusers.LuminaText2ImgPipeline.from_pretrained( 'Alpha-VLLM/Lumina-Next-SFT-diffusers', cache_dir = shared.opts.diffusers_dir, @@ -30,10 +31,10 @@ def load_lumina2(checkpoint_info, diffusers_load_config=None): if shared.opts.teacache_enabled: from modules import teacache - shared.log.debug(f'Transformers cache: type=teacache patch=forward cls={diffusers.Lumina2Transformer2DModel.__name__}') + logger.log.debug(f'Transformers cache: type=teacache patch=forward cls={diffusers.Lumina2Transformer2DModel.__name__}') diffusers.Lumina2Transformer2DModel.forward = teacache.teacache_lumina2_forward # patch must be done before transformer is loaded - shared.log.debug(f'Load model: type=Lumina2 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={diffusers_load_config}') + logger.log.debug(f'Load model: type=Lumina2 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={diffusers_load_config}') transformer = generic.load_transformer(repo_id, cls_name=diffusers.Lumina2Transformer2DModel, load_config=diffusers_load_config) text_encoder = generic.load_text_encoder(repo_id, cls_name=transformers.Gemma2Model, load_config=diffusers_load_config) diff --git a/pipelines/model_meissonic.py b/pipelines/model_meissonic.py index c09cf92e5..ddbf0f9d7 100644 --- a/pipelines/model_meissonic.py +++ b/pipelines/model_meissonic.py @@ -1,6 +1,7 @@ import transformers import diffusers from modules import shared, devices, sd_models, shared_items, sd_hijack_te +from modules import logger def load_meissonic(checkpoint_info, diffusers_load_config=None): @@ -19,7 +20,7 @@ def load_meissonic(checkpoint_info, diffusers_load_config=None): diffusers_load_config['variant'] = 'fp16' diffusers_load_config['trust_remote_code'] = True - shared.log.debug(f'Load model: type=Meissonic repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={diffusers_load_config}') + logger.log.debug(f'Load model: type=Meissonic repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={diffusers_load_config}') model = TransformerMeissonic.from_pretrained( repo_id, subfolder="transformer", diff --git a/pipelines/model_nextstep.py b/pipelines/model_nextstep.py index e6320df5a..aff07e283 100644 --- a/pipelines/model_nextstep.py +++ b/pipelines/model_nextstep.py @@ -1,5 +1,6 @@ # import transformers from modules import shared, devices, sd_models, model_quant # pylint: disable=unused-import +from modules import logger from pipelines import generic # pylint: disable=unused-import @@ -9,11 +10,11 @@ def load_nextstep(checkpoint_info, diffusers_load_config=None): # pylint: disabl repo_id = sd_models.path_to_repo(checkpoint_info) sd_models.hf_auth_check(checkpoint_info) - shared.log.error(f'Load model: type=NextStep model="{checkpoint_info.name}" repo="{repo_id}" not supported') + logger.log.error(f'Load model: type=NextStep model="{checkpoint_info.name}" repo="{repo_id}" not supported') """ load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, module='Model') - shared.log.debug(f'Load model: type=NextStep model="{checkpoint_info.name}" repo="{repo_id}" offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=NextStep model="{checkpoint_info.name}" repo="{repo_id}" offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') from pipelines.nextstep import NextStepPipeline, NextStep diff --git a/pipelines/model_omnigen.py b/pipelines/model_omnigen.py index b301abb81..4b0c08234 100644 --- a/pipelines/model_omnigen.py +++ b/pipelines/model_omnigen.py @@ -1,5 +1,6 @@ import diffusers from modules import shared, devices, sd_models, model_quant, sd_hijack_te +from modules import logger def load_omnigen(checkpoint_info, diffusers_load_config=None): # pylint: disable=unused-argument @@ -9,7 +10,7 @@ def load_omnigen(checkpoint_info, diffusers_load_config=None): # pylint: disable sd_models.hf_auth_check(checkpoint_info) load_config, quant_config = model_quant.get_dit_args(diffusers_load_config, module='Model') - shared.log.debug(f'Load model: type=OmniGen repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={diffusers_load_config}') + logger.log.debug(f'Load model: type=OmniGen repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={diffusers_load_config}') transformer = diffusers.OmniGenTransformer2DModel.from_pretrained( repo_id, subfolder="transformer", @@ -45,7 +46,7 @@ def load_omnigen2(checkpoint_info, diffusers_load_config=None): # pylint: disabl diffusers.pipelines.auto_pipeline.AUTO_INPAINT_PIPELINES_MAPPING["omnigen2"] = diffusers.OmniGen2Pipeline load_config, quant_config = model_quant.get_dit_args(diffusers_load_config, module='Model') - shared.log.debug(f'Load model: type=OmniGen2 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={diffusers_load_config}') + logger.log.debug(f'Load model: type=OmniGen2 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={diffusers_load_config}') transformer = OmniGen2Transformer2DModel.from_pretrained( repo_id, subfolder="transformer", diff --git a/pipelines/model_ovis.py b/pipelines/model_ovis.py index 9dfa0f599..abd89051e 100644 --- a/pipelines/model_ovis.py +++ b/pipelines/model_ovis.py @@ -1,6 +1,7 @@ import transformers import diffusers from modules import shared, devices, sd_models, model_quant, sd_hijack_te +from modules import logger from pipelines import generic @@ -11,7 +12,7 @@ def load_ovis(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False) - shared.log.debug(f'Load model: type=OvisImage repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={diffusers_load_config}') + logger.log.debug(f'Load model: type=OvisImage repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={diffusers_load_config}') transformer = generic.load_transformer(repo_id, cls_name=diffusers.OvisImageTransformer2DModel, load_config=diffusers_load_config) text_encoder = generic.load_text_encoder(repo_id, cls_name=transformers.Qwen3Model, load_config=diffusers_load_config) diff --git a/pipelines/model_pixart.py b/pipelines/model_pixart.py index 206580c0c..ca4821ac3 100644 --- a/pipelines/model_pixart.py +++ b/pipelines/model_pixart.py @@ -2,6 +2,7 @@ import transformers import diffusers from huggingface_hub import file_exists from modules import shared, devices, sd_models, model_quant, sd_hijack_te +from modules import logger from pipelines import generic @@ -21,7 +22,7 @@ def load_pixart(checkpoint_info, diffusers_load_config=None): repo_id_pipe = "PixArt-alpha/PixArt-Sigma-XL-2-1024-MS" load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False) - shared.log.debug(f'Load model: type=PixArtSigma repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=PixArtSigma repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') transformer = generic.load_transformer(repo_id, cls_name=diffusers.PixArtTransformer2DModel, load_config=diffusers_load_config) text_encoder = generic.load_text_encoder(repo_id_tenc, cls_name=transformers.T5EncoderModel, load_config=diffusers_load_config) diff --git a/pipelines/model_prx.py b/pipelines/model_prx.py index 4bcc251cb..44cd36b55 100644 --- a/pipelines/model_prx.py +++ b/pipelines/model_prx.py @@ -1,5 +1,6 @@ import diffusers from modules import shared, devices, sd_models, model_quant, sd_hijack_te +from modules import logger from pipelines import generic @@ -10,7 +11,7 @@ def load_prx(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False) - shared.log.debug(f'Load model: type=PRX repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=PRX repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') from transformers.models.t5gemma.modeling_t5gemma import T5GemmaEncoder transformer = generic.load_transformer(repo_id, cls_name=diffusers.PRXTransformer2DModel, load_config=diffusers_load_config) diff --git a/pipelines/model_qwen.py b/pipelines/model_qwen.py index 546e755cc..7f83240ae 100644 --- a/pipelines/model_qwen.py +++ b/pipelines/model_qwen.py @@ -1,6 +1,7 @@ import transformers import diffusers from modules import shared, devices, sd_models, model_quant, sd_hijack_te, sd_hijack_vae +from modules import logger def load_qwen(checkpoint_info, diffusers_load_config=None): @@ -13,7 +14,7 @@ def load_qwen(checkpoint_info, diffusers_load_config=None): transformer = None load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, module='Model') - shared.log.debug(f'Load model: type=Qwen model="{checkpoint_info.name}" repo="{repo_id}" offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=Qwen model="{checkpoint_info.name}" repo="{repo_id}" offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') if '2509' in repo_id or '2511' in repo_id: cls_name = diffusers.QwenImageEditPlusPipeline diff --git a/pipelines/model_sana.py b/pipelines/model_sana.py index 8b04fcfb0..19e3f093a 100644 --- a/pipelines/model_sana.py +++ b/pipelines/model_sana.py @@ -2,6 +2,7 @@ import torch import diffusers import transformers from modules import shared, sd_models, sd_hijack_te, devices, model_quant +from modules import logger def load_quants(kwargs, repo_id, cache_dir): @@ -10,7 +11,7 @@ def load_quants(kwargs, repo_id, cache_dir): import nunchaku nunchaku_precision = nunchaku.utils.get_precision() nunchaku_repo = "nunchaku-ai/nunchaku-sana/svdq-int4_r32-sana1.6b.safetensors" - shared.log.debug(f'Load module: quant=Nunchaku module=transformer repo="{nunchaku_repo}" precision={nunchaku_precision} attention={shared.opts.nunchaku_attention}') + logger.log.debug(f'Load module: quant=Nunchaku module=transformer repo="{nunchaku_repo}" precision={nunchaku_precision} attention={shared.opts.nunchaku_attention}') kwargs['transformer'] = nunchaku.NunchakuSanaTransformer2DModel.from_pretrained(nunchaku_repo, torch_dtype=devices.dtype, cache_dir=cache_dir) elif model_quant.check_quant('Model'): load_args, quant_args = model_quant.get_dit_args(kwargs_copy, module='Model') @@ -47,7 +48,7 @@ def load_sana(checkpoint_info, kwargs=None): kwargs['variant'] = 'fp16' kwargs = load_quants(kwargs, repo_id, cache_dir=shared.opts.diffusers_dir) - shared.log.debug(f'Load model: type=Sana repo="{repo_id}" args={list(kwargs)}') + logger.log.debug(f'Load model: type=Sana repo="{repo_id}" args={list(kwargs)}') if devices.dtype == torch.bfloat16 or devices.dtype == torch.float32: kwargs['torch_dtype'] = devices.dtype @@ -76,7 +77,7 @@ def load_sana(checkpoint_info, kwargs=None): pipe.text_encoder = pipe.text_encoder.to(dtype=torch.float32) # gemma2 does not support fp16 pipe.vae = pipe.vae.to(dtype=torch.float32) # dc-ae often overflows in fp16 except Exception as e: - shared.log.error(f'Load model: type=Sana {e}') + logger.log.error(f'Load model: type=Sana {e}') sd_hijack_te.init_hijack(pipe) diff --git a/pipelines/model_sd3.py b/pipelines/model_sd3.py index 7b977d154..e6e87e0b6 100644 --- a/pipelines/model_sd3.py +++ b/pipelines/model_sd3.py @@ -1,6 +1,7 @@ import diffusers import transformers from modules import shared, devices, sd_models, model_quant, sd_hijack_te +from modules import logger from pipelines import generic @@ -11,7 +12,7 @@ def load_sd3(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False) - shared.log.debug(f'Load model: type=SD3 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') + logger.log.debug(f'Load model: type=SD3 repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args}') transformer = generic.load_transformer(repo_id, cls_name=diffusers.SD3Transformer2DModel, load_config=diffusers_load_config) # text_encoder = generic.load_text_encoder(repo_id, cls_name=transformers.CLIPTextModelWithProjection, load_config=diffusers_load_config, subfolder="text_encoder") diff --git a/pipelines/model_stablecascade.py b/pipelines/model_stablecascade.py index 7f1df501b..dd2d97020 100644 --- a/pipelines/model_stablecascade.py +++ b/pipelines/model_stablecascade.py @@ -2,6 +2,7 @@ import os import torch import diffusers from modules import shared, devices, sd_models +from modules import logger def get_timestep_ratio_conditioning(t, alphas_cumprod): @@ -43,7 +44,7 @@ def load_text_encoder(path): vocab_size=49408 ) - shared.log.info(f'Load Text Encoder: name="{os.path.basename(os.path.splitext(path)[0])}" file="{path}"') + logger.log.info(f'Load Text Encoder: name="{os.path.basename(os.path.splitext(path)[0])}" file="{path}"') with init_empty_weights(): text_encoder = CLIPTextModelWithProjection(config) @@ -57,7 +58,7 @@ def load_text_encoder(path): except Exception as e: text_encoder = None - shared.log.error(f'Failed to load Text Encoder model: {e}') + logger.log.error(f'Failed to load Text Encoder model: {e}') return None @@ -73,7 +74,7 @@ def load_prior(path, config_file="default"): else: config_file = "configs/stable-cascade/prior/config.json" - shared.log.info(f'Load UNet: name="{os.path.basename(os.path.splitext(path)[0])}" file="{path}" config="{config_file}"') + logger.log.info(f'Load UNet: name="{os.path.basename(os.path.splitext(path)[0])}" file="{path}" config="{config_file}"') prior_unet = StableCascadeUNet.from_single_file(path, config=config_file, torch_dtype=devices.dtype_unet, cache_dir=shared.opts.diffusers_dir) if os.path.isfile(os.path.splitext(path)[0] + "_text_encoder.safetensors"): # OneTrainer @@ -108,7 +109,7 @@ def load_cascade_combined(checkpoint_info, diffusers_load_config=None): decoder = StableCascadeDecoderPipeline.from_pretrained("stabilityai/stable-cascade", cache_dir=shared.opts.diffusers_dir, decoder=decoder_unet, text_encoder=None, **diffusers_load_config) else: decoder = StableCascadeDecoderPipeline.from_pretrained(checkpoint_info.path, cache_dir=shared.opts.diffusers_dir, text_encoder=None, **diffusers_load_config) - # shared.log.debug(f'StableCascade {decoder_folder}: scale={decoder.latent_dim_scale}') + # logger.log.debug(f'StableCascade {decoder_folder}: scale={decoder.latent_dim_scale}') prior_text_encoder = None if shared.opts.sd_unet != "Default": prior_unet, prior_text_encoder = load_prior(unet_dict[shared.opts.sd_unet]) @@ -118,7 +119,7 @@ def load_cascade_combined(checkpoint_info, diffusers_load_config=None): prior = StableCascadePriorPipeline.from_pretrained("stabilityai/stable-cascade-prior", cache_dir=shared.opts.diffusers_dir, prior=prior_unet, text_encoder=prior_text_encoder, image_encoder=None, feature_extractor=None, **diffusers_load_config) else: prior = StableCascadePriorPipeline.from_pretrained("stabilityai/stable-cascade-prior", cache_dir=shared.opts.diffusers_dir, prior=prior_unet, image_encoder=None, feature_extractor=None, **diffusers_load_config) - # shared.log.debug(f'StableCascade {prior_folder}: scale={prior.resolution_multiple}') + # logger.log.debug(f'StableCascade {prior_folder}: scale={prior.resolution_multiple}') sd_model = StableCascadeCombinedPipeline( tokenizer=decoder.tokenizer, text_encoder=None, @@ -159,7 +160,7 @@ def load_cascade_combined(checkpoint_info, diffusers_load_config=None): ) devices.torch_gc(force=True, reason='load') - shared.log.debug(f'StableCascade combined: {sd_model.__class__.__name__}') + logger.log.debug(f'StableCascade combined: {sd_model.__class__.__name__}') return sd_model diff --git a/pipelines/model_wanai.py b/pipelines/model_wanai.py index 57a51f378..f0cd5db44 100644 --- a/pipelines/model_wanai.py +++ b/pipelines/model_wanai.py @@ -2,6 +2,7 @@ import os import transformers import diffusers from modules import shared, devices, sd_models, model_quant, sd_hijack_te, sd_hijack_vae +from modules import logger def load_transformer(repo_id, diffusers_load_config=None, subfolder='transformer'): @@ -18,15 +19,15 @@ def load_transformer(repo_id, diffusers_load_config=None, subfolder='transformer if shared.opts.sd_unet is not None and shared.opts.sd_unet != 'Default': from modules import sd_unet if shared.opts.sd_unet not in list(sd_unet.unet_dict): - shared.log.error(f'Load module: type=Transformer not found: {shared.opts.sd_unet}') + logger.log.error(f'Load module: type=Transformer not found: {shared.opts.sd_unet}') return None fn = sd_unet.unet_dict[shared.opts.sd_unet] if os.path.exists(sd_unet.unet_dict[shared.opts.sd_unet]) else None if fn is not None and 'gguf' in fn.lower(): - shared.log.error('Load model: type=WanAI format="gguf" unsupported') + logger.log.error('Load model: type=WanAI format="gguf" unsupported') transformer = None elif fn is not None and 'safetensors' in fn.lower(): - shared.log.debug(f'Load model: type=WanAI {subfolder}="{fn}" quant="{model_quant.get_quant(repo_id)}" args={load_args}') + logger.log.debug(f'Load model: type=WanAI {subfolder}="{fn}" quant="{model_quant.get_quant(repo_id)}" args={load_args}') transformer = transformer_cls.from_single_file( fn, cache_dir=shared.opts.hfcache_dir, @@ -34,7 +35,7 @@ def load_transformer(repo_id, diffusers_load_config=None, subfolder='transformer **quant_args, ) else: - shared.log.debug(f'Load model: type=WanAI {subfolder}="{repo_id}" quant="{model_quant.get_quant_type(quant_args)}" args={load_args}') + logger.log.debug(f'Load model: type=WanAI {subfolder}="{repo_id}" quant="{model_quant.get_quant_type(quant_args)}" args={load_args}') transformer = transformer_cls.from_pretrained( repo_id, subfolder=subfolder, @@ -52,7 +53,7 @@ def load_text_encoder(repo_id, diffusers_load_config=None): diffusers_load_config = {} load_args, quant_args = model_quant.get_dit_args(diffusers_load_config, module='TE', device_map=True) repo_id = 'Wan-AI/Wan2.1-T2V-1.3B-Diffusers' if 'Wan2.' in repo_id else repo_id # always use shared umt5 - shared.log.debug(f'Load model: type=WanAI te="{repo_id}" quant="{model_quant.get_quant_type(quant_args)}" args={load_args}') + logger.log.debug(f'Load model: type=WanAI te="{repo_id}" quant="{model_quant.get_quant_type(quant_args)}" args={load_args}') text_encoder = transformers.UMT5EncoderModel.from_pretrained( repo_id, subfolder="text_encoder", @@ -86,7 +87,7 @@ def load_wan(checkpoint_info, diffusers_load_config=None): transformer_2 = load_transformer(repo_id, diffusers_load_config, 'transformer_2') boundary_ratio = shared.opts.model_wan_boundary else: - shared.log.error(f'Load model: type=WanAI stage="{shared.opts.model_wan_stage}" unsupported') + logger.log.error(f'Load model: type=WanAI stage="{shared.opts.model_wan_stage}" unsupported') return None else: transformer = load_transformer(repo_id, diffusers_load_config, 'transformer') @@ -109,7 +110,7 @@ def load_wan(checkpoint_info, diffusers_load_config=None): pipe_cls = diffusers.WanPipeline diffusers.pipelines.auto_pipeline.AUTO_TEXT2IMAGE_PIPELINES_MAPPING["wanai"] = diffusers.WanPipeline diffusers.pipelines.auto_pipeline.AUTO_IMAGE2IMAGE_PIPELINES_MAPPING["wanai"] = WanImagePipeline - shared.log.debug(f'Load model: type=WanAI model="{checkpoint_info.name}" repo="{repo_id}" cls={pipe_cls.__name__} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args} stage="{shared.opts.model_wan_stage}" boundary={boundary_ratio}') + logger.log.debug(f'Load model: type=WanAI model="{checkpoint_info.name}" repo="{repo_id}" cls={pipe_cls.__name__} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={load_args} stage="{shared.opts.model_wan_stage}" boundary={boundary_ratio}') pipe = pipe_cls.from_pretrained( repo_id, transformer=transformer, diff --git a/pipelines/model_xomni.py b/pipelines/model_xomni.py index 5b3a96853..07350bed6 100644 --- a/pipelines/model_xomni.py +++ b/pipelines/model_xomni.py @@ -2,6 +2,7 @@ import torch import transformers import diffusers from modules import shared, devices, sd_models, model_quant +from modules import logger class XOmniPipeline(diffusers.DiffusionPipeline): @@ -25,12 +26,12 @@ class XOmniPipeline(diffusers.DiffusionPipeline): ): from pipelines.xomni import modeling_xomni load_args, quant_args = model_quant.get_dit_args(load_config, module='Model', device_map=True) - shared.log.debug(f'Load model: cls=XOmniPipeline module=tokenizer repo_id="{repo_id}"') + logger.log.debug(f'Load model: cls=XOmniPipeline module=tokenizer repo_id="{repo_id}"') self.tokenizer = transformers.AutoTokenizer.from_pretrained( repo_id, use_fast=True, ) - shared.log.debug(f'Load model: cls=XOmniPipeline module=transformer repo_id="{repo_id}" args={load_args}') + logger.log.debug(f'Load model: cls=XOmniPipeline module=transformer repo_id="{repo_id}" args={load_args}') # self.model = transformers.AutoModelForCausalLM.from_pretrained( self.model = modeling_xomni.XOmniForCausalLM.from_pretrained( repo_id, @@ -40,7 +41,7 @@ class XOmniPipeline(diffusers.DiffusionPipeline): **quant_args, ) flux_repo_id = "black-forest-labs/FLUX.1-dev" - shared.log.debug(f'Load model: cls=XOmniPipeline module=vision repo_id="{flux_repo_id}"') + logger.log.debug(f'Load model: cls=XOmniPipeline module=vision repo_id="{flux_repo_id}"') self.model.init_vision( flux_repo_id, **quant_args, diff --git a/pipelines/model_z_image.py b/pipelines/model_z_image.py index 3aa269b48..fd575cbfd 100644 --- a/pipelines/model_z_image.py +++ b/pipelines/model_z_image.py @@ -1,6 +1,7 @@ import transformers import diffusers from modules import shared, devices, sd_models, model_quant, sd_hijack_te +from modules import logger from pipelines import generic @@ -9,7 +10,7 @@ def load_nunchaku(): nunchaku_precision = nunchaku.utils.get_precision() nunchaku_rank = 128 nunchaku_repo = f"nunchaku-ai/nunchaku-z-image-turbo/svdq-{nunchaku_precision}_r{nunchaku_rank}-z-image-turbo.safetensors" - shared.log.debug(f'Load module: quant=Nunchaku module=transformer repo="{nunchaku_repo}" attention={shared.opts.nunchaku_attention}') + logger.log.debug(f'Load module: quant=Nunchaku module=transformer repo="{nunchaku_repo}" attention={shared.opts.nunchaku_attention}') transformer = nunchaku.NunchakuZImageTransformer2DModel.from_pretrained( nunchaku_repo, torch_dtype=devices.dtype, @@ -25,7 +26,7 @@ def load_z_image(checkpoint_info, diffusers_load_config=None): sd_models.hf_auth_check(checkpoint_info) load_args, _quant_args = model_quant.get_dit_args(diffusers_load_config, allow_quant=False) - shared.log.debug(f'Load model: type=ZImage repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={diffusers_load_config}') + logger.log.debug(f'Load model: type=ZImage repo="{repo_id}" config={diffusers_load_config} offload={shared.opts.diffusers_offload_mode} dtype={devices.dtype} args={diffusers_load_config}') if model_quant.check_nunchaku('Model'): # only available model transformer = load_nunchaku() diff --git a/pipelines/qwen/qwen_nunchaku.py b/pipelines/qwen/qwen_nunchaku.py index 4fd964df3..9775041df 100644 --- a/pipelines/qwen/qwen_nunchaku.py +++ b/pipelines/qwen/qwen_nunchaku.py @@ -1,3 +1,4 @@ +from modules import logger from modules import shared, devices @@ -10,7 +11,7 @@ def load_qwen_nunchaku(repo_id, subfolder=None): try: from nunchaku.models.transformers.transformer_qwenimage import NunchakuQwenImageTransformer2DModel except Exception: - shared.log.error(f'Load module: quant=Nunchaku module=transformer repo="{repo_id}" low nunchaku version') + logger.log.error(f'Load module: quant=Nunchaku module=transformer repo="{repo_id}" low nunchaku version') return None if 'pruning' in repo_id.lower() or 'distill' in repo_id.lower(): return None @@ -31,9 +32,9 @@ def load_qwen_nunchaku(repo_id, subfolder=None): else: nunchaku_repo = f"nunchaku-ai/nunchaku-qwen-image-edit/svdq-{nunchaku_precision}_r128-qwen-image-edit-lightningv1.0-8steps.safetensors" else: - shared.log.error(f'Load module: quant=Nunchaku module=transformer repo="{repo_id}" unsupported') + logger.log.error(f'Load module: quant=Nunchaku module=transformer repo="{repo_id}" unsupported') if nunchaku_repo is not None: - shared.log.debug(f'Load module: quant=Nunchaku module=transformer repo="{nunchaku_repo}" precision={nunchaku_precision} offload={shared.opts.nunchaku_offload} attention={shared.opts.nunchaku_attention}') + logger.log.debug(f'Load module: quant=Nunchaku module=transformer repo="{nunchaku_repo}" precision={nunchaku_precision} offload={shared.opts.nunchaku_offload} attention={shared.opts.nunchaku_attention}') transformer = NunchakuQwenImageTransformer2DModel.from_pretrained( nunchaku_repo, offload=shared.opts.nunchaku_offload, diff --git a/refactor_logger.py b/refactor_logger.py new file mode 100644 index 000000000..ed0c48300 --- /dev/null +++ b/refactor_logger.py @@ -0,0 +1,90 @@ +import os +import re + +def refactor_file(filepath): + with open(filepath, 'r', encoding='utf-8') as f: + content = f.read() + + original_content = content + modified = False + + # Check for usages + has_shared_log = 'logger.log' in content + has_installer_log = 'logger.log' in content + has_errors_log = 'logger.log' in content + has_shared_console = 'logger.console' in content + has_installer_console = 'logger.console' in content + + if not (has_shared_log or has_installer_log or has_errors_log or has_shared_console or has_installer_console): + return + + # Add import if needed + # Check if 'from modules import logger' or 'import modules.logger' exists + if not re.search(r'from modules import .*logger', content) and not re.search(r'import modules.logger', content): + # Insert import + # Try to find standard imports block + lines = content.split('\n') + insert_idx = 0 + for i, line in enumerate(lines): + if line.startswith('import ') or line.startswith('from '): + # find last import + pass + if line.startswith('class ') or line.startswith('def '): + insert_idx = i + break + + # refinement: find last from modules import ... + last_import_idx = 0 + for i, line in enumerate(lines): + if line.startswith('from modules import') or line.startswith('import modules'): + last_import_idx = i + + if last_import_idx > 0: + lines.insert(last_import_idx + 1, 'from modules import logger') + else: + # insert at top after __future__ or similar + for i, line in enumerate(lines): + if not line.startswith('#') and not line.strip() == '' and not line.startswith('from __future__'): + insert_idx = i + break + lines.insert(insert_idx, 'from modules import logger') + + content = '\n'.join(lines) + modified = True + + # Replacements + if has_shared_log: + content = content.replace('logger.log', 'logger.log') + modified = True + if has_installer_log: + content = content.replace('logger.log', 'logger.log') + modified = True + if has_errors_log: + content = content.replace('logger.log', 'logger.log') + modified = True + if has_shared_console: + content = content.replace('logger.console', 'logger.console') + modified = True + if has_installer_console: + content = content.replace('logger.console', 'logger.console') + modified = True + + # Specific fix for shared.py and installer.py self-references if any + # (though I already updated them manually mostly) + + if modified and content != original_content: + print(f"Modifying {filepath}") + with open(filepath, 'w', encoding='utf-8') as f: + f.write(content) + +# Walk directory +root_dir = '/home/vlado/dev/sdnext' +for root, dirs, files in os.walk(root_dir): + if 'venv' in dirs: + dirs.remove('venv') + if '.git' in dirs: + dirs.remove('.git') + + for file in files: + if file.endswith('.py'): + refactor_file(os.path.join(root, file)) diff --git a/scripts/animatediff.py b/scripts/animatediff.py index 933d54049..f2f041982 100644 --- a/scripts/animatediff.py +++ b/scripts/animatediff.py @@ -3,6 +3,7 @@ import gradio as gr import diffusers from safetensors.torch import load_file from modules import scripts_manager, processing, shared, devices, sd_models +from modules import logger # config @@ -49,18 +50,18 @@ def set_adapter(adapter_name: str = 'None'): motion_adapter = None loaded_adapter = None if orig_pipe is not None: - shared.log.debug(f'AnimateDiff restore pipeline: adapter="{loaded_adapter}"') + logger.log.debug(f'AnimateDiff restore pipeline: adapter="{loaded_adapter}"') shared.sd_model = orig_pipe orig_pipe = None return if shared.sd_model_type != 'sd' and shared.sd_model_type != 'sdxl' and not (shared.sd_model.__class__.__name__ == 'AnimateDiffPipeline' or shared.sd_model.__class__.__name__ == 'AnimateDiffSDXLPipeline'): - shared.log.warning(f'AnimateDiff: unsupported model type: {shared.sd_model.__class__.__name__}') + logger.log.warning(f'AnimateDiff: unsupported model type: {shared.sd_model.__class__.__name__}') return if motion_adapter is not None and loaded_adapter == adapter_name and (shared.sd_model.__class__.__name__ == 'AnimateDiffPipeline' or shared.sd_model.__class__.__name__ == 'AnimateDiffSDXLPipeline'): - shared.log.debug(f'AnimateDiff: adapter="{adapter_name}" cached') + logger.log.debug(f'AnimateDiff: adapter="{adapter_name}" cached') return if getattr(shared.sd_model, 'image_encoder', None) is not None: - shared.log.debug('AnimateDiff: unloading IP adapter') + logger.log.debug('AnimateDiff: unloading IP adapter') # shared.sd_model.image_encoder = None # shared.sd_model.unet.set_default_attn_processor() shared.sd_model.unet.config.encoder_hid_dim_type = None @@ -69,7 +70,7 @@ def set_adapter(adapter_name: str = 'None'): folder, filename = os.path.split(adapter_name) adapter_name = hf.hf_hub_download(repo_id=folder, filename=filename, cache_dir=shared.opts.diffusers_dir) try: - shared.log.info(f'AnimateDiff load: adapter="{adapter_name}"') + logger.log.info(f'AnimateDiff load: adapter="{adapter_name}"') motion_adapter = None if adapter_name.endswith('.safetensors'): motion_adapter = diffusers.MotionAdapter().to(shared.device, devices.dtype) @@ -84,7 +85,7 @@ def set_adapter(adapter_name: str = 'None'): new_pipe = None if 'Model' in shared.opts.sdnq_quantize_weights: - shared.log.debug(f'AnimateDiff: sdnq={shared.opts.sdnq_quantize_weights} reloading model weights') + logger.log.debug(f'AnimateDiff: sdnq={shared.opts.sdnq_quantize_weights} reloading model weights') prev_opts = shared.opts.sdnq_quantize_weights shared.opts.sdnq_quantize_weights = [] sd_models.reload_model_weights(force=True) @@ -118,7 +119,7 @@ def set_adapter(adapter_name: str = 'None'): if new_pipe is None: motion_adapter = None loaded_adapter = None - shared.log.error(f'AnimateDiff load error: adapter="{adapter_name}"') + logger.log.error(f'AnimateDiff load error: adapter="{adapter_name}"') return orig_pipe = shared.sd_model shared.sd_model = new_pipe @@ -126,11 +127,11 @@ def set_adapter(adapter_name: str = 'None'): sd_models.copy_diffuser_options(new_pipe, orig_pipe) sd_models.set_diffuser_options(shared.sd_model, vae=None, op='model') sd_models.move_model(shared.sd_model.unet, devices.device) # move pipeline to device - shared.log.debug(f'AnimateDiff: adapter="{loaded_adapter}"') + logger.log.debug(f'AnimateDiff: adapter="{loaded_adapter}"') except Exception as e: motion_adapter = None loaded_adapter = None - shared.log.error(f'AnimateDiff load error: adapter="{adapter_name}" {e}') + logger.log.error(f'AnimateDiff load error: adapter="{adapter_name}" {e}') from modules import errors errors.display('e', 'AnimateDiff') @@ -142,7 +143,7 @@ def set_scheduler(p, model, override: bool = False): shared.sd_model.scheduler = diffusers.LCMScheduler.from_config(shared.sd_model.scheduler.config) else: shared.sd_model.scheduler = diffusers.DDIMScheduler.from_config(shared.sd_model.scheduler.config) - shared.log.debug(f'AnimateDiff: scheduler={shared.sd_model.scheduler.__class__.__name__}') + logger.log.debug(f'AnimateDiff: scheduler={shared.sd_model.scheduler.__class__.__name__}') def set_prompt(p): @@ -158,14 +159,14 @@ def set_prompt(p): prompt[int(k.strip())] = v.strip() except Exception: prompt = p.prompt - shared.log.debug(f'AnimateDiff prompt: {prompt}') + logger.log.debug(f'AnimateDiff prompt: {prompt}') p.task_args['prompt'] = prompt p.task_args['negative_prompt'] = p.negative_prompt def set_lora(p, lora, strength): if lora is not None and lora != 'None': - shared.log.debug(f'AnimateDiff: lora="{lora}" strength={strength}') + logger.log.debug(f'AnimateDiff: lora="{lora}" strength={strength}') if lora.endswith('.safetensors'): fn = os.path.basename(lora) lora = lora.replace(f'/{fn}', '') @@ -178,7 +179,7 @@ def set_lora(p, lora, strength): def set_free_init(method, iters, order, spatial, temporal): if hasattr(shared.sd_model, 'enable_free_init') and method != 'none': - shared.log.debug(f'AnimateDiff free init: method={method} iters={iters} order={order} spatial={spatial} temporal={temporal}') + logger.log.debug(f'AnimateDiff free init: method={method} iters={iters} order={order} spatial={spatial} temporal={temporal}') shared.sd_model.enable_free_init( num_iters=iters, use_fast_sampling=False, @@ -193,7 +194,7 @@ def set_free_noise(frames): context_length = 16 context_stride = 4 if frames >= context_length and hasattr(shared.sd_model, 'enable_free_noise'): - shared.log.debug(f'AnimateDiff free noise: frames={frames} context={context_length} stride={context_stride}') + logger.log.debug(f'AnimateDiff free noise: frames={frames} context={context_length} stride={context_stride}') shared.sd_model.enable_free_noise(context_length=context_length, context_stride=context_stride) @@ -251,7 +252,7 @@ class Script(scripts_manager.Script): p.task_args['num_frames'] = frames p.task_args['num_inference_steps'] = p.steps p.task_args['output_type'] = 'np' - shared.log.debug(f'AnimateDiff args: {p.task_args}') + logger.log.debug(f'AnimateDiff args: {p.task_args}') set_prompt(p) orig_prompt_attention = shared.opts.prompt_attention shared.opts.data['prompt_attention'] = 'fixed' @@ -264,5 +265,5 @@ class Script(scripts_manager.Script): def after(self, p: processing.StableDiffusionProcessing, processed: processing.Processed, adapter_index, frames, lora_index, strength, latent_mode, video_type, duration, gif_loop, mp4_pad, mp4_interpolate, override_scheduler, fi_method, fi_iters, fi_order, fi_spatial, fi_temporal): # pylint: disable=arguments-differ, unused-argument from modules.images import save_video if video_type != 'None': - shared.log.debug(f'AnimateDiff video: type={video_type} duration={duration} loop={gif_loop} pad={mp4_pad} interpolate={mp4_interpolate}') + logger.log.debug(f'AnimateDiff video: type={video_type} duration={duration} loop={gif_loop} pad={mp4_pad} interpolate={mp4_interpolate}') save_video(p, filename=None, images=processed.images, video_type=video_type, duration=duration, loop=gif_loop, pad=mp4_pad, interpolate=mp4_interpolate) diff --git a/scripts/apg.py b/scripts/apg.py index c17531f11..87422d1ae 100644 --- a/scripts/apg.py +++ b/scripts/apg.py @@ -1,5 +1,6 @@ import gradio as gr from modules import scripts_manager, processing, shared, sd_models +from modules import logger registered = False @@ -53,7 +54,7 @@ class Script(scripts_manager.Script): def run(self, p: processing.StableDiffusionProcessing, eta = 0.0, momentum = 0.0, threshold = 0.0): # pylint: disable=arguments-differ supported_model_list = ['sd', 'sdxl', 'sc'] if shared.sd_model_type not in supported_model_list: - shared.log.warning(f'APG: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_model_list}') + logger.log.warning(f'APG: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_model_list}') return None from modules import apg apg.eta = getattr(p, 'apg_eta', eta) # use values set by xyz grid or via ui @@ -70,7 +71,7 @@ class Script(scripts_manager.Script): elif shared.sd_model_type == "sc": self.orig_pipe = shared.sd_model.prior_pipe shared.sd_model.prior_pipe = sd_models.switch_pipe(apg.StableCascadePriorPipelineAPG, shared.sd_model.prior_pipe) - shared.log.info(f'APG apply: guidance={p.cfg_scale} momentum={apg.momentum} eta={apg.eta} threshold={apg.threshold} class={shared.sd_model.__class__.__name__}') + logger.log.info(f'APG apply: guidance={p.cfg_scale} momentum={apg.momentum} eta={apg.eta} threshold={apg.threshold} class={shared.sd_model.__class__.__name__}') p.extra_generation_params["APG"] = f'ETA={apg.eta} Momentum={apg.momentum} Threshold={apg.threshold}' # processed = processing.process_images(p) return None diff --git a/scripts/automatic_color_inpaint.py b/scripts/automatic_color_inpaint.py index 9edfdd503..cf94b5af0 100644 --- a/scripts/automatic_color_inpaint.py +++ b/scripts/automatic_color_inpaint.py @@ -2,6 +2,7 @@ import gradio as gr from PIL import Image import numpy as np from modules import shared, scripts_manager, processing, masking +from modules import logger """ Automatic Color Inpaint Script for SD.NEXT - SD & SDXL Support @@ -89,7 +90,7 @@ class Script(scripts_manager.Script): # Run pipeline def run(self, p: processing.StableDiffusionProcessing, *args): # pylint: disable=arguments-differ if shared.sd_model_type not in supported_models: - shared.log.warning(f'MoD: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_models}') + logger.log.warning(f'MoD: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_models}') return None if not hasattr(p, 'init_images') or p.init_images is None or len(p.init_images) == 0: return None @@ -98,7 +99,7 @@ class Script(scripts_manager.Script): # Convert hex color to RGB tuple (0-255) color_to_mask_rgb = tuple(int(color_to_mask_hex[i:i+2], 16) for i in (1, 3, 5)) - shared.log.debug(f'ACI: rgb={color_to_mask_rgb} tolerance={mask_tolerance} dilate={mask_dilate} erode={mask_erode} blur={mask_blur} denoise={inpaint_denoising_strength}') + logger.log.debug(f'ACI: rgb={color_to_mask_rgb} tolerance={mask_tolerance} dilate={mask_dilate} erode={mask_erode} blur={mask_blur} denoise={inpaint_denoising_strength}') # Create Color Mask using vectorized operations init_image = p.init_images[0].convert("RGB") diff --git a/scripts/blipdiffusion.py b/scripts/blipdiffusion.py index 93f610f7b..8731f633c 100644 --- a/scripts/blipdiffusion.py +++ b/scripts/blipdiffusion.py @@ -1,5 +1,6 @@ import gradio as gr from modules import scripts_manager, processing, shared, sd_models +from modules import logger class Script(scripts_manager.Script): @@ -23,7 +24,7 @@ class Script(scripts_manager.Script): def run(self, p: processing.StableDiffusionProcessing, source_subject, target_subject, prompt_strength): # pylint: disable=arguments-differ, unused-argument c = shared.sd_model.__class__.__name__ if shared.sd_loaded else '' if c != 'BlipDiffusionPipeline': - shared.log.error(f'BLIP: model selected={c} required=BLIPDiffusion') + logger.log.error(f'BLIP: model selected={c} required=BLIPDiffusion') return None if hasattr(p, 'init_images') and len(p.init_images) > 0: p.task_args['reference_image'] = p.init_images[0] @@ -33,10 +34,10 @@ class Script(scripts_manager.Script): p.task_args['source_subject_category'] = [source_subject] p.task_args['target_subject_category'] = [target_subject] p.task_args['output_type'] = 'pil' - shared.log.debug(f'BLIP Diffusion: args={p.task_args}') + logger.log.debug(f'BLIP Diffusion: args={p.task_args}') shared.sd_model = sd_models.set_diffuser_pipe(shared.sd_model, sd_models.DiffusersTaskType.IMAGE_2_IMAGE) processed = processing.process_images(p) return processed else: - shared.log.error('BLIP: no init_images') + logger.log.error('BLIP: no init_images') return None diff --git a/scripts/consistory_ext.py b/scripts/consistory_ext.py index b91d74fa7..4e88c9e0f 100644 --- a/scripts/consistory_ext.py +++ b/scripts/consistory_ext.py @@ -13,6 +13,7 @@ import time import gradio as gr import diffusers from modules import scripts_manager, devices, errors, processing, shared, sd_models, sd_samplers +from modules import logger class Script(scripts_manager.Script): @@ -30,7 +31,7 @@ class Script(scripts_manager.Script): def reset(self): self.anchor_cache_first_stage = None self.anchor_cache_second_stage = None - shared.log.debug('ConsiStory reset anchors') + logger.log.debug('ConsiStory reset anchors') def ui(self, _is_img2img): # ui elements with gr.Row(): @@ -68,7 +69,7 @@ class Script(scripts_manager.Script): diffusers.models.embeddings.PositionNet = diffusers.models.embeddings.GLIGENTextBoundingboxProjection # patch as renamed in https://github.com/huggingface/diffusers/pull/6244/files import scripts.consistory as cs if shared.sd_model.__class__.__name__ != 'ConsistoryExtendAttnSDXLPipeline': - shared.log.debug('ConsiStory init') + logger.log.debug('ConsiStory init') t0 = time.time() state_dict = shared.sd_model.unet.state_dict() # save existing unet shared.sd_model = sd_models.switch_pipe(cs.ConsistoryExtendAttnSDXLPipeline, shared.sd_model) @@ -80,7 +81,7 @@ class Script(scripts_manager.Script): sd_models.move_model(shared.sd_model, devices.device) sd_models.move_model(shared.sd_model.unet, devices.device) t1 = time.time() - shared.log.debug(f'ConsiStory load: model={shared.sd_model.__class__.__name__} time={t1-t0:.2f}') + logger.log.debug(f'ConsiStory load: model={shared.sd_model.__class__.__name__} time={t1-t0:.2f}') devices.torch_gc(force=True) def set_args(self, p: processing.StableDiffusionProcessing, *args): @@ -95,7 +96,7 @@ class Script(scripts_manager.Script): freeu_preset = [float(f.strip()) for f in freeu_preset.split(',')] except Exception: freeu_preset = [] - shared.log.warning(f'ConsiStory: freeu="{freeu_preset}" invalid') + logger.log.warning(f'ConsiStory: freeu="{freeu_preset}" invalid') if len(freeu) == 4: shared.sd_model.enable_freeu(s1=freeu[0], s2=freeu[0], b1=freeu[0], b2=freeu[0]) steps = 50 if steps else p.steps @@ -106,14 +107,14 @@ class Script(scripts_manager.Script): alpha = (int(alpha[0]), int(alpha[1]), float(alpha[2])) except Exception: alpha=(10, 20, 0.8) - shared.log.warning(f'ConsiStory: alpha="{alpha}" invalid') + logger.log.warning(f'ConsiStory: alpha="{alpha}" invalid') else: alpha=(10, 20, 0.8) seed = p.seed concepts = [c.strip() for c in concepts.split(',') if c.strip() != ''] for c in concepts: if c not in subject: - shared.log.warning(f'ConsiStory: concept="{c}" not in subject') + logger.log.warning(f'ConsiStory: concept="{c}" not in subject') subject = f'{subject} {c}' settings = [p.strip() for p in prompts.split('\n') if p.strip() != ''] anchors = [f'{subject} {p}' for p in settings] @@ -124,16 +125,16 @@ class Script(scripts_manager.Script): for i, prompt in enumerate(prompts): if subject not in prompt: prompts[i] = f'{subject} {prompt}' - shared.log.debug(f'ConsiStory args: sampler={shared.sd_model.scheduler.__class__.__name__} steps={steps} sdsa={sdsa} queries={queries} same={same} dropout={dropout} freeu={freeu_preset if freeu else None} alpha={alpha if injection else None}') + logger.log.debug(f'ConsiStory args: sampler={shared.sd_model.scheduler.__class__.__name__} steps={steps} sdsa={sdsa} queries={queries} same={same} dropout={dropout} freeu={freeu_preset if freeu else None} alpha={alpha if injection else None}') return concepts, anchors, prompts, alpha, steps, seed def create_anchors(self, anchors, concepts, seed, steps, dropout, same, queries, sdsa, injection, alpha): import scripts.consistory as cs t0 = time.time() if len(anchors) == 0: - shared.log.warning('ConsiStory: no anchors') + logger.log.warning('ConsiStory: no anchors') return [] - shared.log.debug(f'ConsiStory anchors: concepts={concepts} anchors={anchors}') + logger.log.debug(f'ConsiStory anchors: concepts={concepts} anchors={anchors}') with devices.inference_context(): try: images, self.anchor_cache_first_stage, self.anchor_cache_second_stage = cs.run_anchor_generation( @@ -150,19 +151,19 @@ class Script(scripts_manager.Script): perform_injection=injection, ) except Exception as e: - shared.log.error(f'ConsiStory: {e}') + logger.log.error(f'ConsiStory: {e}') errors.display(e, 'ConsiStory') images = [] devices.torch_gc() t1 = time.time() - shared.log.debug(f'ConsiStory anchors: images={len(images)} time={t1-t0:.2f}') + logger.log.debug(f'ConsiStory anchors: images={len(images)} time={t1-t0:.2f}') return images def create_extra(self, prompt, concepts, seed, steps, dropout, same, queries, sdsa, injection, alpha): import scripts.consistory as cs t0 = time.time() images = [] - shared.log.debug(f'ConsiStory extra: concepts={concepts} prompt="{prompt}"') + logger.log.debug(f'ConsiStory extra: concepts={concepts} prompt="{prompt}"') with devices.inference_context(): try: images = cs.run_extra_generation( @@ -181,18 +182,18 @@ class Script(scripts_manager.Script): perform_injection=injection, ) except Exception as e: - shared.log.error(f'ConsiStory: {e}') + logger.log.error(f'ConsiStory: {e}') errors.display(e, 'ConsiStory') images = [] devices.torch_gc() t1 = time.time() - shared.log.debug(f'ConsiStory extra: images={len(images)} time={t1-t0:.2f}') + logger.log.debug(f'ConsiStory extra: images={len(images)} time={t1-t0:.2f}') return images def run(self, p: processing.StableDiffusionProcessing, *args): # pylint: disable=arguments-differ supported_model_list = ['sdxl'] if shared.sd_model_type not in supported_model_list and shared.sd_model.__class__.__name__ != 'ConsistoryExtendAttnSDXLPipeline': - shared.log.warning(f'ConsiStory: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_model_list}') + logger.log.warning(f'ConsiStory: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_model_list}') return None subject, concepts, prompts, dropout, sampler, steps, same, queries, sdsa, freeu, _freeu_preset, alpha, injection = args # pylint: disable=unused-variable diff --git a/scripts/ctrlx_ext.py b/scripts/ctrlx_ext.py index ed611f4ba..51db2518c 100644 --- a/scripts/ctrlx_ext.py +++ b/scripts/ctrlx_ext.py @@ -3,6 +3,7 @@ import gradio as gr from diffusers import StableDiffusionXLPipeline from modules import shared, scripts_manager, processing, processing_helpers, sd_models, devices +from modules import logger class Script(scripts_manager.Script): @@ -40,7 +41,7 @@ class Script(scripts_manager.Script): def run(self, p: processing.StableDiffusionProcessing, struct_prompt, struct_strength, struct_guidance, struct_image, appear_prompt, appear_strength, appear_guidance, appear_image): # pylint: disable=arguments-differ c = shared.sd_model.__class__.__name__ if shared.sd_loaded else '' if shared.sd_model_type != 'sdxl': - shared.log.warning(f'Ctrl-X: pipeline={c} required=StableDiffusionXLPipeline') + logger.log.warning(f'Ctrl-X: pipeline={c} required=StableDiffusionXLPipeline') return None import yaml @@ -55,7 +56,7 @@ class Script(scripts_manager.Script): # calculate ctrx+x schedule if p.sampler_name not in ['DDIM', 'Euler', 'Euler a', 'DPM++ 1S', 'DDPM', 'Euler SGM', 'LCM', 'TCD']: - shared.log.warning(f'Ctrl-X: sampler={p.sampler_name} override="Euler a" supported=[Euler, Euler a, Euler SGM, DDIM, DDPM, , LCM, TCD]') + logger.log.warning(f'Ctrl-X: sampler={p.sampler_name} override="Euler a" supported=[Euler, Euler a, Euler SGM, DDIM, DDPM, , LCM, TCD]') p.sampler_name = 'Euler a' processing_helpers.update_sampler(p, shared.sd_model) shared.sd_model.scheduler.set_timesteps(p.steps, device=devices.device) @@ -85,8 +86,8 @@ class Script(scripts_manager.Script): p.task_args['self_recurrence_schedule'] = get_self_recurrence_schedule(config['self_recurrence_schedule'], p.steps) is_struct = p.task_args.get('structure_image') is not None is_appear = p.task_args.get('appearance_image') is not None - shared.log.info(f'Ctrl-X: structure={struct_strength if is_struct else None} appearance={appear_strength if is_appear else None}') - shared.log.debug(f'Ctrl-X: config={control_config} args={p.task_args}') + logger.log.info(f'Ctrl-X: structure={struct_strength if is_struct else None} appearance={appear_strength if is_appear else None}') + logger.log.debug(f'Ctrl-X: config={control_config} args={p.task_args}') # process processed: processing.Processed = processing.process_images(p) diff --git a/scripts/daam_ext.py b/scripts/daam_ext.py index 5ae16a855..c3b32e3fb 100644 --- a/scripts/daam_ext.py +++ b/scripts/daam_ext.py @@ -3,6 +3,7 @@ import gradio as gr from installer import install from modules import shared, scripts_manager, processing +from modules import logger COLORMAP = ['autumn', 'bone', 'jet', 'winter', 'rainbow', 'ocean', 'summer', 'spring', 'cool', 'hsv', 'pink', 'hot', 'parula', 'magma', 'inferno', 'plasma', 'viridis', 'cividis', 'twilight', 'shifted', 'turbo', 'deepgreen'] @@ -26,7 +27,7 @@ class Script(scripts_manager.Script): def run(self, p: processing.StableDiffusionProcessing, append_images, colormap): # pylint: disable=arguments-differ c = shared.sd_model.__class__.__name__ if shared.sd_loaded else '' if shared.sd_model_type != 'sdxl': - shared.log.warning(f'DAAM: pipeline={c} required=StableDiffusionXLPipeline') + logger.log.warning(f'DAAM: pipeline={c} required=StableDiffusionXLPipeline') return None install('thinc==8.3.4') @@ -40,7 +41,7 @@ class Script(scripts_manager.Script): with daam.trace(shared.sd_model) as tc: processed: processing.Processed = processing.process_images(p) global_heat_map = tc.compute_global_heat_map() - shared.log.info(f'DAAM: prompt="{global_heat_map.prompt}" heatmaps={global_heat_map.heat_maps.shape}') + logger.log.info(f'DAAM: prompt="{global_heat_map.prompt}" heatmaps={global_heat_map.heat_maps.shape}') # word_heat_map = global_heat_map.compute_word_heat_map('woman') parsed_heat_maps = global_heat_map.parsed_heat_maps() @@ -48,7 +49,7 @@ class Script(scripts_manager.Script): image = processed.images[0] for parsed_heat_map in parsed_heat_maps: if len(parsed_heat_map.token.text) > 1: - shared.log.debug(f'DAAM: token="{parsed_heat_map.token.text}"') + logger.log.debug(f'DAAM: token="{parsed_heat_map.token.text}"') overlay = parsed_heat_map.word_heat_map.plot_overlay(image=image, color_normalize=True, cmap=colormap) processed.images.append(overlay) diff --git a/scripts/demofusion.py b/scripts/demofusion.py index f9d8932ab..8251708e5 100644 --- a/scripts/demofusion.py +++ b/scripts/demofusion.py @@ -15,6 +15,7 @@ from diffusers.utils import is_accelerate_available, is_accelerate_version from diffusers.utils.torch_utils import randn_tensor from diffusers.pipelines.pipeline_utils import DiffusionPipeline, ImagePipelineOutput from modules import scripts_manager, processing, shared, sd_models, devices +from modules import logger ### Class definition @@ -164,7 +165,7 @@ class DemoFusionSDXLPipeline(DiffusionPipeline, FromSingleFileMixin, LoraLoaderM text_input_ids, untruncated_ids ): removed_text = tokenizer.batch_decode(untruncated_ids[:, tokenizer.model_max_length - 1 : -1]) - shared.log.warning(f"The following part of your input was truncated because CLIP can only handle sequences up to {tokenizer.model_max_length} tokens: {removed_text}") + logger.log.warning(f"The following part of your input was truncated because CLIP can only handle sequences up to {tokenizer.model_max_length} tokens: {removed_text}") prompt_embeds = text_encoder( text_input_ids.to(device), @@ -346,11 +347,11 @@ class DemoFusionSDXLPipeline(DiffusionPipeline, FromSingleFileMixin, LoraLoaderM # DemoFusion specific checks if max(height, width) % 1024 != 0: - shared.log.error('DemoFusion: resolution={width}x{height} long side must be divisible by 1024') + logger.log.error('DemoFusion: resolution={width}x{height} long side must be divisible by 1024') return None if num_images_per_prompt != 1: - shared.log.warning('DemoFusion: number of images per prompt is not support and will be ignored') + logger.log.warning('DemoFusion: number of images per prompt is not support and will be ignored') num_images_per_prompt = 1 # Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion.StableDiffusionPipeline.prepare_latents @@ -830,7 +831,7 @@ class DemoFusionSDXLPipeline(DiffusionPipeline, FromSingleFileMixin, LoraLoaderM self.text_encoder.cpu() self.text_encoder_2.cpu() - shared.log.debug('DemoFusion: phase=1 denoising') + logger.log.debug('DemoFusion: phase=1 denoising') with self.progress_bar(total=num_inference_steps) as progress_bar: for i, t in enumerate(timesteps): @@ -896,7 +897,7 @@ class DemoFusionSDXLPipeline(DiffusionPipeline, FromSingleFileMixin, LoraLoaderM if needs_upcasting: self.upcast_vae() latents = latents.to(next(iter(self.vae.post_quant_conv.parameters())).dtype) - shared.log.debug('DemoFusion: phase=1 decoding') + logger.log.debug('DemoFusion: phase=1 decoding') if self.lowvram and multi_decoder: current_width_height = self.unet.config.sample_size * self.vae_scale_factor image = self.tiled_decode(latents, current_width_height, current_width_height) @@ -916,7 +917,7 @@ class DemoFusionSDXLPipeline(DiffusionPipeline, FromSingleFileMixin, LoraLoaderM latents = latents.to(device) self.unet.to(device) torch.cuda.empty_cache() - shared.log.debug(f'DemoFusion: phase={current_scale_num} denoising') + logger.log.debug(f'DemoFusion: phase={current_scale_num} denoising') current_height = self.unet.config.sample_size * self.vae_scale_factor * current_scale_num current_width = self.unet.config.sample_size * self.vae_scale_factor * current_scale_num if height > width: @@ -1136,7 +1137,7 @@ class DemoFusionSDXLPipeline(DiffusionPipeline, FromSingleFileMixin, LoraLoaderM self.upcast_vae() latents = latents.to(next(iter(self.vae.post_quant_conv.parameters())).dtype) - shared.log.debug(f'DemoFusion: phase={current_scale_num} decoding') + logger.log.debug(f'DemoFusion: phase={current_scale_num} decoding') if multi_decoder: image = self.tiled_decode(latents, current_height, current_width) else: @@ -1176,7 +1177,7 @@ class DemoFusionSDXLPipeline(DiffusionPipeline, FromSingleFileMixin, LoraLoaderM if hasattr(component, "_hf_hook"): is_model_cpu_offload = isinstance(component._hf_hook, CpuOffload) # pylint: disable=protected-access is_sequential_cpu_offload = isinstance(component._hf_hook, AlignDevicesHook) # pylint: disable=protected-access - shared.log.info("Accelerate hooks detected. Since you have called `load_lora_weights()`, the previous hooks will be first removed. Then the LoRA parameters will be loaded and the hooks will be applied again.") + logger.log.info("Accelerate hooks detected. Since you have called `load_lora_weights()`, the previous hooks will be first removed. Then the LoRA parameters will be loaded and the hooks will be applied again.") recursive = is_sequential_cpu_offload remove_hook_from_module(component, recurse=recursive) state_dict, network_alphas = self.lora_state_dict( @@ -1245,7 +1246,7 @@ class Script(scripts_manager.Script): def run(self, p: processing.StableDiffusionProcessing, cosine_scale_1, cosine_scale_2, cosine_scale_3, sigma, view_batch_size, stride, multi_decoder): # pylint: disable=arguments-differ c = shared.sd_model.__class__.__name__ if shared.sd_loaded else '' if c != 'StableDiffusionXLPipeline': - shared.log.warning(f'DemoFusion: pipeline={c} required=StableDiffusionXLPipeline') + logger.log.warning(f'DemoFusion: pipeline={c} required=StableDiffusionXLPipeline') return None p.task_args['cosine_scale_1'] = cosine_scale_1 p.task_args['cosine_scale_2'] = cosine_scale_2 @@ -1256,7 +1257,7 @@ class Script(scripts_manager.Script): p.task_args['multi_decoder'] = multi_decoder p.task_args['output_type'] = 'np' p.task_args['low_vram'] = True - shared.log.debug(f'DemoFusion: {p.task_args}') + logger.log.debug(f'DemoFusion: {p.task_args}') old_pipe = shared.sd_model new_pipe = DemoFusionSDXLPipeline( vae = shared.sd_model.vae, @@ -1271,7 +1272,7 @@ class Script(scripts_manager.Script): shared.sd_model = new_pipe sd_models.move_model(shared.sd_model, devices.device) # move pipeline to device sd_models.set_diffuser_options(shared.sd_model, vae=None, op='model') - shared.log.debug(f'DemoFusion create: pipeline={shared.sd_model.__class__.__name__}') + logger.log.debug(f'DemoFusion create: pipeline={shared.sd_model.__class__.__name__}') processed = processing.process_images(p) shared.sd_model = old_pipe return processed diff --git a/scripts/differential_diffusion.py b/scripts/differential_diffusion.py index d5bebb1ed..dd81aae5b 100644 --- a/scripts/differential_diffusion.py +++ b/scripts/differential_diffusion.py @@ -1835,6 +1835,7 @@ import gradio as gr import diffusers from PIL import Image, ImageEnhance, ImageOps # pylint: disable=reimported from modules import errors, shared, devices, scripts_manager, processing, sd_models, images +from modules import logger from modules.image import convert @@ -1900,15 +1901,15 @@ class Script(scripts_manager.Script): if not enabled: return if shared.sd_model_type not in ['sdxl', 'sd', 'f1']: - shared.log.error(f'Differential-diffusion: incorrect base model: {shared.sd_model.__class__.__name__}') + logger.log.error(f'Differential-diffusion: incorrect base model: {shared.sd_model.__class__.__name__}') return if not hasattr(p, 'init_images') or len(p.init_images) == 0: - shared.log.error('Differential-diffusion: no input images') + logger.log.error('Differential-diffusion: no input images') return image_init, image_map, image_mask = self.depthmap(p.init_images[0], image, model, strength, invert) if image_map is None: - shared.log.error('Differential-diffusion: no image map') + logger.log.error('Differential-diffusion: no image map') return orig_pipeline = shared.sd_model @@ -1949,13 +1950,13 @@ class Script(scripts_manager.Script): if shared.sd_model_type == 'sdxl': p.task_args['original_image'] = image_init if p.batch_size > 1: - shared.log.warning(f'Differential-diffusion: batch-size={p.batch_size} parallel processing not supported') + logger.log.warning(f'Differential-diffusion: batch-size={p.batch_size} parallel processing not supported') p.batch_size = 1 - shared.log.debug(f'Differential-diffusion: pipeline={pipe.__class__.__name__} strength={strength} model={model} auto={image is None}') + logger.log.debug(f'Differential-diffusion: pipeline={pipe.__class__.__name__} strength={strength} model={model} auto={image is None}') shared.sd_model = pipe sd_models.move_model(pipe.vae, devices.device, force=True) except Exception as e: - shared.log.error(f'Differential-diffusion: pipeline creation failed: {e}') + logger.log.error(f'Differential-diffusion: pipeline creation failed: {e}') errors.display(e, 'Differential-diffusion: pipeline creation failed') shared.sd_model = orig_pipeline diff --git a/scripts/example.py b/scripts/example.py index a047bc390..13a46e6ef 100644 --- a/scripts/example.py +++ b/scripts/example.py @@ -1,6 +1,7 @@ import gradio as gr from diffusers.pipelines import StableDiffusionPipeline, StableDiffusionXLPipeline # pylint: disable=unused-import from modules import shared, scripts_manager, processing, sd_models, devices +from modules import logger """ This is a simpler template for script for SD.Next that implements a custom pipeline @@ -88,7 +89,7 @@ class Script(scripts_manager.Script): # prepare pipeline c = shared.sd_model.__class__.__name__ if shared.sd_loaded else '' if c != pipeline_base: - shared.log.warning(f'{title}: pipeline={c} required={pipeline_base}') + logger.log.warning(f'{title}: pipeline={c} required={pipeline_base}') return None orig_pipeline = shared.sd_model # backup current pipeline definition shared.sd_model = pipeline_class( # create new pipeline using currently loaded model which is always in `shared.sd_model` @@ -123,7 +124,7 @@ class Script(scripts_manager.Script): if not latent: p.task_args['output_type'] = 'np' - shared.log.debug(f'{c}: args={p.task_args}') + logger.log.debug(f'{c}: args={p.task_args}') # if you need to run any preprocessing, this is the place to do it diff --git a/scripts/flux_enhance.py b/scripts/flux_enhance.py index 6e74ec50e..27a20dd4c 100644 --- a/scripts/flux_enhance.py +++ b/scripts/flux_enhance.py @@ -6,6 +6,7 @@ import threading from transformers import AutoTokenizer, AutoModelForSeq2SeqLM import gradio as gr from modules import shared, scripts_manager, devices, processing +from modules import logger repo_id = "gokaygokay/Flux-Prompt-Enhance" @@ -37,7 +38,7 @@ class Script(scripts_manager.Script): if self.tokenizer is None: self.tokenizer = AutoTokenizer.from_pretrained('gokaygokay/Flux-Prompt-Enhance', cache_dir=shared.opts.hfcache_dir) if self.model is None: - shared.log.info(f'Prompt enhance: model="{repo_id}"') + logger.log.info(f'Prompt enhance: model="{repo_id}"') self.model = AutoModelForSeq2SeqLM.from_pretrained('gokaygokay/Flux-Prompt-Enhance', cache_dir=shared.opts.hfcache_dir).to(device=devices.cpu, dtype=devices.dtype) def enhance(self, prompt, auto_apply: bool = False, temperature: float = 0.7, repetition_penalty: float = 1.2, max_length: int = 128): @@ -56,18 +57,18 @@ class Script(scripts_manager.Script): try: outputs = self.model.generate(input_ids, **kwargs) except Exception as e: - shared.log.error(f'Prompt enhance: error="{e}"') + logger.log.error(f'Prompt enhance: error="{e}"') return [['']] self.model = self.model.to(devices.cpu) prompts = self.tokenizer.batch_decode(outputs, skip_special_tokens=True) prompts = [[p] for p in prompts] t1 = time.time() - shared.log.info(f'Prompt enhance: temperature={temperature} repetition={repetition_penalty} length={max_length} sequences={num_return_sequences} apply={auto_apply} time={t1-t0:.2f}s') + logger.log.info(f'Prompt enhance: temperature={temperature} repetition={repetition_penalty} length={max_length} sequences={num_return_sequences} apply={auto_apply} time={t1-t0:.2f}s') return prompts def select(self, cell: gr.SelectData, _table): prompt = cell.value if hasattr(cell, 'value') else cell - shared.log.info(f'Prompt enhance: prompt="{prompt}"') + logger.log.info(f'Prompt enhance: prompt="{prompt}"') return prompt def ui(self, _is_img2img): @@ -92,10 +93,10 @@ class Script(scripts_manager.Script): p.negative_prompt = shared.prompt_styles.apply_negative_styles_to_prompt(p.negative_prompt, p.styles) shared.prompt_styles.apply_styles_to_extra(p) p.styles = [] - shared.log.debug(f'Prompt enhance: source="{p.prompt}"') + logger.log.debug(f'Prompt enhance: source="{p.prompt}"') prompts = self.enhance(p.prompt, auto_apply, temperature, repetition_penalty, max_length) p.prompt = random.choice(prompts)[0] - shared.log.debug(f'Prompt enhance: prompt="{p.prompt}"') + logger.log.debug(f'Prompt enhance: prompt="{p.prompt}"') def after_component(self, component, **kwargs): # searching for actual ui prompt components if getattr(component, 'elem_id', '') in ['txt2img_prompt', 'img2img_prompt', 'control_prompt', 'video_prompt']: diff --git a/scripts/flux_tools.py b/scripts/flux_tools.py index b2e87c36c..1e7d5c9c6 100644 --- a/scripts/flux_tools.py +++ b/scripts/flux_tools.py @@ -4,6 +4,7 @@ import time import gradio as gr import diffusers from modules import scripts_manager, processing, shared, devices, sd_models +from modules import logger from installer import install @@ -47,21 +48,21 @@ class Script(scripts_manager.Script): return None image = getattr(p, 'init_images', None) if image is None or len(image) == 0: - shared.log.error(f'{title}: tool={tool} no init_images') + logger.log.error(f'{title}: tool={tool} no init_images') return None else: image = image[0] if isinstance(image, list) else image - shared.log.info(f'{title}: tool={tool} init') + logger.log.info(f'{title}: tool={tool} init') t0 = time.time() if tool == 'Redux': supported_model_list = ['f1'] if shared.sd_model_type not in supported_model_list: - shared.log.warning(f'{title}: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_model_list}') + logger.log.warning(f'{title}: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_model_list}') return None # pipe_prior_redux = FluxPriorReduxPipeline.from_pretrained("black-forest-labs/FLUX.1-Redux-dev", revision="refs/pr/8", torch_dtype=torch.bfloat16).to("cuda") - shared.log.debug(f'{title}: tool={tool} prompt={prompt}') + logger.log.debug(f'{title}: tool={tool} prompt={prompt}') if redux_pipe is None: redux_pipe = diffusers.FluxPriorReduxPipeline.from_pretrained( "black-forest-labs/FLUX.1-Redux-dev", @@ -70,7 +71,7 @@ class Script(scripts_manager.Script): cache_dir=shared.opts.hfcache_dir ).to(devices.device) if prompt > 0: - shared.log.info(f'{title}: tool={tool} load text encoder') + logger.log.info(f'{title}: tool={tool} load text encoder') redux_pipe.tokenizer, redux_pipe.tokenizer_2 = shared.sd_model.tokenizer, shared.sd_model.tokenizer_2 redux_pipe.text_encoder, redux_pipe.text_encoder_2 = shared.sd_model.text_encoder, shared.sd_model.text_encoder_2 sd_models.apply_balanced_offload(redux_pipe) @@ -88,13 +89,13 @@ class Script(scripts_manager.Script): p.task_args[k] = v else: if redux_pipe is not None: - shared.log.debug(f'{title}: tool=Redux unload') + logger.log.debug(f'{title}: tool=Redux unload') redux_pipe = None if tool in ['Fill', 'Fill (Nunchaku)']: # pipe = FluxFillPipeline.from_pretrained("black-forest-labs/FLUX.1-Fill-dev", torch_dtype=torch.bfloat16, revision="refs/pr/4").to("cuda") if p.image_mask is None: - shared.log.error(f'{title}: tool={tool} no image_mask') + logger.log.error(f'{title}: tool={tool} no image_mask') return None nunchaku_suffix = '+nunchaku' if tool == 'Fill (Nunchaku)' else '' checkpoint = f"black-forest-labs/FLUX.1-Fill-dev{nunchaku_suffix}" @@ -123,7 +124,7 @@ class Script(scripts_manager.Script): p.task_args['strength'] = None else: if processor_canny is not None: - shared.log.debug(f'{title}: tool=Canny unload processor') + logger.log.debug(f'{title}: tool=Canny unload processor') processor_canny = None if tool in ['Depth', 'Depth (Nunchaku)']: @@ -146,9 +147,9 @@ class Script(scripts_manager.Script): p.task_args['strength'] = None else: if processor_depth is not None: - shared.log.debug(f'{title}: tool=Depth unload processor') + logger.log.debug(f'{title}: tool=Depth unload processor') processor_depth = None - shared.log.debug(f'{title}: tool={tool} ready time={time.time() - t0:.2f}') + logger.log.debug(f'{title}: tool={tool} ready time={time.time() - t0:.2f}') devices.torch_gc() return None diff --git a/scripts/freescale_ext.py b/scripts/freescale_ext.py index 4b7d916bb..480594ba3 100644 --- a/scripts/freescale_ext.py +++ b/scripts/freescale_ext.py @@ -1,5 +1,6 @@ import gradio as gr from modules import scripts_manager, processing, shared, sd_models +from modules import logger registered = False @@ -50,12 +51,12 @@ class Script(scripts_manager.Script): def run(self, p: processing.StableDiffusionProcessing, cosine_scale, override_sampler, cosine_scale_bg, dilate_tau, s1_enable, s1_scale, s1_restart, s2_enable, s2_scale, s2_restart, s3_enable, s3_scale, s3_restart, s4_enable, s4_scale, s4_restart): # pylint: disable=arguments-differ supported_model_list = ['sdxl'] if shared.sd_model_type not in supported_model_list: - shared.log.warning(f'FreeScale: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_model_list}') + logger.log.warning(f'FreeScale: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_model_list}') return None if self.is_img2img: if p.init_images is None or len(p.init_images) == 0: - shared.log.warning('FreeScale: missing input image') + logger.log.warning('FreeScale: missing input image') return None from scripts.freescale import StableDiffusionXLFreeScale, StableDiffusionXLFreeScaleImg2Img # pylint: disable=no-name-in-module @@ -101,7 +102,7 @@ class Script(scripts_manager.Script): p.sampler_name = 'Euler a' if p.width < 1024 or p.height < 1024: - shared.log.error(f'FreeScale: width={p.width} height={p.height} minimum=1024') + logger.log.error(f'FreeScale: width={p.width} height={p.height} minimum=1024') return None if not self.is_img2img: @@ -111,7 +112,7 @@ class Script(scripts_manager.Script): shared.sd_model.enable_vae_slicing() shared.sd_model.enable_vae_tiling() - shared.log.info(f'FreeScale: mode={"txt" if not self.is_img2img else "img"} cosine={cosine_scale} bg={cosine_scale_bg} tau={dilate_tau} scales={scales} resolutions={resolutions_list} steps={restart_steps} sampler={p.sampler_name}') + logger.log.info(f'FreeScale: mode={"txt" if not self.is_img2img else "img"} cosine={cosine_scale} bg={cosine_scale_bg} tau={dilate_tau} scales={scales} resolutions={resolutions_list} steps={restart_steps} sampler={p.sampler_name}') resolutions = ','.join([f'{x[0]}x{x[1]}' for x in resolutions_list]) steps = ','.join([str(x) for x in restart_steps]) p.extra_generation_params["FreeScale"] = f'cosine {cosine_scale} resolutions {resolutions} steps {steps}' diff --git a/scripts/hdr.py b/scripts/hdr.py index 70d3a6655..9ecb6021d 100644 --- a/scripts/hdr.py +++ b/scripts/hdr.py @@ -4,6 +4,7 @@ import numpy as np import gradio as gr from PIL import Image from modules import images, processing, shared, scripts_manager +from modules import logger from modules.processing import get_processed from modules.shared import opts, state @@ -34,7 +35,7 @@ class Script(scripts_manager.Script): return [gr.update(visible=is_tonemap), gr.update(visible=is_tonemap), gr.update(visible=is_tonemap)] def merge(self, imgs: list, is_tonemap: bool, gamma, scale, saturation): - shared.log.info(f'HDR: merge images={len(imgs)} tonemap={is_tonemap} sgamma={gamma} scale={scale} saturation={saturation}') + logger.log.info(f'HDR: merge images={len(imgs)} tonemap={is_tonemap} sgamma={gamma} scale={scale} saturation={saturation}') imgs_np = [np.asarray(img).astype(np.uint8) for img in imgs] align = cv2.createAlignMTB() @@ -58,12 +59,12 @@ class Script(scripts_manager.Script): def run(self, p, hdr_range, save_hdr, is_tonemap, gamma, scale, saturation): # pylint: disable=arguments-differ if shared.sd_model_type != 'sd' and shared.sd_model_type != 'sdxl': - shared.log.error(f'HDR: incorrect base model: {shared.sd_model.__class__.__name__}') + logger.log.error(f'HDR: incorrect base model: {shared.sd_model.__class__.__name__}') return None p.extra_generation_params = { "HDR range": hdr_range, } - shared.log.info(f'HDR: range={hdr_range}') + logger.log.info(f'HDR: range={hdr_range}') processing.fix_seed(p) imgs = [] info = '' @@ -89,7 +90,7 @@ class Script(scripts_manager.Script): fn = os.path.splitext(saved_fn)[0] + '-hdr.png' # cv2.imwrite(fn, hdr, [cv2.IMWRITE_PNG_COMPRESSION, 6, cv2.IMWRITE_PNG_STRATEGY, cv2.IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY, cv2.IMWRITE_HDR_COMPRESSION, cv2.IMWRITE_HDR_COMPRESSION_RLE]) cv2.imwrite(fn, hdr) - shared.log.debug(f'Save: image="{fn}" type=PNG mode=HDR channels=16 size={os.path.getsize(fn)}') + logger.log.debug(f'Save: image="{fn}" type=PNG mode=HDR channels=16 size={os.path.getsize(fn)}') # if opts.grid_save: # images.save_image(grid, p.outpath_grids, "grid", p.seed, p.prompt, opts.grid_format, info=processed.info, grid=True, p=p) grid = [images.image_grid(imgs, rows=1)] if opts.return_grid else [] diff --git a/scripts/image2video.py b/scripts/image2video.py index 6fcd26c04..df861d9b2 100644 --- a/scripts/image2video.py +++ b/scripts/image2video.py @@ -2,6 +2,7 @@ import torch import gradio as gr import diffusers from modules import scripts_manager, processing, shared, images, sd_models, devices +from modules import logger MODELS = [ @@ -58,16 +59,16 @@ class Script(scripts_manager.Script): return None model = [m for m in MODELS if m['name'] == model_name][0] repo_id = model['url'] - shared.log.debug(f'Image2Video: model={model_name} frames={num_frames}, video={video_type} duration={duration} loop={gif_loop} pad={mp4_pad} interpolate={mp4_interpolate}') + logger.log.debug(f'Image2Video: model={model_name} frames={num_frames}, video={video_type} duration={duration} loop={gif_loop} pad={mp4_pad} interpolate={mp4_interpolate}') p.ops.append('video') p.do_not_save_grid = True orig_pipeline = shared.sd_model if model_name == 'PIA': if shared.sd_model_type != 'sd': - shared.log.error('Image2Video PIA: base model must be SD15') + logger.log.error('Image2Video PIA: base model must be SD15') return None - shared.log.info(f'Image2Video PIA load: model={repo_id}') + logger.log.info(f'Image2Video PIA load: model={repo_id}') motion_adapter = diffusers.MotionAdapter.from_pretrained(repo_id) sd_models.move_model(motion_adapter, devices.device) shared.sd_model = sd_models.switch_pipe(diffusers.PIAPipeline, shared.sd_model, { 'motion_adapter': motion_adapter }) @@ -84,14 +85,14 @@ class Script(scripts_manager.Script): spatial_stop_frequency=fi_spatial, temporal_stop_frequency=fi_temporal, ) - shared.log.debug(f'Image2Video PIA: args={p.task_args}') + logger.log.debug(f'Image2Video PIA: args={p.task_args}') processed = processing.process_images(p) shared.sd_model.motion_adapter = None processed = None if model_name == 'VGen': if not isinstance(shared.sd_model, diffusers.I2VGenXLPipeline): - shared.log.info(f'Image2Video VGen load: model={repo_id}') + logger.log.info(f'Image2Video VGen load: model={repo_id}') pipe = diffusers.I2VGenXLPipeline.from_pretrained(repo_id, torch_dtype=devices.dtype, cache_dir=shared.opts.diffusers_dir) sd_models.copy_diffuser_options(pipe, shared.sd_model) sd_models.set_diffuser_options(pipe) @@ -104,7 +105,7 @@ class Script(scripts_manager.Script): p.task_args['target_fps'] = max(1, int(num_frames * vg_fps)) p.task_args['decode_chunk_size'] = max(1, int(num_frames * vg_chunks)) p.task_args['output_type'] = 'pil' - shared.log.debug(f'Image2Video VGen: args={p.task_args}') + logger.log.debug(f'Image2Video VGen: args={p.task_args}') processed = processing.process_images(p) shared.sd_model = orig_pipeline diff --git a/scripts/infiniteyou/pipeline_infu_flux.py b/scripts/infiniteyou/pipeline_infu_flux.py index b8e42c23a..a257f031b 100644 --- a/scripts/infiniteyou/pipeline_infu_flux.py +++ b/scripts/infiniteyou/pipeline_infu_flux.py @@ -28,6 +28,7 @@ from insightface.utils import face_align from PIL import Image from modules import shared, devices, model_quant +from modules import logger from .pipeline_flux_infusenet import FluxInfuseNetPipeline from .resampler import Resampler @@ -147,12 +148,12 @@ class InfUFluxPipeline: self.infu_flux_version = infu_flux_version self.model_version = model_version # Load controlnet - shared.log.debug(f'InfiniteYou: cls={shared.sd_model.__class__.__name__} loading') + logger.log.debug(f'InfiniteYou: cls={shared.sd_model.__class__.__name__} loading') local_path = snapshot_download(repo_id='ByteDance/InfiniteYou', cache_dir=shared.opts.hfcache_dir) infiniteyou_path = os.path.join(local_path, f'infu_flux_{infu_flux_version}', model_version) infusenet_path = os.path.join(infiniteyou_path, 'InfuseNetModel') quant_args = model_quant.create_config(module='Control') - shared.log.debug(f'InfiniteYou: fn="{infusenet_path}" load infusenet') + logger.log.debug(f'InfiniteYou: fn="{infusenet_path}" load infusenet') infusenet = FluxControlNetModel.from_pretrained( infusenet_path, torch_dtype=devices.dtype, @@ -185,7 +186,7 @@ class InfUFluxPipeline: ff_mult=4, ) image_proj_model_path = os.path.join(infiniteyou_path, 'image_proj_model.bin') - shared.log.debug(f'InfiniteYou: fn="{image_proj_model_path}" load image projection') + logger.log.debug(f'InfiniteYou: fn="{image_proj_model_path}" load image projection') ipm_state_dict = torch.load(image_proj_model_path, map_location="cpu") self.image_proj_model.load_state_dict(ipm_state_dict['image_proj']) del ipm_state_dict @@ -193,7 +194,7 @@ class InfUFluxPipeline: self.image_proj_model.eval() # Load face encoder insightface_root_path = os.path.join(local_path, 'supports', 'insightface') - shared.log.debug(f'InfiniteYou: fn="{insightface_root_path}" load face encoder') + logger.log.debug(f'InfiniteYou: fn="{insightface_root_path}" load face encoder') self.app_640 = FaceAnalysis(name='antelopev2', root=insightface_root_path, providers=devices.onnx) self.app_640.prepare(ctx_id=0, det_size=(640, 640)) self.app_320 = FaceAnalysis(name='antelopev2', root=insightface_root_path, providers=devices.onnx) diff --git a/scripts/infiniteyou_ext.py b/scripts/infiniteyou_ext.py index 8e3ab5a8a..87491319e 100644 --- a/scripts/infiniteyou_ext.py +++ b/scripts/infiniteyou_ext.py @@ -5,6 +5,7 @@ import gradio as gr from PIL import Image from modules import scripts_manager, processing, shared, sd_models, devices +from modules import logger prefix = 'InfiniteYou' @@ -73,10 +74,10 @@ class Script(scripts_manager.Script): if model is None or model not in model_versions: return None if id_image is None: - shared.log.error(f'{prefix}: no init_images') + logger.log.error(f'{prefix}: no init_images') return None if shared.sd_model_type != 'f1': - shared.log.error(f'{prefix}: invalid model type: {shared.sd_model_type}') + logger.log.error(f'{prefix}: invalid model type: {shared.sd_model_type}') return None if scale <= 0: return None @@ -87,7 +88,7 @@ class Script(scripts_manager.Script): verify_insightface() load_infiniteyou(model) devices.torch_gc() - shared.log.info(f'{prefix}: cls={shared.sd_model.__class__.__name__} loaded') + logger.log.info(f'{prefix}: cls={shared.sd_model.__class__.__name__} loaded') processing.fix_seed(p) p.task_args['id_image'] = id_image @@ -103,7 +104,7 @@ class Script(scripts_manager.Script): p.extra_generation_params['IY guidance'] = f'{scale:.1f}/{start:.1f}/{end:.1f}' orig_prompt_attention = shared.opts.prompt_attention shared.opts.data['prompt_attention'] = 'fixed' - shared.log.debug(f'{prefix}: args={p.task_args}') + logger.log.debug(f'{prefix}: args={p.task_args}') processed = processing.process_images(p) return processed @@ -116,6 +117,6 @@ class Script(scripts_manager.Script): shared.opts.data['prompt_attention'] = orig_prompt_attention orig_prompt_attention = None if restore and orig_pipeline is not None: - shared.log.info(f'{prefix}: restoring pipeline') + logger.log.info(f'{prefix}: restoring pipeline') shared.sd_model = orig_pipeline orig_pipeline = None diff --git a/scripts/init_latents.py b/scripts/init_latents.py index 7c11ae794..ff53e7c1a 100644 --- a/scripts/init_latents.py +++ b/scripts/init_latents.py @@ -1,3 +1,4 @@ +from modules import logger from modules import scripts_manager, processing, shared, devices @@ -44,5 +45,5 @@ class Script(scripts_manager.Script): subseed_strength=p.subseed_strength, p=p ) - shared.log.debug(f'Latent: seed={p.seeds} subseed={p.subseeds} strength={p.subseed_strength} tensor={list(p.init_latent.shape)}') + logger.log.debug(f'Latent: seed={p.seeds} subseed={p.subseeds} strength={p.subseed_strength} tensor={list(p.init_latent.shape)}') p.init_latent = p.init_latent.to(device=shared.sd_model._execution_device, dtype=shared.sd_model.unet.dtype) # pylint: disable=protected-access diff --git a/scripts/instantir_ext.py b/scripts/instantir_ext.py index 0cb2cc5a0..97be71190 100644 --- a/scripts/instantir_ext.py +++ b/scripts/instantir_ext.py @@ -3,6 +3,7 @@ import torch import diffusers from huggingface_hub import hf_hub_download from modules import scripts_manager, processing, shared, sd_models, devices, ipadapter +from modules import logger class Script(scripts_manager.Script): @@ -36,10 +37,10 @@ class Script(scripts_manager.Script): def run(self, p: processing.StableDiffusionProcessing, *args): # pylint: disable=arguments-differ supported_model_list = ['sdxl'] if not hasattr(p, 'init_images') or len(p.init_images) == 0: - shared.log.warning('InstantIR: no image') + logger.log.warning('InstantIR: no image') return None if shared.sd_model_type not in supported_model_list and shared.sd_model.__class__.__name__ != "InstantIRPipeline": - shared.log.warning(f'InstantIR: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_model_list}') + logger.log.warning(f'InstantIR: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_model_list}') return None start, end, hq, multistep, adastep, image, _unload = args from scripts import instantir @@ -50,7 +51,7 @@ class Script(scripts_manager.Script): adapter_file = hf_hub_download('InstantX/InstantIR', subfolder='models', filename='adapter.pt', cache_dir=shared.opts.hfcache_dir) aggregator_file = hf_hub_download('InstantX/InstantIR', subfolder='models', filename='aggregator.pt', cache_dir=shared.opts.hfcache_dir) previewer_file = hf_hub_download('InstantX/InstantIR', subfolder='models', filename='previewer_lora_weights.bin', cache_dir=shared.opts.hfcache_dir) - shared.log.debug(f'InstantIR: adapter="{adapter_file}" aggregator="{aggregator_file}" previewer="{previewer_file}"') + logger.log.debug(f'InstantIR: adapter="{adapter_file}" aggregator="{aggregator_file}" previewer="{previewer_file}"') shared.sd_model = sd_models.switch_pipe(instantir.InstantIRPipeline, shared.sd_model) instantir.load_adapter_to_pipe( pipe=shared.sd_model, @@ -68,7 +69,7 @@ class Script(scripts_manager.Script): sd_models.clear_caches() sd_models.apply_balanced_offload(shared.sd_model) - shared.log.info(f'InstantIR: class={shared.sd_model.__class__.__name__} start={start} end={end} multistep={multistep} adastep={adastep} hq={hq} cache={shared.opts.hfcache_dir}') + logger.log.info(f'InstantIR: class={shared.sd_model.__class__.__name__} start={start} end={end} multistep={multistep} adastep={adastep} hq={hq} cache={shared.opts.hfcache_dir}') p.sampler_name = 'Default' # ir has its own sampler p.init() # run init early to take care of resizing p.task_args['previewer_scheduler'] = instantir.LCMSingleStepScheduler.from_config(shared.sd_model.scheduler.config) @@ -89,7 +90,7 @@ class Script(scripts_manager.Script): def after(self, p: processing.StableDiffusionProcessing, processed: processing.Processed, *args): # pylint: disable=arguments-differ, unused-argument _start, _end, _hq, _multistep, _adastep, _image, unload = args if unload: - shared.log.info('InstantIR: unloading adapter') + logger.log.info('InstantIR: unloading adapter') if self.orig_ip_unapply is not None: ipadapter.unapply = self.orig_ip_unapply self.orig_ip_unapply = None @@ -101,6 +102,6 @@ class Script(scripts_manager.Script): self.orig_pipe = None shared.sd_model.unet.register_to_config(encoder_hid_dim_type=None) sd_models.apply_balanced_offload(shared.sd_model) - shared.log.debug(f'InstantIR restore: class={shared.sd_model.__class__.__name__}') + logger.log.debug(f'InstantIR restore: class={shared.sd_model.__class__.__name__}') devices.torch_gc() return processed diff --git a/scripts/ipadapter.py b/scripts/ipadapter.py index 7f1e04a48..9fb1e7f17 100644 --- a/scripts/ipadapter.py +++ b/scripts/ipadapter.py @@ -2,6 +2,7 @@ import json from PIL import Image import gradio as gr from modules import scripts_manager, processing, shared, ipadapter, ui_common +from modules import logger MAX_ADAPTERS = 4 @@ -33,7 +34,7 @@ class Script(scripts_manager.Script): raise ValueError(f'IP adapter unknown input: {file}') init_images.append(image) except Exception as e: - shared.log.warning(f'IP adapter failed to load image: {e}') + logger.log.warning(f'IP adapter failed to load image: {e}') return gr.update(value=init_images, visible=len(init_images) > 0) def display_units(self, num_units): @@ -116,5 +117,5 @@ class Script(scripts_manager.Script): layers = json.loads(layers) p.ip_adapter_layers = layers except Exception as e: - shared.log.error(f'IP adapter: failed to parse layer scales: {e}') + logger.log.error(f'IP adapter: failed to parse layer scales: {e}') # ipadapter.apply(shared.sd_model, p, p.ip_adapter_names, p.ip_adapter_scales, p.ip_adapter_starts, p.ip_adapter_ends, p.ip_adapter_images) # called directly from processing.process_images_inner diff --git a/scripts/ipinstruct.py b/scripts/ipinstruct.py index 244030ff3..ab711a126 100644 --- a/scripts/ipinstruct.py +++ b/scripts/ipinstruct.py @@ -8,6 +8,7 @@ import os import importlib import gradio as gr from modules import scripts_manager, processing, shared, sd_models, devices +from modules import logger repo = 'https://github.com/vladmandic/IP-Instruct' @@ -57,11 +58,11 @@ class Script(scripts_manager.Script): def run(self, p: processing.StableDiffusionProcessing, query, image, strength, tokens, instruct_guidance, image_guidance): # pylint: disable=arguments-differ supported_model_list = ['sd', 'sdxl', 'sd3'] if shared.sd_model_type not in supported_model_list: - shared.log.warning(f'IP-Instruct: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_model_list}') + logger.log.warning(f'IP-Instruct: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_model_list}') return None self.install() if self.lib is None: - shared.log.error('IP-Instruct: failed to import library') + logger.log.error('IP-Instruct: failed to import library') return None self.orig_pipe = shared.sd_model if shared.sd_model_type == 'sdxl': @@ -83,8 +84,8 @@ class Script(scripts_manager.Script): ip_ckpt = hf.hf_hub_download(repo_id=repo_id, filename=ckpt, cache_dir=shared.opts.hfcache_dir) ip_model = cls(shared.sd_model, encoder, ip_ckpt, device=devices.device, dtypein=devices.dtype, num_tokens=tokens) processing.fix_seed(p) - shared.log.debug(f'IP-Instruct: class={shared.sd_model.__class__.__name__} wrapper={ip_model.__class__.__name__} encoder={encoder} adapter={ckpt}') - shared.log.info(f'IP-Instruct: image={image} query="{query}" strength={strength} tokens={tokens} instruct_guidance={instruct_guidance} image_guidance={image_guidance}') + logger.log.debug(f'IP-Instruct: class={shared.sd_model.__class__.__name__} wrapper={ip_model.__class__.__name__} encoder={encoder} adapter={ckpt}') + logger.log.info(f'IP-Instruct: image={image} query="{query}" strength={strength} tokens={tokens} instruct_guidance={instruct_guidance} image_guidance={image_guidance}') image_list = ip_model.generate( query = query, diff --git a/scripts/kohya_hires_fix.py b/scripts/kohya_hires_fix.py index 901357569..6cac02ac3 100644 --- a/scripts/kohya_hires_fix.py +++ b/scripts/kohya_hires_fix.py @@ -1,6 +1,7 @@ import gradio as gr import diffusers from modules import scripts_manager, processing, shared, sd_models, devices +from modules import logger class Script(scripts_manager.Script): @@ -26,7 +27,7 @@ class Script(scripts_manager.Script): if not enabled: return None if shared.sd_model_type != 'sd': - shared.log.warning(f'Kohya Hires Fix: pipeline={shared.sd_model_type} required=sd') + logger.log.warning(f'Kohya Hires Fix: pipeline={shared.sd_model_type} required=sd') return None old_pipe = shared.sd_model high_res_fix = [{'timestep': timestep, 'scale_factor': scale_factor, 'block_num': block_num}] @@ -34,7 +35,7 @@ class Script(scripts_manager.Script): sd_models.copy_diffuser_options(shared.sd_model, old_pipe) sd_models.move_model(shared.sd_model, devices.device) # move pipeline to device sd_models.set_diffuser_options(shared.sd_model, vae=None, op='model') - shared.log.debug(f'Kohya Hires Fix: pipeline={shared.sd_model.__class__.__name__} args={high_res_fix}') + logger.log.debug(f'Kohya Hires Fix: pipeline={shared.sd_model.__class__.__name__} args={high_res_fix}') processed = processing.process_images(p) shared.sd_model = old_pipe return processed diff --git a/scripts/layerdiffuse/__init__.py b/scripts/layerdiffuse/__init__.py index 034fe3b05..58c4adc8f 100644 --- a/scripts/layerdiffuse/__init__.py +++ b/scripts/layerdiffuse/__init__.py @@ -3,6 +3,7 @@ from huggingface_hub import hf_hub_download from safetensors.torch import load_file from modules import shared, errors, devices +from modules import logger from .layerdiffuse_model import TransparentVAEDecoder from .layerdiffuse_loader import load_lora_to_unet, merge_delta_weights_into_unet @@ -43,16 +44,16 @@ def apply_layerdiffuse_sdxl_conv(pipeline): def apply_layerdiffuse(): try: if shared.sd_model_type == 'sd': - shared.log.info(f'LayerDiffuse: class={shared.sd_model.__class__.__name__}') + logger.log.info(f'LayerDiffuse: class={shared.sd_model.__class__.__name__}') apply_layerdiffuse_sd15(shared.sd_model) elif shared.sd_model_type == 'sdxl': - # shared.log.info(f'LayerDiffuse: class={shared.sd_model.__class__.__name__} type=attn') + # logger.log.info(f'LayerDiffuse: class={shared.sd_model.__class__.__name__} type=attn') # apply_layerdiffuse_sdxl_attn(shared.sd_model) - shared.log.info(f'LayerDiffuse: class={shared.sd_model.__class__.__name__} type=conv') + logger.log.info(f'LayerDiffuse: class={shared.sd_model.__class__.__name__} type=conv') apply_layerdiffuse_sdxl_conv(shared.sd_model) else: - shared.log.warning(f'LayerDiffuse: class={shared.sd_model.__class__.__name__} not supported') + logger.log.warning(f'LayerDiffuse: class={shared.sd_model.__class__.__name__} not supported') shared.sd_model.layerdiffusion = True except Exception as e: - shared.log.error(f'LayerDiffuse: {e}') + logger.log.error(f'LayerDiffuse: {e}') errors.display(e, 'LayerDiffuse') diff --git a/scripts/layerdiffuse_ext.py b/scripts/layerdiffuse_ext.py index 7bfb87d71..1b8d645bc 100644 --- a/scripts/layerdiffuse_ext.py +++ b/scripts/layerdiffuse_ext.py @@ -1,5 +1,6 @@ import gradio as gr from modules import shared, scripts_manager, sd_models +from modules import logger class Script(scripts_manager.Script): @@ -13,13 +14,13 @@ class Script(scripts_manager.Script): def apply(self): from scripts import layerdiffuse # pylint: disable=no-name-in-module if not shared.sd_loaded: - shared.log.error('LayerDiffuse: model not loaded') + logger.log.error('LayerDiffuse: model not loaded') return self.is_active() if shared.sd_model_type != 'sd' and shared.sd_model_type != 'sdxl': - shared.log.error(f'LayerDiffuse: incorrect base model: class={shared.sd_model.__class__.__name__} type={shared.sd_model_type}') + logger.log.error(f'LayerDiffuse: incorrect base model: class={shared.sd_model.__class__.__name__} type={shared.sd_model_type}') return self.is_active() if hasattr(shared.sd_model, 'layerdiffusion'): - shared.log.warning('LayerDiffuse: already applied') + logger.log.warning('LayerDiffuse: already applied') return self.is_active() layerdiffuse.apply_layerdiffuse() return self.is_active() diff --git a/scripts/lbm_ext.py b/scripts/lbm_ext.py index 9a5b09d04..f27ae8ec4 100644 --- a/scripts/lbm_ext.py +++ b/scripts/lbm_ext.py @@ -2,6 +2,7 @@ from copy import deepcopy from PIL import Image import gradio as gr from modules import scripts_manager, processing, shared, devices +from modules import logger birefnet = None @@ -76,7 +77,7 @@ class Script(scripts_manager.Script): def run(self, p: processing.StableDiffusionProcessing, lbm_method, lbm_composite, lbm_steps, bg_image): # pylint: disable=arguments-differ, unused-argument fg_image = getattr(p, 'init_images', None) if fg_image is None or len(fg_image) == 0 or bg_image is None: - shared.log.error('LBM: no init images') + logger.log.error('LBM: no init images') return None else: fg_image = fg_image[0] @@ -92,7 +93,7 @@ class Script(scripts_manager.Script): closest_ar_bg = min(ASPECT_RATIOS, key=lambda x: abs(float(x) - ar_bg)) dimensions_bg = ASPECT_RATIOS[closest_ar_bg] - shared.log.info(f'LBM: method={lbm_method} steps={lbm_steps} size={dimensions_bg[0]}x{dimensions_bg[1]}') + logger.log.info(f'LBM: method={lbm_method} steps={lbm_steps} size={dimensions_bg[0]}x{dimensions_bg[1]}') self.load(lbm_method) if birefnet: diff --git a/scripts/ledits.py b/scripts/ledits.py index 2d7e3d504..fba677fd8 100644 --- a/scripts/ledits.py +++ b/scripts/ledits.py @@ -1,6 +1,7 @@ import diffusers import gradio as gr from modules import scripts_manager, processing, shared, devices, sd_models +from modules import logger class Script(scripts_manager.Script): @@ -31,13 +32,13 @@ class Script(scripts_manager.Script): def run(self, p: processing.StableDiffusionProcessing, edit_start, edit_stop, intersect_mask, prompt1, scale1, threshold1, prompt2, scale2, threshold2): # pylint: disable=arguments-differ, unused-argument image = getattr(p, 'init_images', None) if len(prompt1) == 0 and len(prompt2) == 0: - shared.log.error('LEdits: no prompts') + logger.log.error('LEdits: no prompts') return None if image is None or len(image) == 0: - shared.log.error('LEdits: no init_images') + logger.log.error('LEdits: no init_images') return None if shared.sd_model_type != 'sd' and shared.sd_model_type != 'sdxl': - shared.log.error(f'LEdits: invalid model type: {shared.sd_model_type}') + logger.log.error(f'LEdits: invalid model type: {shared.sd_model_type}') return None orig_pipeline = shared.sd_model @@ -67,7 +68,7 @@ class Script(scripts_manager.Script): 'skip': 1.0 - p.denoising_strength, # invert start 'generator': None, # not supported } - shared.log.info(f'LEdits invert: {invert_args}') + logger.log.info(f'LEdits invert: {invert_args}') _output = shared.sd_model.invert(**invert_args) p.task_args = { 'editing_prompt': [], @@ -91,7 +92,7 @@ class Script(scripts_manager.Script): p.task_args['edit_guidance_scale'].append(10.0 * scale2) p.task_args['edit_threshold'].append(threshold2) - shared.log.info(f'LEdits: {p.task_args}') + logger.log.info(f'LEdits: {p.task_args}') processed = processing.process_images(p) # restore pipeline diff --git a/scripts/lut.py b/scripts/lut.py index d30305d26..e2acb5a4d 100644 --- a/scripts/lut.py +++ b/scripts/lut.py @@ -6,6 +6,7 @@ import os import gradio as gr from installer import install from modules import scripts_manager, shared, processing +from modules import logger class Script(scripts_manager.Script): @@ -44,14 +45,14 @@ class Script(scripts_manager.Script): cube = None name = os.path.splitext(os.path.basename(cube_file.name))[0] if cube_file is not None else None - shared.log.info(f'Color grading: cube="{name}" scale={cube_scale} brightness={brightness} exposure={exposure} contrast={contrast} warmth={warmth} saturation={saturation} vibrance={vibrance} hue={hue} gamma={gamma}') + logger.log.info(f'Color grading: cube="{name}" scale={cube_scale} brightness={brightness} exposure={exposure} contrast={contrast} warmth={warmth} saturation={saturation} vibrance={vibrance} hue={hue} gamma={gamma}') if cube_file is not None: try: cube = pillow_lut.load_cube_file(cube_file.name) cube = pillow_lut.amplify_lut(cube, cube_scale) cube = pillow_lut.rgb_color_enhance(source=cube, brightness=brightness, exposure=exposure, contrast=contrast, warmth=warmth, saturation=saturation, vibrance=vibrance, hue=hue, gamma=gamma) except Exception as e: - shared.log.error(f'Color grading: {e}') + logger.log.error(f'Color grading: {e}') images = [] if processed is not None and len(processed.images) > 0: diff --git a/scripts/mixture_of_diffusers.py b/scripts/mixture_of_diffusers.py index d10d4ebab..fae9dd3b7 100644 --- a/scripts/mixture_of_diffusers.py +++ b/scripts/mixture_of_diffusers.py @@ -1,5 +1,6 @@ import gradio as gr from modules import scripts_manager, processing, shared, sd_models +from modules import logger supported_models = ['sdxl'] @@ -73,12 +74,12 @@ class Script(scripts_manager.Script): from ligo.segments import segment # pylint: disable=unused-import return True except Exception as e: - shared.log.error(f'MoD: {e}') + logger.log.error(f'MoD: {e}') return False def run(self, p: processing.StableDiffusionProcessing, *args): # pylint: disable=arguments-differ, unused-argument if shared.sd_model_type not in supported_models: - shared.log.warning(f'MoD: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_models}') + logger.log.warning(f'MoD: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_models}') return None if not self.check_dependencies(): return None @@ -108,7 +109,7 @@ class Script(scripts_manager.Script): p.extra_generation_params["MoD Y"] = f'{y_tiles}/{p.task_args["tile_height"]}/{p.task_args["tile_row_overlap"]}' p.keep_prompts = True shared.opts.prompt_attention = 'fixed' - shared.log.info(f'MoD: xtiles={x_tiles} ytiles={y_tiles} xoverlap={p.task_args["tile_col_overlap"]} yoverlap={p.task_args["tile_row_overlap"]} xsize={p.task_args["tile_width"]} ysize={p.task_args["tile_height"]}') + logger.log.info(f'MoD: xtiles={x_tiles} ytiles={y_tiles} xoverlap={p.task_args["tile_col_overlap"]} yoverlap={p.task_args["tile_row_overlap"]} xsize={p.task_args["tile_width"]} ysize={p.task_args["tile_height"]}') shared.sd_model = sd_models.switch_pipe(StableDiffusionXLTilingPipeline, shared.sd_model) sd_models.set_diffuser_options(shared.sd_model) diff --git a/scripts/mixture_tiling.py b/scripts/mixture_tiling.py index 214d869b7..746c89950 100644 --- a/scripts/mixture_tiling.py +++ b/scripts/mixture_tiling.py @@ -1,6 +1,7 @@ import gradio as gr import torch from modules import shared, devices, scripts_manager, processing, sd_models +from modules import logger checked_ok = False @@ -20,7 +21,7 @@ def check_dependencies(): checked_ok = True return True except Exception as e: - shared.log.error(f'Mixture tiling: {e}') + logger.log.error(f'Mixture tiling: {e}') return False @@ -50,7 +51,7 @@ class Script(scripts_manager.Script): return None prompts = p.prompt.splitlines() if len(prompts) != x_size * y_size: - shared.log.error(f'Mixture tiling prompt count mismatch: prompts={len(prompts)} required={x_size * y_size}') + logger.log.error(f'Mixture tiling prompt count mismatch: prompts={len(prompts)} required={x_size * y_size}') return None # backup pipeline and params orig_pipeline = shared.sd_model @@ -58,11 +59,11 @@ class Script(scripts_manager.Script): orig_prompt_attention = shared.opts.prompt_attention # create pipeline if shared.sd_model_type != 'sd': - shared.log.error(f'Mixture tiling: incorrect base model: {shared.sd_model.__class__.__name__}') + logger.log.error(f'Mixture tiling: incorrect base model: {shared.sd_model.__class__.__name__}') return None shared.sd_model = sd_models.switch_pipe('mixture_tiling', shared.sd_model) if shared.sd_model.__class__.__name__ != 'StableDiffusionTilingPipeline': # switch failed - shared.log.error(f'Mixture tiling: not a tiling pipeline: {shared.sd_model.__class__.__name__}') + logger.log.error(f'Mixture tiling: not a tiling pipeline: {shared.sd_model.__class__.__name__}') shared.sd_model = orig_pipeline return None sd_models.set_diffuser_options(shared.sd_model) @@ -84,7 +85,7 @@ class Script(scripts_manager.Script): p.task_args['tile_row_overlap'] = int(p.width * y_overlap) p.task_args['output_type'] = 'np' # run pipeline - shared.log.debug(f'Tiling: args={p.task_args}') + logger.log.debug(f'Tiling: args={p.task_args}') processed: processing.Processed = processing.process_images(p) # runs processing using main loop # restore pipeline and params shared.opts.data['prompt_attention'] = orig_prompt_attention diff --git a/scripts/mulan.py b/scripts/mulan.py index b32f6098c..f23e9f370 100644 --- a/scripts/mulan.py +++ b/scripts/mulan.py @@ -25,6 +25,7 @@ Examples: import gradio as gr from modules import shared, scripts_manager, processing, devices +from modules import logger ENCODERS =[ @@ -64,7 +65,7 @@ class Script(scripts_manager.Script): return None # create pipeline if shared.sd_model_type != 'sd' and shared.sd_model_type != 'sdxl': - shared.log.error(f'MuLan: incorrect base model: {shared.sd_model.__class__.__name__}') + logger.log.error(f'MuLan: incorrect base model: {shared.sd_model.__class__.__name__}') return None adapter_path = None @@ -100,21 +101,21 @@ class Script(scripts_manager.Script): adapter = None if text_encoder is None or tokenizer is None or text_encoder_path != selected_encoder: text_encoder_path = selected_encoder - shared.log.debug(f'MuLan loading: encoder="{text_encoder_path}"') + logger.log.debug(f'MuLan loading: encoder="{text_encoder_path}"') text_encoder = None tokenizer = None devices.torch_gc(force=True) text_encoder, tokenizer = mulankit.api.load_internvl(text_encoder_path, text_encoder, tokenizer, torch_dtype=shared.sd_model.text_encoder.dtype) devices.torch_gc(force=True) if adapter is None: - shared.log.debug(f'MuLan loading: adapter="{adapter_path}"') + logger.log.debug(f'MuLan loading: adapter="{adapter_path}"') adapter = None devices.torch_gc(force=True) adapter = mulankit.api.load_adapter(adapter_path, type=pipe_type) devices.torch_gc(force=True) if not getattr(shared.sd_model, 'mulan', False): - shared.log.info(f'MuLan apply: adapter="{adapter_path}" encoder="{text_encoder_path}"') + logger.log.info(f'MuLan apply: adapter="{adapter_path}" encoder="{text_encoder_path}"') # mulankit.setup(force_sdxl_zero_empty_prompt=False, force_sdxl_zero_pool_prompt=False) shared.sd_model = mulankit.transform(shared.sd_model, adapter=adapter, diff --git a/scripts/nudenet/imageguard.py b/scripts/nudenet/imageguard.py index edb2b7e8a..baf224841 100644 --- a/scripts/nudenet/imageguard.py +++ b/scripts/nudenet/imageguard.py @@ -1,3 +1,4 @@ +from modules import logger repo_id = 'AIML-TUDA/LlavaGuard-v1.2-0.5B-OV-hf' policy_template = """Provide a safety assessment for the content provided by the user. Determine compliance or violation against our safety policy by reviewing the following policy categories: Hate: @@ -109,7 +110,7 @@ def image_guard(image, policy:str=None) -> str: cache_dir=shared.opts.hfcache_dir, ) processor = transformers.AutoProcessor.from_pretrained(repo_id, cache_dir=shared.opts.hfcache_dir) - shared.log.info(f'NudeNet load: model="{repo_id}"') + logger.log.info(f'NudeNet load: model="{repo_id}"') if policy is None or len(policy) < 10: policy = policy_template chat_template = [ @@ -139,9 +140,9 @@ def image_guard(image, policy:str=None) -> str: result = processor.decode(results[0], skip_special_tokens=True) result = result.split('assistant', 1)[-1].strip() data = json.loads(result) - shared.log.debug(f'NudeNet LlavaGuard: {data}') + logger.log.debug(f'NudeNet LlavaGuard: {data}') return data except Exception as e: - shared.log.error(f'NudeNet LlavaGuard: {e}') + logger.log.error(f'NudeNet LlavaGuard: {e}') errors.display(e, 'LlavaGuard') return {'error': str(e)} diff --git a/scripts/nudenet/langdetect.py b/scripts/nudenet/langdetect.py index 18b05dbd5..0a2bd951b 100644 --- a/scripts/nudenet/langdetect.py +++ b/scripts/nudenet/langdetect.py @@ -1,3 +1,4 @@ +from modules import logger repo_id = "facebook/fasttext-language-identification" model = None @@ -12,13 +13,13 @@ def lang_detect(text:str, top:int=1, threshold:float=0.25) -> str: import fasttext from huggingface_hub import hf_hub_download model_path = hf_hub_download(repo_id, filename="model.bin", cache_dir=shared.opts.hfcache_dir) - shared.log.info(f'NudeNet load: model="{repo_id}"') + logger.log.info(f'NudeNet load: model="{repo_id}"') model = fasttext.load_model(model_path) text = text.replace('\n', '. ') lang, score = model.predict(text, k=top, threshold=threshold, on_unicode_error="ignore") result = [f'{l.replace("__label__", "").lower()}:{s:.2f}' for l, s in zip(lang, score) if s > threshold][:top] - shared.log.debug(f'NudeNet LangDetect: {result}') + logger.log.debug(f'NudeNet LangDetect: {result}') return result except Exception as e: - shared.log.error(f'NudeNet LangDetect: {e}') + logger.log.error(f'NudeNet LangDetect: {e}') return str(e) diff --git a/scripts/pixelsmith_ext.py b/scripts/pixelsmith_ext.py index 55d0b8d80..163906a5a 100644 --- a/scripts/pixelsmith_ext.py +++ b/scripts/pixelsmith_ext.py @@ -1,6 +1,7 @@ import gradio as gr from PIL import Image from modules import scripts_manager, processing, shared, sd_models, devices, images +from modules import logger class Script(scripts_manager.Script): @@ -37,14 +38,14 @@ class Script(scripts_manager.Script): with devices.inference_context(): latent = shared.sd_model.vae.tiled_encode(tensor) latent = shared.sd_model.vae.config.scaling_factor * latent.latent_dist.sample() - shared.log.info(f'PixelSmith encode: image={image} latent={latent.shape} width={p.width} height={p.height} vae={shared.sd_model.vae.__class__.__name__}') + logger.log.info(f'PixelSmith encode: image={image} latent={latent.shape} width={p.width} height={p.height} vae={shared.sd_model.vae.__class__.__name__}') return latent def run(self, p: processing.StableDiffusionProcessing, slider: int = 20): # pylint: disable=arguments-differ supported_model_list = ['sdxl'] if shared.sd_model_type not in supported_model_list: - shared.log.warning(f'PixelSmith: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_model_list}') + logger.log.warning(f'PixelSmith: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_model_list}') from scripts.pixelsmith import PixelSmithXLPipeline, PixelSmithVAE # pylint: disable=no-name-in-module self.orig_pipe = shared.sd_model self.orig_vae = shared.sd_model.vae @@ -60,7 +61,7 @@ class Script(scripts_manager.Script): if hasattr(p, 'init_images') and p.init_images is not None and len(p.init_images) > 0: p.task_args['image'] = self.encode(p, p.init_images[0]) p.init_images = None - shared.log.info(f'PixelSmith apply: slider={slider} class={shared.sd_model.__class__.__name__} vae={shared.sd_model.vae.__class__.__name__}') + logger.log.info(f'PixelSmith apply: slider={slider} class={shared.sd_model.__class__.__name__} vae={shared.sd_model.vae.__class__.__name__}') # processed = processing.process_images(p) def after(self, p: processing.StableDiffusionProcessing, processed: processing.Processed, slider): # pylint: disable=unused-argument diff --git a/scripts/postprocessing_upscale.py b/scripts/postprocessing_upscale.py index 3633c08a5..aecc67de2 100644 --- a/scripts/postprocessing_upscale.py +++ b/scripts/postprocessing_upscale.py @@ -3,6 +3,7 @@ import gradio as gr from modules import scripts_postprocessing, shared from modules.ui_components import ToolButton import modules.ui_symbols as symbols +from modules import logger class ScriptPostprocessingUpscale(scripts_postprocessing.ScriptPostprocessing): @@ -69,7 +70,7 @@ class ScriptPostprocessingUpscale(scripts_postprocessing.ScriptPostprocessing): upscaler1 = next(iter([x for x in shared.sd_upscalers if x.name == upscaler_1_name]), None) if not upscaler1: if upscaler_1_name is not None: - shared.log.warning(f"Could not find upscaler: {upscaler_1_name or ''}") + logger.log.warning(f"Could not find upscaler: {upscaler_1_name or ''}") return upscaled_image = self.upscale(pp.image, pp.info, upscaler1, upscale_mode, upscale_by, upscale_to_width, upscale_to_height, upscale_crop) pp.info["Postprocess upscaler"] = upscaler1.name @@ -78,7 +79,7 @@ class ScriptPostprocessingUpscale(scripts_postprocessing.ScriptPostprocessing): upscaler_2_name = None upscaler2 = next(iter([x for x in shared.sd_upscalers if x.name == upscaler_2_name and x.name != "None"]), None) if not upscaler2 and (upscaler_2_name is not None): - shared.log.warning(f"Could not find upscaler: {upscaler_2_name or ''}") + logger.log.warning(f"Could not find upscaler: {upscaler_2_name or ''}") if upscaler2 and upscaler_2_visibility > 0: second_upscale = self.upscale(pp.image, pp.info, upscaler2, upscale_mode, upscale_by, upscale_to_width, upscale_to_height, upscale_crop) upscaled_image = Image.blend(upscaled_image, second_upscale, upscaler_2_visibility) @@ -108,6 +109,6 @@ class ScriptPostprocessingUpscaleSimple(ScriptPostprocessingUpscale): return upscaler1 = next(iter([x for x in shared.sd_upscalers if x.name == upscaler_name]), None) if upscaler1 is None: - shared.log.debug(f"Upscaler not found: {upscaler_name}") + logger.log.debug(f"Upscaler not found: {upscaler_name}") pp.image = self.upscale(pp.image, pp.info, upscaler1, 0, upscale_by, 0, 0, False) pp.info["Postprocess upscaler"] = upscaler1.name diff --git a/scripts/prompt_enhance.py b/scripts/prompt_enhance.py index 245773e78..c387ed4bb 100644 --- a/scripts/prompt_enhance.py +++ b/scripts/prompt_enhance.py @@ -11,10 +11,11 @@ import gradio as gr from PIL import Image from modules import scripts_manager, shared, devices, errors, processing, sd_models, sd_modules, timer, ui_symbols from modules import ui_control_helpers +from modules import logger debug_enabled = os.environ.get('SD_LLM_DEBUG', None) is not None -debug_log = shared.log.trace if debug_enabled else lambda *args, **kwargs: None +debug_log = logger.log.trace if debug_enabled else lambda *args, **kwargs: None def b64(image): @@ -203,7 +204,7 @@ class Script(scripts_manager.Script): # Strip symbols from display name if present name = get_model_repo_from_display(name) if name else self.options.default if self.busy: - shared.log.debug('Prompt enhance: busy') + logger.log.debug('Prompt enhance: busy') return self.busy = True if self.model is not None and self.model == name: @@ -223,8 +224,8 @@ class Script(scripts_manager.Script): if model_type is not None and model_file is not None and len(model_type) > 2 and len(model_file) > 2: debug_log(f'Prompt enhance: gguf supported={self.options.supported}') if model_type not in self.options.supported: - shared.log.error(f'Prompt enhance: name="{name}" repo="{model_repo}" fn="{model_file}" type={model_type} gguf not supported') - shared.log.trace(f'Prompt enhance: gguf supported={self.options.supported}') + logger.log.error(f'Prompt enhance: name="{name}" repo="{model_repo}" fn="{model_file}" type={model_type} gguf not supported') + logger.log.trace(f'Prompt enhance: gguf supported={self.options.supported}') self.busy = False return ggml.install_gguf() @@ -237,7 +238,7 @@ class Script(scripts_manager.Script): t0 = time.time() if self.llm is not None: self.llm = None - shared.log.debug(f'Prompt enhance: name="{self.model}" unload') + logger.log.debug(f'Prompt enhance: name="{self.model}" unload') self.model = None load_args = { 'pretrained_model_name_or_path': model_repo if not gguf_args else model_gguf } if model_subfolder: @@ -281,10 +282,10 @@ class Script(scripts_manager.Script): debug_log(f'Prompt enhance: {m}') self.model = name t1 = time.time() - shared.log.info(f'Prompt enhance: cls={self.llm.__class__.__name__} name="{name}" repo="{model_repo}" fn="{model_file}" time={t1-t0:.2f} loaded') + logger.log.info(f'Prompt enhance: cls={self.llm.__class__.__name__} name="{name}" repo="{model_repo}" fn="{model_file}" time={t1-t0:.2f} loaded') self.compile() except Exception as e: - shared.log.error(f'Prompt enhance: load {e}') + logger.log.error(f'Prompt enhance: load {e}') errors.display(e, 'Prompt enhance') devices.torch_gc() self.busy = False @@ -296,15 +297,15 @@ class Script(scripts_manager.Script): def unload(self): if self.llm is not None: model_name = self.model - shared.log.debug(f'Prompt enhance: unloading model="{model_name}"') + logger.log.debug(f'Prompt enhance: unloading model="{model_name}"') sd_models.move_model(self.llm, devices.cpu, force=True) self.model = None self.llm = None self.tokenizer = None devices.torch_gc(force=True, reason='prompt enhance unload') - shared.log.debug(f'Prompt enhance: model="{model_name}" unloaded') + logger.log.debug(f'Prompt enhance: model="{model_name}" unloaded') else: - shared.log.debug('Prompt enhance: no model loaded') + logger.log.debug('Prompt enhance: no model loaded') def clean(self, response, keep_thinking=False, prefill_text='', keep_prefill=False): # Handle thinking tags FIRST (before generic tag removal) @@ -413,7 +414,7 @@ class Script(scripts_manager.Script): seed = int(random.randrange(4294967294)) torch.manual_seed(seed) if self.llm is None: - shared.log.error('Prompt enhance: model not loaded') + logger.log.error('Prompt enhance: model not loaded') return prompt prompt_text, networks = self.extract(prompt) # Use prompt_text after extraction debug_log(f'Prompt enhance: networks={networks}') @@ -440,7 +441,7 @@ class Script(scripts_manager.Script): # Check if vision was requested but no image is available if use_vision and is_vision_model(model) and current_image is None: - shared.log.error(f'Prompt enhance: model="{model}" error="No input image provided"') + logger.log.error(f'Prompt enhance: model="{model}" error="No input image provided"') return 'Error: No input image provided. Please upload or select an image.' # Resize large images to match VQA performance (Qwen3-VL performance is sensitive to resolution) @@ -466,7 +467,7 @@ class Script(scripts_manager.Script): if current_image is not None and isinstance(current_image, Image.Image): if (self.tokenizer is None) or (not self.tokenizer.is_processor): - shared.log.error('Prompt enhance: image not supported by model') + logger.log.error('Prompt enhance: image not supported by model') return prompt_text # Return original text part if image cannot be processed if prompt_text is not None and len(prompt_text) > 0: if not has_system: @@ -573,7 +574,7 @@ class Script(scripts_manager.Script): input_len = inputs['input_ids'].shape[1] debug_log(f'Prompt enhance: input_len={input_len} input_ids_shape={inputs["input_ids"].shape} sample={sample} temp={temperature} penalty={penalty} max_tokens={tokens}') except Exception as e: - shared.log.error(f'Prompt enhance tokenize: {e}') + logger.log.error(f'Prompt enhance tokenize: {e}') errors.display(e, 'Prompt enhance') self.busy = False return prompt_text # Return original text part on error @@ -605,7 +606,7 @@ class Script(scripts_manager.Script): debug_log(f'Prompt enhance: response_before_clean="{response_before_clean}"') except Exception as e: outputs = None - shared.log.error(f'Prompt enhance generate: {e}') + logger.log.error(f'Prompt enhance generate: {e}') errors.display(e, 'Prompt enhance') self.busy = False response = f'Error: {str(e)}' @@ -617,12 +618,12 @@ class Script(scripts_manager.Script): if not is_censored: response = self.clean(response, keep_thinking=keep_thinking, prefill_text=prefill_text, keep_prefill=keep_prefill) response = self.post(response, prefix, suffix, networks) - shared.log.info(f'Prompt enhance: model="{model}" nsfw={nsfw} time={t1-t0:.2f} seed={seed} sample={sample} temperature={temperature} penalty={penalty} thinking={thinking} keep_thinking={keep_thinking} prefill="{prefill_text[:20] if prefill_text else ""}" keep_prefill={keep_prefill} tokens={tokens} inputs={input_len} outputs={outputs.shape[-1] if isinstance(outputs, torch.Tensor) else 0} prompt={len(prompt_text)} response={len(response)}') + logger.log.info(f'Prompt enhance: model="{model}" nsfw={nsfw} time={t1-t0:.2f} seed={seed} sample={sample} temperature={temperature} penalty={penalty} thinking={thinking} keep_thinking={keep_thinking} prefill="{prefill_text[:20] if prefill_text else ""}" keep_prefill={keep_prefill} tokens={tokens} inputs={input_len} outputs={outputs.shape[-1] if isinstance(outputs, torch.Tensor) else 0} prompt={len(prompt_text)} response={len(response)}') debug_log(f'Prompt enhance: prompt="{prompt_text}"') debug_log(f'Prompt enhance: response_after_clean="{response}"') self.busy = False if is_censored: - shared.log.warning(f'Prompt enhance: censored response="{response}"') + logger.log.warning(f'Prompt enhance: censored response="{response}"') return prompt # Return original full prompt on censorship return response diff --git a/scripts/pulid/pulid_flux.py b/scripts/pulid/pulid_flux.py index a419ca9c0..6c1389633 100644 --- a/scripts/pulid/pulid_flux.py +++ b/scripts/pulid/pulid_flux.py @@ -2,11 +2,12 @@ from types import MethodType import accelerate from diffusers import FluxPipeline from modules import shared, sd_models +from modules import logger def apply_flux(pipe: FluxPipeline): if not hasattr(pipe, 'transformer') or not 'Nunchaku' in pipe.transformer.__class__.__name__: - shared.log.error('PuLID: flux support requires nunchaku') + logger.log.error('PuLID: flux support requires nunchaku') return pipe from nunchaku.pipeline.pipeline_flux_pulid import PuLIDFluxPipeline @@ -19,7 +20,7 @@ def apply_flux(pipe: FluxPipeline): pipe.transformer.forward = MethodType(pulid_forward, pipe.transformer) pipe = sd_models.apply_balanced_offload(pipe) pipe.pulid_model = sd_models.apply_balanced_offload(pipe.pulid_model) - shared.log.info(f'PuLID: flux applied cls={pipe.__class__.__name__} pipe={pipe.pulid_model.__class__.__name__}') + logger.log.info(f'PuLID: flux applied cls={pipe.__class__.__name__} pipe={pipe.pulid_model.__class__.__name__}') return pipe diff --git a/scripts/pulid_ext.py b/scripts/pulid_ext.py index 9fdb85e3d..87d42fb9a 100644 --- a/scripts/pulid_ext.py +++ b/scripts/pulid_ext.py @@ -5,6 +5,7 @@ import contextlib import gradio as gr from PIL import Image from modules import shared, devices, errors, scripts_manager, processing, processing_helpers, sd_models +from modules import logger debug = os.environ.get('SD_PULID_DEBUG', None) is not None @@ -79,7 +80,7 @@ class Script(scripts_manager.Script): raise ValueError(f'IP adapter unknown input: {file}') uploaded_images.append(image) except Exception as e: - shared.log.warning(f'IP adapter failed to load image: {e}') + logger.log.warning(f'IP adapter failed to load image: {e}') return gr.update(value=uploaded_images, visible=len(uploaded_images) > 0) # return signature is array of gradio components @@ -132,15 +133,15 @@ class Script(scripts_manager.Script): images = gallery images = [np.array(image) for image in images] except Exception as e: - shared.log.error(f'PuLID: failed to load images: {e}') + logger.log.error(f'PuLID: failed to load images: {e}') return None if len(images) == 0: - shared.log.error('PuLID: no images') + logger.log.error('PuLID: no images') return None supported_model_list = ['sdxl', 'f1'] if shared.sd_model_type not in supported_model_list: - shared.log.error(f'PuLID: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_model_list}') + logger.log.error(f'PuLID: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_model_list}') return None if self.pulid is None: self.dependencies() @@ -152,20 +153,20 @@ class Script(scripts_manager.Script): pipelines.auto_pipeline.AUTO_IMAGE2IMAGE_PIPELINES_MAPPING["pulid"] = pulid.StableDiffusionXLPuLIDPipelineImage pipelines.auto_pipeline.AUTO_INPAINT_PIPELINES_MAPPING["pulid"] = pulid.StableDiffusionXLPuLIDPipelineInpaint except Exception as e: - shared.log.error(f'PuLID: failed to import library: {e}') + logger.log.error(f'PuLID: failed to import library: {e}') return None if self.pulid is None: - shared.log.error('PuLID: failed to load PuLID library') + logger.log.error('PuLID: failed to load PuLID library') return None try: images = [self.pulid.resize(image, 1024) for image in images] except Exception as e: - shared.log.error(f'PuLID: failed to resize images: {e}') + logger.log.error(f'PuLID: failed to resize images: {e}') return None if p.batch_size > 1: - shared.log.warning('PuLID: batch size not supported') + logger.log.warning('PuLID: batch size not supported') p.batch_size = 1 sdp = shared.opts.cross_attention_optimization == "Scaled-Dot-Product" @@ -198,7 +199,7 @@ class Script(scripts_manager.Script): # shared.sd_model.hack_unet_attn_layers(shared.sd_model.pipe.unet) # reapply attention layers devices.torch_gc() except Exception as e: - shared.log.error(f'PuLID: failed to create pipeline: {e}') + logger.log.error(f'PuLID: failed to create pipeline: {e}') errors.display(e, 'PuLID') return None elif shared.sd_model_type == 'f1': @@ -209,7 +210,7 @@ class Script(scripts_manager.Script): elif shared.sd_model_type == 'f1': processed = self.run_flux(p, images, strength) else: - shared.log.error(f'PuLID: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_model_list}') + logger.log.error(f'PuLID: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_model_list}') processed = None return processed @@ -226,13 +227,13 @@ class Script(scripts_manager.Script): shared.sd_model.handler_ante = None shared.sd_model = shared.sd_model.pipe devices.torch_gc(force=True, reason='pulid') - shared.log.debug(f'PuLID complete: class={shared.sd_model.__class__.__name__} preprocess={self.preprocess:.2f} pipe={"restore" if restore else "cache"}') + logger.log.debug(f'PuLID complete: class={shared.sd_model.__class__.__name__} preprocess={self.preprocess:.2f} pipe={"restore" if restore else "cache"}') if shared.sd_model_type == "f1": restore = getattr(p, 'pulid_restore', restore) if restore: shared.sd_model = self.pulid.unapply_flux(shared.sd_model) devices.torch_gc(force=True, reason='pulid') - shared.log.debug(f'PuLID complete: class={shared.sd_model.__class__.__name__} pipe={"restore" if restore else "cache"}') + logger.log.debug(f'PuLID complete: class={shared.sd_model.__class__.__name__} pipe={"restore" if restore else "cache"}') return processed def run_sdxl(self, p: processing.StableDiffusionProcessing, images: list, strength: float, zero: int, sampler: str, ortho: str, restore: bool, offload: bool, version: str): @@ -240,7 +241,7 @@ class Script(scripts_manager.Script): if sampler_fn is None: sampler_fn = self.pulid.sampling.sample_dpmpp_2m_sde shared.sd_model.sampler = sampler_fn - shared.log.info(f'PuLID: class={shared.sd_model.__class__.__name__} version="{version}" strength={strength} zero={zero} ortho={ortho} sampler={sampler_fn} images={[i.shape for i in images]} offload={offload} restore={restore}') + logger.log.info(f'PuLID: class={shared.sd_model.__class__.__name__} version="{version}" strength={strength} zero={zero} ortho={ortho} sampler={sampler_fn} images={[i.shape for i in images]} offload={offload} restore={restore}') self.pulid.attention.NUM_ZERO = zero self.pulid.attention.ORTHO = ortho == 'v1' self.pulid.attention.ORTHO_v2 = ortho == 'v2' @@ -289,14 +290,14 @@ class Script(scripts_manager.Script): processed: processing.Processed = processing.process_images(p) # runs processing using main loop # interim = [Image.fromarray(img) for img in shared.sd_model.debug_img_list] - # shared.log.debug(f'PuLID: time={t1-t0:.2f}') + # logger.log.debug(f'PuLID: time={t1-t0:.2f}') return processed def run_flux(self, p: processing.StableDiffusionProcessing, images: list, strength: float): image = Image.fromarray(images[0]) # takes single pil image p.task_args['id_image'] = image p.task_args['id_weight'] = strength - shared.log.info(f'PuLID: class={shared.sd_model.__class__.__name__} strength={strength} image={image}') + logger.log.info(f'PuLID: class={shared.sd_model.__class__.__name__} strength={strength} image={image}') p.extra_generation_params["PuLID"] = f'Strength={strength}' processed: processing.Processed = processing.process_images(p) # runs processing using main loop diff --git a/scripts/regional_prompting.py b/scripts/regional_prompting.py index 9792693b7..24e417377 100644 --- a/scripts/regional_prompting.py +++ b/scripts/regional_prompting.py @@ -4,6 +4,7 @@ import gradio as gr from diffusers.pipelines import pipeline_utils from modules import shared, devices, scripts_manager, processing, sd_models, prompt_parser_diffusers +from modules import logger def hijack_register_modules(self, **kwargs): @@ -52,7 +53,7 @@ class Script(scripts_manager.Script): orig_prompt_attention = shared.opts.prompt_attention # create pipeline if shared.sd_model_type != 'sd': - shared.log.error(f'Regional prompting: incorrect base model: {shared.sd_model.__class__.__name__}') + logger.log.error(f'Regional prompting: incorrect base model: {shared.sd_model.__class__.__name__}') return None pipeline_utils.DiffusionPipeline.register_modules = hijack_register_modules @@ -60,7 +61,7 @@ class Script(scripts_manager.Script): shared.sd_model = sd_models.switch_pipe('regional_prompting_stable_diffusion', shared.sd_model) if shared.sd_model.__class__.__name__ != 'RegionalPromptingStableDiffusionPipeline': # switch failed - shared.log.error(f'Regional prompting: not a tiling pipeline: {shared.sd_model.__class__.__name__}') + logger.log.error(f'Regional prompting: not a tiling pipeline: {shared.sd_model.__class__.__name__}') shared.sd_model = orig_pipeline return None sd_models.set_diffuser_options(shared.sd_model) @@ -81,7 +82,7 @@ class Script(scripts_manager.Script): 'rp_args': rp_args, } # run pipeline - shared.log.debug(f'Regional: args={p.task_args}') + logger.log.debug(f'Regional: args={p.task_args}') p.task_args['prompt'] = p.prompt processed: processing.Processed = processing.process_images(p) # runs processing using main loop diff --git a/scripts/resadapter.py b/scripts/resadapter.py index c55ee5387..9ce82319c 100644 --- a/scripts/resadapter.py +++ b/scripts/resadapter.py @@ -2,6 +2,7 @@ from safetensors.torch import load_file from huggingface_hub import hf_hub_download import gradio as gr from modules import scripts_manager, processing, shared, sd_models, devices +from modules import logger repo = 'jiaxiangc/res-adapter' @@ -38,11 +39,11 @@ class Script(scripts_manager.Script): return None if shared.sd_model_type == 'sd': if not model.startswith('SD15'): - shared.log.warning(f'ResAdapter: pipeline={shared.sd_model_type} selected={model}') + logger.log.warning(f'ResAdapter: pipeline={shared.sd_model_type} selected={model}') return None if shared.sd_model_type == 'sdxl': if not model.startswith('SDXL'): - shared.log.warning(f'ResAdapter: pipeline={shared.sd_model_type} selected={model}') + logger.log.warning(f'ResAdapter: pipeline={shared.sd_model_type} selected={model}') return None old_pipe = shared.sd_model @@ -51,7 +52,7 @@ class Script(scripts_manager.Script): shared.sd_model.unet.load_state_dict(load_file(hf_hub_download(repo_id=repo, subfolder=models[model], filename="diffusion_pytorch_model.safetensors")), strict=False) sd_models.move_model(shared.sd_model, devices.device) # move pipeline to device sd_models.set_diffuser_options(shared.sd_model, vae=None, op='model') - shared.log.debug(f'ResAdapter: pipeline={shared.sd_model.__class__.__name__} model="{model}" weight={weight} file="{models[model]}"') + logger.log.debug(f'ResAdapter: pipeline={shared.sd_model.__class__.__name__} model="{model}" weight={weight} file="{models[model]}"') processed = processing.process_images(p) shared.sd_model = old_pipe return processed diff --git a/scripts/skip_layer_guidance.py b/scripts/skip_layer_guidance.py index c8b72cd03..0de332b85 100644 --- a/scripts/skip_layer_guidance.py +++ b/scripts/skip_layer_guidance.py @@ -1,6 +1,7 @@ import sys import gradio as gr from modules import scripts_manager, processing, shared +from modules import logger registered = False @@ -41,7 +42,7 @@ class Script(scripts_manager.Script): except Exception: return if len(val) > 0: - shared.log.debug(f'SLG: {field}={val}') + logger.log.debug(f'SLG: {field}={val}') p.task_args[field] = val return fun @@ -70,4 +71,4 @@ class Script(scripts_manager.Script): if len(parsed) == 0: return p.task_args['skip_guidance_layers'] = parsed - shared.log.info(f'SLG: layers={parsed} scale={scale} start={start} stop={stop}') + logger.log.info(f'SLG: layers={parsed} scale={scale} start={start} stop={stop}') diff --git a/scripts/softfill.py b/scripts/softfill.py index e4c84db31..2ac22f8ac 100644 --- a/scripts/softfill.py +++ b/scripts/softfill.py @@ -1605,6 +1605,7 @@ class StableDiffusionXLSoftFillPipeline( import gradio as gr from installer import install from modules import shared, scripts_manager, processing, sd_models +from modules import logger class Script(scripts_manager.Script): @@ -1630,13 +1631,13 @@ class Script(scripts_manager.Script): if not enabled: return if shared.sd_model_type not in ['sdxl']: - shared.log.error(f'SoftFill: incorrect base model: {shared.sd_model.__class__.__name__}') + logger.log.error(f'SoftFill: incorrect base model: {shared.sd_model.__class__.__name__}') return if not hasattr(p, 'init_images') or len(p.init_images) == 0: - shared.log.error('SoftFill: no input image') + logger.log.error('SoftFill: no input image') return if not hasattr(p, 'mask') or p.mask is None: - shared.log.error('SoftFill: no input mask') + logger.log.error('SoftFill: no input mask') return try: @@ -1645,7 +1646,7 @@ class Script(scripts_manager.Script): import noise as noise_module pnoise2 = noise_module.pnoise2 except Exception as e: - shared.log.error(f'SoftFill: {e}') + logger.log.error(f'SoftFill: {e}') return self.orig_pipeline = shared.sd_model @@ -1654,7 +1655,7 @@ class Script(scripts_manager.Script): if shared.sd_model.__class__.__name__ not in sd_models.pipe_switch_task_exclude: sd_models.pipe_switch_task_exclude.append(shared.sd_model.__class__.__name__) except Exception as e: - shared.log.error(f'SoftFill: {e}') + logger.log.error(f'SoftFill: {e}') shared.sd_model = self.orig_pipeline self.orig_pipeline = None return @@ -1663,7 +1664,7 @@ class Script(scripts_manager.Script): p.task_args['strength'] = strength p.task_args['image'] = p.init_images[0] p.task_args['mask'] = p.mask - shared.log.info(f'SoftFill: cls={shared.sd_model.__class__.__name__} {p.task_args}') + logger.log.info(f'SoftFill: cls={shared.sd_model.__class__.__name__} {p.task_args}') def after(self, p: processing.StableDiffusionProcessingImg2Img, *args, **kwargs): # pylint: disable=unused-argument if self.orig_pipeline is not None: diff --git a/scripts/stablevideodiffusion.py b/scripts/stablevideodiffusion.py index 0e2d25ab7..82237e732 100644 --- a/scripts/stablevideodiffusion.py +++ b/scripts/stablevideodiffusion.py @@ -6,6 +6,7 @@ import os import torch import gradio as gr from modules import scripts_manager, processing, shared, sd_models, images, modelloader +from modules import logger models = { @@ -44,7 +45,7 @@ class Script(scripts_manager.Script): def _encode_image(self, image: torch.Tensor, device, num_videos_per_prompt, do_classifier_free_guidance): image = image.to(device=device, dtype=shared.sd_model.vae.dtype) - shared.log.debug(f'Video encode: type=svd input={image.shape} dtype={image.dtype} device={image.device}') + logger.log.debug(f'Video encode: type=svd input={image.shape} dtype={image.dtype} device={image.device}') image_latents = shared.sd_model.vae.encode(image).latent_dist.mode() image_latents = image_latents.repeat(num_videos_per_prompt, 1, 1, 1) if do_classifier_free_guidance: @@ -53,7 +54,7 @@ class Script(scripts_manager.Script): return image_latents def _decode_latents(self, latents: torch.Tensor, num_frames: int, decode_chunk_size: int = 14): - shared.log.debug(f'Video decode: type=svd input={latents.shape} dtype={latents.dtype} device={latents.device} chunk={decode_chunk_size} frames={num_frames}') + logger.log.debug(f'Video decode: type=svd input={latents.shape} dtype={latents.dtype} device={latents.device} chunk={decode_chunk_size} frames={num_frames}') latents = latents.flatten(0, 1) latents = 1 / shared.sd_model.vae.config.scaling_factor * latents frames = [] @@ -70,7 +71,7 @@ class Script(scripts_manager.Script): def run(self, p: processing.StableDiffusionProcessing, model, num_frames, override_resolution, min_guidance_scale, max_guidance_scale, decode_chunk_size, motion_bucket_id, noise_aug_strength, video_type, duration, gif_loop, mp4_pad, mp4_interpolate): # pylint: disable=arguments-differ, unused-argument image = getattr(p, 'init_images', None) if image is None or len(image) == 0: - shared.log.error('SVD: no init_images') + logger.log.error('SVD: no init_images') return None else: image = image[0] @@ -80,7 +81,7 @@ class Script(scripts_manager.Script): model_name = os.path.basename(model_path) has_checkpoint = sd_models.get_closest_checkpoint_match(model_path) if has_checkpoint is None: - shared.log.error(f'SVD: no checkpoint for {model_name}') + logger.log.error(f'SVD: no checkpoint for {model_name}') modelloader.load_reference(model_path, variant='fp16') c = shared.sd_model.__class__.__name__ model_loaded = shared.sd_model.sd_checkpoint_info.model_name if shared.sd_loaded else None @@ -115,7 +116,7 @@ class Script(scripts_manager.Script): p.task_args['num_inference_steps'] = p.steps p.task_args['min_guidance_scale'] = min_guidance_scale p.task_args['max_guidance_scale'] = max_guidance_scale - shared.log.debug(f'SVD: args={p.task_args}') + logger.log.debug(f'SVD: args={p.task_args}') # run processing processed = processing.process_images(p) diff --git a/scripts/style_aligned_ext.py b/scripts/style_aligned_ext.py index 021cc94f0..b45780bde 100644 --- a/scripts/style_aligned_ext.py +++ b/scripts/style_aligned_ext.py @@ -3,6 +3,7 @@ import torch import numpy as np import diffusers from modules import scripts_manager, processing, shared, devices +from modules import logger handler = None @@ -22,7 +23,7 @@ class Script(scripts_manager.Script): global handler, zts # pylint: disable=global-statement handler = None zts = None - shared.log.info('SA: image upload') + logger.log.info('SA: image upload') def preset(self, preset): if preset == 'text': @@ -61,7 +62,7 @@ class Script(scripts_manager.Script): def run(self, p: processing.StableDiffusionProcessing, image, prompt, scheduler, shared_opts, shared_score_scale, shared_score_shift, only_self_level): # pylint: disable=arguments-differ global handler, zts, orig_prompt_attention # pylint: disable=global-statement if shared.sd_model_type not in supported_model_list: - shared.log.warning(f'SA: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_model_list}') + logger.log.warning(f'SA: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_model_list}') return None from scripts.style_aligned import sa_handler, inversion # pylint: disable=no-name-in-module @@ -86,7 +87,7 @@ class Script(scripts_manager.Script): p.sampler_name = 'None' if image is not None and zts is None: - shared.log.info(f'SA: inversion image={image} prompt="{prompt}"') + logger.log.info(f'SA: inversion image={image} prompt="{prompt}"') image = image.resize((1024, 1024)) x0 = np.array(image).astype(np.float32) / 255.0 shared.sd_model.scheduler = diffusers.DDIMScheduler(beta_start=0.00085, beta_end=0.012, beta_schedule="scaled_linear", clip_sample=False, set_alpha_to_one=False) @@ -107,7 +108,7 @@ class Script(scripts_manager.Script): p.task_args['latents'] = latents p.task_args['callback_on_step_end'] = inversion_callback - shared.log.info(f'SA: batch={p.batch_size} type={"image" if zts is not None else "text"} config={sa_args.__dict__}') + logger.log.info(f'SA: batch={p.batch_size} type={"image" if zts is not None else "text"} config={sa_args.__dict__}') return None def after(self, p: processing.StableDiffusionProcessing, *args): # pylint: disable=unused-argument diff --git a/scripts/t_gate.py b/scripts/t_gate.py index 7f2999959..9bae96658 100644 --- a/scripts/t_gate.py +++ b/scripts/t_gate.py @@ -1,5 +1,6 @@ import gradio as gr from modules import scripts_manager, processing, shared, sd_models, devices +from modules import logger from installer import install @@ -31,14 +32,14 @@ class Script(scripts_manager.Script): elif shared.sd_model_type == 'sdxl': cls = tgate.TgateSDXLLoader else: - shared.log.warning(f'T-Gate: pipeline={shared.sd_model_type} required=sd or sdxl') + logger.log.warning(f'T-Gate: pipeline={shared.sd_model_type} required=sd or sdxl') return None old_pipe = shared.sd_model shared.sd_model = cls(shared.sd_model, gate_step=p.gate_step) sd_models.copy_diffuser_options(shared.sd_model, old_pipe) sd_models.move_model(shared.sd_model, devices.device) # move pipeline to device sd_models.set_diffuser_options(shared.sd_model, vae=None, op='model') - shared.log.debug(f'T-Gate: pipeline={shared.sd_model.__class__.__name__} steps={p.gate_step}') + logger.log.debug(f'T-Gate: pipeline={shared.sd_model.__class__.__name__} steps={p.gate_step}') processed = processing.process_images(p) shared.sd_model = old_pipe del shared.sd_model.tgate diff --git a/scripts/text2video.py b/scripts/text2video.py index f6880b10f..9650a22cd 100644 --- a/scripts/text2video.py +++ b/scripts/text2video.py @@ -8,6 +8,7 @@ TODO text2video items: import gradio as gr from modules import scripts_manager, processing, shared, images, sd_models, modelloader +from modules import logger MODELS = [ @@ -57,20 +58,20 @@ class Script(scripts_manager.Script): if model_name == 'None': return None model = [m for m in MODELS if m['name'] == model_name][0] - shared.log.debug(f'Text2Video: model={model} defaults={use_default} frames={num_frames}, video={video_type} duration={duration} loop={gif_loop} pad={mp4_pad} interpolate={mp4_interpolate}') + logger.log.debug(f'Text2Video: model={model} defaults={use_default} frames={num_frames}, video={video_type} duration={duration} loop={gif_loop} pad={mp4_pad} interpolate={mp4_interpolate}') if model['path'] in shared.opts.sd_model_checkpoint: - shared.log.debug(f'Text2Video cached: model={shared.opts.sd_model_checkpoint}') + logger.log.debug(f'Text2Video cached: model={shared.opts.sd_model_checkpoint}') else: checkpoint = sd_models.get_closest_checkpoint_match(model['path']) if checkpoint is None: - shared.log.debug(f'Text2Video downloading: model={model["path"]}') + logger.log.debug(f'Text2Video downloading: model={model["path"]}') checkpoint = modelloader.download_diffusers_model(hub_id=model['path']) sd_models.list_models() if checkpoint is None: - shared.log.error(f'Text2Video: failed to find model={model["path"]}') + logger.log.error(f'Text2Video: failed to find model={model["path"]}') return None - shared.log.debug(f'Text2Video loading: model={checkpoint}') + logger.log.debug(f'Text2Video loading: model={checkpoint}') shared.opts.sd_model_checkpoint = checkpoint.name sd_models.reload_model_weights(op='model') @@ -83,11 +84,11 @@ class Script(scripts_manager.Script): elif num_frames > 0: p.task_args['num_frames'] = num_frames else: - shared.log.error('Text2Video: invalid number of frames') + logger.log.error('Text2Video: invalid number of frames') return None shared.sd_model = sd_models.set_diffuser_pipe(shared.sd_model, sd_models.DiffusersTaskType.TEXT_2_IMAGE) - shared.log.debug(f'Text2Video: args={p.task_args}') + logger.log.debug(f'Text2Video: args={p.task_args}') processed = processing.process_images(p) if video_type != 'None': diff --git a/scripts/tiling.py b/scripts/tiling.py index 2cb37ee07..5210f8f2a 100644 --- a/scripts/tiling.py +++ b/scripts/tiling.py @@ -7,6 +7,7 @@ from torch import Tensor from torch.nn import functional as F from torch.nn.modules.utils import _pair from modules import scripts_manager, processing, shared +from modules import logger modex = 'constant' @@ -49,7 +50,7 @@ class Script(scripts_manager.Script): global modex, modey # pylint: disable=global-statement supported_model_list = ['sd', 'sdxl'] if shared.sd_model_type not in supported_model_list: - shared.log.warning(f'Tiling: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_model_list}') + logger.log.warning(f'Tiling: class={shared.sd_model.__class__.__name__} model={shared.sd_model_type} required={supported_model_list}') return None if not tilex and not tiley: return None @@ -70,7 +71,7 @@ class Script(scripts_manager.Script): if hasattr(cl, '_conv_forward'): cl._orig_conv_forward = cl._conv_forward # pylint: disable=protected-access cl._conv_forward = asymmetricConv2DConvForward.__get__(cl, torch.nn.Conv2d) # pylint: disable=protected-access, no-value-for-parameter - shared.log.info(f'Tiling: x={tilex}:{numx} y={tiley}:{numy}') + logger.log.info(f'Tiling: x={tilex}:{numx} y={tiley}:{numy}') return None def after(self, p: processing.StableDiffusionProcessing, processed: processing.Processed, tilex:bool=False, numx:int=1, tiley:bool=False, numy:int=1): # pylint: disable=arguments-differ, unused-argument diff --git a/scripts/xadapter_ext.py b/scripts/xadapter_ext.py index 0f244babd..4c5abff60 100644 --- a/scripts/xadapter_ext.py +++ b/scripts/xadapter_ext.py @@ -5,6 +5,7 @@ import diffusers import gradio as gr import huggingface_hub as hf from modules import errors, shared, devices, scripts_manager, processing, sd_models, sd_samplers +from modules import logger adapter = None @@ -46,11 +47,11 @@ class Script(scripts_manager.Script): else: shared.opts.sd_model_refiner = model if shared.sd_model_type != 'sdxl': - shared.log.error(f'X-Adapter: incorrect base model: {shared.sd_model.__class__.__name__}') + logger.log.error(f'X-Adapter: incorrect base model: {shared.sd_model.__class__.__name__}') return if adapter is None: - shared.log.debug('X-Adapter: adapter loading') + logger.log.debug('X-Adapter: adapter loading') adapter = Adapter_XL() adapter_path = hf.hf_hub_download(repo_id='Lingmin-Ran/X-Adapter', filename='X_Adapter_v1.bin') adapter_dict = torch.load(adapter_path) @@ -61,7 +62,7 @@ class Script(scripts_manager.Script): except Exception: pass if adapter is None: - shared.log.error('X-Adapter: adapter loading failed') + logger.log.error('X-Adapter: adapter loading failed') return sd_models.unload_model_weights(op='model') @@ -75,7 +76,7 @@ class Script(scripts_manager.Script): diffusers.models.UNet2DConditionModel = orig_unetcondmodel # unpatch diffusers if shared.sd_refiner_type != 'sd': - shared.log.error(f'X-Adapter: incorrect adapter model: {shared.sd_model.__class__.__name__}') + logger.log.error(f'X-Adapter: incorrect adapter model: {shared.sd_model.__class__.__name__}') return # backup pipeline and params @@ -84,7 +85,7 @@ class Script(scripts_manager.Script): pipe = None try: - shared.log.debug('X-Adapter: creating pipeline') + logger.log.debug('X-Adapter: creating pipeline') pipe = StableDiffusionXLAdapterPipeline( vae=shared.sd_model.vae, text_encoder=shared.sd_model.text_encoder, @@ -125,10 +126,10 @@ class Script(scripts_manager.Script): pipe.scheduler = diffusers.DPMSolverMultistepScheduler.from_config(pipe.scheduler.config) pipe.scheduler_sd1_5 = diffusers.DPMSolverMultistepScheduler.from_config(pipe.scheduler_sd1_5.config) pipe.scheduler_sd1_5.config.timestep_spacing = "leading" - shared.log.debug(f'X-Adapter: pipeline={pipe.__class__.__name__} args={p.task_args}') + logger.log.debug(f'X-Adapter: pipeline={pipe.__class__.__name__} args={p.task_args}') shared.sd_model = pipe except Exception as e: - shared.log.error(f'X-Adapter: pipeline creation failed: {e}') + logger.log.error(f'X-Adapter: pipeline creation failed: {e}') errors.display(e, 'X-Adapter: pipeline creation failed') shared.sd_model = orig_pipeline diff --git a/scripts/xyz/xyz_grid_draw.py b/scripts/xyz/xyz_grid_draw.py index 2338d089d..974680b5a 100644 --- a/scripts/xyz/xyz_grid_draw.py +++ b/scripts/xyz/xyz_grid_draw.py @@ -2,6 +2,7 @@ import time from copy import copy from PIL import Image from modules import shared, images, processing +from modules import logger from modules.image.util import draw_text @@ -18,7 +19,7 @@ def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend def process_cell(x, y, z, ix, iy, iz): nonlocal processed_result, i i += 1 - shared.log.debug(f'XYZ grid process: x={ix+1}/{len(xs)} y={iy+1}/{len(ys)} z={iz+1}/{len(zs)} total={i/list_size:.2f}') + logger.log.debug(f'XYZ grid process: x={ix+1}/{len(xs)} y={iy+1}/{len(ys)} z={iz+1}/{len(zs)} total={i/list_size:.2f}') def index(ix, iy, iz): return ix + iy * len(xs) + iz * len(xs) * len(ys) @@ -29,7 +30,7 @@ def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend if processed_result is None: processed_result = copy(processed) if processed_result is None: - shared.log.error('XYZ grid: no processing results') + logger.log.error('XYZ grid: no processing results') return processing.Processed(p, []) processed_result.images = [None] * list_size processed_result.all_prompts = [None] * list_size @@ -97,10 +98,10 @@ def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend process_cell(x, y, z, ix, iy, iz) if not processed_result: - shared.log.error("XYZ grid: failed to initialize processing") + logger.log.error("XYZ grid: failed to initialize processing") return processing.Processed(p, []) elif not any(processed_result.images): - shared.log.error("XYZ grid: failed to return processed image") + logger.log.error("XYZ grid: failed to return processed image") return processing.Processed(p, []) t1 = time.time() @@ -111,7 +112,7 @@ def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend to_process = processed_result.images[idx0:idx1] w, h = max(i.width for i in to_process if i is not None), max(i.height for i in to_process if i is not None) if w is None or h is None or w == 0 or h == 0: - shared.log.error("XYZ grid: failed get valid image") + logger.log.error("XYZ grid: failed get valid image") continue if (not no_grid or include_sub_grids) and images.check_grid_size(to_process): grid = images.image_grid(to_process, rows=len(ys)) @@ -129,6 +130,6 @@ def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend processed_result.infotexts.insert(0, processed_result.infotexts[0]) t2 = time.time() - shared.log.info(f'XYZ grid complete: images={list_size} results={len(processed_result.images)} size={grid.size if grid is not None else None} time={t1-t0:.2f} save={t2-t1:.2f}') + logger.log.info(f'XYZ grid complete: images={list_size} results={len(processed_result.images)} size={grid.size if grid is not None else None} time={t1-t0:.2f} save={t2-t1:.2f}') p.skip_processing = True return processed_result diff --git a/scripts/xyz/xyz_grid_shared.py b/scripts/xyz/xyz_grid_shared.py index d11c8bee4..61df59fff 100644 --- a/scripts/xyz/xyz_grid_shared.py +++ b/scripts/xyz/xyz_grid_shared.py @@ -3,6 +3,7 @@ import os import re from modules import shared, processing, sd_samplers, sd_models, sd_vae, sd_unet +from modules import logger re_range = re.compile(r'([-+]?[0-9]*\.?[0-9]+)-([-+]?[0-9]*\.?[0-9]+):?([0-9]+)?') @@ -15,14 +16,14 @@ def restore_comma(val: str): def apply_field(field): def fun(p, x, xs): - shared.log.debug(f'XYZ grid apply field: {field}={x}') + logger.log.debug(f'XYZ grid apply field: {field}={x}') setattr(p, field, x) return fun def apply_task_arg(field): def fun(p, x, xs): - shared.log.debug(f'XYZ grid apply task-arg: {field}={x}') + logger.log.debug(f'XYZ grid apply task-arg: {field}={x}') p.task_args[field] = x return fun @@ -34,7 +35,7 @@ def apply_task_args(p, x, xs): if v.replace('.','',1).isdigit(): v = float(v) if '.' in v else int(v) p.task_args[k] = v - shared.log.debug(f'XYZ grid apply task-arg: {k}={type(v)}:{v}') + logger.log.debug(f'XYZ grid apply task-arg: {k}={type(v)}:{v}') def apply_processing(p, x, xs): @@ -45,7 +46,7 @@ def apply_processing(p, x, xs): v = float(v) if '.' in v else int(v) found = 'existing' if hasattr(p, k) else 'new' setattr(p, k, v) - shared.log.debug(f'XYZ grid apply processing-arg: type={found} {k}={type(v)}:{v} ') + logger.log.debug(f'XYZ grid apply processing-arg: type={found} {k}={type(v)}:{v} ') def apply_options(p, x, xs): @@ -56,7 +57,7 @@ def apply_options(p, x, xs): v = float(v) if '.' in v else int(v) found = 'existing' if v in shared.opts.data else 'new' shared.opts.data[k] = v - shared.log.debug(f'XYZ grid apply options: type={found} {k}={type(v)}:{v} ') + logger.log.debug(f'XYZ grid apply options: type={found} {k}={type(v)}:{v} ') def apply_setting(field): @@ -67,7 +68,7 @@ def apply_setting(field): x = x.lower() in ['true', 't', 'yes', 'y'] if isinstance(x, int) or isinstance(x, float): x = x > 0 - shared.log.debug(f'XYZ grid apply setting: {field}={t}:{x}') + logger.log.debug(f'XYZ grid apply setting: {field}={t}:{x}') shared.opts.data[field] = x return fun @@ -75,12 +76,12 @@ def apply_setting(field): def apply_seed(p, x, xs): p.seed = x p.all_seeds = None - shared.log.debug(f'XYZ grid apply seed: {x}') + logger.log.debug(f'XYZ grid apply seed: {x}') def apply_prompt(positive, negative, p, x, xs): for s in xs: - shared.log.debug(f'XYZ grid apply prompt: fields={positive}/{negative} "{s}"="{x}"') + logger.log.debug(f'XYZ grid apply prompt: fields={positive}/{negative} "{s}"="{x}"') orig_positive = getattr(p, positive) orig_negative = getattr(p, negative) if s in orig_positive: @@ -129,39 +130,39 @@ def apply_order(p, x, xs): def apply_sampler(p, x, xs): sampler_name = sd_samplers.samplers_map.get(x.lower(), None) if sampler_name is None: - shared.log.warning(f"XYZ grid: unknown sampler: {x}") + logger.log.warning(f"XYZ grid: unknown sampler: {x}") else: p.sampler_name = sampler_name - shared.log.debug(f'XYZ grid apply sampler: "{x}"') + logger.log.debug(f'XYZ grid apply sampler: "{x}"') def apply_hr_sampler_name(p, x, xs): hr_sampler_name = sd_samplers.samplers_map.get(x.lower(), None) if hr_sampler_name is None: - shared.log.warning(f"XYZ grid: unknown sampler: {x}") + logger.log.warning(f"XYZ grid: unknown sampler: {x}") else: p.hr_sampler_name = hr_sampler_name - shared.log.debug(f'XYZ grid apply HR sampler: "{x}"') + logger.log.debug(f'XYZ grid apply HR sampler: "{x}"') def confirm_samplers(p, xs): for x in xs: if x.lower() not in sd_samplers.samplers_map: - shared.log.warning(f"XYZ grid: unknown sampler: {x}") + logger.log.warning(f"XYZ grid: unknown sampler: {x}") def apply_sdnq_quant(p, x, xs): shared.opts.sdnq_quantize_weights_mode = x sd_models.unload_model_weights(op='model') sd_models.reload_model_weights() - shared.log.debug(f'XYZ grid apply sdnq quant: mode="{x}"') + logger.log.debug(f'XYZ grid apply sdnq quant: mode="{x}"') def apply_sdnq_quant_te(p, x, xs): shared.opts.sdnq_quantize_weights_mode_te = x sd_models.unload_model_weights(op='model') sd_models.reload_model_weights() - shared.log.debug(f'XYZ grid apply sdnq quant te: mode="{x}"') + logger.log.debug(f'XYZ grid apply sdnq quant te: mode="{x}"') def apply_checkpoint(p, x, xs): @@ -169,11 +170,11 @@ def apply_checkpoint(p, x, xs): return info = sd_models.get_closest_checkpoint_match(x) if info is None: - shared.log.warning(f"XYZ grid: apply checkpoint unknown checkpoint: {x}") + logger.log.warning(f"XYZ grid: apply checkpoint unknown checkpoint: {x}") else: sd_models.reload_model_weights(shared.sd_model, info) p.override_settings['sd_model_checkpoint'] = info.name - shared.log.debug(f'XYZ grid apply checkpoint: "{x}"') + logger.log.debug(f'XYZ grid apply checkpoint: "{x}"') def apply_refiner(p, x, xs): @@ -183,11 +184,11 @@ def apply_refiner(p, x, xs): return info = sd_models.get_closest_checkpoint_match(x) if info is None: - shared.log.warning(f"XYZ grid: apply refiner unknown checkpoint: {x}") + logger.log.warning(f"XYZ grid: apply refiner unknown checkpoint: {x}") else: sd_models.reload_model_weights(shared.sd_refiner, info) p.override_settings['sd_model_refiner'] = info.name - shared.log.debug(f'XYZ grid apply refiner: "{x}"') + logger.log.debug(f'XYZ grid apply refiner: "{x}"') def apply_unet(p, x, xs): @@ -198,12 +199,12 @@ def apply_unet(p, x, xs): p.override_settings['sd_unet'] = x shared.opts.data['sd_unet'] = x sd_unet.load_unet(shared.sd_model) - shared.log.debug(f'XYZ grid apply unet: "{x}"') + logger.log.debug(f'XYZ grid apply unet: "{x}"') def apply_clip_skip(p, x, xs): p.clip_skip = x - shared.log.debug(f'XYZ grid apply clip-skip: "{x}"') + logger.log.debug(f'XYZ grid apply clip-skip: "{x}"') def find_vae(name: str): @@ -214,7 +215,7 @@ def find_vae(name: str): else: choices = [x for x in sorted(sd_vae.vae_dict, key=lambda x: len(x)) if name.lower().strip() in x.lower()] if len(choices) == 0: - shared.log.warning(f"No VAE found for {name}; using automatic") + logger.log.warning(f"No VAE found for {name}; using automatic") return sd_vae.unspecified else: return sd_vae.vae_dict[choices[0]] @@ -222,7 +223,7 @@ def find_vae(name: str): def apply_vae(p, x, xs): sd_vae.reload_vae_weights(shared.sd_model, vae_file=find_vae(x)) - shared.log.debug(f'XYZ grid apply VAE: "{x}"') + logger.log.debug(f'XYZ grid apply VAE: "{x}"') def list_lora(): @@ -239,11 +240,11 @@ def apply_lora(p, x, xs): return x = os.path.basename(x) p.prompt = p.prompt + f" " - shared.log.debug(f'XYZ grid apply LoRA: "{x}"') + logger.log.debug(f'XYZ grid apply LoRA: "{x}"') def apply_lora_strength(p, x, xs): - shared.log.debug(f'XYZ grid apply LoRA strength: "{x}"') + logger.log.debug(f'XYZ grid apply LoRA strength: "{x}"') p.prompt = p.prompt.replace(':1.0>', '>') p.prompt = p.prompt.replace(f':{shared.opts.extra_networks_default_multiplier}>', '>') p.all_prompts = None @@ -254,19 +255,19 @@ def apply_lora_strength(p, x, xs): def apply_te(p, x, xs): shared.opts.data["sd_text_encoder"] = x sd_models.reload_text_encoder() - shared.log.debug(f'XYZ grid apply text-encoder: "{x}"') + logger.log.debug(f'XYZ grid apply text-encoder: "{x}"') def apply_guidance(p, x, xs): from modules.modular_guiders import guiders guiders = list(guiders.keys()) p.guidance_name = [g for g in guiders if g.lower().startswith(x.lower())][0] - shared.log.debug(f'XYZ grid apply guidance: "{p.guidance_name}"') + logger.log.debug(f'XYZ grid apply guidance: "{p.guidance_name}"') def apply_styles(p: processing.StableDiffusionProcessingTxt2Img, x: str, _): p.styles.extend(x.split(',')) - shared.log.debug(f'XYZ grid apply style: "{x}"') + logger.log.debug(f'XYZ grid apply style: "{x}"') def apply_upscaler(p: processing.StableDiffusionProcessingTxt2Img, opt, x): @@ -274,25 +275,25 @@ def apply_upscaler(p: processing.StableDiffusionProcessingTxt2Img, opt, x): p.hr_force = True p.denoising_strength = 0.0 p.hr_upscaler = opt - shared.log.debug(f'XYZ grid apply upscaler: "{x}"') + logger.log.debug(f'XYZ grid apply upscaler: "{x}"') def apply_context(p: processing.StableDiffusionProcessingTxt2Img, opt, x): p.resize_mode = 5 p.resize_context = opt - shared.log.debug(f'XYZ grid apply resize-context: "{x}"') + logger.log.debug(f'XYZ grid apply resize-context: "{x}"') def apply_detailer(p, opt, x): p.detailer_enabled = bool(opt) - shared.log.debug(f'XYZ grid apply detailer: "{x}"') + logger.log.debug(f'XYZ grid apply detailer: "{x}"') def apply_control(field): def fun(p, x, xs): init_images = getattr(p, 'orig_init_images', None) or getattr(p, 'init_images', None) or getattr(p, 'orig_init_images', None) or [] if init_images is None or len(init_images) == 0: - shared.log.error('XYZ grid apply control: init image is required') + logger.log.error('XYZ grid apply control: init image is required') return if field in ['controlnet', 't2i adapter', 'processor']: from modules.control import run, processor @@ -320,7 +321,7 @@ def apply_control(field): end = getattr(end, 'value', end), strength = getattr(strength, 'value', strength), ) - shared.log.debug(f'XYZ grid apply control: {field}="{x}" unit={unit}') + logger.log.debug(f'XYZ grid apply control: {field}="{x}" unit={unit}') if len(run.unit.current) > 0: if hasattr(run.unit.current[0], 'reset'): run.unit.current[0].reset() @@ -335,13 +336,13 @@ def apply_control(field): if pipe is not None: shared.sd_model = pipe elif field == 'control_start': - shared.log.debug(f'XYZ grid apply control: {field}={x}') + logger.log.debug(f'XYZ grid apply control: {field}={x}') p.task_args['control_guidance_start'] = float(x) elif field == 'control_end': - shared.log.debug(f'XYZ grid apply control: {field}={x}') + logger.log.debug(f'XYZ grid apply control: {field}={x}') p.task_args['control_guidance_end'] = float(x) elif field == 'control_strength': - shared.log.debug(f'XYZ grid apply control: {field}={x}') + logger.log.debug(f'XYZ grid apply control: {field}={x}') p.task_args['adapter_conditioning_scale'] = float(x) p.task_args['controlnet_conditioning_scale'] = float(x) return fun @@ -350,7 +351,7 @@ def apply_control(field): def apply_override(field): def fun(p, x, xs): p.override_settings[field] = x - shared.log.debug(f'XYZ grid apply override: "{field}"="{x}"') + logger.log.debug(f'XYZ grid apply override: "{field}"="{x}"') return fun diff --git a/scripts/xyz_grid.py b/scripts/xyz_grid.py index a518657b0..c767201b4 100644 --- a/scripts/xyz_grid.py +++ b/scripts/xyz_grid.py @@ -16,9 +16,10 @@ from modules import shared, errors, scripts_manager, images, processing from modules.ui_components import ToolButton from modules.ui_sections import create_video_inputs import modules.ui_symbols as symbols +from modules import logger -debug = shared.log.trace if os.environ.get('SD_XYZ_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_XYZ_DEBUG', None) is not None else lambda *args, **kwargs: None class Script(scripts_manager.Script): @@ -186,11 +187,11 @@ class Script(scripts_manager.Script): end_val = int(m.group(2)) if m.group(2) is not None else val num = int(m.group(3)) if m.group(3) is not None else int(end_val-start_val) valslist_ext += [int(x) for x in np.linspace(start=start_val, stop=end_val, num=max(2, num)).tolist()] - shared.log.debug(f'XYZ grid range: start={start_val} end={end_val} num={max(2, num)} list={valslist}') + logger.log.debug(f'XYZ grid range: start={start_val} end={end_val} num={max(2, num)} list={valslist}') else: valslist_ext.append(int(val)) except Exception as e: - shared.log.error(f"XYZ grid: value={val} {e}") + logger.log.error(f"XYZ grid: value={val} {e}") valslist.clear() valslist = [x for x in valslist_ext if x not in valslist] elif opt.type == float: @@ -203,11 +204,11 @@ class Script(scripts_manager.Script): end_val = float(m.group(2)) if m.group(2) is not None else val num = int(m.group(3)) if m.group(3) is not None else int(end_val-start_val) valslist_ext += [round(float(x), 2) for x in np.linspace(start=start_val, stop=end_val, num=max(2, num)).tolist()] - shared.log.debug(f'XYZ grid range: start={start_val} end={end_val} num={max(2, num)} list={valslist}') + logger.log.debug(f'XYZ grid range: start={start_val} end={end_val} num={max(2, num)} list={valslist}') else: valslist_ext.append(float(val)) except Exception as e: - shared.log.error(f"XYZ grid: value={val} {e}") + logger.log.error(f"XYZ grid: value={val} {e}") valslist.clear() valslist = [x for x in valslist_ext if x not in valslist] elif opt.type == str_permutations: # pylint: disable=comparison-with-callable @@ -241,7 +242,7 @@ class Script(scripts_manager.Script): y_opt, ys = parse_axis(y_type, y_values, y_values_dropdown) z_opt, zs = parse_axis(z_type, z_values, z_values_dropdown) except Exception as e: - shared.log.error(f"XYZ grid: invalid axis values {e}") + logger.log.error(f"XYZ grid: invalid axis values {e}") errors.display(e, 'xyz') return None @@ -284,7 +285,7 @@ class Script(scripts_manager.Script): shared.state.update('Grid', total_steps, total_jobs * p.n_iter) image_cell_count = p.n_iter * p.batch_size - shared.log.info(f"XYZ grid start: images={len(xs)*len(ys)*len(zs)*image_cell_count} grid={len(zs)} shape={len(xs)}x{len(ys)} cells={len(zs)} steps={total_steps} csv={csv_mode} legend={draw_legend} grid={include_grid} subgrid={include_subgrids} images={include_images} time={include_time} text={include_text}") + logger.log.info(f"XYZ grid start: images={len(xs)*len(ys)*len(zs)*image_cell_count} grid={len(zs)} shape={len(xs)}x{len(ys)} cells={len(zs)} steps={total_steps} csv={csv_mode} legend={draw_legend} grid={include_grid} subgrid={include_subgrids} images={include_images} time={include_time} text={include_text}") AxisInfo = namedtuple('AxisInfo', ['axis', 'values']) shared.state.xyz_plot_x = AxisInfo(x_opt, xs) shared.state.xyz_plot_y = AxisInfo(y_opt, ys) @@ -326,7 +327,7 @@ class Script(scripts_manager.Script): try: processed = processing.process_images(pc) except Exception as e: - shared.log.error(f"XYZ grid: Failed to process image: {e}") + logger.log.error(f"XYZ grid: Failed to process image: {e}") errors.display(e, 'XYZ grid') processed = None subgrid_index = 1 + iz # Sets subgrid infotexts @@ -387,7 +388,7 @@ class Script(scripts_manager.Script): have_subgrids = len(zs) if len(zs) > 1 and include_subgrids else 0 have_images = processed.images[have_grid+have_subgrids:] processed.infotexts[:have_grid+have_subgrids] = grid_infotext[:have_grid+have_subgrids] # update infotexts with grid and subgrid info - shared.log.debug(f'XYZ grid: grid={have_grid} subgrids={have_subgrids} images={len(have_images)} total={len(processed.images)}') + logger.log.debug(f'XYZ grid: grid={have_grid} subgrids={have_subgrids} images={len(have_images)} total={len(processed.images)}') if not include_images: # dont need images anymore, drop from list: processed.images = processed.images[:have_grid+have_subgrids] diff --git a/scripts/xyz_grid_on.py b/scripts/xyz_grid_on.py index dfbd963b8..f7a718845 100644 --- a/scripts/xyz_grid_on.py +++ b/scripts/xyz_grid_on.py @@ -15,11 +15,12 @@ from modules import shared, errors, scripts_manager, images, processing from modules.ui_components import ToolButton from modules.ui_sections import create_video_inputs import modules.ui_symbols as symbols +from modules import logger active = False xyz_results_cache = None -debug = shared.log.trace if os.environ.get('SD_XYZ_DEBUG', None) is not None else lambda *args, **kwargs: None +debug = logger.log.trace if os.environ.get('SD_XYZ_DEBUG', None) is not None else lambda *args, **kwargs: None class Script(scripts_manager.Script): @@ -202,11 +203,11 @@ class Script(scripts_manager.Script): end_val = int(m.group(2)) if m.group(2) is not None else val num = int(m.group(3)) if m.group(3) is not None else int(end_val-start_val) valslist_ext += [int(x) for x in np.linspace(start=start_val, stop=end_val, num=max(2, num)).tolist()] - shared.log.debug(f'XYZ grid range: start={start_val} end={end_val} num={max(2, num)} list={valslist}') + logger.log.debug(f'XYZ grid range: start={start_val} end={end_val} num={max(2, num)} list={valslist}') else: valslist_ext.append(int(val)) except Exception as e: - shared.log.error(f"XYZ grid: value={val} {e}") + logger.log.error(f"XYZ grid: value={val} {e}") valslist.clear() valslist = [x for x in valslist_ext if x not in valslist] elif opt.type == float: @@ -219,11 +220,11 @@ class Script(scripts_manager.Script): end_val = float(m.group(2)) if m.group(2) is not None else val num = int(m.group(3)) if m.group(3) is not None else int(end_val-start_val) valslist_ext += [round(float(x), 2) for x in np.linspace(start=start_val, stop=end_val, num=max(2, num)).tolist()] - shared.log.debug(f'XYZ grid range: start={start_val} end={end_val} num={max(2, num)} list={valslist}') + logger.log.debug(f'XYZ grid range: start={start_val} end={end_val} num={max(2, num)} list={valslist}') else: valslist_ext.append(float(val)) except Exception as e: - shared.log.error(f"XYZ grid: value={val} {e}") + logger.log.error(f"XYZ grid: value={val} {e}") valslist.clear() valslist = [x for x in valslist_ext if x not in valslist] elif opt.type == str_permutations: # pylint: disable=comparison-with-callable @@ -257,7 +258,7 @@ class Script(scripts_manager.Script): y_opt, ys = parse_axis(y_type, y_values, y_values_dropdown) z_opt, zs = parse_axis(z_type, z_values, z_values_dropdown) except Exception as e: - shared.log.error(f"XYZ grid: invalid axis values {e}") + logger.log.error(f"XYZ grid: invalid axis values {e}") errors.display(e, 'xyz') return None @@ -302,7 +303,7 @@ class Script(scripts_manager.Script): shared.state.update('Grid', total_steps, total_jobs) image_cell_count = p.n_iter * p.batch_size - shared.log.info(f"XYZ grid start: images={len(xs)*len(ys)*len(zs)*image_cell_count} grid={len(zs)} shape={len(xs)}x{len(ys)} cells={len(zs)} steps={total_steps} csv={csv_mode} legend={draw_legend} grid={include_grid} subgrid={include_subgrids} images={include_images} time={include_time} text={include_text}") + logger.log.info(f"XYZ grid start: images={len(xs)*len(ys)*len(zs)*image_cell_count} grid={len(zs)} shape={len(xs)}x{len(ys)} cells={len(zs)} steps={total_steps} csv={csv_mode} legend={draw_legend} grid={include_grid} subgrid={include_subgrids} images={include_images} time={include_time} text={include_text}") AxisInfo = namedtuple('AxisInfo', ['axis', 'values']) shared.state.xyz_plot_x = AxisInfo(x_opt, xs) shared.state.xyz_plot_y = AxisInfo(y_opt, ys) @@ -332,7 +333,7 @@ class Script(scripts_manager.Script): def cell(x, y, z, ix, iy, iz): if shared.state.interrupted: - shared.log.warning('XYZ grid: Interrupted') + logger.log.warning('XYZ grid: Interrupted') return processing.Processed(p, [], p.seed, ""), 0 p.xyz = True pc = copy(p) @@ -351,7 +352,7 @@ class Script(scripts_manager.Script): try: processed = processing.process_images(pc) except Exception as e: - shared.log.error(f"XYZ grid: Failed to process image: {e}") + logger.log.error(f"XYZ grid: Failed to process image: {e}") errors.display(e, 'XYZ grid') processed = None @@ -415,7 +416,7 @@ class Script(scripts_manager.Script): have_subgrids = len(zs) if len(zs) > 1 and include_subgrids else 0 have_images = processed.images[have_grid+have_subgrids:] processed.infotexts[:have_grid+have_subgrids] = grid_infotext[:have_grid+have_subgrids] # update infotexts with grid and subgrid info - shared.log.debug(f'XYZ grid: grid={have_grid} subgrids={have_subgrids} images={len(have_images)} total={len(processed.images)}') + logger.log.debug(f'XYZ grid: grid={have_grid} subgrids={have_subgrids} images={len(have_images)} total={len(processed.images)}') if not include_images: # dont need images anymore, drop from list: processed.images = processed.images[:have_grid+have_subgrids] diff --git a/webui.py b/webui.py index e6a995533..b043426f8 100644 --- a/webui.py +++ b/webui.py @@ -9,7 +9,8 @@ import logging import importlib import contextlib from threading import Thread -from installer import log, git_commit, custom_excepthook, version +from installer import git_commit, custom_excepthook, version +from modules.logger import log from modules import timer import modules.loader import modules.hashes @@ -45,6 +46,7 @@ import modules.ui_extra_networks import modules.textual_inversion import modules.script_callbacks import modules.api.middleware +from modules import logger if not modules.loader.initialized: @@ -240,7 +242,7 @@ def start_common(): async_policy() initialize() if shared.cmd_opts.backend == 'original': - shared.log.error('Legacy option: backend=original is no longer supported') + logger.log.error('Legacy option: backend=original is no longer supported') shared.cmd_opts.backend = 'diffusers' try: from installer import diffusers_commit @@ -262,7 +264,7 @@ def mount_subpath(app): if not shared.opts.subpath.startswith('/'): shared.opts.subpath = f'/{shared.opts.subpath}' gradio.mount_gradio_app(app, shared.demo, path=shared.opts.subpath) - shared.log.info(f'Mounted: subpath="{shared.opts.subpath}"') + logger.log.info(f'Mounted: subpath="{shared.opts.subpath}"') def start_ui(): @@ -300,7 +302,7 @@ def start_ui(): allowed_paths.append(shared.cmd_opts.models_dir) if shared.cmd_opts.allowed_paths is not None: allowed_paths += [p for p in shared.cmd_opts.allowed_paths if os.path.isdir(p)] - shared.log.debug(f'Root paths: {allowed_paths}') + logger.log.debug(f'Root paths: {allowed_paths}') with contextlib.redirect_stdout(stdout): app, local_url, share_url = shared.demo.launch( # app is FastAPI(Starlette) instance share=shared.cmd_opts.share, @@ -322,25 +324,25 @@ def start_ui(): ) if shared.cmd_opts.data_dir is not None: modules.gr_tempdir.register_tmp_file(shared.demo, os.path.join(shared.cmd_opts.data_dir, 'x')) - shared.log.info(f'Local URL: {local_url}') + logger.log.info(f'Local URL: {local_url}') if shared.cmd_opts.listen: if not gradio_auth_creds: - shared.log.warning('Public URL: enabled without authentication') + logger.log.warning('Public URL: enabled without authentication') if shared.cmd_opts.insecure: - shared.log.warning('Public URL: enabled with insecure flag') + logger.log.warning('Public URL: enabled with insecure flag') proto = 'https' if shared.cmd_opts.tls_keyfile is not None else 'http' external_ip = get_external_ip() if external_ip is not None: - shared.log.info(f'External URL: {proto}://{external_ip}:{shared.cmd_opts.port}') + logger.log.info(f'External URL: {proto}://{external_ip}:{shared.cmd_opts.port}') public_ip = get_remote_ip() if public_ip is not None: - shared.log.info(f'Public URL: {proto}://{public_ip}:{shared.cmd_opts.port}') + logger.log.info(f'Public URL: {proto}://{public_ip}:{shared.cmd_opts.port}') if shared.cmd_opts.docs: - shared.log.info(f'API docs: {local_url[:-1]}/docs') # pylint: disable=unsubscriptable-object - shared.log.info(f'API redocs: {local_url[:-1]}/redocs') # pylint: disable=unsubscriptable-object + logger.log.info(f'API docs: {local_url[:-1]}/docs') # pylint: disable=unsubscriptable-object + logger.log.info(f'API redocs: {local_url[:-1]}/redocs') # pylint: disable=unsubscriptable-object if share_url is not None: - shared.log.info(f'Share URL: {share_url}') - # shared.log.debug(f'Gradio functions: registered={len(shared.demo.fns)}') + logger.log.info(f'Share URL: {share_url}') + # logger.log.debug(f'Gradio functions: registered={len(shared.demo.fns)}') shared.demo.server.wants_restart = False modules.api.middleware.setup_middleware(app, shared.cmd_opts) @@ -358,10 +360,10 @@ def start_ui(): time_sorted = sorted(modules.scripts_manager.time_setup.items(), key=lambda x: x[1], reverse=True) time_script = [f'{k}:{round(v,3)}' for (k,v) in time_sorted if v > 0.05] time_total = sum(modules.scripts_manager.time_setup.values()) - shared.log.debug(f'Scripts setup: time={time_total:.3f} {time_script}') + logger.log.debug(f'Scripts setup: time={time_total:.3f} {time_script}') time_component = [f'{k}:{round(v,3)}' for (k,v) in modules.scripts_manager.time_component.items() if v > 0.005] if len(time_component) > 0: - shared.log.debug(f'Scripts components: {time_component}') + logger.log.debug(f'Scripts components: {time_component}') return app @@ -381,7 +383,7 @@ def webui(restart=False): if shared.cmd_opts.profile: for k, v in modules.script_callbacks.callback_map.items(): - shared.log.debug(f'Registered callbacks: {k}={len(v)} {[c.script for c in v]}') + logger.log.debug(f'Registered callbacks: {k}={len(v)} {[c.script for c in v]}') debug = log.trace if os.environ.get('SD_SCRIPT_DEBUG', None) is not None else lambda *args, **kwargs: None debug('Trace: SCRIPTS') for m in modules.scripts_manager.scripts_data: @@ -410,7 +412,7 @@ def webui(restart=False): # autolaunch only on initial start if (shared.opts.autolaunch or shared.cmd_opts.autolaunch) and local_url is not None: shared.cmd_opts.autolaunch = False - shared.log.info('Launching browser') + logger.log.info('Launching browser') import webbrowser webbrowser.open(local_url, new=2, autoraise=True) else: