1515from compel .prompt_parser import FlattenedPrompt , Blend , Fragment , CrossAttentionControlSubstitute , PromptParser , \
1616 Conjunction
1717from .devices import torch_dtype
18+ from .generator .diffusers_pipeline import StableDiffusionGeneratorPipeline
1819from ..models .diffusion .shared_invokeai_diffusion import InvokeAIDiffuserComponent
1920from ldm .invoke .globals import Globals
2021
21- def get_tokenizer (model ) -> CLIPTokenizer :
22- # TODO remove legacy ckpt fallback handling
23- return (getattr (model , 'tokenizer' , None ) # diffusers
24- or model .cond_stage_model .tokenizer ) # ldm
25-
26- def get_text_encoder (model ) -> Any :
27- # TODO remove legacy ckpt fallback handling
28- return (getattr (model , 'text_encoder' , None ) # diffusers
29- or UnsqueezingLDMTransformer (model .cond_stage_model .transformer )) # ldm
30-
3122class UnsqueezingLDMTransformer :
3223 def __init__ (self , ldm_transformer ):
3324 self .ldm_transformer = ldm_transformer
@@ -41,15 +32,15 @@ def __call__(self, *args, **kwargs):
4132 return insufficiently_unsqueezed_tensor .unsqueeze (0 )
4233
4334
44- def get_uc_and_c_and_ec (prompt_string , model , log_tokens = False , skip_normalize_legacy_blend = False ):
35+ def get_uc_and_c_and_ec (prompt_string ,
36+ model : StableDiffusionGeneratorPipeline ,
37+ log_tokens = False , skip_normalize_legacy_blend = False ):
4538 # lazy-load any deferred textual inversions.
4639 # this might take a couple of seconds the first time a textual inversion is used.
4740 model .textual_inversion_manager .create_deferred_token_ids_for_any_trigger_terms (prompt_string )
4841
49- tokenizer = get_tokenizer (model )
50- text_encoder = get_text_encoder (model )
51- compel = Compel (tokenizer = tokenizer ,
52- text_encoder = text_encoder ,
42+ compel = Compel (tokenizer = model .tokenizer ,
43+ text_encoder = model .text_encoder ,
5344 textual_inversion_manager = model .textual_inversion_manager ,
5445 dtype_for_device_getter = torch_dtype )
5546
@@ -78,14 +69,20 @@ def get_uc_and_c_and_ec(prompt_string, model, log_tokens=False, skip_normalize_l
7869 negative_conjunction = Compel .parse_prompt_string (negative_prompt_string )
7970 negative_prompt : FlattenedPrompt | Blend = negative_conjunction .prompts [0 ]
8071
72+ tokens_count = get_max_token_count (model .tokenizer , positive_prompt )
8173 if log_tokens or getattr (Globals , "log_tokenization" , False ):
82- log_tokenization (positive_prompt , negative_prompt , tokenizer = tokenizer )
83-
84- c , options = compel .build_conditioning_tensor_for_prompt_object (positive_prompt )
85- uc , _ = compel .build_conditioning_tensor_for_prompt_object (negative_prompt )
86-
87- tokens_count = get_max_token_count (tokenizer , positive_prompt )
88-
74+ log_tokenization (positive_prompt , negative_prompt , tokenizer = model .tokenizer )
75+
76+ # some LoRA models also mess with the text encoder, so they must be active while compel builds conditioning tensors
77+ lora_conditioning_ec = InvokeAIDiffuserComponent .ExtraConditioningInfo (tokens_count_including_eos_bos = tokens_count ,
78+ lora_conditions = lora_conditions )
79+ with InvokeAIDiffuserComponent .custom_attention_context (model .unet ,
80+ extra_conditioning_info = lora_conditioning_ec ,
81+ step_count = - 1 ):
82+ c , options = compel .build_conditioning_tensor_for_prompt_object (positive_prompt )
83+ uc , _ = compel .build_conditioning_tensor_for_prompt_object (negative_prompt )
84+
85+ # now build the "real" ec
8986 ec = InvokeAIDiffuserComponent .ExtraConditioningInfo (tokens_count_including_eos_bos = tokens_count ,
9087 cross_attention_control_args = options .get (
9188 'cross_attention_control' , None ),
0 commit comments