From 6a7edf367f80a786c200d216ef07bb1a46901a5f Mon Sep 17 00:00:00 2001 From: Jesse Rabek Date: Thu, 27 Nov 2025 19:36:52 +0100 Subject: [PATCH] Implement logging for find_flux_transformer and apply_adapter methods - Added logging configuration to control verbosity via the BOKEH_DEBUG environment variable. - Enhanced `find_flux_transformer` with detailed logging to trace the search process for FLUX transformers, including model structure and attribute checks. - Updated `apply_adapter` to log the steps taken during adapter application, including transformer verification and adapter loading. - Improved error handling with logging for better diagnostics in case of failures. --- nodes.py | 400 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 337 insertions(+), 63 deletions(-) diff --git a/nodes.py b/nodes.py index 44d6d1d..b44d072 100644 --- a/nodes.py +++ b/nodes.py @@ -3,6 +3,7 @@ import numpy as np from typing import Optional, Tuple import sys import os +import logging # Import bokeh adapter from .bokeh_diffusion.adapter_flux import BokehFluxControlAdapter @@ -10,137 +11,339 @@ from .bokeh_diffusion.utils import color_transfer_lab MIN_BOKEH, MAX_BOKEH = 0, 30 +# Configure logging - can be controlled via BOKEH_DEBUG environment variable +# Set BOKEH_DEBUG=1 for DEBUG level, BOKEH_DEBUG=2 for even more verbose +_log_level = os.environ.get('BOKEH_DEBUG', '1') +if _log_level == '2': + logging.basicConfig(level=logging.DEBUG, format='[BokehDiffusion] %(levelname)s: %(message)s') + logger = logging.getLogger(__name__) + logger.setLevel(logging.DEBUG) +elif _log_level == '1': + logging.basicConfig(level=logging.INFO, format='[BokehDiffusion] %(levelname)s: %(message)s') + logger = logging.getLogger(__name__) + logger.setLevel(logging.INFO) +else: + logging.basicConfig(level=logging.WARNING, format='[BokehDiffusion] %(levelname)s: %(message)s') + logger = logging.getLogger(__name__) + logger.setLevel(logging.WARNING) + def find_flux_transformer(model): """Find the FLUX transformer in a ComfyUI model""" + logger.info("=" * 80) + logger.info("Starting FLUX transformer search") + logger.info(f"Model type: {type(model)}") + logger.info(f"Model ID: {id(model)}") + # Helper function to check if an object is a FLUX transformer - def is_flux_transformer(obj): + def is_flux_transformer(obj, obj_name="unknown"): if obj is None: + logger.debug(f" [is_flux_transformer] {obj_name}: Object is None") return False obj_type = str(type(obj)) + logger.debug(f" [is_flux_transformer] {obj_name}: Type = {obj_type}") + # Check for FluxTransformer2DModel class name if 'FluxTransformer2DModel' in obj_type: + logger.info(f" [is_flux_transformer] {obj_name}: ✓ MATCH - FluxTransformer2DModel detected!") return True + # Check for attn_processors attribute (key indicator of FLUX transformer) - if hasattr(obj, 'attn_processors'): + has_attn_procs = hasattr(obj, 'attn_processors') + has_set_attn = hasattr(obj, 'set_attn_processor') + logger.debug(f" [is_flux_transformer] {obj_name}: has attn_processors={has_attn_procs}, has set_attn_processor={has_set_attn}") + + if has_attn_procs: # Additional check: FLUX transformers have set_attn_processor method - if hasattr(obj, 'set_attn_processor'): + if has_set_attn: + logger.info(f" [is_flux_transformer] {obj_name}: ✓ MATCH - Has attn_processors and set_attn_processor!") return True + else: + logger.debug(f" [is_flux_transformer] {obj_name}: Has attn_processors but missing set_attn_processor") + + logger.debug(f" [is_flux_transformer] {obj_name}: ✗ Not a transformer") return False # Try different possible locations for the transformer # Most common: model.model.diffusion_model (ComfyUI ModelPatcher structure) + logger.info("Checking model.model structure...") if hasattr(model, 'model'): + logger.info(f" model.model exists: {type(model.model)}") + logger.debug(f" model.model attributes: {[a for a in dir(model.model) if not a.startswith('__')][:20]}") + if hasattr(model.model, 'diffusion_model'): + logger.info(" Found model.model.diffusion_model") flux_model = model.model.diffusion_model flux_type = str(type(flux_model)) + logger.info(f" flux_model type: {flux_type}") # Check if it's a ComfyUI Flux wrapper (comfy.ldm.flux.model.Flux) # In this case, the actual transformer is usually in flux_model.transformer if 'comfy.ldm.flux' in flux_type or 'comfy.model_base.Flux' in flux_type: + logger.info(" ✓ Detected ComfyUI Flux wrapper - searching for transformer inside...") + # The actual FluxTransformer2DModel is typically in the 'transformer' attribute + logger.info(" Checking flux_model.transformer...") if hasattr(flux_model, 'transformer'): + logger.info(" flux_model.transformer exists!") transformer = flux_model.transformer - if is_flux_transformer(transformer): + logger.info(f" transformer type: {type(transformer)}") + if is_flux_transformer(transformer, "flux_model.transformer"): + logger.info(" ✓ FOUND TRANSFORMER at flux_model.transformer!") return transformer - # Also check other common locations - for attr_name in ['model', '_model']: + else: + logger.warning(" flux_model.transformer exists but is_flux_transformer returned False") + else: + logger.warning(" flux_model.transformer attribute NOT FOUND") + + # Check all direct attributes (including private ones) + logger.info(" Checking direct attributes: model, _model, transformer, _transformer...") + for attr_name in ['model', '_model', 'transformer', '_transformer']: + logger.debug(f" Checking attribute: {attr_name}") if hasattr(flux_model, attr_name): - inner_obj = getattr(flux_model, attr_name) - if inner_obj is not None and is_flux_transformer(inner_obj): - return inner_obj + logger.info(f" {attr_name} exists!") + try: + inner_obj = getattr(flux_model, attr_name) + logger.debug(f" {attr_name} type: {type(inner_obj)}") + if inner_obj is not None: + if is_flux_transformer(inner_obj, f"flux_model.{attr_name}"): + logger.info(f" ✓ FOUND TRANSFORMER at flux_model.{attr_name}!") + return inner_obj + # Recursively check if it contains the transformer + if hasattr(inner_obj, 'attn_processors') or 'FluxTransformer' in str(type(inner_obj)): + logger.debug(f" {attr_name} has attn_processors or FluxTransformer in type") + # Check nested + if hasattr(inner_obj, 'transformer'): + logger.info(f" {attr_name}.transformer exists!") + nested = getattr(inner_obj, 'transformer') + if is_flux_transformer(nested, f"flux_model.{attr_name}.transformer"): + logger.info(f" ✓ FOUND TRANSFORMER at flux_model.{attr_name}.transformer!") + return nested + except (AttributeError, RuntimeError, TypeError) as e: + logger.debug(f" Error accessing {attr_name}: {e}") + continue + else: + logger.debug(f" {attr_name} does not exist") # Search through all named modules/children to find the transformer # ComfyUI might store it as a submodule + logger.info(" Searching through named_modules...") + transformer_candidates = [] + attn_processor_candidates = [] try: + module_count = 0 for name, module in flux_model.named_modules(): - if is_flux_transformer(module): - return module - except (AttributeError, RuntimeError, TypeError): + module_count += 1 + module_type = str(type(module)) + # Check if it's a FluxTransformer2DModel + if 'FluxTransformer2DModel' in module_type: + logger.debug(f" Found FluxTransformer2DModel candidate: {name}") + transformer_candidates.append((name, module_type)) + if is_flux_transformer(module, f"named_modules[{name}]"): + logger.info(f" ✓ FOUND TRANSFORMER in named_modules: {name} ({type(module)})!") + return module + # Check if it has attn_processors + elif hasattr(module, 'attn_processors') and hasattr(module, 'set_attn_processor'): + logger.debug(f" Found attn_processor candidate: {name}") + attn_processor_candidates.append((name, module_type)) + if is_flux_transformer(module, f"named_modules[{name}]"): + logger.info(f" ✓ FOUND TRANSFORMER-LIKE in named_modules: {name} ({type(module)})!") + return module + + logger.info(f" Searched {module_count} modules total") + logger.info(f" Found {len(transformer_candidates)} FluxTransformer2DModel candidates") + logger.info(f" Found {len(attn_processor_candidates)} attn_processor candidates") + + # Print candidate modules for debugging + if transformer_candidates: + logger.info(" FluxTransformer2DModel candidates:") + for name, mod_type in transformer_candidates[:20]: # Show first 20 + logger.info(f" {name}: {mod_type}") + + if attn_processor_candidates: + logger.info(" attn_processor candidates:") + for name, mod_type in attn_processor_candidates[:20]: # Show first 20 + logger.info(f" {name}: {mod_type}") + + except (AttributeError, RuntimeError, TypeError) as e: + logger.error(f" Error searching named_modules: {e}", exc_info=True) pass # Also check direct children + logger.info(" Checking direct children...") try: + child_count = 0 for child in flux_model.children(): - if is_flux_transformer(child): + child_count += 1 + logger.debug(f" Child {child_count}: {type(child)}") + if is_flux_transformer(child, f"children[{child_count}]"): + logger.info(f" ✓ FOUND TRANSFORMER in children: {type(child)}!") return child - except (AttributeError, RuntimeError, TypeError): + logger.info(f" Checked {child_count} direct children") + except (AttributeError, RuntimeError, TypeError) as e: + logger.error(f" Error searching children: {e}", exc_info=True) + pass + + # Try searching through all attributes more thoroughly + # Check if any attribute contains FluxTransformer2DModel + logger.info(" Searching through all private attributes...") + try: + all_attrs = [a for a in dir(flux_model) if a.startswith('_') and not a.startswith('__')] + logger.debug(f" Found {len(all_attrs)} private attributes to check") + checked_count = 0 + for attr_name in all_attrs: + checked_count += 1 + if checked_count % 10 == 0: + logger.debug(f" Checked {checked_count}/{len(all_attrs)} attributes...") + try: + attr_obj = getattr(flux_model, attr_name, None) + if attr_obj is not None: + attr_type = str(type(attr_obj)) + # Check if it's a FluxTransformer2DModel + if 'FluxTransformer2DModel' in attr_type: + logger.info(f" Found FluxTransformer2DModel in attribute: {attr_name} ({attr_type})") + if is_flux_transformer(attr_obj, f"attr[{attr_name}]"): + logger.info(f" ✓ FOUND TRANSFORMER in attribute: {attr_name}!") + return attr_obj + # Check if it has attn_processors + if hasattr(attr_obj, 'attn_processors') and hasattr(attr_obj, 'set_attn_processor'): + logger.info(f" Found transformer-like object in attribute: {attr_name} ({attr_type})") + if is_flux_transformer(attr_obj, f"attr[{attr_name}]"): + logger.info(f" ✓ FOUND TRANSFORMER in attribute: {attr_name}!") + return attr_obj + except (AttributeError, RuntimeError, TypeError) as e: + logger.debug(f" Error accessing {attr_name}: {e}") + continue + logger.info(f" Checked {checked_count} private attributes") + except Exception as e: + logger.error(f" Error searching attributes: {e}", exc_info=True) pass else: # Not a ComfyUI wrapper, check if it's the transformer directly - if is_flux_transformer(flux_model): + logger.info(" Not a ComfyUI wrapper, checking if flux_model is transformer directly...") + if is_flux_transformer(flux_model, "flux_model (direct)"): + logger.info(" ✓ FOUND TRANSFORMER - flux_model is transformer directly!") return flux_model + else: + logger.warning(" model.model.diffusion_model does not exist") + logger.info(" Checking model.model.transformer...") if hasattr(model.model, 'transformer'): + logger.info(" model.model.transformer exists!") transformer = model.model.transformer - if is_flux_transformer(transformer): + if is_flux_transformer(transformer, "model.model.transformer"): + logger.info(" ✓ FOUND TRANSFORMER at model.model.transformer!") return transformer + else: + logger.debug(" model.model.transformer does not exist") + # Sometimes the model.model itself might be the transformer - if is_flux_transformer(model.model): + logger.info(" Checking if model.model is transformer directly...") + if is_flux_transformer(model.model, "model.model (direct)"): + logger.info(" ✓ FOUND TRANSFORMER - model.model is transformer directly!") return model.model + else: + logger.warning(" model.model does not exist") # Check for private _model attribute (some wrappers use this) + logger.info("Checking model._model...") if hasattr(model, '_model'): + logger.info(" model._model exists!") try: inner_model = model._model if inner_model is not None: + logger.info(f" _model type: {type(inner_model)}") if hasattr(inner_model, 'diffusion_model'): + logger.info(" _model.diffusion_model exists!") transformer = inner_model.diffusion_model - if is_flux_transformer(transformer): + if is_flux_transformer(transformer, "model._model.diffusion_model"): + logger.info(" ✓ FOUND TRANSFORMER at model._model.diffusion_model!") return transformer if hasattr(inner_model, 'transformer'): + logger.info(" _model.transformer exists!") transformer = inner_model.transformer - if is_flux_transformer(transformer): + if is_flux_transformer(transformer, "model._model.transformer"): + logger.info(" ✓ FOUND TRANSFORMER at model._model.transformer!") return transformer - if is_flux_transformer(inner_model): + if is_flux_transformer(inner_model, "model._model (direct)"): + logger.info(" ✓ FOUND TRANSFORMER - model._model is transformer directly!") return inner_model - except (AttributeError, RuntimeError, TypeError): + except (AttributeError, RuntimeError, TypeError) as e: + logger.debug(f" Error accessing _model: {e}") pass + else: + logger.debug(" model._model does not exist") # Check if model has a get_model() method (some ComfyUI wrappers) + logger.info("Checking model.get_model()...") if hasattr(model, 'get_model'): + logger.info(" model.get_model() exists!") try: inner_model = model.get_model() + logger.info(f" get_model() returned: {type(inner_model)}") if inner_model is not None: if hasattr(inner_model, 'diffusion_model'): + logger.info(" inner_model.diffusion_model exists!") transformer = inner_model.diffusion_model - if is_flux_transformer(transformer): + if is_flux_transformer(transformer, "get_model().diffusion_model"): + logger.info(" ✓ FOUND TRANSFORMER at get_model().diffusion_model!") return transformer if hasattr(inner_model, 'transformer'): + logger.info(" inner_model.transformer exists!") transformer = inner_model.transformer - if is_flux_transformer(transformer): + if is_flux_transformer(transformer, "get_model().transformer"): + logger.info(" ✓ FOUND TRANSFORMER at get_model().transformer!") return transformer - if is_flux_transformer(inner_model): + if is_flux_transformer(inner_model, "get_model() (direct)"): + logger.info(" ✓ FOUND TRANSFORMER - get_model() result is transformer directly!") return inner_model - except (AttributeError, RuntimeError, TypeError): + except (AttributeError, RuntimeError, TypeError) as e: + logger.debug(f" Error calling get_model(): {e}") pass + else: + logger.debug(" model.get_model() does not exist") # Direct access: model.diffusion_model + logger.info("Checking model.diffusion_model (direct)...") if hasattr(model, 'diffusion_model'): + logger.info(" model.diffusion_model exists!") transformer = model.diffusion_model - if is_flux_transformer(transformer): + if is_flux_transformer(transformer, "model.diffusion_model (direct)"): + logger.info(" ✓ FOUND TRANSFORMER at model.diffusion_model!") return transformer + else: + logger.debug(" model.diffusion_model does not exist") # Direct access: model.transformer + logger.info("Checking model.transformer (direct)...") if hasattr(model, 'transformer'): + logger.info(" model.transformer exists!") transformer = model.transformer - if is_flux_transformer(transformer): + if is_flux_transformer(transformer, "model.transformer (direct)"): + logger.info(" ✓ FOUND TRANSFORMER at model.transformer!") return transformer + else: + logger.debug(" model.transformer does not exist") # Last resort: check if model itself is the transformer - if is_flux_transformer(model): + logger.info("Checking if model itself is transformer...") + if is_flux_transformer(model, "model (self)"): + logger.info(" ✓ FOUND TRANSFORMER - model itself is transformer!") return model # Recursive search as final fallback - def search_recursive(obj, depth=0, max_depth=3, visited=None): + logger.info("Starting recursive search as final fallback...") + def search_recursive(obj, depth=0, max_depth=3, visited=None, path=""): if visited is None: visited = set() if depth > max_depth or id(obj) in visited: return None visited.add(id(obj)) + logger.debug(f" [recursive] depth={depth}, path={path}, type={type(obj)}") # Check if current object is the transformer - if is_flux_transformer(obj): + if is_flux_transformer(obj, f"recursive[{path}]"): + logger.info(f" ✓ FOUND TRANSFORMER in recursive search at: {path}!") return obj # Search in common attribute names @@ -149,7 +352,8 @@ def find_flux_transformer(model): try: attr_obj = getattr(obj, attr_name) if attr_obj is not None and id(attr_obj) not in visited: - result = search_recursive(attr_obj, depth + 1, max_depth, visited) + new_path = f"{path}.{attr_name}" if path else attr_name + result = search_recursive(attr_obj, depth + 1, max_depth, visited, new_path) if result is not None: return result except (AttributeError, RuntimeError, TypeError): @@ -160,7 +364,8 @@ def find_flux_transformer(model): try: inner_model = obj.get_model() if inner_model is not None and id(inner_model) not in visited: - result = search_recursive(inner_model, depth + 1, max_depth, visited) + new_path = f"{path}.get_model()" if path else "get_model()" + result = search_recursive(inner_model, depth + 1, max_depth, visited, new_path) if result is not None: return result except (AttributeError, RuntimeError, TypeError): @@ -168,37 +373,50 @@ def find_flux_transformer(model): return None - transformer = search_recursive(model) + transformer = search_recursive(model, path="model") if transformer is not None: + logger.info(" ✓ FOUND TRANSFORMER via recursive search!") return transformer - # Debug: print model structure to help diagnose - print("DEBUG: Model structure:") - print(f" Model type: {type(model)}") + # Final debug summary + logger.error("=" * 80) + logger.error("FAILED TO FIND FLUX TRANSFORMER") + logger.error("=" * 80) + logger.error("Model structure summary:") + logger.error(f" Model type: {type(model)}") + logger.error(f" Model attributes: {[a for a in dir(model) if not a.startswith('__')][:30]}") if hasattr(model, 'model'): - print(f" model.model type: {type(model.model)}") + logger.error(f" model.model type: {type(model.model)}") + logger.error(f" model.model attributes: {[a for a in dir(model.model) if not a.startswith('__')][:30]}") if hasattr(model.model, 'diffusion_model'): flux_model = model.model.diffusion_model flux_type = str(type(flux_model)) - print(f" model.model.diffusion_model type: {flux_type}") - print(f" Has attn_processors: {hasattr(flux_model, 'attn_processors')}") + logger.error(f" model.model.diffusion_model type: {flux_type}") + logger.error(f" Has attn_processors: {hasattr(flux_model, 'attn_processors')}") + logger.error(f" Has set_attn_processor: {hasattr(flux_model, 'set_attn_processor')}") # Check if it's a ComfyUI Flux wrapper if 'comfy.ldm.flux' in flux_type or 'comfy.model_base.Flux' in flux_type: - print(" Detected ComfyUI Flux wrapper - searching for transformer...") + logger.error(" Detected ComfyUI Flux wrapper") # Check for transformer attribute if hasattr(flux_model, 'transformer'): transformer = flux_model.transformer - print(f" Found flux_model.transformer: {type(transformer)}") - print(f" Has attn_processors: {hasattr(transformer, 'attn_processors')}") - print(f" Has set_attn_processor: {hasattr(transformer, 'set_attn_processor')}") + logger.error(f" flux_model.transformer exists: {type(transformer)}") + logger.error(f" Has attn_processors: {hasattr(transformer, 'attn_processors')}") + logger.error(f" Has set_attn_processor: {hasattr(transformer, 'set_attn_processor')}") else: - print(" flux_model.transformer attribute NOT FOUND") + logger.error(" flux_model.transformer attribute NOT FOUND") # List all attributes that might be relevant - relevant_attrs = [attr for attr in dir(flux_model) - if not attr.startswith('__') and - not isinstance(getattr(flux_model, attr, None), (str, int, float, bool, list, dict, tuple))] - print(f" Relevant attributes: {relevant_attrs[:20]}") # Show first 20 + all_attrs = [attr for attr in dir(flux_model) if not attr.startswith('__')] + logger.error(f" All non-private attributes ({len(all_attrs)} total):") + for attr in all_attrs[:50]: # Show first 50 + try: + attr_obj = getattr(flux_model, attr, None) + if attr_obj is not None and not isinstance(attr_obj, (str, int, float, bool, list, dict, tuple)): + logger.error(f" {attr}: {type(attr_obj)}") + except: + pass + logger.error("=" * 80) return None @@ -266,47 +484,103 @@ class ApplyBokehAdapter: def apply_adapter(self, model, adapter): """Apply the bokeh adapter to the model's transformer""" + logger.info("=" * 80) + logger.info("ApplyBokehAdapter.apply_adapter() called") + logger.info(f"Adapter config: {adapter}") try: # Find the transformer + logger.info("Step 1: Finding FLUX transformer...") transformer = find_flux_transformer(model) if transformer is None: + logger.error("Transformer is None - search failed!") raise Exception("Could not find FLUX transformer in model. Make sure you're using a FLUX model.") + logger.info(f"✓ Transformer found: {type(transformer)}") + logger.info(f" Transformer ID: {id(transformer)}") + # Check if transformer has attn_processors (required for adapter) + logger.info("Step 2: Verifying transformer has attn_processors...") if not hasattr(transformer, 'attn_processors'): + logger.error("Transformer does not have attn_processors attribute!") raise Exception("Model transformer does not have attn_processors. This may not be a FLUX model.") + logger.info("✓ Transformer has attn_processors") + logger.debug(f" attn_processors type: {type(transformer.attn_processors)}") + if hasattr(transformer.attn_processors, '__len__'): + logger.debug(f" Number of processors: {len(transformer.attn_processors)}") + + # Check for set_attn_processor method + if not hasattr(transformer, 'set_attn_processor'): + logger.error("Transformer does not have set_attn_processor method!") + raise Exception("Model transformer does not have set_attn_processor method. This may not be a FLUX model.") + logger.info("✓ Transformer has set_attn_processor method") + # Load the adapter if not already loaded adapter_name = adapter["adapter_name"] + logger.info(f"Step 3: Loading adapter from {adapter_name}...") if adapter["adapter"] is None: - print(f"Loading Bokeh adapter from {adapter_name}...") - adapter_obj = BokehFluxControlAdapter.from_pretrained( - adapter_name, - base_model=transformer, - ) - # Move to same device as transformer - device = next(transformer.parameters()).device - dtype = next(transformer.parameters()).dtype - adapter_obj = adapter_obj.to(device=device, dtype=dtype) - adapter["adapter"] = adapter_obj - print("Bokeh adapter loaded successfully.") + logger.info(f" Adapter not yet loaded, loading now...") + try: + adapter_obj = BokehFluxControlAdapter.from_pretrained( + adapter_name, + base_model=transformer, + ) + logger.info(" ✓ Adapter loaded from HuggingFace") + + # Move to same device as transformer + logger.info("Step 4: Moving adapter to same device/dtype as transformer...") + try: + device = next(transformer.parameters()).device + dtype = next(transformer.parameters()).dtype + logger.info(f" Transformer device: {device}, dtype: {dtype}") + adapter_obj = adapter_obj.to(device=device, dtype=dtype) + logger.info(" ✓ Adapter moved to transformer device/dtype") + except Exception as e: + logger.warning(f" Error moving adapter to device: {e}") + logger.info(" Continuing anyway...") + + adapter["adapter"] = adapter_obj + logger.info("✓ Bokeh adapter loaded and configured successfully") + except Exception as e: + logger.error(f" Failed to load adapter: {e}", exc_info=True) + raise + else: + logger.info(" Adapter already loaded, reusing existing instance") adapter_obj = adapter["adapter"] + logger.info(f" Adapter object: {type(adapter_obj)}") # Set scales - if adapter["bokeh_scale"] != 1.0: - adapter_obj.set_bokeh_scale(adapter["bokeh_scale"]) - if adapter["lora_scale"] != 1.0: - adapter_obj.set_lora_scale(adapter["lora_scale"]) + logger.info("Step 5: Setting adapter scales...") + bokeh_scale = adapter.get("bokeh_scale", 1.0) + lora_scale = adapter.get("lora_scale", 1.0) + logger.info(f" bokeh_scale: {bokeh_scale}, lora_scale: {lora_scale}") + + if bokeh_scale != 1.0: + logger.info(f" Setting bokeh_scale to {bokeh_scale}") + adapter_obj.set_bokeh_scale(bokeh_scale) + if lora_scale != 1.0: + logger.info(f" Setting lora_scale to {lora_scale}") + adapter_obj.set_lora_scale(lora_scale) # Store adapter in model for use during sampling + logger.info("Step 6: Storing adapter in model...") model.bokeh_adapter = adapter_obj model.bokeh_adapter_config = adapter model._bokeh_transformer = transformer + logger.info("✓ Adapter stored in model") + logger.info("=" * 80) + logger.info("✓ Bokeh adapter applied successfully!") + logger.info("=" * 80) return (model,) except Exception as e: + logger.error("=" * 80) + logger.error("FAILED TO APPLY BOKEH ADAPTER") + logger.error("=" * 80) + logger.error(f"Error: {e}", exc_info=True) + logger.error("=" * 80) raise Exception(f"Failed to apply bokeh adapter: {e}")