Files
2025-10-24 21:40:19 +03:00

180 lines
6.5 KiB
Python

"""
ComfyUI LLM SDXL Adapter v3.0.1
ComfyUI nodes for using Large Language Models as text encoders for SDXL image generation through trained adapters.
"""
import logging
import sys
import os
from typing import Dict, Tuple
# Setup logging
logger = logging.getLogger("LLM-SDXL-Adapter")
logger.setLevel(logging.WARN)
# Add custom formatter with module prefix
if not logger.handlers:
handler = logging.StreamHandler()
formatter = logging.Formatter('[LLM-SDXL-Adapter] %(levelname)s: %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.propagate = False # Prevent duplicate logs from parent loggers
# Add current directory to path for imports
current_dir = os.path.dirname(os.path.abspath(__file__))
if current_dir not in sys.path:
sys.path.append(current_dir)
# Check dependencies
try:
import torch
import transformers
import safetensors
import einops
logger.info("All required dependencies found")
except ImportError as e:
logger.error(f"Missing dependency: {e}")
logger.error("Please install: pip install transformers safetensors einops")
raise
# Import all node modules from separate files
try:
from .llm_model_loader import NODE_CLASS_MAPPINGS as LLM_MODEL_LOADER_MAPPINGS
from .llm_model_loader import NODE_DISPLAY_NAME_MAPPINGS as LLM_MODEL_LOADER_DISPLAY_MAPPINGS
from .llm_gguf_model_loader import NODE_CLASS_MAPPINGS as LLM_GGUF_MODEL_LOADER_MAPPINGS
from .llm_gguf_model_loader import NODE_DISPLAY_NAME_MAPPINGS as LLM_GGUF_MODEL_LOADER_DISPLAY_MAPPINGS
from .t5gemma_model_loader import NODE_CLASS_MAPPINGS as T5GEMMA_MODEL_LOADER_MAPPINGS
from .t5gemma_model_loader import NODE_DISPLAY_NAME_MAPPINGS as T5GEMMA_MODEL_LOADER_DISPLAY_MAPPINGS
from .llm_text_encoder import NODE_CLASS_MAPPINGS as LLM_ENCODER_MAPPINGS
from .llm_text_encoder import NODE_DISPLAY_NAME_MAPPINGS as LLM_ENCODER_DISPLAY_MAPPINGS
from .t5gemma_text_encoder import NODE_CLASS_MAPPINGS as T5GEMMA_ENCODER_MAPPINGS
from .t5gemma_text_encoder import NODE_DISPLAY_NAME_MAPPINGS as T5GEMMA_ENCODER_DISPLAY_MAPPINGS
from .llm_adapter_loader import NODE_CLASS_MAPPINGS as ADAPTER_LOADER_MAPPINGS
from .llm_adapter_loader import NODE_DISPLAY_NAME_MAPPINGS as ADAPTER_LOADER_DISPLAY_MAPPINGS
from .llm_adapter_loader_custom import NODE_CLASS_MAPPINGS as ADAPTER_LOADER_CUSTOM_MAPPINGS
from .llm_adapter_loader_custom import NODE_DISPLAY_NAME_MAPPINGS as ADAPTER_LOADER_CUSTOM_DISPLAY_MAPPINGS
from .apply_llm_to_sdxl_adapter import NODE_CLASS_MAPPINGS as ADAPTER_NODE_MAPPINGS
from .apply_llm_to_sdxl_adapter import NODE_DISPLAY_NAME_MAPPINGS as ADAPTER_NODE_DISPLAY_MAPPINGS
from .t5gemma_apply_llm_to_sdxl_adapter import NODE_CLASS_MAPPINGS as T5GEMMA_ADAPTER_NODE_MAPPINGS
from .t5gemma_apply_llm_to_sdxl_adapter import NODE_DISPLAY_NAME_MAPPINGS as T5GEMMA_ADAPTER_NODE_DISPLAY_MAPPINGS
logger.info("Successfully imported all node modules from separate files")
except Exception as e:
logger.error(f"Failed to import node modules: {e}")
raise
# Combine all node mappings
NODE_CLASS_MAPPINGS: Dict[str, type] = {}
NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = {}
# Add all mappings from separate files
all_class_mappings = [
LLM_MODEL_LOADER_MAPPINGS,
LLM_GGUF_MODEL_LOADER_MAPPINGS,
T5GEMMA_MODEL_LOADER_MAPPINGS,
LLM_ENCODER_MAPPINGS,
T5GEMMA_ENCODER_MAPPINGS,
ADAPTER_LOADER_MAPPINGS,
ADAPTER_LOADER_CUSTOM_MAPPINGS,
ADAPTER_NODE_MAPPINGS,
T5GEMMA_ADAPTER_NODE_MAPPINGS,
]
all_display_mappings = [
LLM_MODEL_LOADER_DISPLAY_MAPPINGS,
LLM_GGUF_MODEL_LOADER_DISPLAY_MAPPINGS,
T5GEMMA_MODEL_LOADER_DISPLAY_MAPPINGS,
LLM_ENCODER_DISPLAY_MAPPINGS,
T5GEMMA_ENCODER_DISPLAY_MAPPINGS,
ADAPTER_LOADER_DISPLAY_MAPPINGS,
ADAPTER_LOADER_CUSTOM_DISPLAY_MAPPINGS,
ADAPTER_NODE_DISPLAY_MAPPINGS,
T5GEMMA_ADAPTER_NODE_DISPLAY_MAPPINGS,
]
for mapping in all_class_mappings:
NODE_CLASS_MAPPINGS.update(mapping)
for mapping in all_display_mappings:
NODE_DISPLAY_NAME_MAPPINGS.update(mapping)
# Version and metadata
__version__ = "3.0.1"
__author__ = "NeuroSenko"
__description__ = "ComfyUI nodes for LLM to SDXL adapter workflow"
# Export information for ComfyUI
WEB_DIRECTORY = "./web" # For any web UI components (if needed)
# Log successful initialization
logger.info(f"LLM SDXL Adapter v{__version__} initialized successfully")
logger.info(f"Registered {len(NODE_CLASS_MAPPINGS)} nodes from separate files:")
for node_name in sorted(NODE_CLASS_MAPPINGS.keys()):
display_name = NODE_DISPLAY_NAME_MAPPINGS.get(node_name, node_name)
logger.info(f" - {node_name} ({display_name})")
# Custom type definitions for ComfyUI
CUSTOM_TYPES = {
"LLM_MODEL": "Language Model instance",
"LLM_TOKENIZER": "Language Model tokenizer instance",
"LLM_HIDDEN_STATES": "LLM model hidden states",
"LLM_ADAPTER": "Adapter model instance",
"LLM_ATTENTION_MASK": "LLM attention mask",
"VECTOR_CONDITIONING": "SDXL vector conditioning",
}
def get_node_info() -> Dict[str, any]:
"""
Return information about available nodes for debugging/documentation
"""
return {
"version": __version__,
"author": __author__,
"description": __description__,
"nodes": {
name: {
"display_name": NODE_DISPLAY_NAME_MAPPINGS.get(name, name),
"class": cls.__name__,
"category": getattr(cls, "CATEGORY", "unknown") if hasattr(cls, "CATEGORY") else "unknown",
"function": getattr(cls, "FUNCTION", "unknown") if hasattr(cls, "FUNCTION") else "unknown"
}
for name, cls in NODE_CLASS_MAPPINGS.items()
},
"custom_types": CUSTOM_TYPES
}
# Optional: Setup hook for ComfyUI initialization
def setup_js():
"""
Setup any JavaScript/web components if needed
"""
pass
# Export what ComfyUI expects
__all__ = [
"NODE_CLASS_MAPPINGS",
"NODE_DISPLAY_NAME_MAPPINGS",
"WEB_DIRECTORY",
"get_node_info"
]
# Print initialization message
print(f"\n{'='*60}")
print(f" ComfyUI LLM SDXL Adapter v{__version__} - Loaded Successfully")
print(f"{'='*60}")
print(f" Available Nodes: {len(NODE_CLASS_MAPPINGS)}")
print(f" Main Workflow: LLMModelLoader -> LLMTextEncoder -> LLMAdapterLoader -> ApplyLLMToSDXLAdapter -> KSampler")
print(f" Supports: Gemma, Llama, Mistral, and other compatible LLMs")
print(f" Quick Start: Use modular nodes for flexible workflows")
print(f"{'='*60}\n")