Phase 1 of logging work.
This commit is contained in:
@@ -205,6 +205,27 @@ Example workflows are available in the `example_workflows/` folder. In ComfyUI,
|
||||
|
||||
The sidebar tabs (LLM Chat, Prompt Builder) will appear automatically in the ComfyUI interface.
|
||||
|
||||
## Logging Configuration
|
||||
|
||||
SageUtils uses a dedicated logging system that is separate from ComfyUI's logging. You can control log verbosity using the `SAGEUTILS_LOG_LEVEL` environment variable:
|
||||
|
||||
```bash
|
||||
# Show detailed debug information
|
||||
SAGEUTILS_LOG_LEVEL=DEBUG python main.py
|
||||
|
||||
# Show only warnings and errors (quieter)
|
||||
SAGEUTILS_LOG_LEVEL=WARNING python main.py
|
||||
|
||||
# Default level is INFO (normal operation messages)
|
||||
python main.py
|
||||
```
|
||||
|
||||
Available log levels: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL`
|
||||
|
||||
All SageUtils logs are prefixed with `[SageUtils.*]` for easy identification.
|
||||
|
||||
For developers, see the [Logging Guide](docs/LOGGING.md) for information on using the logger in your code.
|
||||
|
||||
## Documentation
|
||||
|
||||
- 📖 [LLM Tab Guide](docs/LLM_TAB_GUIDE.md) - Complete guide to using the LLM chat interface
|
||||
|
||||
+12
-6
@@ -1,8 +1,15 @@
|
||||
import os
|
||||
import logging
|
||||
|
||||
# Uncomment the next line to enable debug logging
|
||||
# logging.basicConfig(level=logging.DEBUG)
|
||||
# Initialize SageUtils logging infrastructure
|
||||
from .utils.logger import configure_logging, configure_third_party_logging, get_logger
|
||||
|
||||
# Configure SageUtils logger early in initialization
|
||||
# Uses SAGEUTILS_LOG_LEVEL environment variable or defaults to INFO
|
||||
configure_logging()
|
||||
configure_third_party_logging()
|
||||
|
||||
# Get logger for this module
|
||||
logger = get_logger('init')
|
||||
|
||||
SAGEUTILS_PRINT_TIMING = False # Set to True to enable timing report
|
||||
# Print timing report if enabled via environment variable
|
||||
@@ -55,8 +62,7 @@ try:
|
||||
from . import server_routes
|
||||
log_init("SERVER_ROUTES_LOADED")
|
||||
except Exception as e:
|
||||
import logging
|
||||
logging.warning(f"Warning: Failed to load SageUtils custom routes: {e}")
|
||||
logger.warning(f"Failed to load SageUtils custom routes: {e}")
|
||||
log_init("SERVER_ROUTES_FAILED")
|
||||
|
||||
WEB_DIRECTORY = "./js"
|
||||
@@ -70,7 +76,7 @@ try:
|
||||
from .utils.performance_fix import populate_llm_cache_async
|
||||
populate_llm_cache_async()
|
||||
except Exception as e:
|
||||
logging.warning(f"Warning: Failed to start background LLM cache population: {e}")
|
||||
logger.warning(f"Failed to start background LLM cache population: {e}")
|
||||
|
||||
# Print timing report if enabled.
|
||||
if SAGEUTILS_PRINT_TIMING:
|
||||
|
||||
+95
-16
@@ -212,10 +212,22 @@ class Sage_FlexibleCLIPSelector(io.ComfyNode):
|
||||
io.Combo.Input(f"clip_name_{i}", display_name=f"clip_name_{i}", options=clip_list)
|
||||
)
|
||||
# Add clip_type selector
|
||||
default_type = "chroma" if num_clips == 1 else "sdxl"
|
||||
clip_options[num_clips].append(
|
||||
io.Combo.Input("clip_type", display_name="clip_type", options=mi.single_clip_loader_options, default=default_type)
|
||||
)
|
||||
options = None
|
||||
|
||||
if num_clips == 1:
|
||||
options = mi.single_clip_loader_options
|
||||
default_type = "chroma"
|
||||
elif num_clips == 2:
|
||||
options = mi.dual_clip_loader_options
|
||||
default_type = "sdxl"
|
||||
else:
|
||||
options = None
|
||||
default_type = ""
|
||||
|
||||
if options:
|
||||
clip_options[num_clips].append(
|
||||
io.Combo.Input("clip_type", display_name="clip_type", options=options, default=default_type)
|
||||
)
|
||||
|
||||
# Build dynamic combo options
|
||||
dynamic_options = [
|
||||
@@ -250,6 +262,78 @@ class Sage_FlexibleCLIPSelector(io.ComfyNode):
|
||||
info = mi.get_model_info_clips(clip_names, clip_type)
|
||||
return io.NodeOutput(info)
|
||||
|
||||
class Sage_MultiSelectorFlexibleClip(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls):
|
||||
unet_options = get_model_list("unet")
|
||||
vae_options = get_model_list("vae")
|
||||
clip_list = get_model_list("clip")
|
||||
clip_options = {}
|
||||
|
||||
# Build clip options for 1-4 clips
|
||||
for num_clips in range(1, 5):
|
||||
clip_options[num_clips] = []
|
||||
for i in range(1, num_clips + 1):
|
||||
clip_options[num_clips].append(
|
||||
io.Combo.Input(f"clip_name_{i}", display_name=f"clip_name_{i}", options=clip_list)
|
||||
)
|
||||
# Add clip_type selector
|
||||
options = None
|
||||
|
||||
if num_clips == 1:
|
||||
options = mi.single_clip_loader_options
|
||||
default_type = "chroma"
|
||||
elif num_clips == 2:
|
||||
options = mi.dual_clip_loader_options
|
||||
default_type = "sdxl"
|
||||
else:
|
||||
options = None
|
||||
default_type = ""
|
||||
|
||||
if options:
|
||||
clip_options[num_clips].append(
|
||||
io.Combo.Input("clip_type", display_name="clip_type", options=options, default=default_type)
|
||||
)
|
||||
|
||||
# Build dynamic combo options
|
||||
dynamic_options = [
|
||||
io.DynamicCombo.Option(str(num), list(clip_options[num]))
|
||||
for num in range(1, 5)
|
||||
]
|
||||
|
||||
return io.Schema(
|
||||
node_id="Sage_MultiSelectorFlexibleClip",
|
||||
display_name="Multi Selector Flexible CLIP",
|
||||
description="Selects checkpoint, UNET, VAE, and a flexible number of CLIP models from lists.",
|
||||
category="Sage Utils/selector",
|
||||
inputs=[
|
||||
io.Combo.Input("unet_name", display_name="unet_name", options=unet_options),
|
||||
io.Combo.Input("weight_dtype", display_name="weight_dtype", options=mi.weight_dtype_options, default="default"),
|
||||
io.DynamicCombo.Input("num_of_clips", display_name="num_of_clips", options=dynamic_options),
|
||||
io.Combo.Input("vae_name", display_name="vae_name", options=vae_options),
|
||||
],
|
||||
outputs=[
|
||||
ModelInfo.Output("model_info", display_name="model_info")
|
||||
]
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def execute(cls, **kwargs):
|
||||
unet_name = kwargs.get("unet_name", "")
|
||||
weight_dtype = kwargs.get("weight_dtype", "default")
|
||||
vae_name = kwargs.get("vae_name", "")
|
||||
|
||||
args = kwargs.get("num_of_clips", {})
|
||||
clip_names = [args.get(key, "") for key in sorted(args.keys()) if key.startswith("clip_name_")]
|
||||
clip_type = kwargs.get("clip_type", "chroma")
|
||||
|
||||
unet_info = mi.get_model_info_unet(unet_name, weight_dtype)
|
||||
clip_info = mi.get_model_info_clips(clip_names, clip_type)
|
||||
vae_info = mi.get_model_info_vae(vae_name)
|
||||
|
||||
ret = (unet_info[0], clip_info[0], vae_info[0])
|
||||
return io.NodeOutput(ret,)
|
||||
|
||||
class Sage_MultiSelectorSingleClip(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls):
|
||||
@@ -311,13 +395,12 @@ class Sage_MultiSelectorDoubleClip(io.ComfyNode):
|
||||
def execute(cls, **kwargs):
|
||||
unet_name = kwargs.get("unet_name", "")
|
||||
weight_dtype = kwargs.get("weight_dtype", "default")
|
||||
clip_name_1 = kwargs.get("clip_name_1", "")
|
||||
clip_name_2 = kwargs.get("clip_name_2", "")
|
||||
clip_name = [kwargs.get("clip_name_1", ""), kwargs.get("clip_name_2", "")]
|
||||
clip_type = kwargs.get("clip_type", "sdxl")
|
||||
vae_name = kwargs.get("vae_name", "")
|
||||
|
||||
unet_info = mi.get_model_info_unet(unet_name, weight_dtype)
|
||||
clip_info = mi.get_model_info_clips([clip_name_1, clip_name_2], clip_type)
|
||||
clip_info = mi.get_model_info_clips(clip_name, clip_type)
|
||||
vae_info = mi.get_model_info_vae(vae_name)
|
||||
|
||||
ret = (unet_info[0], clip_info[0], vae_info[0])
|
||||
@@ -349,13 +432,11 @@ class Sage_MultiSelectorTripleClip(io.ComfyNode):
|
||||
def execute(cls, **kwargs):
|
||||
unet_name = kwargs.get("unet_name", "")
|
||||
weight_dtype = kwargs.get("weight_dtype", "default")
|
||||
clip_name_1 = kwargs.get("clip_name_1", "")
|
||||
clip_name_2 = kwargs.get("clip_name_2", "")
|
||||
clip_name_3 = kwargs.get("clip_name_3", "")
|
||||
clip_name = [kwargs.get("clip_name_1", ""), kwargs.get("clip_name_2", ""), kwargs.get("clip_name_3", "")]
|
||||
vae_name = kwargs.get("vae_name", "")
|
||||
|
||||
unet_info = mi.get_model_info_unet(unet_name, weight_dtype)
|
||||
clip_info = mi.get_model_info_clips([clip_name_1, clip_name_2, clip_name_3])
|
||||
clip_info = mi.get_model_info_clips(clip_name)
|
||||
vae_info = mi.get_model_info_vae(vae_name)
|
||||
|
||||
ret = (unet_info[0], clip_info[0], vae_info[0])
|
||||
@@ -388,14 +469,11 @@ class Sage_MultiSelectorQuadClip(io.ComfyNode):
|
||||
def execute(cls, **kwargs):
|
||||
unet_name = kwargs.get("unet_name", "")
|
||||
weight_dtype = kwargs.get("weight_dtype", "default")
|
||||
clip_name_1 = kwargs.get("clip_name_1", "")
|
||||
clip_name_2 = kwargs.get("clip_name_2", "")
|
||||
clip_name_3 = kwargs.get("clip_name_3", "")
|
||||
clip_name_4 = kwargs.get("clip_name_4", "")
|
||||
clip_name = [kwargs.get("clip_name_1", ""), kwargs.get("clip_name_2", ""), kwargs.get("clip_name_3", ""), kwargs.get("clip_name_4", "")]
|
||||
vae_name = kwargs.get("vae_name", "")
|
||||
|
||||
unet_info = mi.get_model_info_unet(unet_name, weight_dtype)
|
||||
clip_info = mi.get_model_info_clips([clip_name_1, clip_name_2, clip_name_3, clip_name_4])
|
||||
clip_info = mi.get_model_info_clips(clip_name)
|
||||
vae_info = mi.get_model_info_vae(vae_name)
|
||||
|
||||
ret = (unet_info[0], clip_info[0], vae_info[0])
|
||||
@@ -946,6 +1024,7 @@ SELECTOR_NODES = [
|
||||
Sage_MultiSelectorTripleClip,
|
||||
Sage_MultiSelectorQuadClip,
|
||||
Sage_FlexibleCLIPSelector,
|
||||
Sage_MultiSelectorFlexibleClip,
|
||||
Sage_ModelShifts,
|
||||
Sage_ModelShiftOnly,
|
||||
Sage_FreeU2,
|
||||
|
||||
+8
-16
@@ -334,7 +334,7 @@ def pull_metadata(file_paths, timestamp = True, force_all = False, pbar = None,
|
||||
force = force_all
|
||||
hash = cache.hash.get(str(file_path), None)
|
||||
if hash is None:
|
||||
print(f"Hash not found in cache for {file_path}. Adding to cache.")
|
||||
logging.debug(f"Hash not found in cache for {file_path}. Adding to cache.")
|
||||
hash = add_file_to_cache(file_path)
|
||||
|
||||
file_cache = cache.by_path(file_path)
|
||||
@@ -344,7 +344,7 @@ def pull_metadata(file_paths, timestamp = True, force_all = False, pbar = None,
|
||||
modified = get_file_modification_date(file_path)
|
||||
# If file was modified after last used, force metadata pull
|
||||
if last_used_date is not None and modified is not None and modified > last_used_date:
|
||||
print(f"File was modified after last used. Pulling metadata.")
|
||||
logging.info(f"File was modified after last used. Pulling metadata.")
|
||||
force = True
|
||||
|
||||
# Only skip pull if not forced and civitai is True and recently pulled
|
||||
@@ -361,16 +361,16 @@ def pull_metadata(file_paths, timestamp = True, force_all = False, pbar = None,
|
||||
|
||||
if file_cache.get('blacklist'):
|
||||
if not force:
|
||||
print(f"File {file_path} is blacklisted (previously not found). Skipping metadata pull.")
|
||||
logging.warning(f"File {file_path} is blacklisted (previously not found). Skipping metadata pull.")
|
||||
pull_json = False
|
||||
|
||||
# If force, recalculate hash before any API call
|
||||
if force:
|
||||
print(f"Force flag is set. Recalculating hash for {file_path}.")
|
||||
logging.debug(f"Force flag is set. Recalculating hash for {file_path}.")
|
||||
hash = recheck_hash(file_path, hash)
|
||||
|
||||
if pull_json or force:
|
||||
print(f"Currently pulling metadata for {file_path}.")
|
||||
logging.debug(f"Currently pulling metadata for {file_path}.")
|
||||
json = get_civitai_model_version_json_by_hash(hash)
|
||||
|
||||
if 'error' in json:
|
||||
@@ -383,15 +383,15 @@ def pull_metadata(file_paths, timestamp = True, force_all = False, pbar = None,
|
||||
# Try fallback with modelId if available
|
||||
if dead_model is False:
|
||||
if 'modelId' in file_cache:
|
||||
print(f"Using cached model id {file_cache.get('id', None)}")
|
||||
logging.debug(f"Using cached model id {file_cache.get('id', None)}")
|
||||
json = get_civitai_model_version_json_by_id(file_cache['id'])
|
||||
retried = True
|
||||
else:
|
||||
print(f"No cached model id.")
|
||||
logging.debug(f"No cached model id.")
|
||||
|
||||
if 'error' in json:
|
||||
if retried:
|
||||
print(f"Error: {json['error']}")
|
||||
logging.error(f"Error: {json['error']}")
|
||||
if dead_model:
|
||||
file_cache['blacklist'] = True
|
||||
print(f"Unable to find on civitai.")
|
||||
@@ -669,14 +669,6 @@ def clean_keywords(keywords):
|
||||
return ', '.join(keywords)
|
||||
|
||||
def clean_text(text):
|
||||
# ret = ' '.join(filter(None, (x.strip() for x in text.split())))
|
||||
# ret = ', '.join(filter(None, (x.strip() for x in ret.split(','))))
|
||||
# ret = '\n'.join(filter(None, (x.strip() for x in ret.split('\n'))))
|
||||
|
||||
|
||||
# # Strip whitespace from the start and end of text in parentheses
|
||||
# ret = ' ('.join(part.strip() for part in ret.split('('))
|
||||
# ret = ')'.join(part.strip() for part in ret.split(')'))
|
||||
ret = normalize_prompt_weights(text)
|
||||
return ret
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ from .llm_cache import get_llm_cache
|
||||
_ollama_initialized = False
|
||||
_lmstudio_initialized = False
|
||||
|
||||
logging.getLogger('httpx').setLevel(logging.WARNING)
|
||||
|
||||
# Attempt to import ollama, if available. Set a flag if it is not available.
|
||||
try:
|
||||
import ollama
|
||||
@@ -13,6 +15,7 @@ try:
|
||||
ollama_client = None # Will be initialized in init_ollama
|
||||
ollama_logger = logging.getLogger('ollama')
|
||||
ollama_logger.setLevel(logging.ERROR)
|
||||
|
||||
|
||||
except ImportError:
|
||||
ollama = None
|
||||
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
"""
|
||||
SageUtils logging infrastructure.
|
||||
Provides a dedicated logger for all SageUtils operations.
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
# Logger name for all SageUtils components
|
||||
LOGGER_NAME = "SageUtils"
|
||||
|
||||
# Default log level (can be overridden via environment variable)
|
||||
DEFAULT_LOG_LEVEL = logging.INFO
|
||||
|
||||
# Environment variable for log level control
|
||||
LOG_LEVEL_ENV_VAR = "SAGEUTILS_LOG_LEVEL"
|
||||
|
||||
# Valid log level names
|
||||
LOG_LEVELS = {
|
||||
"DEBUG": logging.DEBUG,
|
||||
"INFO": logging.INFO,
|
||||
"WARNING": logging.WARNING,
|
||||
"ERROR": logging.ERROR,
|
||||
"CRITICAL": logging.CRITICAL,
|
||||
}
|
||||
|
||||
|
||||
def get_logger(name: Optional[str] = None) -> logging.Logger:
|
||||
"""
|
||||
Get a logger instance for SageUtils.
|
||||
|
||||
Args:
|
||||
name: Optional sub-module name (e.g., 'cache', 'routes', 'helpers')
|
||||
If provided, creates logger as 'SageUtils.{name}'
|
||||
If None, returns the root SageUtils logger
|
||||
|
||||
Returns:
|
||||
Logger instance configured for SageUtils
|
||||
|
||||
Example:
|
||||
# In utils/helpers.py
|
||||
logger = get_logger('helpers')
|
||||
logger.info("Processing model...") # Logs as [SageUtils.helpers]
|
||||
|
||||
# In routes/cache_routes.py
|
||||
logger = get_logger('routes.cache')
|
||||
logger.debug("Cache route called") # Logs as [SageUtils.routes.cache]
|
||||
"""
|
||||
if name:
|
||||
logger_name = f"{LOGGER_NAME}.{name}"
|
||||
else:
|
||||
logger_name = LOGGER_NAME
|
||||
|
||||
return logging.getLogger(logger_name)
|
||||
|
||||
|
||||
def configure_logging(level: Optional[int] = None, handler: Optional[logging.Handler] = None):
|
||||
"""
|
||||
Configure the SageUtils logger with desired level and handler.
|
||||
|
||||
This should be called once during initialization (__init__.py).
|
||||
|
||||
Args:
|
||||
level: Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
|
||||
If None, reads from SAGEUTILS_LOG_LEVEL env var or uses DEFAULT_LOG_LEVEL
|
||||
handler: Custom handler to use. If None, uses StreamHandler with standard formatting
|
||||
|
||||
Notes:
|
||||
- Only affects SageUtils logger, not ComfyUI's logging
|
||||
- Sub-loggers (e.g., SageUtils.helpers) inherit this configuration
|
||||
- Third-party library loggers can be configured separately
|
||||
|
||||
Returns:
|
||||
The configured root SageUtils logger
|
||||
"""
|
||||
# Get or create the root SageUtils logger
|
||||
logger = logging.getLogger(LOGGER_NAME)
|
||||
|
||||
# Determine log level
|
||||
if level is None:
|
||||
# Check environment variable
|
||||
env_level = os.environ.get(LOG_LEVEL_ENV_VAR, "").upper()
|
||||
level = LOG_LEVELS.get(env_level, DEFAULT_LOG_LEVEL)
|
||||
|
||||
logger.setLevel(level)
|
||||
|
||||
# Clear existing handlers to avoid duplicates
|
||||
logger.handlers.clear()
|
||||
|
||||
# Add handler
|
||||
if handler is None:
|
||||
handler = logging.StreamHandler()
|
||||
formatter = logging.Formatter(
|
||||
'[%(name)s] %(levelname)s: %(message)s'
|
||||
)
|
||||
handler.setFormatter(formatter)
|
||||
|
||||
logger.addHandler(handler)
|
||||
|
||||
# Prevent propagation to root logger to avoid duplicate messages
|
||||
logger.propagate = False
|
||||
|
||||
return logger
|
||||
|
||||
|
||||
def configure_third_party_logging():
|
||||
"""
|
||||
Configure logging levels for third-party libraries used by SageUtils.
|
||||
|
||||
Some libraries are very verbose and should have higher logging thresholds.
|
||||
This function sets appropriate levels for known chatty libraries.
|
||||
"""
|
||||
# HTTP libraries
|
||||
logging.getLogger('httpx').setLevel(logging.WARNING)
|
||||
logging.getLogger('urllib3').setLevel(logging.WARNING)
|
||||
|
||||
# LLM libraries (if available)
|
||||
try:
|
||||
logging.getLogger('ollama').setLevel(logging.ERROR)
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
logging.getLogger('lmstudio').setLevel(logging.ERROR)
|
||||
except:
|
||||
pass
|
||||
|
||||
# Add more as needed
|
||||
logging.getLogger('asyncio').setLevel(logging.WARNING)
|
||||
|
||||
|
||||
def get_sageutils_logger() -> logging.Logger:
|
||||
"""
|
||||
Get the root SageUtils logger.
|
||||
|
||||
This is a convenience function for getting the main logger.
|
||||
For module-specific loggers, use get_logger(name) instead.
|
||||
|
||||
Returns:
|
||||
The root SageUtils logger
|
||||
"""
|
||||
return logging.getLogger(LOGGER_NAME)
|
||||
|
||||
|
||||
def set_log_level(level: str):
|
||||
"""
|
||||
Dynamically change the log level for SageUtils logger.
|
||||
|
||||
Args:
|
||||
level: Log level name ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL')
|
||||
|
||||
Raises:
|
||||
ValueError: If level is not a valid log level name
|
||||
|
||||
Example:
|
||||
set_log_level('DEBUG') # Enable debug logging
|
||||
set_log_level('WARNING') # Only show warnings and errors
|
||||
"""
|
||||
level_upper = level.upper()
|
||||
if level_upper not in LOG_LEVELS:
|
||||
raise ValueError(
|
||||
f"Invalid log level: {level}. "
|
||||
f"Valid levels are: {', '.join(LOG_LEVELS.keys())}"
|
||||
)
|
||||
|
||||
logger = logging.getLogger(LOGGER_NAME)
|
||||
logger.setLevel(LOG_LEVELS[level_upper])
|
||||
|
||||
|
||||
def get_log_level() -> str:
|
||||
"""
|
||||
Get the current log level name for SageUtils logger.
|
||||
|
||||
Returns:
|
||||
Log level name ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL')
|
||||
"""
|
||||
logger = logging.getLogger(LOGGER_NAME)
|
||||
level = logger.level
|
||||
|
||||
# Reverse lookup
|
||||
for name, value in LOG_LEVELS.items():
|
||||
if value == level:
|
||||
return name
|
||||
|
||||
return "UNKNOWN"
|
||||
+2
-2
@@ -7,8 +7,8 @@ from .model_cache import cache
|
||||
from .lora_stack import norm_lora_stack
|
||||
|
||||
weight_dtype_options = ["default", "fp8_e4m3fn", "fp8_e4m3fn_fast", "fp8_e5m2"]
|
||||
single_clip_loader_options = ["stable_diffusion", "stable_cascade", "sd3", "stable_audio", "mochi", "ltxv", "pixart", "cosmos", "lumina2", "wan", "hidream", "chroma", "ace", "omnigen2", "qwen_image"]
|
||||
dual_clip_loader_options = ["sdxl", "sd3", "flux", "hunyuan_video", "hidream", "ace"]
|
||||
single_clip_loader_options = ["stable_diffusion", "stable_cascade", "sd3", "stable_audio", "mochi", "ltxv", "pixart", "cosmos", "lumina2", "wan", "hidream", "chroma", "ace", "omnigen2", "qwen_image", "hunyuan_image", "flux2", "ovis"]
|
||||
dual_clip_loader_options = ["sdxl", "sd3", "flux", "hunyuan_video", "hidream", "hunyuan_image", "hunyuan_video_15", "kandinsky5", "kandinsky5_image", "ltxv", "newbie", "ace"]
|
||||
|
||||
def get_model_info_ckpt(ckpt_name: str) -> tuple:
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user