V 2.0.0 - Auto config #22 - new params
This commit is contained in:
+135
-102
@@ -647,11 +647,14 @@ class PrimereModelConceptSelector:
|
||||
zimage_model, zimage_clip, zimage_vae
|
||||
)
|
||||
|
||||
class PrimereAutoSamplerSettings:
|
||||
class PrimereModelControl:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
CATEGORY = TREE_DASHBOARD
|
||||
RETURN_TYPES = ("TUPLE", comfy.samplers.KSampler.SAMPLERS, comfy.samplers.KSampler.SCHEDULERS, "INT", "FLOAT", "STRING")
|
||||
RETURN_NAMES = ("DATA", "SAMPLER_NAME", "SCHEDULER_NAME", "STEPS", "CFG", "MODEL_CONCEPT")
|
||||
FUNCTION = "get_controlledsampler"
|
||||
RETURN_NAMES = ("CONTROL_DATA", "SAMPLER_NAME", "SCHEDULER_NAME", "STEPS", "CFG", "MODEL_CONCEPT")
|
||||
FUNCTION = "get_primeremodelcontrol"
|
||||
OUTPUT_NODE = True
|
||||
|
||||
kolors_schedulers = ["EulerDiscreteScheduler", "EulerAncestralDiscreteScheduler", "DPMSolverMultistepScheduler", "DPMSolverMultistepScheduler_SDE_karras", "UniPCMultistepScheduler", "DEISMultistepScheduler"]
|
||||
@@ -686,57 +689,74 @@ class PrimereAutoSamplerSettings:
|
||||
"required": {
|
||||
"model_concept": ("STRING", {"default": None, "forceInput": True}),
|
||||
"model_name": ("CHECKPOINT_NAME", {"default": None, "forceInput": True}),
|
||||
|
||||
"concepts": (["Auto"] + cls.CONCEPT_LIST,),
|
||||
"models": (["Auto"] + cls.MODELLIST,),
|
||||
|
||||
"sampler_name": (comfy.samplers.KSampler.SAMPLERS,),
|
||||
"scheduler_name": (cls.sana_schedulers + cls.kolors_schedulers + comfy.samplers.KSampler.SCHEDULERS,),
|
||||
"steps": ("INT", {"default": 12, "min": 1, "max": 1000, "step": 1}),
|
||||
"override_steps": ("BOOLEAN", {"default": False, "label_off": "Set by sampler settings", "label_on": "Set by model filename"}),
|
||||
"cfg": ("FLOAT", {"default": 7, "min": 0.1, "max": 100, "step": 0.01}),
|
||||
"rescale_cfg": ("FLOAT", {"default": 1, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"align_your_steps": ("BOOLEAN", {"default": False, "label_on": "Use AlignYourSteps", "label_off": "Ignore AlignYourSteps"}),
|
||||
"model_sampling": ("FLOAT", {"default": 2.5, "min": 0.0, "max": 10.0, "step": 0.01}),
|
||||
"last_layer": ("INT", {"default": 0, "min": -24, "max": 0, "step": 1}),
|
||||
"sigma_max": ("FLOAT", {"default": 120, "min": 1, "max": 200, "step": 0.001}),
|
||||
"sigma_min": ("FLOAT", {"default": 1, "min": 0.001, "max": 100, "step": 0.001}),
|
||||
|
||||
"vae": (cls.VAELIST,),
|
||||
"vae_selection": ("BOOLEAN", {"default": True, "label_on": "Use baked if exist", "label_off": "Always use custom"}),
|
||||
"clip_selection": ("BOOLEAN", {"default": True, "label_on": "Use baked if exist", "label_off": "Always use custom"}),
|
||||
"last_layer": ("INT", {"default": 0, "min": -24, "max": 0, "step": 1}),
|
||||
|
||||
"encoder_1": (list(dict.fromkeys(["None"] + cls.TEXT_ENCODERS + cls.CLIPLIST + cls.UNETLIST + cls.TEXT_ENCODERS_PATHS)),),
|
||||
"encoder_2": (list(dict.fromkeys(["None"] + cls.TEXT_ENCODERS + cls.CLIPLIST + cls.UNETLIST + cls.TEXT_ENCODERS_PATHS)),),
|
||||
"encoder_3": (list(dict.fromkeys(["None"] + cls.TEXT_ENCODERS + cls.CLIPLIST + cls.UNETLIST + cls.TEXT_ENCODERS_PATHS)),),
|
||||
"clip_attn": (["Custom"] + list(clipping.CLIP_ATTN_PRESETS.keys()), {"default": "Natural"}),
|
||||
"clip_attn_mult_query": ('FLOAT', {"default": 1.00, "min": 0.80, "max": 1.20, "step": 0.01}),
|
||||
"clip_attn_mult_key": ('FLOAT', {"default": 1.00, "min": 0.80, "max": 1.20, "step": 0.01}),
|
||||
"clip_attn_mult_value": ('FLOAT', {"default": 1.00, "min": 0.80, "max": 1.20, "step": 0.01}),
|
||||
"clip_attn_mult_output": ('FLOAT', {"default": 1.00, "min": 0.80, "max": 1.20, "step": 0.01}),
|
||||
|
||||
"attn_preset": (["Custom", "Auto"] + list(clipping.ATTN_PRESETS.keys()), {"default": "Off"}),
|
||||
"attn_query": ('FLOAT', {"default": 1.00, "min": 0.80, "max": 1.20, "step": 0.01}),
|
||||
"attn_key": ('FLOAT', {"default": 1.00, "min": 0.80, "max": 1.20, "step": 0.01}),
|
||||
"attn_value": ('FLOAT', {"default": 1.00, "min": 0.80, "max": 1.20, "step": 0.01}),
|
||||
"attn_output": ('FLOAT', {"default": 1.00, "min": 0.80, "max": 1.20, "step": 0.01}),
|
||||
"attn_cross_query": ("FLOAT", {"default": 1.0, "min": 0.80, "max": 1.20, "step": 0.01}),
|
||||
"attn_cross_key": ("FLOAT", {"default": 1.0, "min": 0.80, "max": 1.20, "step": 0.01}),
|
||||
"attn_cross_value": ("FLOAT", {"default": 1.0, "min": 0.80, "max": 1.20, "step": 0.01}),
|
||||
"attn_cross_output": ("FLOAT", {"default": 1.0, "min": 0.80, "max": 1.20, "step": 0.01}),
|
||||
|
||||
"sampler": (["custom_advanced", "ksampler"], {"default": "ksampler"}),
|
||||
"align_your_steps": ("BOOLEAN", {"default": False, "label_on": "Use AlignYourSteps", "label_off": "Ignore AlignYourSteps"}),
|
||||
"model_sampling": ("FLOAT", {"default": 2.5, "min": 0.0, "max": 10.0, "step": 0.01}),
|
||||
"edm_sampling": (["edm_playground_v2.5", "v_prediction", "edm", "eps", "cosmos_rflow"], {"default": "edm_playground_v2.5"}),
|
||||
"discrete_sampling": (["default", "eps", "v_prediction", "x0"], {"default": "default"}),
|
||||
"discrete_zsnr": ("BOOLEAN", {"default": False, "label_on": "Zero SNR", "label_off": "No Zero SNR"}),
|
||||
"sigma_max": ("FLOAT", {"default": 120, "min": 1, "max": 200, "step": 0.001}),
|
||||
"sigma_min": ("FLOAT", {"default": 1, "min": 0.001, "max": 100, "step": 0.001}),
|
||||
"flux_max_shift": ("FLOAT", {"default": 1.15, "min": 0.0, "max": 100.0, "step": 0.01}),
|
||||
"flux_base_shift": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 100.0, "step": 0.01}),
|
||||
"beta_alpha": ("FLOAT", {"default": 0.6, "min": 0.0, "max": 50.0, "step": 0.01}),
|
||||
"beta_beta": ("FLOAT", {"default": 0.6, "min": 0.0, "max": 50.0, "step": 0.01}),
|
||||
|
||||
"guidance": ('FLOAT', {"default": 3.5, "min": 0.0, "max": 100.0, "step": 0.1}),
|
||||
"weight_dtype": (["None"] + ["Auto", "default", "fp16", "bf16", "fp32", "fp8_e4m3fn", "fp8_e5m2"], {"default": "default"}),
|
||||
"precision": (["None"] + ['fp32', 'fp16', 'quant8', 'quant4'], {"default": "fp16"}),
|
||||
|
||||
"lcm_lora": ("BOOLEAN", {"default": False, "label_on": "LCM lora ON", "label_off": "LCM lora OFF"}),
|
||||
# "lcm_lora_name": (cls.LCM_LORAS,),
|
||||
"lcm_lora_strength": ("FLOAT", {"default": 1.000, "min": -20.000, "max": 20.000, "step": 0.001}),
|
||||
|
||||
"speed_lora": ("BOOLEAN", {"default": False, "label_on": "Speed lora ON", "label_off": "Speed lora OFF"}),
|
||||
"speed_lora_name": (cls.SPEED_LORAS,),
|
||||
# "speed_lora_version": ([1.0, 1.1, 2.0], {"default": 2.0}),
|
||||
# "speed_lora_precision": ("BOOLEAN", {"default": True, "label_on": "FP32", "label_off": "BF16"}),
|
||||
# "speed_lora_step": ([4, 6, 8, 10, 12, 16], {"default": 8}),
|
||||
"speed_lora_strength": ("FLOAT", {"default": 1.00, "min": -20.00, "max": 20.00, "step": 0.01}),
|
||||
"speed_lora_cfg": ("FLOAT", {"default": 1.0, "min": 0.1, "max": 100, "step": 0.01}),
|
||||
"speed_lora_steps_offset": ("INT", {"default": 0, "min": -5, "max": 5, "step": 1}),
|
||||
|
||||
"srpo_lora": ("BOOLEAN", {"default": False, "label_on": "Use SRPO Lora", "label_off": "Ignore SRPO Lora"}),
|
||||
"srpo_lora_name": (cls.SRPO_LORAS,),
|
||||
# "srpo_lora_type": (["R&Q", "RockerBOO", "oficial", "adaptive"], {"default": "oficial"}),
|
||||
# "srpo_lora_rank": ([8, 16, 32, 64, 128, 256], {"default": 8}),
|
||||
"srpo_lora_strength": ("FLOAT", {"default": 1, "min": -20.000, "max": 20.000, "step": 0.001}),
|
||||
|
||||
"srpo_svdq_lora": ("BOOLEAN", {"default": False, "label_on": "Use SRPO SVDQ Lora", "label_off": "Ignore SRPO SVDQ Lora"}),
|
||||
"srpo_svdq_lora_name": (cls.SRPO_SVDQ_LORAS,),
|
||||
"srpo_svdq_lora_strength": ("FLOAT", {"default": 1, "min": -20.000, "max": 20.000, "step": 0.001}),
|
||||
|
||||
"nunchaku_lora": ("BOOLEAN", {"default": False, "label_on": "Use nunchaku Lora", "label_off": "Ignore nunchaku Lora"}),
|
||||
"nunchaku_lora_name": (cls.NUNCHAKU_LORAS,),
|
||||
# "nunchaku_lora_type": (["kontext_deblur", "kontext_face_detailer", "anything_extracted"], {"default": "anything_extracted"}),
|
||||
# "nunchaku_lora_rank": ([64, 256], {"default": 64}),
|
||||
"nunchaku_lora_strength": ("FLOAT", {"default": 1, "min": -20.000, "max": 20.000, "step": 0.001}),
|
||||
|
||||
"refiner": ("BOOLEAN", {"default": False, "label_on": "Refiner ON", "label_off": "Refiner OFF"}),
|
||||
"refiner_model": (cls.REFINER_MODELS,),
|
||||
"refiner_sampler": (comfy.samplers.KSampler.SAMPLERS, {"default": "dpmpp_2m"}),
|
||||
@@ -746,11 +766,11 @@ class PrimereAutoSamplerSettings:
|
||||
"refiner_start": ("INT", {"default": 12, "min": 1, "max": 1000, "step": 1}),
|
||||
"refiner_denoise": ("FLOAT", {"default": 0.9, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"refiner_sampling_denoise": ("FLOAT", {"default": 0.9, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"refiner_ignore_prompt": ("BOOLEAN", {"default": True, "label_on": "Ignore prompt", "label_off": "Send prompt to refiner"}),
|
||||
"refiner_ignore_prompt": ("BOOLEAN", {"default": True, "label_on": "Ignore prompt", "label_off": "Send prompt to refiner"})
|
||||
}
|
||||
}
|
||||
|
||||
def get_controlledsampler(self, **kwargs):
|
||||
def get_primeremodelcontrol(self, **kwargs):
|
||||
model_concept = kwargs.pop('model_concept', 'SD1')
|
||||
model_name = kwargs.pop('model_name', None)
|
||||
concepts = kwargs.pop('concepts', 'Auto')
|
||||
@@ -802,18 +822,27 @@ class PrimereAutoSamplerSettings:
|
||||
speed_lora_cfg_val = kwargs.get('speed_lora_cfg')
|
||||
if speed_lora_cfg_val is not None:
|
||||
cfg = float(speed_lora_cfg_val)
|
||||
clip_attn = kwargs.pop('clip_attn', 'Natural')
|
||||
clip_attn_mult_query = kwargs.pop('clip_attn_mult_query', 1.0)
|
||||
clip_attn_mult_key = kwargs.pop('clip_attn_mult_key', 1.0)
|
||||
clip_attn_mult_value = kwargs.pop('clip_attn_mult_value', 1.0)
|
||||
clip_attn_mult_output = kwargs.pop('clip_attn_mult_output', 1.0)
|
||||
if clip_attn == 'Custom':
|
||||
attn_q, attn_k, attn_v, attn_out = clip_attn_mult_query, clip_attn_mult_key, clip_attn_mult_value, clip_attn_mult_output
|
||||
attn_preset = kwargs.pop('attn_preset', 'Off')
|
||||
attn_query = kwargs.pop('attn_query', 1.0)
|
||||
attn_key = kwargs.pop('attn_key', 1.0)
|
||||
attn_value = kwargs.pop('attn_value', 1.0)
|
||||
attn_output = kwargs.pop('attn_output', 1.0)
|
||||
attn_cross_query = kwargs.pop('attn_cross_query', 1.0)
|
||||
attn_cross_key = kwargs.pop('attn_cross_key', 1.0)
|
||||
attn_cross_value = kwargs.pop('attn_cross_value', 1.0)
|
||||
attn_cross_output = kwargs.pop('attn_cross_output', 1.0)
|
||||
if attn_preset == 'Auto':
|
||||
attn_preset = clipping.detect_attn_preset(model_name)
|
||||
attn_q, attn_k, attn_v, attn_out, cross_q, cross_k, cross_v, cross_out = clipping.ATTN_PRESETS.get(attn_preset, (1.0,)*8)
|
||||
elif attn_preset == 'Custom':
|
||||
attn_q, attn_k, attn_v, attn_out = attn_query, attn_key, attn_value, attn_output
|
||||
cross_q, cross_k, cross_v, cross_out = attn_cross_query, attn_cross_key, attn_cross_value, attn_cross_output
|
||||
else:
|
||||
attn_q, attn_k, attn_v, attn_out = clipping.CLIP_ATTN_PRESETS.get(clip_attn, (1.0, 1.0, 1.0, 1.0))
|
||||
attn_q, attn_k, attn_v, attn_out, cross_q, cross_k, cross_v, cross_out = clipping.ATTN_PRESETS.get(attn_preset, (1.0,)*8)
|
||||
suppressed = [k + "_" for k, v in kwargs.items() if v == "None" or v is False]
|
||||
kwargs = {k: v for k, v in kwargs.items() if v != "None" and not any(k.startswith(p) for p in suppressed)}
|
||||
kwargs['encoders'] = [kwargs[k] for k in ('encoder_1', 'encoder_2', 'encoder_3') if kwargs.get(k) not in (None, 'None')]
|
||||
kwargs['model_name'] = model_name
|
||||
kwargs['model_concept'] = active_concept
|
||||
kwargs['sampler_name'] = sampler_name
|
||||
kwargs['scheduler_name'] = scheduler_name
|
||||
@@ -823,6 +852,10 @@ class PrimereAutoSamplerSettings:
|
||||
kwargs['clip_attn_k'] = attn_k
|
||||
kwargs['clip_attn_v'] = attn_v
|
||||
kwargs['clip_attn_out'] = attn_out
|
||||
kwargs['attn_cross_q'] = cross_q
|
||||
kwargs['attn_cross_k'] = cross_k
|
||||
kwargs['attn_cross_v'] = cross_v
|
||||
kwargs['attn_cross_out'] = cross_out
|
||||
return {"ui": {"active_concept": [active_display]}, "result": (kwargs, sampler_name, scheduler_name, steps, round(cfg, 2), active_concept,)}
|
||||
|
||||
class PrimereConceptDataTuple:
|
||||
@@ -864,15 +897,15 @@ class PrimereCKPTLoader:
|
||||
},
|
||||
"optional": {
|
||||
# "model_concept": ("STRING", {"forceInput": True}),
|
||||
"concept_data": ("TUPLE", {"default": None, "forceInput": True}),
|
||||
"control_data": ("TUPLE", {"default": None, "forceInput": True}),
|
||||
"loaded_model": ('MODEL', {"forceInput": True, "default": None}),
|
||||
"loaded_clip": ('CLIP', {"forceInput": True, "default": None}),
|
||||
"loaded_vae": ('VAE', {"forceInput": True, "default": None}),
|
||||
},
|
||||
}
|
||||
|
||||
def load_primere_ckpt(self, ckpt_name, use_yaml, concept_data=None, loaded_model=None, loaded_clip=None, loaded_vae=None):
|
||||
model_concept = concept_data['model_concept']
|
||||
def load_primere_ckpt(self, ckpt_name, use_yaml, control_data=None, loaded_model=None, loaded_clip=None, loaded_vae=None):
|
||||
model_concept = control_data['model_concept']
|
||||
|
||||
try:
|
||||
comfy.model_management.soft_empty_cache()
|
||||
@@ -901,35 +934,35 @@ class PrimereCKPTLoader:
|
||||
|
||||
match model_concept:
|
||||
case 'SD1' | 'SD2' | 'SDXL' | 'Illustrious' | 'Turbo' | 'Pony':
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_sd_model(self, ckpt_name, use_yaml, ModelConfigFullPath, concept_data)
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_sd_model(self, ckpt_name, use_yaml, ModelConfigFullPath, control_data)
|
||||
case 'SD3':
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_sd3_model(self, ckpt_name, concept_data)
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_sd3_model(self, ckpt_name, control_data)
|
||||
case 'StableCascade':
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_stable_cascade_model(self, ckpt_name, concept_data)
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_stable_cascade_model(self, ckpt_name, control_data)
|
||||
case 'Z-Image':
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_zimage_model(self, ckpt_name, concept_data)
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_zimage_model(self, ckpt_name, control_data)
|
||||
case 'Flux':
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_flux_model(self, ckpt_name, concept_data)
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_flux_model(self, ckpt_name, control_data)
|
||||
case 'LCM':
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_lcm_model(self, ckpt_name, concept_data)
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_lcm_model(self, ckpt_name, control_data)
|
||||
case 'Hyper' | 'Lightning':
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_lightning_hyper_model(self, ckpt_name, concept_data)
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_lightning_hyper_model(self, ckpt_name, control_data)
|
||||
case 'Playground':
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_playground_model(self, ckpt_name, use_yaml, ModelConfigFullPath, concept_data)
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_playground_model(self, ckpt_name, use_yaml, ModelConfigFullPath, control_data)
|
||||
case 'PixartSigma':
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_pixart_model(self, ckpt_name, concept_data)
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_pixart_model(self, ckpt_name, control_data)
|
||||
case 'AuraFlow':
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_auraflow_model(self, ckpt_name, concept_data)
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_auraflow_model(self, ckpt_name, control_data)
|
||||
case 'SANA1024' | 'SANA512':
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_sana_model(self, ckpt_name, concept_data)
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_sana_model(self, ckpt_name, control_data)
|
||||
case 'KwaiKolors':
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_kolors_model(self, ckpt_name, concept_data)
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_kolors_model(self, ckpt_name, control_data)
|
||||
case 'Hunyuan':
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_hunyuan_model(self, ckpt_name, concept_data)
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_hunyuan_model(self, ckpt_name, control_data)
|
||||
case 'QwenGen' | 'QwenEdit':
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_qwen_model(self, ckpt_name, concept_data)
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_qwen_model(self, ckpt_name, control_data)
|
||||
case 'Chroma':
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_chroma_model(self, ckpt_name, concept_data)
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = model_loaders.load_chroma_model(self, ckpt_name, control_data)
|
||||
|
||||
return (OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE, MODEL_VERSION_ORIGINAL)
|
||||
|
||||
@@ -1036,7 +1069,7 @@ class PrimereFastSeed:
|
||||
|
||||
class PrimereFractalLatent:
|
||||
RETURN_TYPES = ("LATENT", "IMAGE", "TUPLE")
|
||||
RETURN_NAMES = ("LATENTS", "PREVIEWS", "WORKFLOW_TUPLE")
|
||||
RETURN_NAMES = ("LATENTS", "PREVIEWS", "CONTROL_DATA")
|
||||
FUNCTION = "primere_latent_noise"
|
||||
CATEGORY = TREE_DASHBOARD
|
||||
|
||||
@@ -1062,7 +1095,7 @@ class PrimereFractalLatent:
|
||||
},
|
||||
"optional": {
|
||||
"optional_vae": ("VAE",),
|
||||
"workflow_tuple": ("TUPLE", {"default": None}),
|
||||
"control_data": ("TUPLE", {"default": None}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1075,19 +1108,19 @@ class PrimereFractalLatent:
|
||||
if kwargs['expand_random_limits'] == True or kwargs['rand_noise_type'] == True or kwargs['rand_device'] == True or kwargs['rand_alpha_exponent'] == True or kwargs['rand_modulator'] == True:
|
||||
return float('NaN')
|
||||
|
||||
def primere_latent_noise(self, width, height, rand_noise_type, noise_type, rand_alpha_exponent, alpha_exponent, alpha_exp_rand_min, alpha_exp_rand_max, rand_modulator, modulator, modulator_rand_min, modulator_rand_max, noise_seed, rand_device, device, optional_vae=None, workflow_tuple=None, expand_random_limits=False):
|
||||
if workflow_tuple is not None and len(workflow_tuple) > 0 and 'exif_status' in workflow_tuple and workflow_tuple['exif_status'] == 'SUCCEED':
|
||||
if 'latent_data' in workflow_tuple and len(workflow_tuple['latent_data']) > 0 and 'setup_states' in workflow_tuple and 'latent_setup' in workflow_tuple['setup_states']:
|
||||
if workflow_tuple['setup_states']['latent_setup'] == True:
|
||||
def primere_latent_noise(self, width, height, rand_noise_type, noise_type, rand_alpha_exponent, alpha_exponent, alpha_exp_rand_min, alpha_exp_rand_max, rand_modulator, modulator, modulator_rand_min, modulator_rand_max, noise_seed, rand_device, device, optional_vae=None, control_data=None, expand_random_limits=False):
|
||||
if control_data is not None and len(control_data) > 0 and 'exif_status' in control_data and control_data['exif_status'] == 'SUCCEED':
|
||||
if 'latent_data' in control_data and len(control_data['latent_data']) > 0 and 'setup_states' in control_data and 'latent_setup' in control_data['setup_states']:
|
||||
if control_data['setup_states']['latent_setup'] == True:
|
||||
expand_random_limits = False
|
||||
rand_device = False
|
||||
rand_alpha_exponent = False
|
||||
rand_modulator = False
|
||||
rand_noise_type = False
|
||||
noise_type = workflow_tuple['latent_data']['noise_type']
|
||||
device = workflow_tuple['latent_data']['device']
|
||||
alpha_exponent = workflow_tuple['latent_data']['alpha_exponent']
|
||||
modulator = workflow_tuple['latent_data']['modulator']
|
||||
noise_type = control_data['latent_data']['noise_type']
|
||||
device = control_data['latent_data']['device']
|
||||
alpha_exponent = control_data['latent_data']['alpha_exponent']
|
||||
modulator = control_data['latent_data']['modulator']
|
||||
|
||||
if expand_random_limits == True:
|
||||
rand_device = True
|
||||
@@ -1124,7 +1157,7 @@ class PrimereFractalLatent:
|
||||
if optional_vae is None:
|
||||
latents = tensors.permute(0, 3, 1, 2)
|
||||
latents = F.interpolate(latents, size=((height // 8), (width // 8)), mode='nearest-exact')
|
||||
return {'samples': latents}, tensors, workflow_tuple
|
||||
return {'samples': latents}, tensors, control_data
|
||||
|
||||
encoder = nodes.VAEEncode()
|
||||
latents = []
|
||||
@@ -1135,21 +1168,21 @@ class PrimereFractalLatent:
|
||||
except Exception:
|
||||
latents = tensors.permute(0, 3, 1, 2)
|
||||
latents = F.interpolate(latents, size=((height // 8), (width // 8)), mode='nearest-exact')
|
||||
return {'samples': latents}, tensors, workflow_tuple
|
||||
return {'samples': latents}, tensors, control_data
|
||||
latents = torch.cat(latents)
|
||||
|
||||
if workflow_tuple is not None:
|
||||
workflow_tuple['latent_data'] = {}
|
||||
workflow_tuple['latent_data']['noise_type'] = noise_type
|
||||
workflow_tuple['latent_data']['alpha_exponent'] = alpha_exponent
|
||||
workflow_tuple['latent_data']['modulator'] = modulator
|
||||
workflow_tuple['latent_data']['device'] = device
|
||||
if control_data is not None:
|
||||
control_data['latent_data'] = {}
|
||||
control_data['latent_data']['noise_type'] = noise_type
|
||||
control_data['latent_data']['alpha_exponent'] = alpha_exponent
|
||||
control_data['latent_data']['modulator'] = modulator
|
||||
control_data['latent_data']['device'] = device
|
||||
|
||||
return {'samples': latents}, tensors, workflow_tuple
|
||||
return {'samples': latents}, tensors, control_data
|
||||
|
||||
class PrimereCLIP:
|
||||
RETURN_TYPES = ("CONDITIONING", "CONDITIONING", "STRING", "STRING", "STRING", "STRING", "STRING", "TUPLE")
|
||||
RETURN_NAMES = ("COND+", "COND-", "PROMPT+", "PROMPT-", "T5XXL_PROMPT", "PROMPT L+", "PROMPT L-", "WORKFLOW_TUPLE")
|
||||
RETURN_NAMES = ("COND+", "COND-", "PROMPT+", "PROMPT-", "T5XXL_PROMPT", "PROMPT L+", "PROMPT L-", "CONTROL_DATA")
|
||||
FUNCTION = "clip_encode"
|
||||
CATEGORY = TREE_DASHBOARD
|
||||
|
||||
@@ -1176,7 +1209,7 @@ class PrimereCLIP:
|
||||
return {
|
||||
"required": {
|
||||
"clip": ("CLIP", {"forceInput": True}),
|
||||
"concept_data": ("TUPLE", {"default": None, "forceInput": True}),
|
||||
"control_data": ("TUPLE", {"default": None, "forceInput": True}),
|
||||
"positive_prompt": ("STRING", {"forceInput": True}),
|
||||
"negative_prompt": ("STRING", {"forceInput": True}),
|
||||
"negative_strength": ("FLOAT", {"default": 1.2, "min": 0.0, "max": 10.0, "step": 0.01}),
|
||||
@@ -1220,7 +1253,7 @@ class PrimereCLIP:
|
||||
"l_strength": ("FLOAT", {"default": 1, "min": 0.0, "max": 10.0, "step": 0.01}),
|
||||
"width": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION, "forceInput": True}),
|
||||
"height": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION, "forceInput": True}),
|
||||
"workflow_tuple": ("TUPLE", {"default": None}),
|
||||
"control_data": ("TUPLE", {"default": None}),
|
||||
},
|
||||
"hidden": {
|
||||
"extra_pnginfo": "EXTRA_PNGINFO",
|
||||
@@ -1228,8 +1261,8 @@ class PrimereCLIP:
|
||||
}
|
||||
}
|
||||
|
||||
def clip_encode(self, clip, concept_data, negative_strength, int_style_pos_strength, int_style_neg_strength, opt_pos_strength, opt_neg_strength, style_pos_strength, style_neg_strength, style_handling, style_swap, enhanced_prompt_strength, int_style_pos, int_style_neg, adv_encode, token_normalization, weight_interpretation, l_strength, extra_pnginfo, prompt, copy_prompt_to_l=True, width=1024, height=1024, positive_prompt="", negative_prompt="", enhanced_prompt="", enhanced_prompt_usage="T5-XXL", clip_model='Default', longclip_model='Default', model_keywords=None, lora_keywords=None, lycoris_keywords=None, embedding_pos=None, embedding_neg=None, opt_pos_prompt="", opt_neg_prompt="", style_position=False, style_neg_prompt="", style_pos_prompt="", positive_l="", negative_l="", use_int_style=False, edit_image_list=None, edit_vae=None, workflow_tuple=None):
|
||||
model_concept = concept_data.get('model_concept', 'SD1')
|
||||
def clip_encode(self, clip, negative_strength, int_style_pos_strength, int_style_neg_strength, opt_pos_strength, opt_neg_strength, style_pos_strength, style_neg_strength, style_handling, style_swap, enhanced_prompt_strength, int_style_pos, int_style_neg, adv_encode, token_normalization, weight_interpretation, l_strength, extra_pnginfo, prompt, copy_prompt_to_l=True, width=1024, height=1024, positive_prompt="", negative_prompt="", enhanced_prompt="", enhanced_prompt_usage="T5-XXL", clip_model='Default', longclip_model='Default', model_keywords=None, lora_keywords=None, lycoris_keywords=None, embedding_pos=None, embedding_neg=None, opt_pos_prompt="", opt_neg_prompt="", style_position=False, style_neg_prompt="", style_pos_prompt="", positive_l="", negative_l="", use_int_style=False, edit_image_list=None, edit_vae=None, control_data=None):
|
||||
model_concept = control_data.get('model_concept', 'SD1')
|
||||
|
||||
advanced_default = ['StableCascade', 'Chroma', 'KwaiKolors', 'Flux', "Z-Image", 'Pony', 'SD1', 'SD2', 'SD3', 'Lightning', 'Hunyuan', 'QwenGen', 'QwenEdit', 'AuraFlow']
|
||||
if model_concept in advanced_default:
|
||||
@@ -1250,29 +1283,29 @@ class PrimereCLIP:
|
||||
embedding_pos, embedding_neg,
|
||||
)
|
||||
|
||||
clip = clipping.apply_clip_attention_multiply(clip, workflow_tuple)
|
||||
clip = clipping.apply_clip_attention_multiply(clip, control_data)
|
||||
match model_concept:
|
||||
case 'SD3':
|
||||
return clipping.encode_sd3(clip, positive_text, negative_text, t5xxl_prompt, workflow_tuple)
|
||||
return clipping.encode_sd3(clip, positive_text, negative_text, t5xxl_prompt, control_data)
|
||||
case 'StableCascade':
|
||||
return clipping.encode_stable_cascade(clip, positive_text, negative_text, workflow_tuple)
|
||||
return clipping.encode_stable_cascade(clip, positive_text, negative_text, control_data)
|
||||
case 'Flux':
|
||||
return clipping.encode_flux(clip, positive_text, negative_text, t5xxl_prompt, workflow_tuple)
|
||||
return clipping.encode_flux(clip, positive_text, negative_text, t5xxl_prompt, control_data)
|
||||
case 'PixartSigma':
|
||||
return clipping.encode_pixart_sigma(clip, positive_text, negative_text, workflow_tuple)
|
||||
return clipping.encode_pixart_sigma(clip, positive_text, negative_text, control_data)
|
||||
case 'SANA1024' | 'SANA512':
|
||||
return clipping.encode_sana(clip, positive_text, negative_text, t5xxl_prompt, workflow_tuple)
|
||||
return clipping.encode_sana(clip, positive_text, negative_text, t5xxl_prompt, control_data)
|
||||
case 'KwaiKolors':
|
||||
return clipping.encode_kolors(clip, positive_text, negative_text, t5xxl_prompt, workflow_tuple)
|
||||
return clipping.encode_kolors(clip, positive_text, negative_text, t5xxl_prompt, control_data)
|
||||
case 'Hunyuan':
|
||||
return clipping.encode_hunyuan(self, clip, positive_text, negative_text, t5xxl_prompt, workflow_tuple)
|
||||
return clipping.encode_hunyuan(self, clip, positive_text, negative_text, t5xxl_prompt, control_data)
|
||||
case 'QwenEdit':
|
||||
return clipping.encode_qwen_edit(self, clip, positive_text, negative_text, t5xxl_prompt, edit_vae, edit_image_list, workflow_tuple)
|
||||
return clipping.encode_qwen_edit(self, clip, positive_text, negative_text, t5xxl_prompt, edit_vae, edit_image_list, control_data)
|
||||
# case 'Chroma':
|
||||
# return clipping.encode_chroma(clip, positive_text, negative_text, workflow_tuple)
|
||||
# return clipping.encode_chroma(clip, positive_text, negative_text, control_data)
|
||||
case _:
|
||||
clip = clipping.apply_clip_overrides(self, clip, workflow_tuple)
|
||||
return clipping.encode_standard(clip, positive_text, negative_text, t5xxl_prompt, adv_encode, token_normalization, weight_interpretation, positive_l, negative_l, width, height, workflow_tuple, advanced_encode)
|
||||
clip = clipping.apply_clip_overrides(self, clip, control_data)
|
||||
return clipping.encode_standard(clip, positive_text, negative_text, t5xxl_prompt, adv_encode, token_normalization, weight_interpretation, positive_l, negative_l, width, height, control_data, advanced_encode)
|
||||
|
||||
class PrimereResolution:
|
||||
RETURN_TYPES = ("INT", "INT", "INT", "STRING")
|
||||
@@ -1750,37 +1783,37 @@ class PrimereNetworkTagLoader:
|
||||
"lycoris_keyword_weight": ("FLOAT", {"default": 1.0, "min": 0, "max": 10.0, "step": 0.1}),
|
||||
},
|
||||
"optional": {
|
||||
"workflow_tuple": ("TUPLE", {"default": None}),
|
||||
"control_data": ("TUPLE", {"default": None}),
|
||||
}
|
||||
}
|
||||
|
||||
def load_networks(self, model, clip, positive_prompt, process_lora, process_lycoris, process_hypernetwork, copy_weight_to_clip, lora_clip_custom_weight, lycoris_clip_custom_weight, use_lora_keyword, use_lycoris_keyword, lora_keyword_placement, lycoris_keyword_placement, lora_keyword_selection, lycoris_keyword_selection, lora_keywords_num, lycoris_keywords_num, lora_keyword_weight, lycoris_keyword_weight, hypernetwork_safe_load=True, workflow_tuple=None):
|
||||
if workflow_tuple is not None and len(workflow_tuple) > 0 and 'setup_states' in workflow_tuple and 'exif_status' in workflow_tuple and workflow_tuple['exif_status'] == 'SUCCEED':
|
||||
def load_networks(self, model, clip, positive_prompt, process_lora, process_lycoris, process_hypernetwork, copy_weight_to_clip, lora_clip_custom_weight, lycoris_clip_custom_weight, use_lora_keyword, use_lycoris_keyword, lora_keyword_placement, lycoris_keyword_placement, lora_keyword_selection, lycoris_keyword_selection, lora_keywords_num, lycoris_keywords_num, lora_keyword_weight, lycoris_keyword_weight, hypernetwork_safe_load=True, control_data=None):
|
||||
if control_data is not None and len(control_data) > 0 and 'setup_states' in control_data and 'exif_status' in control_data and control_data['exif_status'] == 'SUCCEED':
|
||||
concept = 'Auto'
|
||||
stack_version = workflow_tuple['model_version']
|
||||
if 'model_concept' in workflow_tuple:
|
||||
concept = workflow_tuple['model_concept']
|
||||
if 'model_version' in workflow_tuple:
|
||||
if concept == 'Auto' and workflow_tuple['model_version'] == 'SDXL':
|
||||
stack_version = control_data['model_version']
|
||||
if 'model_concept' in control_data:
|
||||
concept = control_data['model_concept']
|
||||
if 'model_version' in control_data:
|
||||
if concept == 'Auto' and control_data['model_version'] == 'SDXL':
|
||||
stack_version = 'SDXL'
|
||||
|
||||
if 'setup_states' in workflow_tuple and 'network_data' in workflow_tuple:
|
||||
if 'lora_setup' in workflow_tuple['setup_states'] and workflow_tuple['setup_states']['lora_setup'] == True:
|
||||
loader = networkhandler.getNetworkLoader(workflow_tuple, 'lora', self.LORASCOUNT, True, stack_version)
|
||||
if 'setup_states' in control_data and 'network_data' in control_data:
|
||||
if 'lora_setup' in control_data['setup_states'] and control_data['setup_states']['lora_setup'] == True:
|
||||
loader = networkhandler.getNetworkLoader(control_data, 'lora', self.LORASCOUNT, True, stack_version)
|
||||
if len(loader) > 0:
|
||||
networkData = networkhandler.LoraHandler(self, loader, model, clip, [], False, lora_keywords_num, use_lora_keyword, lora_keyword_selection, lora_keyword_weight, lora_keyword_placement)
|
||||
model = networkData[0]
|
||||
clip = networkData[1]
|
||||
|
||||
if 'lycoris_setup' in workflow_tuple['setup_states'] and workflow_tuple['setup_states']['lycoris_setup'] == True:
|
||||
loader = networkhandler.getNetworkLoader(workflow_tuple, 'lycoris', self.LYCOSCOUNT, True, stack_version)
|
||||
if 'lycoris_setup' in control_data['setup_states'] and control_data['setup_states']['lycoris_setup'] == True:
|
||||
loader = networkhandler.getNetworkLoader(control_data, 'lycoris', self.LYCOSCOUNT, True, stack_version)
|
||||
if len(loader) > 0:
|
||||
networkData = networkhandler.LycorisHandler(self, loader, model, clip, [], False, lycoris_keywords_num, use_lycoris_keyword, lycoris_keyword_selection, lycoris_keyword_weight, lycoris_keyword_placement)
|
||||
model = networkData[0]
|
||||
clip = networkData[1]
|
||||
|
||||
if 'embedding_setup' in workflow_tuple['setup_states'] and workflow_tuple['setup_states']['embedding_setup'] == True:
|
||||
loader = networkhandler.getNetworkLoader(workflow_tuple, 'embedding', self.EMBCOUNT, False, stack_version)
|
||||
if 'embedding_setup' in control_data['setup_states'] and control_data['setup_states']['embedding_setup'] == True:
|
||||
loader = networkhandler.getNetworkLoader(control_data, 'embedding', self.EMBCOUNT, False, stack_version)
|
||||
if len(loader) > 0:
|
||||
networkData = networkhandler.EmbeddingHandler(self, loader, None, None)
|
||||
if networkData[0][0] is not None:
|
||||
@@ -1788,8 +1821,8 @@ class PrimereNetworkTagLoader:
|
||||
tokens = clip.tokenize(positive_prompt)
|
||||
clip = clip.encode_from_tokens(tokens, return_pooled=False)
|
||||
|
||||
if 'hypernetwork_setup' in workflow_tuple['setup_states'] and workflow_tuple['setup_states']['hypernetwork_setup'] == True:
|
||||
loader = networkhandler.getNetworkLoader(workflow_tuple, 'hypernetwork', self.HNCOUNT, False, stack_version)
|
||||
if 'hypernetwork_setup' in control_data['setup_states'] and control_data['setup_states']['hypernetwork_setup'] == True:
|
||||
loader = networkhandler.getNetworkLoader(control_data, 'hypernetwork', self.HNCOUNT, False, stack_version)
|
||||
if len(loader) > 0:
|
||||
networkData = networkhandler.HypernetworkHandler(self, loader, model, hypernetwork_safe_load)
|
||||
model = networkData[0]
|
||||
|
||||
+81
-145
@@ -160,20 +160,8 @@ class PrimereMetaSave:
|
||||
subdirs.append(file_output.sanitize_path_part(Path(concept_name).stem.upper()))
|
||||
|
||||
if add_modelname_to_path == True and 'model' in image_metadata:
|
||||
if 'model_concept' in image_metadata and 'model_version' in image_metadata:
|
||||
original_model_concept_selector = 'Auto'
|
||||
if extra_pnginfo is not None:
|
||||
WORKFLOWDATA = extra_pnginfo['workflow']['nodes']
|
||||
original_model_concept_selector = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereModelConceptSelector', 'model_concept', prompt)
|
||||
if image_metadata['model_concept'] != image_metadata['model_version'] or original_model_concept_selector != 'Auto':
|
||||
match image_metadata['model_concept']:
|
||||
case 'Flux':
|
||||
if image_metadata['concept_data']['flux_selector'] == 'GGUF':
|
||||
image_metadata['model'] = image_metadata['concept_data']['flux_gguf']
|
||||
else:
|
||||
image_metadata['model'] = image_metadata['concept_data']['flux_diffusion']
|
||||
case 'StableCascade':
|
||||
image_metadata['model'] = image_metadata['concept_data']['cascade_stage_c']
|
||||
if image_metadata.get('model_name'):
|
||||
image_metadata['model'] = image_metadata['model_name']
|
||||
subdirs.append(file_output.sanitize_path_part(Path(image_metadata['model']).stem.upper()))
|
||||
|
||||
if subpath_priority == True and 'preferred' in image_metadata and type(image_metadata['preferred']).__name__ == 'dict' and len(image_metadata['preferred']) > 0 and 'subpath' in image_metadata['preferred']:
|
||||
@@ -396,27 +384,22 @@ class PrimereMetaCollector:
|
||||
|
||||
INPUT_DICT = {
|
||||
"required": {
|
||||
"positive": ('STRING', {"forceInput": True, "default": "Red sportcar racing"}),
|
||||
"model_name": ('CHECKPOINT_NAME', {"forceInput": True, "default": None}),
|
||||
"positive": ('STRING', {"forceInput": True, "default": "Red sportcar racing on the street of metropolis"}),
|
||||
"negative": ('STRING', {"forceInput": True, "default": "Cute cat, nsfw, nude, nudity, porn"})
|
||||
}, "optional": {
|
||||
"model_concept": ("STRING", {"default": "Auto", "forceInput": True}),
|
||||
"control_data": ("TUPLE", {"default": None, "forceInput": True}),
|
||||
"seed": ('INT', {"forceInput": True, "default": 1}),
|
||||
"t5_xxl_prompt": ('STRING', {"forceInput": True}),
|
||||
"positive_l": ('STRING', {"forceInput": True}),
|
||||
"negative_l": ('STRING', {"forceInput": True}),
|
||||
"positive_r": ('STRING', {"forceInput": True}),
|
||||
"negative_r": ('STRING', {"forceInput": True}),
|
||||
"model": ('CHECKPOINT_NAME', {"forceInput": True, "default": None}),
|
||||
"model_version": ("STRING", {"default": 'SD1', "forceInput": True}),
|
||||
"model_concept": ("STRING", {"default": "Auto", "forceInput": True}),
|
||||
"concept_data": ("TUPLE", {"default": None, "forceInput": True}),
|
||||
"sampler": (comfy.samplers.KSampler.SAMPLERS, {"forceInput": True, "default": "euler"}),
|
||||
"scheduler": (comfy.samplers.KSampler.SCHEDULERS, {"forceInput": True, "default": "normal"}),
|
||||
"width": ('INT', {"forceInput": True, "default": 512}),
|
||||
"height": ('INT', {"forceInput": True, "default": 512}),
|
||||
"model_shapes": ('TUPLE', {"forceInput": True, "default": None}),
|
||||
"cfg": ('FLOAT', {"forceInput": True, "default": 7}),
|
||||
"steps": ('INT', {"forceInput": True, "default": 12}),
|
||||
"vae_name_sd": ('VAE_NAME', {"forceInput": True, "default": None}),
|
||||
"vae_name_sdxl": ('VAE_NAME', {"forceInput": True, "default": None}),
|
||||
"width": ('INT', {"forceInput": True, "default": 512}),
|
||||
"height": ('INT', {"forceInput": True, "default": 512}),
|
||||
"preferred": ("TUPLE", {"default": None, "forceInput": True}),
|
||||
"aesthetic_score": ('INT', {"forceInput": True, "default": 0})
|
||||
},
|
||||
@@ -446,7 +429,7 @@ class PrimereMetaCollector:
|
||||
class PrimereKSampler:
|
||||
CATEGORY = TREE_OUTPUTS
|
||||
RETURN_TYPES = ("LATENT", "TUPLE")
|
||||
RETURN_NAMES = ("LATENT", "WORKFLOW_TUPLE")
|
||||
RETURN_NAMES = ("LATENT", "CONTROL_DATA")
|
||||
FUNCTION = "pk_sampler"
|
||||
|
||||
def __init__(self):
|
||||
@@ -471,13 +454,11 @@ class PrimereKSampler:
|
||||
"variation_extender": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"variation_batch_step": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 0.5, "step": 0.01}),
|
||||
"variation_level": ("BOOLEAN", {"default": False, "label_on": "Maximize", "label_off": "Off"}),
|
||||
# "model_sampling": ("FLOAT", {"default": 2.5, "min": 0.0, "max": 10.0, "step": 0.01}),
|
||||
"device": (["DEFAULT", "GPU", "CPU"], {"default": 'DEFAULT'}),
|
||||
# "align_your_steps": ("BOOLEAN", {"default": False, "label_on": "Use AlignYourSteps", "label_off": "Ignore AlignYourSteps"}),
|
||||
"device": (["DEFAULT", "GPU", "CPU"], {"default": 'DEFAULT'})
|
||||
},
|
||||
"optional": {
|
||||
"model_concept": ("STRING", {"default": "Auto", "forceInput": True}),
|
||||
"workflow_tuple": ("TUPLE", {"default": None}),
|
||||
"control_data": ("TUPLE", {"default": None}),
|
||||
},
|
||||
"hidden": {
|
||||
"extra_pnginfo": "EXTRA_PNGINFO",
|
||||
@@ -490,24 +471,24 @@ class PrimereKSampler:
|
||||
if kwargs['variation_extender'] > 0 or kwargs['device'] != 'DEFAULT' or kwargs['variation_batch_step'] > 0 or kwargs['variation_level'] == True:
|
||||
return float("NaN")
|
||||
|
||||
def pk_sampler(self, model, seed, steps, cfg, sampler_name, scheduler_name, positive, negative, latent_image, extra_pnginfo, prompt, model_concept = "Auto", workflow_tuple = None, denoise=1.0, variation_extender = 0, variation_batch_step = 0, variation_level = False, model_sampling = 2.5, device = 'DEFAULT', align_your_steps = False):
|
||||
def pk_sampler(self, model, seed, steps, cfg, sampler_name, scheduler_name, positive, negative, latent_image, extra_pnginfo, prompt, model_concept = "Auto", control_data = None, denoise=1.0, variation_extender = 0, variation_batch_step = 0, variation_level = False, model_sampling = 2.5, device = 'DEFAULT', align_your_steps = False):
|
||||
timestamp_start = time.time()
|
||||
if workflow_tuple is not None:
|
||||
align_your_steps = workflow_tuple.get('align_your_steps', align_your_steps)
|
||||
model_sampling = workflow_tuple.get('model_sampling', model_sampling)
|
||||
if workflow_tuple is not None and len(workflow_tuple) > 0 and 'exif_status' in workflow_tuple and workflow_tuple['exif_status'] == 'SUCCEED':
|
||||
if 'sampler_settings' in workflow_tuple and len(workflow_tuple['sampler_settings']) > 0 and 'setup_states' in workflow_tuple and 'sampler_setup' in workflow_tuple['setup_states']:
|
||||
if workflow_tuple['setup_states']['sampler_setup'] == True:
|
||||
if control_data is not None:
|
||||
align_your_steps = control_data.get('align_your_steps', align_your_steps)
|
||||
model_sampling = control_data.get('model_sampling', model_sampling)
|
||||
if control_data is not None and len(control_data) > 0 and 'exif_status' in control_data and control_data['exif_status'] == 'SUCCEED':
|
||||
if 'sampler_settings' in control_data and len(control_data['sampler_settings']) > 0 and 'setup_states' in control_data and 'sampler_setup' in control_data['setup_states']:
|
||||
if control_data['setup_states']['sampler_setup'] == True:
|
||||
variation_batch_step = 0
|
||||
variation_level = False
|
||||
denoise = workflow_tuple['sampler_settings']['denoise']
|
||||
device = workflow_tuple['sampler_settings']['device']
|
||||
align_your_steps = workflow_tuple['sampler_settings']['align_your_steps']
|
||||
model_sampling = workflow_tuple['sampler_settings']['model_sampling']
|
||||
if workflow_tuple['sampler_settings']['variation_level'] == True:
|
||||
variation_extender = workflow_tuple['sampler_settings']['noise_constant']
|
||||
denoise = control_data['sampler_settings']['denoise']
|
||||
device = control_data['sampler_settings']['device']
|
||||
align_your_steps = control_data['sampler_settings']['align_your_steps']
|
||||
model_sampling = control_data['sampler_settings']['model_sampling']
|
||||
if control_data['sampler_settings']['variation_level'] == True:
|
||||
variation_extender = control_data['sampler_settings']['noise_constant']
|
||||
else:
|
||||
variation_extender = workflow_tuple['sampler_settings']['variation_extender_original']
|
||||
variation_extender = control_data['sampler_settings']['variation_extender_original']
|
||||
|
||||
samples_out = latent_image
|
||||
# out = latent_image.copy()
|
||||
@@ -605,7 +586,7 @@ class PrimereKSampler:
|
||||
variation_extender, variation_batch_step_original,
|
||||
batch_counter, variation_extender_original,
|
||||
variation_batch_step, variation_level, variation_limit,
|
||||
align_your_steps, noise_extender_ksampler, workflow_tuple)[0]
|
||||
align_your_steps, noise_extender_ksampler, control_data)[0]
|
||||
case "KwaiKolors":
|
||||
samples_out = primeresamplers.PSamplerKOROLS(self, model, seed, cfg, positive, negative, latent_image, steps, denoise, sampler_name, scheduler_name, model_sampling, 1000)[0]
|
||||
case "SD3":
|
||||
@@ -617,20 +598,17 @@ class PrimereKSampler:
|
||||
noise_constant = noise_extender_cascade
|
||||
samples_out = primeresamplers.PCascadeSampler(self, model, seed, steps, cfg, sampler_name, scheduler_name, positive, negative, latent_image, denoise, device, variation_level, variation_limit, variation_extender_original, variation_batch_step_original, variation_extender, variation_batch_step, batch_counter, noise_extender_cascade)[0]
|
||||
case "Hyper":
|
||||
CONCEPT_SELECTOR = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereModelConceptSelector', 'model_concept', prompt)
|
||||
OriginalBaseModel = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereVisualCKPT', 'base_model', prompt)
|
||||
CONCEPT_SELECTOR = control_data.get('model_concept') if control_data else None
|
||||
OriginalBaseModel = control_data.get('model_name') if control_data else None
|
||||
fullpathFile = folder_paths.get_full_path('checkpoints', OriginalBaseModel)
|
||||
is_link = os.path.islink(str(fullpathFile))
|
||||
if is_link == True:
|
||||
HYPERSD_SELECTOR = 'UNET'
|
||||
else:
|
||||
HYPERSD_SELECTOR = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereModelConceptSelector', 'hypersd_selector', prompt)
|
||||
HYPERSD_SAMPLER = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereModelConceptSelector', 'hypersd_sampler', prompt)
|
||||
HYPERSD_SELECTOR = 'UNET' if is_link else 'LORA'
|
||||
HYPERSD_SAMPLER = True
|
||||
|
||||
if model_concept == 'Hyper' and (CONCEPT_SELECTOR == 'Hyper' or CONCEPT_SELECTOR == 'Auto') and steps == 12 and HYPERSD_SELECTOR == 'LORA' and HYPERSD_SAMPLER == True:
|
||||
cfg = 3.80
|
||||
scheduler_name = 'normal'
|
||||
samples_out = primeresamplers.PSamplerHyper(self, extra_pnginfo, model, seed, steps, cfg, positive, negative, sampler_name, scheduler_name, latent_image, denoise, prompt)[0]
|
||||
cfg = float(control_data.get('cfg', 3.80))
|
||||
scheduler_name = control_data.get('scheduler_name', "normal")
|
||||
samples_out = primeresamplers.PSamplerHyper(self, extra_pnginfo, model, seed, steps, cfg, positive, negative, sampler_name, scheduler_name, latent_image, denoise, prompt, control_data)[0]
|
||||
|
||||
case 'QwenGen' | 'QwenEdit':
|
||||
align_your_steps = False
|
||||
@@ -657,14 +635,14 @@ class PrimereKSampler:
|
||||
align_your_steps, noise_extender_ksampler, None)[0]
|
||||
|
||||
case 'Flux':
|
||||
FLUX_SAMPLER = workflow_tuple.get('sampler', 'ksampler') if workflow_tuple else 'ksampler'
|
||||
FLUX_GUIDANCE = float(workflow_tuple.get('guidance', 3.5)) if workflow_tuple else 3.5
|
||||
FLUX_SAMPLER = control_data.get('sampler', 'ksampler') if control_data else 'ksampler'
|
||||
FLUX_GUIDANCE = float(control_data.get('guidance', 3.5)) if control_data else 3.5
|
||||
align_your_steps = False
|
||||
if FLUX_SAMPLER == 'custom_advanced':
|
||||
samples_out = primeresamplers.PSamplerAdvanced(self, model, seed, FLUX_GUIDANCE, positive, scheduler_name, sampler_name, steps, denoise, latent_image)[0]
|
||||
elif FLUX_SAMPLER == 'ksampler':
|
||||
CONDITIONING_POS = nodes_flux.FluxGuidance.execute(positive, FLUX_GUIDANCE)[0] if FLUX_GUIDANCE > 0 else positive
|
||||
if workflow_tuple is not None and float(workflow_tuple.get('cfg', 2.0)) < 1.2:
|
||||
if control_data is not None and float(control_data.get('cfg', 2.0)) < 1.2:
|
||||
CONDITIONING_NEG = CONDITIONING_POS
|
||||
else:
|
||||
CONDITIONING_NEG = nodes_flux.FluxGuidance.execute(negative, FLUX_GUIDANCE)[0]
|
||||
@@ -673,14 +651,14 @@ class PrimereKSampler:
|
||||
CONDITIONING_POS, CONDITIONING_NEG,
|
||||
latent_image, denoise,
|
||||
variation_extender, variation_batch_step_original, batch_counter, variation_extender_original, variation_batch_step, variation_level, variation_limit,
|
||||
align_your_steps, noise_extender_ksampler, None)[0]
|
||||
align_your_steps, noise_extender_ksampler, None, control_data)[0]
|
||||
else:
|
||||
samples_out = primeresamplers.PKSampler(self, device, seed, model,
|
||||
steps, cfg, sampler_name, scheduler_name,
|
||||
positive, negative,
|
||||
latent_image, denoise,
|
||||
variation_extender, variation_batch_step_original, batch_counter, variation_extender_original, variation_batch_step, variation_level, variation_limit,
|
||||
align_your_steps, noise_extender_ksampler, None)[0]
|
||||
align_your_steps, noise_extender_ksampler, None, control_data)[0]
|
||||
|
||||
case _:
|
||||
if model_concept == 'AuraFlow' and model_sampling is not None and model_sampling > 0:
|
||||
@@ -690,25 +668,24 @@ class PrimereKSampler:
|
||||
positive, negative,
|
||||
latent_image, denoise,
|
||||
variation_extender, variation_batch_step_original, batch_counter, variation_extender_original, variation_batch_step, variation_level, variation_limit,
|
||||
align_your_steps, noise_extender_ksampler, None)[0]
|
||||
align_your_steps, noise_extender_ksampler, None, control_data)[0]
|
||||
|
||||
if workflow_tuple is not None:
|
||||
workflow_tuple['sampler_settings'] = {}
|
||||
workflow_tuple['sampler_settings']['denoise'] = denoise
|
||||
workflow_tuple['sampler_settings']['variation_extender_original'] = variation_extender_original
|
||||
workflow_tuple['sampler_settings']['variation_batch_step_original'] = variation_batch_step_original
|
||||
workflow_tuple['sampler_settings']['variation_level'] = variation_level
|
||||
workflow_tuple['sampler_settings']['device'] = device
|
||||
workflow_tuple['sampler_settings']['align_your_steps'] = align_your_steps
|
||||
workflow_tuple['sampler_settings']['noise_constant'] = noise_constant
|
||||
workflow_tuple['sampler_settings']['variation_seed'] = seed
|
||||
workflow_tuple['sampler_settings']['batch_counter'] = batch_counter
|
||||
workflow_tuple['sampler_settings']['model_sampling'] = model_sampling
|
||||
if control_data is not None:
|
||||
control_data['sampler_settings'] = {}
|
||||
control_data['sampler_settings']['denoise'] = denoise
|
||||
control_data['sampler_settings']['variation_extender_original'] = variation_extender_original
|
||||
control_data['sampler_settings']['variation_batch_step_original'] = variation_batch_step_original
|
||||
control_data['sampler_settings']['variation_level'] = variation_level
|
||||
control_data['sampler_settings']['device'] = device
|
||||
control_data['sampler_settings']['align_your_steps'] = align_your_steps
|
||||
control_data['sampler_settings']['noise_constant'] = noise_constant
|
||||
control_data['sampler_settings']['variation_seed'] = seed
|
||||
control_data['sampler_settings']['batch_counter'] = batch_counter
|
||||
control_data['sampler_settings']['model_sampling'] = model_sampling
|
||||
|
||||
timestamp_diff = int(time.time() - timestamp_start)
|
||||
original_model_concept_selector = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereModelConceptSelector', 'model_concept', prompt)
|
||||
is_random_model = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereVisualCKPT', 'random_model', prompt)
|
||||
selected_model = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereVisualCKPT', 'base_model', prompt)
|
||||
selected_model = control_data.get('model_name') if control_data else utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereVisualCKPT', 'base_model', prompt)
|
||||
if is_random_model == True:
|
||||
fullSource = PrimereVisualCKPT.allModels
|
||||
slashIndex = selected_model.find('\\')
|
||||
@@ -718,17 +695,6 @@ class PrimereKSampler:
|
||||
random.seed(seed)
|
||||
selected_model = random.choice(models_by_path)
|
||||
|
||||
if original_model_concept_selector != 'Auto':
|
||||
match original_model_concept_selector:
|
||||
case 'Flux':
|
||||
flux_selector = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereModelConceptSelector', 'flux_selector', prompt)
|
||||
if flux_selector == 'GGUF':
|
||||
selected_model = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereModelConceptSelector', 'flux_gguf', prompt)
|
||||
else:
|
||||
selected_model = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereModelConceptSelector', 'flux_diffusion', prompt)
|
||||
case 'StableCascade':
|
||||
selected_model = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereModelConceptSelector', 'cascade_stage_c', prompt)
|
||||
|
||||
if selected_model is not None:
|
||||
modelname_only = Path(selected_model).stem
|
||||
model_samplingtime = utility.get_value_from_cache('model_samplingtime', modelname_only)
|
||||
@@ -740,7 +706,7 @@ class PrimereKSampler:
|
||||
diffvalue = str(int(model_samplingtime_list[1]) + timestamp_diff)
|
||||
utility.add_value_to_cache('model_samplingtime', modelname_only, counter + '|' + diffvalue)
|
||||
|
||||
return (samples_out, workflow_tuple)
|
||||
return (samples_out, control_data)
|
||||
|
||||
class PrimerePreviewImage():
|
||||
CATEGORY = TREE_OUTPUTS
|
||||
@@ -878,7 +844,7 @@ class PrimereAestheticCKPTScorer:
|
||||
"image": ("IMAGE", ),
|
||||
},
|
||||
"optional": {
|
||||
"workflow_data": ('TUPLE', {"forceInput": True}),
|
||||
"control_data": ('TUPLE', {"forceInput": True}),
|
||||
},
|
||||
"hidden": {
|
||||
"extra_pnginfo": "EXTRA_PNGINFO",
|
||||
@@ -886,59 +852,17 @@ class PrimereAestheticCKPTScorer:
|
||||
},
|
||||
}
|
||||
|
||||
def aesthetic_scorer(self, image, get_aesthetic_score, add_to_checkpoint, add_to_saved_prompt, prompt, dual_mode = True, workflow_data = None, **kwargs):
|
||||
def aesthetic_scorer(self, image, get_aesthetic_score, add_to_checkpoint, add_to_saved_prompt, prompt, dual_mode = True, control_data = None, **kwargs):
|
||||
final_prediction = '*** Aesthetic scorer off ***'
|
||||
models = []
|
||||
WORKFLOWDATA = kwargs['extra_pnginfo']['workflow']['nodes']
|
||||
AE_SCORE_MIN = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereVisualCKPT', 'aescore_percent_min', prompt)
|
||||
AE_SCORE_MAX = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereVisualCKPT', 'aescore_percent_max', prompt)
|
||||
|
||||
def pipe(model):
|
||||
return pipeline(task="image-classification", model=model, device=model_management.get_torch_device())
|
||||
|
||||
if (get_aesthetic_score == True):
|
||||
'''AESTHETIC_PATH = os.path.join(folder_paths.models_dir, 'aesthetic')
|
||||
folder_paths.add_model_folder_path("aesthetic", AESTHETIC_PATH)
|
||||
if os.path.exists(AESTHETIC_PATH) == False:
|
||||
Path(AESTHETIC_PATH).mkdir(parents=True, exist_ok=True)
|
||||
AESTH_FULL_LIST = folder_paths.get_filename_list("aesthetic")
|
||||
aestheticFiles = folder_paths.filter_files_extensions(AESTH_FULL_LIST, ['.pth'])
|
||||
|
||||
if 'chadscorer.pth' not in aestheticFiles:
|
||||
FileUrl = 'https://huggingface.co/primerecomfydev/chadscorer/resolve/main/chadscorer.pth?download=true'
|
||||
FullFilePath = os.path.join(AESTHETIC_PATH, 'chadscorer.pth')
|
||||
ModelDownload = utility.downloader(FileUrl, FullFilePath)
|
||||
if (ModelDownload == True):
|
||||
AESTH_FULL_LIST = folder_paths.get_filename_list("aesthetic")
|
||||
aestheticFiles = folder_paths.filter_files_extensions(AESTH_FULL_LIST, ['.pth'])
|
||||
|
||||
if 'chadscorer.pth' in aestheticFiles:
|
||||
folder_paths.folder_names_and_paths["aesthetic"] = ([os.path.join(folder_paths.models_dir, "aesthetic")], folder_paths.supported_pt_extensions)
|
||||
m_path = folder_paths.folder_names_and_paths["aesthetic"][0]
|
||||
aesthetic_model = os.path.join(m_path[0], 'chadscorer.pth')
|
||||
fsize = os.path.getsize(aesthetic_model)
|
||||
freemem = comfy.model_management.get_free_memory()
|
||||
if (fsize * 1.2) < freemem:
|
||||
model = utility.MLP(768)
|
||||
s = torch.load(aesthetic_model)
|
||||
model.load_state_dict(s)
|
||||
model.to("cuda")
|
||||
model.eval()
|
||||
device = "cuda"
|
||||
try:
|
||||
model2, preprocess = clip.load("ViT-L/14", device=device) # RN50x64
|
||||
tensor_image = image[0]
|
||||
img = (tensor_image * 255).to(torch.uint8).numpy()
|
||||
pil_image = Image.fromarray(img, mode='RGB')
|
||||
image2 = preprocess(pil_image).unsqueeze(0).to(device)
|
||||
with torch.no_grad():
|
||||
image_features = model2.encode_image(image2)
|
||||
pass
|
||||
im_emb_arr = utility.normalized(image_features.cpu().detach().numpy())
|
||||
prediction = model(torch.from_numpy(im_emb_arr).to(device).type(torch.cuda.FloatTensor))
|
||||
final_prediction = int(float(prediction[0]) * 100)
|
||||
del model
|
||||
except Exception:
|
||||
final_prediction = 0
|
||||
else:
|
||||
final_prediction = 0'''
|
||||
|
||||
AE_MODEL_ROOT = os.path.join(folder_paths.models_dir, 'aesthetic')
|
||||
AEMODELS_ENCODERS_PATHS = utility.getValidAscorerPaths(AE_MODEL_ROOT)
|
||||
if len(AEMODELS_ENCODERS_PATHS) > 0:
|
||||
@@ -985,13 +909,15 @@ class PrimereAestheticCKPTScorer:
|
||||
else:
|
||||
final_prediction = '*** No aesthetic models downloaded ***'
|
||||
|
||||
if (type(final_prediction) != 'str'):
|
||||
if type(final_prediction) != str:
|
||||
final_prediction = str(final_prediction)
|
||||
|
||||
if workflow_data is not None and final_prediction.isdigit():
|
||||
if add_to_checkpoint == True and (workflow_data['model_concept'] == workflow_data['model_version']):
|
||||
if 'model' in workflow_data:
|
||||
selected_model = workflow_data['model']
|
||||
if control_data is not None and final_prediction.isdigit():
|
||||
if add_to_checkpoint == True and (control_data['model_concept']):
|
||||
if 'model_name' in control_data:
|
||||
AE_SCORE_MIN = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereVisualCKPT', 'aescore_percent_min', prompt)
|
||||
AE_SCORE_MAX = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereVisualCKPT', 'aescore_percent_max', prompt)
|
||||
selected_model = control_data['model_name']
|
||||
modelname_only = Path(selected_model).stem
|
||||
model_ascore = utility.get_value_from_cache('model_ascores', modelname_only)
|
||||
if model_ascore is None:
|
||||
@@ -1003,8 +929,7 @@ class PrimereAestheticCKPTScorer:
|
||||
utility.add_value_to_cache('model_ascores', modelname_only, counter + '|' + score)
|
||||
|
||||
if add_to_saved_prompt == True and final_prediction.isdigit():
|
||||
if 'positive' in workflow_data:
|
||||
WORKFLOWDATA = kwargs['extra_pnginfo']['workflow']['nodes']
|
||||
if 'positive' in control_data:
|
||||
selectedStyle = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereVisualStyle', 'styles', prompt)
|
||||
if selectedStyle is None:
|
||||
selectedStyle = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereStyleLoader', 'styles', prompt)
|
||||
@@ -1042,7 +967,9 @@ class PrimereAestheticCKPTScorer:
|
||||
if (positive_prompt is not None):
|
||||
if len(positive_prompt) > 100:
|
||||
positive_prompt = positive_prompt[:100]
|
||||
if positive_prompt in workflow_data['positive']:
|
||||
if positive_prompt in control_data['positive']:
|
||||
AE_SCORE_MIN = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereVisualStyle', 'aescore_percent_min', prompt)
|
||||
AE_SCORE_MAX = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereVisualStyle', 'aescore_percent_max', prompt)
|
||||
style_ascore = utility.get_value_from_cache('styles_ascores', selectedStyle)
|
||||
if style_ascore is None:
|
||||
utility.add_value_to_cache('styles_ascores', selectedStyle, '1|' + final_prediction)
|
||||
@@ -1052,7 +979,16 @@ class PrimereAestheticCKPTScorer:
|
||||
score = str(int(style_ascore_list[1]) + int(final_prediction))
|
||||
utility.add_value_to_cache('styles_ascores', selectedStyle, counter + '|' + score)
|
||||
|
||||
return {"ui": {"text": [final_prediction]}, "result": (final_prediction,)}
|
||||
if isinstance(final_prediction, str) and final_prediction.isdigit():
|
||||
if AE_SCORE_MIN is not None and AE_SCORE_MAX is not None:
|
||||
final_prediction = max(0, min(100, int(((int(final_prediction) - AE_SCORE_MIN) / (AE_SCORE_MAX - AE_SCORE_MIN)) * 100)))
|
||||
else:
|
||||
final_prediction = int(final_prediction)
|
||||
else:
|
||||
final_prediction = '*** Aesthetic scorer error ***'
|
||||
|
||||
result_int = final_prediction if isinstance(final_prediction, int) else 0
|
||||
return {"ui": {"text": [final_prediction]}, "result": (result_int,)}
|
||||
|
||||
class DebugToFile():
|
||||
CATEGORY = TREE_OUTPUTS
|
||||
|
||||
+2
-2
@@ -38,7 +38,7 @@ for subdirs in valid_FElist:
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"PrimereSamplersSteps": Dashboard.PrimereSamplersSteps,
|
||||
"PrimereAutoSamplerSettings": Dashboard.PrimereAutoSamplerSettings,
|
||||
"PrimereModelControl": Dashboard.PrimereModelControl,
|
||||
"PrimereVAE": Dashboard.PrimereVAE,
|
||||
"PrimereCKPT": Dashboard.PrimereCKPT,
|
||||
"PrimereVAELoader": Dashboard.PrimereVAELoader,
|
||||
@@ -117,7 +117,7 @@ NODE_CLASS_MAPPINGS = {
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"PrimereSamplersSteps": "Primere Samplers & Steps & Cfg",
|
||||
"PrimereAutoSamplerSettings": "Primere Auto Sampler Settings",
|
||||
"PrimereModelControl": "Primere Primere ModelControl",
|
||||
"PrimereVAE": "Primere VAE Selector",
|
||||
"PrimereCKPT": "Primere CKPT Selector",
|
||||
"PrimereVAELoader": "Primere VAE Loader",
|
||||
|
||||
+78
-55
@@ -558,32 +558,55 @@ def build_prompt_context(
|
||||
|
||||
SDXL_CONCEPTS = {'SDXL', 'Illustrious', 'Pony', 'Playground'}
|
||||
|
||||
CLIP_ATTN_PRESETS = {
|
||||
"Off": (1.00, 1.00, 1.00, 1.00),
|
||||
"Natural": (1.00, 1.02, 0.98, 1.00),
|
||||
"Realism": (1.00, 1.05, 0.95, 1.00),
|
||||
"Photography": (1.02, 1.05, 0.93, 0.98),
|
||||
"Cinematic": (1.05, 1.05, 1.00, 0.95),
|
||||
"Portrait": (1.03, 1.08, 0.92, 0.97),
|
||||
"Art": (0.95, 0.95, 1.10, 1.05),
|
||||
"Illustration": (0.90, 1.00, 1.15, 1.00),
|
||||
"Anime": (0.88, 0.95, 1.18, 1.05),
|
||||
"Prompt adherence": (1.10, 1.10, 1.00, 1.00),
|
||||
"Abstract": (0.85, 0.88, 1.18, 1.12),
|
||||
"Creative": (0.85, 0.90, 1.20, 1.10),
|
||||
"Surreal": (0.80, 0.85, 1.25, 1.15),
|
||||
# Unified preset: (q, k, v, out, cross_q, cross_k, cross_v, cross_out)
|
||||
# First 4: applied to CLIP attention + UNet self-attention (attn1)
|
||||
# Last 4: applied to UNet cross-attention (attn2) — ignored for clip-only models
|
||||
ATTN_PRESETS = {
|
||||
"Off": (1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00),
|
||||
"Natural": (1.00, 1.02, 0.98, 1.00, 1.00, 1.02, 0.98, 1.00),
|
||||
"Realism": (1.00, 1.05, 0.95, 1.00, 1.05, 1.05, 0.95, 1.00),
|
||||
"Photography": (1.02, 1.05, 0.93, 0.98, 1.05, 1.05, 0.93, 0.98),
|
||||
"Cinematic": (1.05, 1.05, 1.00, 0.95, 1.05, 1.05, 1.00, 0.95),
|
||||
"Portrait": (1.03, 1.08, 0.92, 0.97, 1.05, 1.10, 0.90, 1.00),
|
||||
"Art": (0.95, 0.95, 1.10, 1.05, 0.90, 0.95, 1.10, 1.00),
|
||||
"Illustration": (0.90, 1.00, 1.15, 1.00, 0.90, 1.00, 1.15, 1.00),
|
||||
"Anime": (0.88, 0.95, 1.18, 1.05, 0.88, 0.95, 1.18, 1.00),
|
||||
"Prompt adherence": (1.10, 1.10, 1.00, 1.00, 1.10, 1.10, 1.00, 1.00),
|
||||
"Abstract": (0.85, 0.88, 1.18, 1.12, 0.85, 0.88, 1.15, 1.05),
|
||||
"Creative": (0.85, 0.90, 1.20, 1.10, 0.85, 0.90, 1.15, 1.05),
|
||||
}
|
||||
|
||||
def apply_clip_overrides(loader_self, clip, workflow_tuple):
|
||||
if not workflow_tuple:
|
||||
ATTN_PRESET_KEYWORDS = {
|
||||
'Anime': ['anime', 'waifu', 'nai', 'hentai', 'manga'],
|
||||
'Photography': ['photo', 'realistic', 'realvis', 'realism'],
|
||||
'Illustration': ['illustration', 'illus', 'cartoon', 'draw'],
|
||||
'Cinematic': ['cinematic', 'film', 'movie', 'cinema'],
|
||||
'Portrait': ['portrait'],
|
||||
'Art': ['paint', 'artistic', 'watercolor'],
|
||||
'Natural': ['natural'],
|
||||
'Abstract': ['abstract', 'surreal'],
|
||||
}
|
||||
|
||||
|
||||
def detect_attn_preset(model_name, default='Off'):
|
||||
if not model_name:
|
||||
return default
|
||||
name = model_name.lower().replace('\\', '/').split('/')[-1].split('.')[0]
|
||||
for preset, keywords in ATTN_PRESET_KEYWORDS.items():
|
||||
if any(kw in name for kw in keywords):
|
||||
return preset
|
||||
return default
|
||||
|
||||
def apply_clip_overrides(loader_self, clip, control_data):
|
||||
if not control_data:
|
||||
return clip
|
||||
encoder_1 = workflow_tuple.get('encoder_1', None)
|
||||
last_layer = int(workflow_tuple.get('last_layer', 0))
|
||||
encoder_1 = control_data.get('encoder_1', None)
|
||||
last_layer = int(control_data.get('last_layer', 0))
|
||||
baked_clip = clip
|
||||
|
||||
if encoder_1 and encoder_1 != 'None' and not workflow_tuple.get('clip_selection', False):
|
||||
if encoder_1 and encoder_1 != 'None' and not control_data.get('clip_selection', False):
|
||||
try:
|
||||
model_concept = workflow_tuple.get('model_concept', 'SD1')
|
||||
model_concept = control_data.get('model_concept', 'SD1')
|
||||
is_longclip = 'longclip' in encoder_1.lower() or encoder_1.lower().endswith('.pt')
|
||||
if is_longclip:
|
||||
if model_concept in SDXL_CONCEPTS:
|
||||
@@ -603,13 +626,13 @@ def apply_clip_overrides(loader_self, clip, workflow_tuple):
|
||||
return clip
|
||||
|
||||
|
||||
def apply_clip_attention_multiply(clip, workflow_tuple):
|
||||
if not workflow_tuple:
|
||||
def apply_clip_attention_multiply(clip, control_data):
|
||||
if not control_data:
|
||||
return clip
|
||||
q = float(workflow_tuple.get('clip_attn_q', 1.0))
|
||||
k = float(workflow_tuple.get('clip_attn_k', 1.0))
|
||||
v = float(workflow_tuple.get('clip_attn_v', 1.0))
|
||||
out = float(workflow_tuple.get('clip_attn_out', 1.0))
|
||||
q = float(control_data.get('clip_attn_q', 1.0))
|
||||
k = float(control_data.get('clip_attn_k', 1.0))
|
||||
v = float(control_data.get('clip_attn_v', 1.0))
|
||||
out = float(control_data.get('clip_attn_out', 1.0))
|
||||
if q == 1.0 and k == 1.0 and v == 1.0 and out == 1.0:
|
||||
return clip
|
||||
try:
|
||||
@@ -618,14 +641,14 @@ def apply_clip_attention_multiply(clip, workflow_tuple):
|
||||
return clip
|
||||
|
||||
|
||||
def encode_standard(clip, positive_text, negative_text, t5xxl_prompt, adv_encode, token_normalization, weight_interpretation, positive_l, negative_l, width, height, workflow_tuple, advanced_encode_fn):
|
||||
def encode_standard(clip, positive_text, negative_text, t5xxl_prompt, adv_encode, token_normalization, weight_interpretation, positive_l, negative_l, width, height, control_data, advanced_encode_fn):
|
||||
if adv_encode:
|
||||
tokens_p = clip.tokenize(positive_text)
|
||||
tokens_n = clip.tokenize(negative_text)
|
||||
if 'l' not in tokens_p or 'g' not in tokens_p or 'l' not in tokens_n or 'g' not in tokens_n:
|
||||
embeddings_final_pos, pooled_pos = advanced_encode_fn(clip, positive_text, token_normalization, weight_interpretation, w_max=1.0, apply_to_pooled=True)
|
||||
embeddings_final_neg, pooled_neg = advanced_encode_fn(clip, negative_text, token_normalization, weight_interpretation, w_max=1.0, apply_to_pooled=True)
|
||||
return ([[embeddings_final_pos, {"pooled_output": pooled_pos}]], [[embeddings_final_neg, {"pooled_output": pooled_neg}]], positive_text, negative_text, t5xxl_prompt, "", "", workflow_tuple)
|
||||
return ([[embeddings_final_pos, {"pooled_output": pooled_pos}]], [[embeddings_final_neg, {"pooled_output": pooled_neg}]], positive_text, negative_text, t5xxl_prompt, "", "", control_data)
|
||||
else:
|
||||
if 'l' in clip.tokenize(positive_l):
|
||||
tokens_p["l"] = clip.tokenize(positive_l)["l"]
|
||||
@@ -645,7 +668,7 @@ def encode_standard(clip, positive_text, negative_text, t5xxl_prompt, adv_encode
|
||||
tokens_n["g"] += empty["g"]
|
||||
cond_p, pooled_p = clip.encode_from_tokens(tokens_p, return_pooled=True)
|
||||
cond_n, pooled_n = clip.encode_from_tokens(tokens_n, return_pooled=True)
|
||||
return ([[cond_p, {"pooled_output": pooled_p, "width": width, "height": height, "crop_w": 0, "crop_h": 0, "target_width": width, "target_height": height}]], [[cond_n, {"pooled_output": pooled_n, "width": width, "height": height, "crop_w": 0, "crop_h": 0, "target_width": width, "target_height": height}]], positive_text, negative_text, "", positive_l, negative_l, workflow_tuple)
|
||||
return ([[cond_p, {"pooled_output": pooled_p, "width": width, "height": height, "crop_w": 0, "crop_h": 0, "target_width": width, "target_height": height}]], [[cond_n, {"pooled_output": pooled_n, "width": width, "height": height, "crop_w": 0, "crop_h": 0, "target_width": width, "target_height": height}]], positive_text, negative_text, "", positive_l, negative_l, control_data)
|
||||
else:
|
||||
tokens_pos = clip.tokenize(positive_text)
|
||||
tokens_neg = clip.tokenize(negative_text)
|
||||
@@ -657,16 +680,16 @@ def encode_standard(clip, positive_text, negative_text, t5xxl_prompt, adv_encode
|
||||
out_neg = clip.encode_from_tokens(tokens_neg, return_pooled=True, return_dict=True)
|
||||
cond_pos = out_pos.pop("cond")
|
||||
cond_neg = out_neg.pop("cond")
|
||||
return ([[cond_pos, out_pos]], [[cond_neg, out_neg]], positive_text, negative_text, t5xxl_prompt, "", "", workflow_tuple)
|
||||
return ([[cond_pos, out_pos]], [[cond_neg, out_neg]], positive_text, negative_text, t5xxl_prompt, "", "", control_data)
|
||||
|
||||
|
||||
def encode_sd3(clip, positive_text, negative_text, t5xxl_prompt, workflow_tuple):
|
||||
def encode_sd3(clip, positive_text, negative_text, t5xxl_prompt, control_data):
|
||||
if t5xxl_prompt:
|
||||
pos_out = nodes_sd3.CLIPTextEncodeSD3.execute(clip, positive_text, positive_text, t5xxl_prompt, 'none')
|
||||
tokens_neg = clip.tokenize(negative_text)
|
||||
out_neg = clip.encode_from_tokens(tokens_neg, return_pooled=True, return_dict=True)
|
||||
cond_neg = out_neg.pop("cond")
|
||||
return (pos_out[0], [[cond_neg, out_neg]], positive_text, negative_text, t5xxl_prompt, "", "", workflow_tuple)
|
||||
return (pos_out[0], [[cond_neg, out_neg]], positive_text, negative_text, t5xxl_prompt, "", "", control_data)
|
||||
else:
|
||||
tokens_pos = clip.tokenize(positive_text)
|
||||
tokens_neg = clip.tokenize(negative_text)
|
||||
@@ -674,20 +697,20 @@ def encode_sd3(clip, positive_text, negative_text, t5xxl_prompt, workflow_tuple)
|
||||
out_neg = clip.encode_from_tokens(tokens_neg, return_pooled=True, return_dict=True)
|
||||
cond_pos = out_pos.pop("cond")
|
||||
cond_neg = out_neg.pop("cond")
|
||||
return ([[cond_pos, out_pos]], [[cond_neg, out_neg]], positive_text, negative_text, "", "", "", workflow_tuple)
|
||||
return ([[cond_pos, out_pos]], [[cond_neg, out_neg]], positive_text, negative_text, "", "", "", control_data)
|
||||
|
||||
|
||||
def encode_stable_cascade(clip, positive_text, negative_text, workflow_tuple):
|
||||
def encode_stable_cascade(clip, positive_text, negative_text, control_data):
|
||||
positive_text = utility.DiT_cleaner(positive_text)
|
||||
negative_text = utility.DiT_cleaner(negative_text)
|
||||
tokens_pos = clip.tokenize(positive_text)
|
||||
tokens_neg = clip.tokenize(negative_text)
|
||||
cond_pos, pooled_pos = clip.encode_from_tokens(tokens_pos, return_pooled=True)
|
||||
cond_neg, pooled_neg = clip.encode_from_tokens(tokens_neg, return_pooled=True)
|
||||
return ([[cond_pos, {"pooled_output": pooled_pos}]], [[cond_neg, {"pooled_output": pooled_neg}]], positive_text, negative_text, "", "", "", workflow_tuple)
|
||||
return ([[cond_pos, {"pooled_output": pooled_pos}]], [[cond_neg, {"pooled_output": pooled_neg}]], positive_text, negative_text, "", "", "", control_data)
|
||||
|
||||
|
||||
def encode_pixart_sigma(clip, positive_text, negative_text, workflow_tuple):
|
||||
def encode_pixart_sigma(clip, positive_text, negative_text, control_data):
|
||||
positive_text = utility.DiT_cleaner(positive_text)
|
||||
negative_text = utility.DiT_cleaner(negative_text)
|
||||
|
||||
@@ -710,32 +733,32 @@ def encode_pixart_sigma(clip, positive_text, negative_text, workflow_tuple):
|
||||
cond_pos_main = out_pos_main.pop("cond")
|
||||
cond_neg_main = out_neg_main.pop("cond")
|
||||
|
||||
return ({'refiner': [[cond_pos_ref, out_pos_ref]], 'main': [[cond_pos_main, out_pos_main]]}, {'refiner': [[cond_neg_ref, out_neg_ref]], 'main': [[cond_neg_main, out_neg_main]]}, positive_text, negative_text, "", "", "", workflow_tuple)
|
||||
return ({'refiner': [[cond_pos_ref, out_pos_ref]], 'main': [[cond_pos_main, out_pos_main]]}, {'refiner': [[cond_neg_ref, out_neg_ref]], 'main': [[cond_neg_main, out_neg_main]]}, positive_text, negative_text, "", "", "", control_data)
|
||||
|
||||
|
||||
def encode_chroma(clip, positive_text, negative_text, workflow_tuple):
|
||||
def encode_chroma(clip, positive_text, negative_text, control_data):
|
||||
tokens_pos = clip.tokenize(positive_text)
|
||||
tokens_neg = clip.tokenize(negative_text)
|
||||
out_pos = clip.encode_from_tokens(tokens_pos, return_pooled=True, return_dict=True)
|
||||
out_neg = clip.encode_from_tokens(tokens_neg, return_pooled=True, return_dict=True)
|
||||
cond_pos = out_pos.pop("cond")
|
||||
cond_neg = out_neg.pop("cond")
|
||||
return ([[cond_pos, out_pos]], [[cond_neg, out_neg]], positive_text, negative_text, "", "", "", workflow_tuple)
|
||||
return ([[cond_pos, out_pos]], [[cond_neg, out_neg]], positive_text, negative_text, "", "", "", control_data)
|
||||
|
||||
|
||||
def encode_flux(clip, positive_text, negative_text, t5xxl_prompt, workflow_tuple):
|
||||
FLUX_SAMPLER = workflow_tuple.get('sampler', 'ksampler')
|
||||
FLUX_GUIDANCE = workflow_tuple.get('guidance', 2)
|
||||
def encode_flux(clip, positive_text, negative_text, t5xxl_prompt, control_data):
|
||||
FLUX_SAMPLER = control_data.get('sampler', 'ksampler')
|
||||
FLUX_GUIDANCE = control_data.get('guidance', 2)
|
||||
if FLUX_SAMPLER == 'custom_advanced' and len(t5xxl_prompt) > 5:
|
||||
CONDITIONING_POS = nodes_flux.CLIPTextEncodeFlux.execute(clip, positive_text, t5xxl_prompt, FLUX_GUIDANCE)[0]
|
||||
return (CONDITIONING_POS, CONDITIONING_POS, positive_text, negative_text, t5xxl_prompt, "", "", workflow_tuple)
|
||||
return (CONDITIONING_POS, CONDITIONING_POS, positive_text, negative_text, t5xxl_prompt, "", "", control_data)
|
||||
tokens_pos = clip.tokenize(positive_text)
|
||||
tokens_neg = clip.tokenize(negative_text)
|
||||
out_pos = clip.encode_from_tokens(tokens_pos, return_pooled=True, return_dict=True)
|
||||
out_neg = clip.encode_from_tokens(tokens_neg, return_pooled=True, return_dict=True)
|
||||
cond_pos = out_pos.pop("cond")
|
||||
cond_neg = out_neg.pop("cond")
|
||||
return ([[cond_pos, out_pos]], [[cond_neg, out_neg]], positive_text, negative_text, t5xxl_prompt, "", "", workflow_tuple)
|
||||
return ([[cond_pos, out_pos]], [[cond_neg, out_neg]], positive_text, negative_text, t5xxl_prompt, "", "", control_data)
|
||||
|
||||
|
||||
_SANA_MAX_TOKENS = 300
|
||||
@@ -757,8 +780,8 @@ def _sana_encode_text(tokenizer, text_encoder, text, device):
|
||||
return embs * masks.unsqueeze(-1)
|
||||
|
||||
|
||||
def encode_sana(clip, positive_text, negative_text, t5xxl_prompt, workflow_tuple):
|
||||
scheduler_name = workflow_tuple.get('scheduler_name', 'flow_dpm-solver') if workflow_tuple else 'flow_dpm-solver'
|
||||
def encode_sana(clip, positive_text, negative_text, t5xxl_prompt, control_data):
|
||||
scheduler_name = control_data.get('scheduler_name', 'flow_dpm-solver') if control_data else 'flow_dpm-solver'
|
||||
device = model_management.get_torch_device()
|
||||
|
||||
if scheduler_name == 'flow_dpm-solver' and hasattr(clip, 'text_encoder'):
|
||||
@@ -776,7 +799,7 @@ def encode_sana(clip, positive_text, negative_text, t5xxl_prompt, workflow_tuple
|
||||
null_y = null_embs.repeat(len(prompts), 1, 1)[:, None]
|
||||
clip.text_encoder.to(model_management.text_encoder_offload_device())
|
||||
comfy.model_management.soft_empty_cache(True)
|
||||
return ([[caption_embs, {"emb_masks": emb_masks}]], [[null_y, {}]], positive_text, negative_text, t5xxl_prompt, "", "", workflow_tuple)
|
||||
return ([[caption_embs, {"emb_masks": emb_masks}]], [[null_y, {}]], positive_text, negative_text, t5xxl_prompt, "", "", control_data)
|
||||
else:
|
||||
tokenizer = clip["tokenizer"]
|
||||
text_encoder = clip["text_encoder"]
|
||||
@@ -784,10 +807,10 @@ def encode_sana(clip, positive_text, negative_text, t5xxl_prompt, workflow_tuple
|
||||
with torch.no_grad():
|
||||
sana_embs_pos = _sana_encode_text(tokenizer, text_encoder, positive_text, enc_device)
|
||||
sana_embs_neg = _sana_encode_text(tokenizer, text_encoder, negative_text, enc_device)
|
||||
return ([[sana_embs_pos, {}]], [[sana_embs_neg, {}]], positive_text, negative_text, t5xxl_prompt, "", "", workflow_tuple)
|
||||
return ([[sana_embs_pos, {}]], [[sana_embs_neg, {}]], positive_text, negative_text, t5xxl_prompt, "", "", control_data)
|
||||
|
||||
|
||||
def encode_qwen_edit(loader_self, clip, positive_text, negative_text, t5xxl_prompt, edit_vae, edit_image_list, workflow_tuple):
|
||||
def encode_qwen_edit(loader_self, clip, positive_text, negative_text, t5xxl_prompt, edit_vae, edit_image_list, control_data):
|
||||
if type(edit_image_list).__name__ == "Tensor":
|
||||
edit_image_list = [edit_image_list]
|
||||
positive_text = utility.DiT_cleaner(positive_text)
|
||||
@@ -795,10 +818,10 @@ def encode_qwen_edit(loader_self, clip, positive_text, negative_text, t5xxl_prom
|
||||
conditioning = utility.edit_encoder(clip, positive_text, edit_vae, edit_image_list)
|
||||
tokens_neg = clip.tokenize(negative_text, images=[])
|
||||
conditioning_neg = clip.encode_from_tokens_scheduled(tokens_neg)
|
||||
return (conditioning, conditioning_neg, positive_text, negative_text, t5xxl_prompt, "", "", workflow_tuple)
|
||||
return (conditioning, conditioning_neg, positive_text, negative_text, t5xxl_prompt, "", "", control_data)
|
||||
|
||||
|
||||
def encode_kolors(clip, positive_text, negative_text, t5xxl_prompt, workflow_tuple):
|
||||
def encode_kolors(clip, positive_text, negative_text, t5xxl_prompt, control_data):
|
||||
positive_text = utility.DiT_cleaner(positive_text)
|
||||
negative_text = utility.DiT_cleaner(negative_text)
|
||||
device = model_management.text_encoder_device()
|
||||
@@ -847,17 +870,17 @@ def encode_kolors(clip, positive_text, negative_text, t5xxl_prompt, workflow_tup
|
||||
'pooled_prompt_embeds': text_proj.half(),
|
||||
'negative_pooled_prompt_embeds': negative_text_proj.half(),
|
||||
}
|
||||
return (kolors_embeds, None, positive_text, negative_text, t5xxl_prompt, "", "", workflow_tuple)
|
||||
return (kolors_embeds, None, positive_text, negative_text, t5xxl_prompt, "", "", control_data)
|
||||
|
||||
|
||||
def encode_hunyuan(loader_self, clip, positive_text, negative_text, t5xxl_prompt, workflow_tuple):
|
||||
def encode_hunyuan(loader_self, clip, positive_text, negative_text, t5xxl_prompt, control_data):
|
||||
if clip['t5'] is not None:
|
||||
positive_text = utility.DiT_cleaner(positive_text)
|
||||
negative_text = utility.DiT_cleaner(negative_text)
|
||||
t5xxl_prompt = utility.DiT_cleaner(t5xxl_prompt)
|
||||
pos_out = HunyuanClipping(loader_self, positive_text, t5xxl_prompt, clip['clip'], clip['t5'])
|
||||
neg_out = HunyuanClipping(loader_self, negative_text, "", clip['clip'], clip['t5'])
|
||||
return (pos_out[0], neg_out[0], positive_text, negative_text, t5xxl_prompt, "", "", workflow_tuple)
|
||||
return (pos_out[0], neg_out[0], positive_text, negative_text, t5xxl_prompt, "", "", control_data)
|
||||
else:
|
||||
clip_model = clip['clip']
|
||||
positive_text = utility.DiT_cleaner(positive_text, 512)
|
||||
@@ -866,4 +889,4 @@ def encode_hunyuan(loader_self, clip, positive_text, negative_text, t5xxl_prompt
|
||||
out_neg = clip_model.encode_from_tokens(clip_model.tokenize(negative_text), return_pooled=True, return_dict=True)
|
||||
cond_pos = out_pos.pop("cond")
|
||||
cond_neg = out_neg.pop("cond")
|
||||
return ([[cond_pos, out_pos]], [[cond_neg, out_neg]], positive_text, negative_text, t5xxl_prompt, "", "", workflow_tuple)
|
||||
return ([[cond_pos, out_pos]], [[cond_neg, out_neg]], positive_text, negative_text, t5xxl_prompt, "", "", control_data)
|
||||
+69
-6
@@ -8,6 +8,7 @@ import nodes
|
||||
import comfy_extras.nodes_sd3 as nodes_sd3
|
||||
import comfy_extras.nodes_model_advanced as nodes_model_advanced
|
||||
import comfy_extras.nodes_cfg as nodes_cfg
|
||||
from comfy_extras.nodes_attention_multiply import attention_multiply
|
||||
from comfy import model_management
|
||||
from pathlib import Path
|
||||
from .tree import PRIMERE_ROOT
|
||||
@@ -56,6 +57,56 @@ def resolve_symlink(ckpt_name):
|
||||
return File_link, linkedFileName, model_ext
|
||||
|
||||
|
||||
DISCRETE_CONCEPTS = {'SD1', 'SD2', 'SDXL', 'Illustrious', 'Turbo', 'Pony', 'Hyper', 'Lightning'}
|
||||
UNET_CONCEPTS = {'SD1', 'SD2', 'SDXL', 'Illustrious', 'Turbo', 'Pony', 'Hyper', 'Lightning', 'Playground', 'LCM'}
|
||||
|
||||
|
||||
def apply_generic_patches(loader_self, model, concept_data):
|
||||
model_concept = concept_data.get('model_concept', '')
|
||||
|
||||
discrete_sampling = concept_data.get('discrete_sampling', 'default')
|
||||
if discrete_sampling != 'default' and model_concept in DISCRETE_CONCEPTS:
|
||||
try:
|
||||
discrete_zsnr = bool(concept_data.get('discrete_zsnr', False))
|
||||
model = nodes_model_advanced.ModelSamplingDiscrete.patch(loader_self, model, discrete_sampling, discrete_zsnr)[0]
|
||||
except Exception as e:
|
||||
print(f"Primere: ModelSamplingDiscrete failed: {e}")
|
||||
|
||||
if model_concept in UNET_CONCEPTS:
|
||||
self_q = concept_data.get('clip_attn_q', 1.0)
|
||||
self_k = concept_data.get('clip_attn_k', 1.0)
|
||||
self_v = concept_data.get('clip_attn_v', 1.0)
|
||||
self_out = concept_data.get('clip_attn_out', 1.0)
|
||||
if (self_q, self_k, self_v, self_out) != (1.0, 1.0, 1.0, 1.0):
|
||||
try:
|
||||
model = attention_multiply("attn1", model, self_q, self_k, self_v, self_out)
|
||||
except Exception as e:
|
||||
print(f"Primere: UNet self-attention multiply failed: {e}")
|
||||
|
||||
if model_concept in UNET_CONCEPTS:
|
||||
cross_q = concept_data.get('attn_cross_q', 1.0)
|
||||
cross_k = concept_data.get('attn_cross_k', 1.0)
|
||||
cross_v = concept_data.get('attn_cross_v', 1.0)
|
||||
cross_out = concept_data.get('attn_cross_out', 1.0)
|
||||
if (cross_q, cross_k, cross_v, cross_out) != (1.0, 1.0, 1.0, 1.0):
|
||||
try:
|
||||
model = attention_multiply("attn2", model, cross_q, cross_k, cross_v, cross_out)
|
||||
except Exception as e:
|
||||
print(f"Primere: UNet cross-attention multiply failed: {e}")
|
||||
|
||||
precision = concept_data.get('precision', None)
|
||||
if precision and precision not in ('quant8', 'quant4'):
|
||||
dtype_map = {'fp32': 'fp32', 'fp16': 'fp16'}
|
||||
dtype = dtype_map.get(precision)
|
||||
if dtype:
|
||||
try:
|
||||
model = nodes_model_advanced.ModelComputeDtype.patch(loader_self, model, dtype)[0]
|
||||
except Exception as e:
|
||||
print(f"Primere: ModelComputeDtype failed: {e}")
|
||||
|
||||
return model
|
||||
|
||||
|
||||
def apply_lora(loader_self, model, lora_path, strength):
|
||||
if not os.path.exists(lora_path) or strength == 0:
|
||||
return model
|
||||
@@ -102,6 +153,7 @@ def load_sd_model(loader_self, ckpt_name, use_yaml, model_config_full_path, conc
|
||||
OUTPUT_VAE = utility.vae_loader_class.load_vae(vae_name)[0]
|
||||
else:
|
||||
OUTPUT_VAE = LOADED_CHECKPOINT[2]
|
||||
OUTPUT_MODEL = apply_generic_patches(loader_self, OUTPUT_MODEL, concept_data)
|
||||
return OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE
|
||||
|
||||
|
||||
@@ -131,6 +183,7 @@ def load_sd3_model(loader_self, ckpt_name, concept_data):
|
||||
lora_path = folder_paths.get_full_path('loras', lora_name)
|
||||
if lora_path:
|
||||
OUTPUT_MODEL = apply_lora(loader_self, OUTPUT_MODEL, lora_path, lora_strength)
|
||||
OUTPUT_MODEL = apply_generic_patches(loader_self, OUTPUT_MODEL, concept_data)
|
||||
return OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE
|
||||
|
||||
|
||||
@@ -212,6 +265,13 @@ def load_flux_model(loader_self, ckpt_name, concept_data):
|
||||
rescale_cfg = concept_data.get('rescale_cfg', 1.0)
|
||||
if rescale_cfg != 1.0:
|
||||
OUTPUT_MODEL = nodes_model_advanced.RescaleCFG.patch(loader_self, OUTPUT_MODEL, rescale_cfg)[0]
|
||||
flux_max_shift = concept_data.get('flux_max_shift', 1.15)
|
||||
flux_base_shift = concept_data.get('flux_base_shift', 0.5)
|
||||
try:
|
||||
OUTPUT_MODEL = nodes_model_advanced.ModelSamplingFlux.patch(loader_self, OUTPUT_MODEL, flux_max_shift, flux_base_shift, 1024, 1024)[0]
|
||||
except Exception as e:
|
||||
print(f"Primere: ModelSamplingFlux failed: {e}")
|
||||
OUTPUT_MODEL = apply_generic_patches(loader_self, OUTPUT_MODEL, concept_data)
|
||||
return OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE
|
||||
|
||||
|
||||
@@ -268,7 +328,11 @@ def load_playground_model(loader_self, ckpt_name, use_yaml, model_config_full_pa
|
||||
OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE = load_sd_model(loader_self, ckpt_name, use_yaml, model_config_full_path, concept_data)
|
||||
sigma_max = concept_data.get('sigma_max', 120)
|
||||
sigma_min = concept_data.get('sigma_min', 0.002)
|
||||
OUTPUT_MODEL = nodes_model_advanced.ModelSamplingContinuousEDM.patch(loader_self, OUTPUT_MODEL, 'edm_playground_v2.5', sigma_max, sigma_min)[0]
|
||||
edm_sampling = concept_data.get('edm_sampling', 'edm_playground_v2.5')
|
||||
try:
|
||||
OUTPUT_MODEL = nodes_model_advanced.ModelSamplingContinuousEDM.patch(loader_self, OUTPUT_MODEL, edm_sampling, sigma_max, sigma_min)[0]
|
||||
except Exception as e:
|
||||
print(f"Primere: ModelSamplingContinuousEDM failed: {e}")
|
||||
return OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE
|
||||
|
||||
|
||||
@@ -300,6 +364,7 @@ def load_lightning_hyper_model(loader_self, ckpt_name, concept_data):
|
||||
if lora_path:
|
||||
OUTPUT_MODEL = utility.BDanceConceptHelper(loader_self, model_concept, True, 'LORA', None, OUTPUT_MODEL, lora_path, None, None, lora_strength)
|
||||
|
||||
OUTPUT_MODEL = apply_generic_patches(loader_self, OUTPUT_MODEL, concept_data)
|
||||
return OUTPUT_MODEL, OUTPUT_CLIP, OUTPUT_VAE
|
||||
|
||||
|
||||
@@ -312,11 +377,9 @@ def load_lcm_model(loader_self, ckpt_name, concept_data):
|
||||
MODEL_VERSION = utility.getModelType(ckpt_name, 'checkpoints')
|
||||
|
||||
if concept_data.get('lcm_lora') == True:
|
||||
lora_name = concept_data.get('lcm_lora_name', None)
|
||||
if lora_name:
|
||||
lora_path = folder_paths.get_full_path('loras', lora_name)
|
||||
if lora_path:
|
||||
OUTPUT_MODEL = apply_lora(loader_self, OUTPUT_MODEL, lora_path, concept_data.get('lcm_lora_strength', 1.0))
|
||||
lora_file = 'lcm_lora_sdxl.safetensors' if 'SDXL' in MODEL_VERSION else 'lcm_lora_sd.safetensors'
|
||||
lora_path = os.path.join(PRIMERE_ROOT, 'Nodes', 'Downloads', lora_file)
|
||||
OUTPUT_MODEL = apply_lora(loader_self, OUTPUT_MODEL, lora_path, concept_data.get('lcm_lora_strength', 1.0))
|
||||
|
||||
class ModelSamplingAdvanced(utility.ModelSamplingDiscreteLCM, nodes_model_advanced.LCM):
|
||||
pass
|
||||
|
||||
@@ -25,32 +25,71 @@ def PKSampler(self, device, seed, model,
|
||||
steps, cfg, sampler_name, scheduler_name,
|
||||
positive, negative,
|
||||
latent_image, denoise,
|
||||
variation_extender, variation_batch_step_original, batch_counter, variation_extender_original, variation_batch_step, variation_level, variation_limit, align_your_steps, noise_extender, model_sampling = None):
|
||||
variation_extender, variation_batch_step_original, batch_counter, variation_extender_original, variation_batch_step, variation_level, variation_limit, align_your_steps, noise_extender, model_sampling=None, control_data=None):
|
||||
|
||||
if model_sampling is not None and model_sampling > 0:
|
||||
model = nodes_model_advanced.ModelSamplingSD3.patch(self, model, model_sampling, 1.0)[0]
|
||||
|
||||
if variation_level == True:
|
||||
samples = latentnoise.noisy_samples(model, device, steps, cfg, sampler_name, scheduler_name, positive, negative, latent_image, denoise, seed, noise_extender)
|
||||
else:
|
||||
if variation_extender_original > 0 or device != 'DEFAULT' or variation_batch_step_original > 0:
|
||||
samples = None
|
||||
|
||||
if scheduler_name == 'beta' and control_data is not None:
|
||||
beta_alpha = float(control_data.get('beta_alpha', 0.6))
|
||||
beta_beta = float(control_data.get('beta_beta', 0.6))
|
||||
try:
|
||||
sigmas = comfy.samplers.beta_scheduler(model.get_model_object("model_sampling"), steps, alpha=beta_alpha, beta=beta_beta)
|
||||
sampler = comfy.samplers.sampler_object(sampler_name)
|
||||
samples = (nodes_custom_sampler.SamplerCustom.execute(model, True, seed, cfg, positive, negative, sampler, sigmas, latent_image)[0],)
|
||||
except Exception as e:
|
||||
print(f"Primere: BetaSamplingScheduler failed: {e}")
|
||||
|
||||
if samples is None:
|
||||
if variation_level == True:
|
||||
samples = latentnoise.noisy_samples(model, device, steps, cfg, sampler_name, scheduler_name, positive, negative, latent_image, denoise, seed, noise_extender)
|
||||
else:
|
||||
if align_your_steps == True:
|
||||
modelname_only = model
|
||||
model_version = utility.get_value_from_cache('model_version', modelname_only)
|
||||
match model_version:
|
||||
case 'SDXL':
|
||||
model_type = 'SDXL'
|
||||
case _:
|
||||
model_type = 'SD1'
|
||||
|
||||
sigmas = nodes_align_your_steps.AlignYourStepsScheduler.get_sigmas(self, model_type, steps, denoise)
|
||||
sampler = comfy.samplers.sampler_object(sampler_name)
|
||||
AYS_samples = nodes_custom_sampler.SamplerCustom.execute(model, True, seed, cfg, positive, negative, sampler, sigmas[0], latent_image)
|
||||
samples = (AYS_samples[0],)
|
||||
if variation_extender_original > 0 or device != 'DEFAULT' or variation_batch_step_original > 0:
|
||||
samples = latentnoise.noisy_samples(model, device, steps, cfg, sampler_name, scheduler_name, positive, negative, latent_image, denoise, seed, noise_extender)
|
||||
else:
|
||||
samples = nodes.KSampler.sample(self, model, seed, steps, cfg, sampler_name, scheduler_name, positive, negative, latent_image, denoise=denoise)
|
||||
if align_your_steps == True:
|
||||
modelname_only = model
|
||||
model_version = utility.get_value_from_cache('model_version', modelname_only)
|
||||
match model_version:
|
||||
case 'SDXL':
|
||||
model_type = 'SDXL'
|
||||
case _:
|
||||
model_type = 'SD1'
|
||||
sigmas = nodes_align_your_steps.AlignYourStepsScheduler.get_sigmas(self, model_type, steps, denoise)
|
||||
sampler = comfy.samplers.sampler_object(sampler_name)
|
||||
AYS_samples = nodes_custom_sampler.SamplerCustom.execute(model, True, seed, cfg, positive, negative, sampler, sigmas[0], latent_image)
|
||||
samples = (AYS_samples[0],)
|
||||
else:
|
||||
samples = nodes.KSampler.sample(self, model, seed, steps, cfg, sampler_name, scheduler_name, positive, negative, latent_image, denoise=denoise)
|
||||
|
||||
if control_data and control_data.get('refiner') == True:
|
||||
refiner_model_name = control_data.get('refiner_model', None)
|
||||
if refiner_model_name and refiner_model_name != 'None':
|
||||
try:
|
||||
REFINER_CHECKPOINT = nodes.CheckpointLoaderSimple.load_checkpoint(self, refiner_model_name)
|
||||
RAW_IMAGE = nodes.VAEDecode.decode(self, REFINER_CHECKPOINT[2], samples[0])[0]
|
||||
RAW_IMAGE_ENCODED = nodes.VAEEncode.encode(self, REFINER_CHECKPOINT[2], RAW_IMAGE)[0]
|
||||
REFINER_SAMPLER = control_data.get('refiner_sampler', 'dpmpp_2m')
|
||||
REFINER_SCHEDULER = control_data.get('refiner_scheduler', 'normal')
|
||||
REFINER_CFG = float(control_data.get('refiner_cfg', 2.0))
|
||||
REFINER_STEPS = int(control_data.get('refiner_steps', 22))
|
||||
REFINER_DENOISE = float(control_data.get('refiner_denoise', 0.9))
|
||||
REFINER_START = int(control_data.get('refiner_start', 12))
|
||||
sigmas_refiner = nodes_custom_sampler.BasicScheduler.execute(REFINER_CHECKPOINT[0], REFINER_SCHEDULER, REFINER_STEPS, REFINER_DENOISE)[0]
|
||||
splitted_sigma = nodes_custom_sampler.SplitSigmas.execute(sigmas_refiner, REFINER_START)[1]
|
||||
sampler_refiner = comfy.samplers.sampler_object(REFINER_SAMPLER)
|
||||
if control_data.get('refiner_ignore_prompt', True):
|
||||
empty_cond = nodes.CLIPTextEncode.encode(self, REFINER_CHECKPOINT[1], "")[0]
|
||||
refiner_pos = empty_cond
|
||||
refiner_neg = empty_cond
|
||||
else:
|
||||
refiner_pos = positive
|
||||
refiner_neg = negative
|
||||
samples = (nodes_custom_sampler.SamplerCustom.execute(REFINER_CHECKPOINT[0], True, seed, REFINER_CFG, refiner_pos, refiner_neg, sampler_refiner, splitted_sigma, RAW_IMAGE_ENCODED)[0],)
|
||||
except Exception as e:
|
||||
print(f"Primere: Refiner sampling failed: {e}")
|
||||
|
||||
return samples
|
||||
|
||||
@@ -97,16 +136,15 @@ def PCascadeSampler(self, model, seed, steps, cfg, sampler_name, scheduler_name,
|
||||
|
||||
return samples
|
||||
|
||||
def PSamplerHyper(self, extra_pnginfo, model, seed, steps, cfg, positive, negative, sampler_name, scheduler_name, latent_image, denoise, prompt):
|
||||
WORKFLOWDATA = extra_pnginfo['workflow']['nodes']
|
||||
OriginalBaseModel = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereVisualCKPT', 'base_model', prompt)
|
||||
def PSamplerHyper(self, extra_pnginfo, model, seed, steps, cfg, positive, negative, sampler_name, scheduler_name, latent_image, denoise, prompt, control_data):
|
||||
# WORKFLOWDATA = extra_pnginfo['workflow']['nodes']
|
||||
OriginalBaseModel = control_data['model_name'] # OriginalBaseModel = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereVisualCKPT', 'base_model', prompt)
|
||||
fullpathFile = folder_paths.get_full_path('checkpoints', OriginalBaseModel)
|
||||
is_link = os.path.islink(str(fullpathFile))
|
||||
HyperSDSelector = None
|
||||
if is_link == True:
|
||||
HyperSDSelector = 'UNET'
|
||||
else:
|
||||
HyperSDSelector = utility.getDataFromWorkflowByName(WORKFLOWDATA, 'PrimereModelConceptSelector', 'hypersd_selector', prompt)
|
||||
if (HyperSDSelector == 'UNET'):
|
||||
if HyperSDSelector == 'UNET':
|
||||
sigmas = utility.get_hypersd_sigmas(model)
|
||||
sampler = comfy.samplers.sampler_object(sampler_name)
|
||||
hyper_samples = nodes_custom_sampler.SamplerCustom.execute(model, True, seed, cfg, positive, negative, sampler, sigmas[0], latent_image)
|
||||
@@ -155,14 +193,14 @@ def PSamplerPixart(self, device, seed, model,
|
||||
steps, cfg, sampler_name, scheduler_name,
|
||||
positive, negative,
|
||||
latent_image, denoise,
|
||||
variation_extender, variation_batch_step_original, batch_counter, variation_extender_original, variation_batch_step, variation_level, variation_limit, align_your_steps, noise_extender, workflow_tuple):
|
||||
variation_extender, variation_batch_step_original, batch_counter, variation_extender_original, variation_batch_step, variation_level, variation_limit, align_your_steps, noise_extender, control_data):
|
||||
|
||||
if workflow_tuple:
|
||||
sampler_name = workflow_tuple.get('sampler_name', sampler_name)
|
||||
scheduler_name = workflow_tuple.get('scheduler_name', scheduler_name)
|
||||
steps = workflow_tuple.get('steps', steps)
|
||||
cfg = workflow_tuple.get('cfg', cfg)
|
||||
PIXART_DENOISE = float(workflow_tuple.get('refiner_sampling_denoise', denoise)) if workflow_tuple and workflow_tuple.get('refiner') == True else denoise
|
||||
if control_data:
|
||||
sampler_name = control_data.get('sampler_name', sampler_name)
|
||||
scheduler_name = control_data.get('scheduler_name', scheduler_name)
|
||||
steps = control_data.get('steps', steps)
|
||||
cfg = control_data.get('cfg', cfg)
|
||||
PIXART_DENOISE = float(control_data.get('refiner_sampling_denoise', denoise)) if control_data and control_data.get('refiner') == True else denoise
|
||||
|
||||
sigmas_main = nodes_custom_sampler.BasicScheduler.execute(model['main'], scheduler_name, steps, denoise=PIXART_DENOISE)[0]
|
||||
sampler = comfy.samplers.sampler_object(sampler_name)
|
||||
@@ -182,22 +220,22 @@ def PSamplerPixart(self, device, seed, model,
|
||||
samples_main = nodes_custom_sampler.SamplerCustom.execute(model['main'], True, seed, cfg, positive['main'], negative['main'], sampler, sigmas_main, latent_image)[0]
|
||||
|
||||
if 'refiner' in model and model['refiner'] is not None:
|
||||
PIXART_VAE = utility.vae_loader_class.load_vae(workflow_tuple.get('vae'))[0]
|
||||
PIXART_VAE = utility.vae_loader_class.load_vae(control_data.get('vae'))[0]
|
||||
RAW_IMAGE = nodes.VAEDecode.decode(self, PIXART_VAE, samples_main)[0]
|
||||
PIXART_REFINER_CHECKPOINT = nodes.CheckpointLoaderSimple.load_checkpoint(self, workflow_tuple.get('refiner_model'))
|
||||
PIXART_REFINER_CHECKPOINT = nodes.CheckpointLoaderSimple.load_checkpoint(self, control_data.get('refiner_model'))
|
||||
RAW_IMAGE_ENCODED = nodes.VAEEncode.encode(self, PIXART_REFINER_CHECKPOINT[2], RAW_IMAGE)[0]
|
||||
|
||||
REFINER_SAMPLER = workflow_tuple.get('refiner_sampler', 'dpmpp_2m')
|
||||
REFINER_SCHEDULER = workflow_tuple.get('refiner_scheduler', 'normal')
|
||||
REFINER_CFG = float(workflow_tuple.get('refiner_cfg', 2.0))
|
||||
REFINER_STEPS = int(workflow_tuple.get('refiner_steps', 22))
|
||||
PIXART_DENOISE_REFINER = float(workflow_tuple.get('refiner_denoise', 0.9))
|
||||
PIXART_REFINER_START = int(workflow_tuple.get('refiner_start', 12))
|
||||
REFINER_SAMPLER = control_data.get('refiner_sampler', 'dpmpp_2m')
|
||||
REFINER_SCHEDULER = control_data.get('refiner_scheduler', 'normal')
|
||||
REFINER_CFG = float(control_data.get('refiner_cfg', 2.0))
|
||||
REFINER_STEPS = int(control_data.get('refiner_steps', 22))
|
||||
PIXART_DENOISE_REFINER = float(control_data.get('refiner_denoise', 0.9))
|
||||
PIXART_REFINER_START = int(control_data.get('refiner_start', 12))
|
||||
|
||||
sigmas_refiner = nodes_custom_sampler.BasicScheduler.execute(model['refiner'], REFINER_SCHEDULER, REFINER_STEPS, PIXART_DENOISE_REFINER)[0]
|
||||
splitted_low_sigma = nodes_custom_sampler.SplitSigmas.execute(sigmas_refiner, PIXART_REFINER_START)[1]
|
||||
sampler_refiner = comfy.samplers.sampler_object(REFINER_SAMPLER)
|
||||
REFINER_IGNORE_PROMPT = workflow_tuple.get('refiner_ignore_prompt', False)
|
||||
REFINER_IGNORE_PROMPT = control_data.get('refiner_ignore_prompt', False)
|
||||
if REFINER_IGNORE_PROMPT:
|
||||
empty_cond = nodes.CLIPTextEncode.encode(self, PIXART_REFINER_CHECKPOINT[1], "")[0]
|
||||
refiner_pos = empty_cond
|
||||
|
||||
@@ -2,16 +2,18 @@ import { app } from "/scripts/app.js";
|
||||
import { ComfyWidgets } from "/scripts/widgets.js";
|
||||
import { applyPrimereButtonStyle, showToast } from "./frontend_helper.js";
|
||||
|
||||
const TARGET_NODE_NAME = "PrimereAutoSamplerSettings";
|
||||
const TARGET_NODE_NAME = "PrimereModelControl";
|
||||
const CONCEPT_JSON_URL = new URL("/extensions/ComfyUI_Primere_Nodes/model_concept.json", import.meta.url).href;
|
||||
|
||||
const JSON_EXCLUDE_KEYS = new Set(["model_name"]);
|
||||
|
||||
function modelNameToKey(modelPath) {
|
||||
const base = modelPath.split(/[\\/]/).pop();
|
||||
return base.replace(/\.[^/.]+$/, "");
|
||||
}
|
||||
|
||||
function collectNodeData(node, includeLoraToggles = false) {
|
||||
const SKIP_KEYS = new Set(["concepts", "models", "runtime_concept"]);
|
||||
const SKIP_KEYS = new Set(["concepts", "models", "runtime_concept", ...JSON_EXCLUDE_KEYS]);
|
||||
const widgets = node.widgets || [];
|
||||
|
||||
const loraBooleans = new Set(
|
||||
@@ -175,7 +177,7 @@ function initializeSamplerNode(node) {
|
||||
}
|
||||
|
||||
app.registerExtension({
|
||||
name: "Primere.AutoSamplerSettings",
|
||||
name: "Primere.ModelControl",
|
||||
|
||||
setup() {
|
||||
app.api.addEventListener("primere.concept_setting", (event) => {
|
||||
|
||||
@@ -20,8 +20,8 @@ const state = {
|
||||
sortType: 'name',
|
||||
operator: 'ASC',
|
||||
PreviewPath: true,
|
||||
aeScoreMin: 400,
|
||||
aeScoreMax: 900,
|
||||
aeScoreMin: 550,
|
||||
aeScoreMax: 800,
|
||||
nodeHelper: {},
|
||||
cache_key: '',
|
||||
source_subdirname: '',
|
||||
|
||||
@@ -12,25 +12,50 @@ primere_root = Path(__file__).parent.parent.absolute()
|
||||
components_path = os.path.join(primere_root, 'components')
|
||||
sys.path.append(components_path)
|
||||
|
||||
import utility as utility
|
||||
import utility
|
||||
|
||||
EmbeddingList = folder_paths.get_filename_list("embeddings")
|
||||
|
||||
def match_supported(name):
|
||||
name_lower = name.lower()
|
||||
for supported in utility.SUPPORTED_MODELS:
|
||||
if supported.lower() == name_lower:
|
||||
return supported
|
||||
return None
|
||||
|
||||
def get_type_from_dir(oneEmbedding):
|
||||
parts = Path(oneEmbedding).parts
|
||||
if len(parts) > 1:
|
||||
return match_supported(parts[0])
|
||||
return None
|
||||
|
||||
print('------------------- START -------------------------')
|
||||
print(str(len(EmbeddingList)) + ' embeddings in system')
|
||||
|
||||
print('--------------- CACHED EMBEDDING INFO ---------------------')
|
||||
|
||||
if len(EmbeddingList) > 0:
|
||||
model_counter = 1
|
||||
for onelora in EmbeddingList:
|
||||
name_only = Path(onelora).stem
|
||||
for oneEmbedding in EmbeddingList:
|
||||
name_only = Path(oneEmbedding).stem
|
||||
prefix = f"Embedding [{model_counter}] / {len(EmbeddingList)}"
|
||||
|
||||
model_version = utility.get_value_from_cache('embedding_version', name_only)
|
||||
if model_version is None or model_version not in utility.SUPPORTED_MODELS:
|
||||
model_version = 'SD1'
|
||||
utility.add_value_to_cache('embedding_version', name_only, model_version)
|
||||
print('Embedding cached: ' + name_only + ' -> ' + str(model_version))
|
||||
else:
|
||||
print('Embedding already cached: ' + name_only + ' -> ' + str(model_version))
|
||||
model_counter = model_counter + 1
|
||||
if model_version is not None and model_version in utility.SUPPORTED_MODELS:
|
||||
print(f"{prefix} already cached: {name_only} -> {model_version}")
|
||||
model_counter += 1
|
||||
continue
|
||||
|
||||
dir_version = get_type_from_dir(oneEmbedding)
|
||||
if dir_version:
|
||||
utility.add_value_to_cache('embedding_version', name_only, dir_version)
|
||||
print(f"{prefix} cached from directory: {name_only} -> {dir_version}")
|
||||
model_counter += 1
|
||||
continue
|
||||
|
||||
cache_msg = f"UNKNOWN | path: models/embeddings/{oneEmbedding}"
|
||||
utility.add_value_to_cache('embedding_version', name_only, cache_msg)
|
||||
print(f"{prefix} {cache_msg}")
|
||||
|
||||
model_counter += 1
|
||||
else:
|
||||
print('No embedding in your system....')
|
||||
print('No embeddings in your system....')
|
||||
|
||||
@@ -12,30 +12,57 @@ primere_root = Path(__file__).parent.parent.absolute()
|
||||
components_path = os.path.join(primere_root, 'components')
|
||||
sys.path.append(components_path)
|
||||
|
||||
import utility as utility
|
||||
import utility
|
||||
|
||||
def match_supported(name):
|
||||
name_lower = name.lower()
|
||||
for supported in utility.SUPPORTED_MODELS:
|
||||
if supported.lower() == name_lower:
|
||||
return supported
|
||||
return None
|
||||
|
||||
def get_type_from_dir(oneModel):
|
||||
parts = Path(oneModel).parts
|
||||
if len(parts) > 1:
|
||||
return match_supported(parts[0])
|
||||
return None
|
||||
|
||||
ModelsList = folder_paths.get_filename_list("loras")
|
||||
|
||||
print('------------------- START -------------------------')
|
||||
print(str(len(ModelsList)) + ' loras in system')
|
||||
|
||||
print('--------------- CACHED LORAS INFO ---------------------')
|
||||
|
||||
if len(ModelsList) > 0:
|
||||
model_counter = 1
|
||||
for oneModel in ModelsList:
|
||||
model_path = folder_paths.get_full_path("loras", oneModel)
|
||||
modelaname_only = Path(oneModel).stem
|
||||
model_version = utility.get_value_from_cache('lora_version', modelaname_only)
|
||||
if model_version is None or model_version not in utility.SUPPORTED_MODELS:
|
||||
model_version = utility.getModelType(oneModel, 'loras')
|
||||
if model_version and model_version is not None and model_version != 'NoneType':
|
||||
utility.add_value_to_cache('lora_version', modelaname_only, str(model_version))
|
||||
print('Lora [' + str(model_counter) + '] / ' + str(len(ModelsList)) + ' cached: ' + modelaname_only + ' -> ' + str(model_version))
|
||||
else:
|
||||
utility.add_value_to_cache('lora_version', modelaname_only, 'unknown')
|
||||
print('Lora [' + str(model_counter) + '] / ' + str(len(ModelsList)) + ' cached: ' + modelaname_only + ' -> ' + 'unknown')
|
||||
else:
|
||||
print('Lora [' + str(model_counter) + '] / ' + str(len(ModelsList)) + ' already cached: ' + modelaname_only + ' -> ' + str(model_version))
|
||||
model_counter = model_counter + 1
|
||||
modelname_only = Path(oneModel).stem
|
||||
prefix = f"Lora [{model_counter}] / {len(ModelsList)}"
|
||||
|
||||
model_version = utility.get_value_from_cache('lora_version', modelname_only)
|
||||
if model_version is not None and model_version in utility.SUPPORTED_MODELS:
|
||||
print(f"{prefix} already cached: {modelname_only} -> {model_version}")
|
||||
model_counter += 1
|
||||
continue
|
||||
|
||||
model_version = utility.getModelType(oneModel, 'loras')
|
||||
if model_version and model_version not in (None, False, 'NoneType') and model_version in utility.SUPPORTED_MODELS:
|
||||
utility.add_value_to_cache('lora_version', modelname_only, model_version)
|
||||
print(f"{prefix} cached from metadata: {modelname_only} -> {model_version}")
|
||||
model_counter += 1
|
||||
continue
|
||||
|
||||
dir_version = get_type_from_dir(oneModel)
|
||||
if dir_version:
|
||||
utility.add_value_to_cache('lora_version', modelname_only, dir_version)
|
||||
print(f"{prefix} cached from directory: {modelname_only} -> {dir_version}")
|
||||
model_counter += 1
|
||||
continue
|
||||
|
||||
cache_msg = f"UNKNOWN | path: models/loras/{oneModel}"
|
||||
utility.add_value_to_cache('lora_version', modelname_only, cache_msg)
|
||||
print(f"{prefix} {cache_msg}")
|
||||
|
||||
model_counter += 1
|
||||
else:
|
||||
print('No loras in your system....')
|
||||
print('No loras in your system....')
|
||||
|
||||
@@ -12,33 +12,60 @@ primere_root = Path(__file__).parent.parent.absolute()
|
||||
components_path = os.path.join(primere_root, 'components')
|
||||
sys.path.append(components_path)
|
||||
|
||||
import utility as utility
|
||||
import utility
|
||||
|
||||
LYCO_DIR = os.path.join(folder_paths.models_dir, 'lycoris')
|
||||
folder_paths.add_model_folder_path("lycoris", LYCO_DIR)
|
||||
LyCORIS = folder_paths.get_filename_list("lycoris")
|
||||
ModelsList = folder_paths.filter_files_extensions(LyCORIS, ['.ckpt', '.safetensors'])
|
||||
|
||||
def match_supported(name):
|
||||
name_lower = name.lower()
|
||||
for supported in utility.SUPPORTED_MODELS:
|
||||
if supported.lower() == name_lower:
|
||||
return supported
|
||||
return None
|
||||
|
||||
def get_type_from_dir(oneModel):
|
||||
parts = Path(oneModel).parts
|
||||
if len(parts) > 1:
|
||||
return match_supported(parts[0])
|
||||
return None
|
||||
|
||||
print('------------------- START -------------------------')
|
||||
print(str(len(ModelsList)) + ' lycoris in system')
|
||||
|
||||
print('--------------- CACHED LYCORIS INFO ---------------------')
|
||||
|
||||
if len(ModelsList) > 0:
|
||||
model_counter = 1
|
||||
for oneModel in ModelsList:
|
||||
model_path = folder_paths.get_full_path("lycoris", oneModel)
|
||||
modelaname_only = Path(oneModel).stem
|
||||
model_version = utility.get_value_from_cache('lycoris_version', modelaname_only)
|
||||
if model_version is None or model_version not in utility.SUPPORTED_MODELS:
|
||||
model_version = utility.getModelType(oneModel, 'lycoris')
|
||||
if model_version and model_version is not None and model_version != 'NoneType':
|
||||
utility.add_value_to_cache('lycoris_version', modelaname_only, str(model_version))
|
||||
print('Lyco [' + str(model_counter) + '] / ' + str(len(ModelsList)) + ' cached: ' + modelaname_only + ' -> ' + str(model_version))
|
||||
else:
|
||||
utility.add_value_to_cache('lycoris_version', modelaname_only, 'unknown')
|
||||
print('Lyco [' + str(model_counter) + '] / ' + str(len(ModelsList)) + ' cached: ' + modelaname_only + ' -> ' + 'unknown')
|
||||
else:
|
||||
print('Lyco [' + str(model_counter) + '] / ' + str(len(ModelsList)) + ' already cached: ' + modelaname_only + ' -> ' + str(model_version))
|
||||
model_counter = model_counter + 1
|
||||
modelname_only = Path(oneModel).stem
|
||||
prefix = f"Lyco [{model_counter}] / {len(ModelsList)}"
|
||||
|
||||
model_version = utility.get_value_from_cache('lycoris_version', modelname_only)
|
||||
if model_version is not None and model_version in utility.SUPPORTED_MODELS:
|
||||
print(f"{prefix} already cached: {modelname_only} -> {model_version}")
|
||||
model_counter += 1
|
||||
continue
|
||||
|
||||
model_version = utility.getModelType(oneModel, 'lycoris')
|
||||
if model_version and model_version not in (None, False, 'NoneType') and model_version in utility.SUPPORTED_MODELS:
|
||||
utility.add_value_to_cache('lycoris_version', modelname_only, model_version)
|
||||
print(f"{prefix} cached from metadata: {modelname_only} -> {model_version}")
|
||||
model_counter += 1
|
||||
continue
|
||||
|
||||
dir_version = get_type_from_dir(oneModel)
|
||||
if dir_version:
|
||||
utility.add_value_to_cache('lycoris_version', modelname_only, dir_version)
|
||||
print(f"{prefix} cached from directory: {modelname_only} -> {dir_version}")
|
||||
model_counter += 1
|
||||
continue
|
||||
|
||||
cache_msg = f"UNKNOWN | path: models/lycoris/{oneModel}"
|
||||
utility.add_value_to_cache('lycoris_version', modelname_only, cache_msg)
|
||||
print(f"{prefix} {cache_msg}")
|
||||
|
||||
model_counter += 1
|
||||
else:
|
||||
print('No lycoris in your system....')
|
||||
print('No lycoris in your system....')
|
||||
|
||||
@@ -12,54 +12,80 @@ primere_root = Path(__file__).parent.parent.absolute()
|
||||
components_path = os.path.join(primere_root, 'components')
|
||||
sys.path.append(components_path)
|
||||
|
||||
import utility as utility
|
||||
import utility
|
||||
|
||||
EXCLUDED_SUBDIRS = {'.locks', 'Bjornulf_civitAI', 'depthfm', 'models--xiaozaa--cat-tryoff-flux'}
|
||||
|
||||
def match_supported(name):
|
||||
name_lower = name.lower()
|
||||
for supported in utility.SUPPORTED_MODELS:
|
||||
if supported.lower() == name_lower:
|
||||
return supported
|
||||
return None
|
||||
|
||||
def get_type_from_dirs(oneModel, resolved_path=None):
|
||||
parts = Path(oneModel).parts
|
||||
if len(parts) > 1:
|
||||
matched = match_supported(parts[0])
|
||||
if matched:
|
||||
return matched
|
||||
if resolved_path is not None:
|
||||
parent_dir = Path(resolved_path).parent.name
|
||||
matched = match_supported(parent_dir)
|
||||
if matched:
|
||||
return matched
|
||||
return None
|
||||
|
||||
ModelsList = folder_paths.get_filename_list("checkpoints")
|
||||
|
||||
print('------------------- START -------------------------')
|
||||
print(str(len(ModelsList)) + ' models in system')
|
||||
|
||||
print('--------------- CACHED MODELS INFO ---------------------')
|
||||
|
||||
if len(ModelsList) > 0:
|
||||
model_counter = 1
|
||||
for oneModel in ModelsList:
|
||||
parts = Path(oneModel).parts
|
||||
first_part = parts[0] if len(parts) > 1 else ''
|
||||
if first_part in EXCLUDED_SUBDIRS:
|
||||
model_counter += 1
|
||||
continue
|
||||
|
||||
model_path = folder_paths.get_full_path("checkpoints", oneModel)
|
||||
is_link = os.path.islink(str(model_path))
|
||||
modelaname_only = Path(oneModel).stem
|
||||
if is_link == False:
|
||||
model_version = utility.get_value_from_cache('model_version', modelaname_only)
|
||||
if model_version is None or model_version not in utility.SUPPORTED_MODELS:
|
||||
model_version = utility.getModelType(oneModel, 'checkpoints')
|
||||
if model_version and model_version is not None and model_version != 'NoneType':
|
||||
utility.add_value_to_cache('model_version', modelaname_only, str(model_version))
|
||||
print('Model [' + str(model_counter) + '] / ' + str(len(ModelsList)) + ' cached: ' + modelaname_only + ' -> ' + str(model_version))
|
||||
else:
|
||||
utility.add_value_to_cache('model_version', modelaname_only, 'unknown')
|
||||
print('Model [' + str(model_counter) + '] / ' + str(len(ModelsList)) + ' cached: ' + modelaname_only + ' -> ' + 'unknown')
|
||||
else:
|
||||
print('Model [' + str(model_counter) + '] / ' + str(len(ModelsList)) + ' already cached: ' + modelaname_only + ' -> ' + str(model_version))
|
||||
else:
|
||||
model_version = utility.get_value_from_cache('model_version', modelaname_only)
|
||||
if model_version is None or model_version not in utility.SUPPORTED_MODELS:
|
||||
File_link = Path(str(model_path)).resolve()
|
||||
comfyModelDir = str(Path(folder_paths.folder_names_and_paths['checkpoints'][0][0]).parent)
|
||||
# modelType = str(File_link)[(len(comfyModelDir) + 1):(str(File_link).find('\\', len(comfyModelDir) + 1))]
|
||||
try:
|
||||
modelType = str(File_link)[str(File_link).index(os.sep + Path(comfyModelDir).stem) + len(Path(comfyModelDir).stem) + 2:(str(File_link).find(os.sep, len(comfyModelDir) + 1))]
|
||||
linkName_U = str(folder_paths.folder_names_and_paths["diffusion_models"][0][0])
|
||||
linkName_D = str(folder_paths.folder_names_and_paths["diffusion_models"][0][1])
|
||||
if str(Path(linkName_U).stem + '\\') in str(File_link):
|
||||
modelType = str(Path(linkName_U).stem)
|
||||
if str(Path(linkName_D).stem + '\\') in str(File_link):
|
||||
modelType = str(Path(linkName_D).stem)
|
||||
modelname_only = Path(oneModel).stem
|
||||
resolved_path = Path(str(model_path)).resolve() if is_link else None
|
||||
prefix = f"Model [{model_counter}] / {len(ModelsList)}"
|
||||
|
||||
utility.add_value_to_cache('model_version', modelaname_only, f"{modelType}_symlink")
|
||||
print(f"Model [{model_counter}] / {len(ModelsList)} symlinked file: {modelaname_only} -> from: {modelType}")
|
||||
except Exception:
|
||||
utility.add_value_to_cache('model_version', modelaname_only, f"unknown_symlink")
|
||||
print(f"Model [{model_counter}] / {len(ModelsList)} unknown by meta error: {modelaname_only}")
|
||||
else:
|
||||
print('Model [' + str(model_counter) + '] / ' + str(len(ModelsList)) + ' already cached: ' + modelaname_only + ' -> ' + str(model_version))
|
||||
model_counter = model_counter + 1
|
||||
model_version = utility.get_value_from_cache('model_version', modelname_only)
|
||||
if model_version is not None and model_version in utility.SUPPORTED_MODELS:
|
||||
print(f"{prefix} already cached: {modelname_only} -> {model_version}")
|
||||
model_counter += 1
|
||||
continue
|
||||
|
||||
model_version = utility.getModelType(oneModel, 'checkpoints')
|
||||
if model_version and model_version not in (None, False, 'NoneType') and model_version in utility.SUPPORTED_MODELS:
|
||||
utility.add_value_to_cache('model_version', modelname_only, model_version)
|
||||
src = f" (symlink from: {resolved_path})" if is_link else ""
|
||||
print(f"{prefix} cached from metadata: {modelname_only} -> {model_version}{src}")
|
||||
model_counter += 1
|
||||
continue
|
||||
|
||||
dir_version = get_type_from_dirs(oneModel, resolved_path)
|
||||
if dir_version:
|
||||
utility.add_value_to_cache('model_version', modelname_only, dir_version)
|
||||
src = f" (symlink from: {resolved_path})" if is_link else ""
|
||||
print(f"{prefix} cached from directory: {modelname_only} -> {dir_version}{src}")
|
||||
model_counter += 1
|
||||
continue
|
||||
|
||||
if is_link:
|
||||
cache_msg = f"UNKNOWN | checkpoint: models/checkpoints/{oneModel} | original: {resolved_path}"
|
||||
else:
|
||||
cache_msg = f"UNKNOWN | path: models/checkpoints/{oneModel}"
|
||||
utility.add_value_to_cache('model_version', modelname_only, cache_msg)
|
||||
print(f"{prefix} {cache_msg}")
|
||||
|
||||
model_counter += 1
|
||||
else:
|
||||
print('No models in your system....')
|
||||
print('No models in your system....')
|
||||
|
||||
Reference in New Issue
Block a user