Add split workflow nodes and profile controls
This commit is contained in:
+334
@@ -5,9 +5,15 @@ import json
|
||||
try:
|
||||
from .prompt_builder import (
|
||||
build_camera_config_json,
|
||||
build_cast_config_json,
|
||||
build_category_config_json,
|
||||
build_character_profile_json,
|
||||
build_filter_config_json,
|
||||
build_generation_profile_json,
|
||||
build_insta_of_options_json,
|
||||
build_insta_of_pair,
|
||||
build_prompt,
|
||||
build_prompt_from_configs,
|
||||
build_seed_config_json,
|
||||
camera_angle_choices,
|
||||
camera_distance_choices,
|
||||
@@ -17,7 +23,12 @@ try:
|
||||
camera_phone_choices,
|
||||
camera_priority_choices,
|
||||
camera_shot_choices,
|
||||
cast_preset_choices,
|
||||
category_preset_choices,
|
||||
category_choices,
|
||||
character_profile_choices,
|
||||
generation_profile_choices,
|
||||
load_character_profile_json,
|
||||
subcategory_choices,
|
||||
)
|
||||
from .caption_naturalizer import naturalize_caption
|
||||
@@ -25,9 +36,15 @@ try:
|
||||
except ImportError:
|
||||
from prompt_builder import (
|
||||
build_camera_config_json,
|
||||
build_cast_config_json,
|
||||
build_category_config_json,
|
||||
build_character_profile_json,
|
||||
build_filter_config_json,
|
||||
build_generation_profile_json,
|
||||
build_insta_of_options_json,
|
||||
build_insta_of_pair,
|
||||
build_prompt,
|
||||
build_prompt_from_configs,
|
||||
build_seed_config_json,
|
||||
camera_angle_choices,
|
||||
camera_distance_choices,
|
||||
@@ -37,7 +54,12 @@ except ImportError:
|
||||
camera_phone_choices,
|
||||
camera_priority_choices,
|
||||
camera_shot_choices,
|
||||
cast_preset_choices,
|
||||
category_preset_choices,
|
||||
category_choices,
|
||||
character_profile_choices,
|
||||
generation_profile_choices,
|
||||
load_character_profile_json,
|
||||
subcategory_choices,
|
||||
)
|
||||
from caption_naturalizer import naturalize_caption
|
||||
@@ -72,6 +94,7 @@ class SxCPPromptBuilder:
|
||||
"optional": {
|
||||
"seed_config": ("STRING", {"default": "", "multiline": True}),
|
||||
"camera_config": ("STRING", {"default": "", "multiline": True}),
|
||||
"character_profile": ("STRING", {"default": "", "multiline": True}),
|
||||
"extra_positive": ("STRING", {"default": "", "multiline": True}),
|
||||
"extra_negative": ("STRING", {"default": "", "multiline": True}),
|
||||
},
|
||||
@@ -105,6 +128,7 @@ class SxCPPromptBuilder:
|
||||
prepend_trigger_to_prompt,
|
||||
seed_config="",
|
||||
camera_config="",
|
||||
character_profile="",
|
||||
extra_positive="",
|
||||
extra_negative="",
|
||||
):
|
||||
@@ -132,6 +156,7 @@ class SxCPPromptBuilder:
|
||||
extra_negative=extra_negative or "",
|
||||
seed_config=seed_config or "",
|
||||
camera_config=camera_config or "",
|
||||
character_profile=character_profile or "",
|
||||
)
|
||||
return (
|
||||
row["prompt"],
|
||||
@@ -239,6 +264,294 @@ class SxCPCameraControl:
|
||||
)
|
||||
|
||||
|
||||
class SxCPCategoryPreset:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"preset": (category_preset_choices(), {"default": "auto_weighted"}),
|
||||
"subcategory": (subcategory_choices(), {"default": "random"}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING", "STRING", "STRING")
|
||||
RETURN_NAMES = ("category_config", "category", "subcategory")
|
||||
FUNCTION = "build"
|
||||
CATEGORY = "prompt_builder"
|
||||
|
||||
def build(self, preset, subcategory):
|
||||
config = build_category_config_json(preset=preset, subcategory=subcategory)
|
||||
parsed = json.loads(config)
|
||||
return config, parsed["category"], parsed["subcategory"]
|
||||
|
||||
|
||||
class SxCPCastControl:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"cast_mode": (cast_preset_choices(), {"default": "mixed_couple"}),
|
||||
"women_count": ("INT", {"default": 1, "min": 0, "max": 12, "step": 1}),
|
||||
"men_count": ("INT", {"default": 1, "min": 0, "max": 12, "step": 1}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING", "INT", "INT", "STRING")
|
||||
RETURN_NAMES = ("cast_config", "women_count", "men_count", "cast_summary")
|
||||
FUNCTION = "build"
|
||||
CATEGORY = "prompt_builder"
|
||||
|
||||
def build(self, cast_mode, women_count, men_count):
|
||||
config = build_cast_config_json(cast_mode=cast_mode, women_count=women_count, men_count=men_count)
|
||||
parsed = json.loads(config)
|
||||
summary = f"{parsed['women_count']} women, {parsed['men_count']} men"
|
||||
return config, parsed["women_count"], parsed["men_count"], summary
|
||||
|
||||
|
||||
class SxCPGenerationProfile:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"profile": (generation_profile_choices(), {"default": "balanced"}),
|
||||
"clothing_override": (["profile_default", "full", "minimal"], {"default": "profile_default"}),
|
||||
"poses_override": (["profile_default", "standard", "evocative"], {"default": "profile_default"}),
|
||||
"expression_intensity": ("FLOAT", {"default": -1.0, "min": -1.0, "max": 1.0, "step": 0.01}),
|
||||
"backside_bias": ("FLOAT", {"default": -1.0, "min": -1.0, "max": 1.0, "step": 0.01}),
|
||||
"minimal_clothing_ratio": ("FLOAT", {"default": -1.0, "min": -1.0, "max": 1.0, "step": 0.01}),
|
||||
"standard_pose_ratio": ("FLOAT", {"default": -1.0, "min": -1.0, "max": 1.0, "step": 0.01}),
|
||||
"trigger_policy": (["profile_default", "prepend_trigger", "do_not_prepend"], {"default": "profile_default"}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING", "STRING")
|
||||
RETURN_NAMES = ("generation_profile", "summary")
|
||||
FUNCTION = "build"
|
||||
CATEGORY = "prompt_builder"
|
||||
|
||||
def build(
|
||||
self,
|
||||
profile,
|
||||
clothing_override,
|
||||
poses_override,
|
||||
expression_intensity,
|
||||
backside_bias,
|
||||
minimal_clothing_ratio,
|
||||
standard_pose_ratio,
|
||||
trigger_policy,
|
||||
):
|
||||
config = build_generation_profile_json(
|
||||
profile=profile,
|
||||
clothing_override=clothing_override,
|
||||
poses_override=poses_override,
|
||||
expression_intensity=expression_intensity,
|
||||
backside_bias=backside_bias,
|
||||
minimal_clothing_ratio=minimal_clothing_ratio,
|
||||
standard_pose_ratio=standard_pose_ratio,
|
||||
trigger_policy=trigger_policy,
|
||||
)
|
||||
parsed = json.loads(config)
|
||||
summary = f"{parsed['profile']}: {parsed['clothing']}, {parsed['poses']}, expression {parsed['expression_intensity']}"
|
||||
return config, summary
|
||||
|
||||
|
||||
class SxCPAdvancedFilters:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"ethnicity": (["any", "asian", "white_asian"], {"default": "any"}),
|
||||
"figure": (["curvy", "balanced", "bombshell"], {"default": "curvy"}),
|
||||
"no_plus_women": ("BOOLEAN", {"default": False}),
|
||||
"no_black": ("BOOLEAN", {"default": False}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ("filter_config",)
|
||||
FUNCTION = "build"
|
||||
CATEGORY = "prompt_builder"
|
||||
|
||||
def build(self, ethnicity, figure, no_plus_women, no_black):
|
||||
return (
|
||||
build_filter_config_json(
|
||||
ethnicity=ethnicity,
|
||||
figure=figure,
|
||||
no_plus_women=no_plus_women,
|
||||
no_black=no_black,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class SxCPPromptBuilderFromConfigs:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"row_number": ("INT", {"default": 1, "min": 1, "max": 1000000, "step": 1}),
|
||||
"start_index": ("INT", {"default": 41, "min": 1, "max": 1000000, "step": 1}),
|
||||
"seed": ("INT", {"default": 20260614, "min": 0, "max": 0xFFFFFFFF, "step": 1}),
|
||||
},
|
||||
"optional": {
|
||||
"category_config": ("STRING", {"default": "", "multiline": True}),
|
||||
"cast_config": ("STRING", {"default": "", "multiline": True}),
|
||||
"generation_profile": ("STRING", {"default": "", "multiline": True}),
|
||||
"filter_config": ("STRING", {"default": "", "multiline": True}),
|
||||
"seed_config": ("STRING", {"default": "", "multiline": True}),
|
||||
"camera_config": ("STRING", {"default": "", "multiline": True}),
|
||||
"character_profile": ("STRING", {"default": "", "multiline": True}),
|
||||
"extra_positive": ("STRING", {"default": "", "multiline": True}),
|
||||
"extra_negative": ("STRING", {"default": "", "multiline": True}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING", "STRING", "STRING", "STRING", "STRING", "STRING")
|
||||
RETURN_NAMES = ("prompt", "negative_prompt", "caption", "metadata_json", "category", "subcategory")
|
||||
FUNCTION = "build"
|
||||
CATEGORY = "prompt_builder"
|
||||
|
||||
def build(
|
||||
self,
|
||||
row_number,
|
||||
start_index,
|
||||
seed,
|
||||
category_config="",
|
||||
cast_config="",
|
||||
generation_profile="",
|
||||
filter_config="",
|
||||
seed_config="",
|
||||
camera_config="",
|
||||
character_profile="",
|
||||
extra_positive="",
|
||||
extra_negative="",
|
||||
):
|
||||
row = build_prompt_from_configs(
|
||||
row_number=row_number,
|
||||
start_index=start_index,
|
||||
seed=seed,
|
||||
category_config=category_config or "",
|
||||
cast_config=cast_config or "",
|
||||
generation_profile=generation_profile or "",
|
||||
filter_config=filter_config or "",
|
||||
seed_config=seed_config or "",
|
||||
camera_config=camera_config or "",
|
||||
character_profile=character_profile or "",
|
||||
extra_positive=extra_positive or "",
|
||||
extra_negative=extra_negative or "",
|
||||
)
|
||||
return (
|
||||
row["prompt"],
|
||||
row["negative_prompt"],
|
||||
row["caption"],
|
||||
json.dumps(row, ensure_ascii=True, sort_keys=True),
|
||||
row.get("main_category", ""),
|
||||
row.get("subcategory", ""),
|
||||
)
|
||||
|
||||
|
||||
class SxCPCharacterProfileSave:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"profile_name": ("STRING", {"default": "saved_character"}),
|
||||
"source": (["metadata_json", "manual"], {"default": "metadata_json"}),
|
||||
"subject_type": (["woman", "man"], {"default": "woman"}),
|
||||
"age": ("STRING", {"default": ""}),
|
||||
"body": ("STRING", {"default": ""}),
|
||||
"body_phrase": ("STRING", {"default": ""}),
|
||||
"skin": ("STRING", {"default": ""}),
|
||||
"hair": ("STRING", {"default": ""}),
|
||||
"eyes": ("STRING", {"default": ""}),
|
||||
"figure": ("STRING", {"default": ""}),
|
||||
"save_now": ("BOOLEAN", {"default": False}),
|
||||
},
|
||||
"optional": {
|
||||
"metadata_json": ("STRING", {"default": "", "multiline": True}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING", "STRING", "STRING", "STRING", "STRING")
|
||||
RETURN_NAMES = ("character_profile", "descriptor", "profile_name", "saved_path", "status")
|
||||
FUNCTION = "build"
|
||||
CATEGORY = "prompt_builder"
|
||||
|
||||
def build(
|
||||
self,
|
||||
profile_name,
|
||||
source,
|
||||
subject_type,
|
||||
age,
|
||||
body,
|
||||
body_phrase,
|
||||
skin,
|
||||
hair,
|
||||
eyes,
|
||||
figure,
|
||||
save_now,
|
||||
metadata_json="",
|
||||
):
|
||||
profile = build_character_profile_json(
|
||||
profile_name=profile_name,
|
||||
source=source,
|
||||
metadata_json=metadata_json or "",
|
||||
subject_type=subject_type,
|
||||
age=age,
|
||||
body=body,
|
||||
body_phrase=body_phrase,
|
||||
skin=skin,
|
||||
hair=hair,
|
||||
eyes=eyes,
|
||||
figure=figure,
|
||||
save_now=save_now,
|
||||
)
|
||||
return profile["profile_json"], profile["descriptor"], profile["profile_name"], profile["saved_path"], profile["status"]
|
||||
|
||||
|
||||
class SxCPCharacterProfileLoad:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"enabled": ("BOOLEAN", {"default": True}),
|
||||
"profile_name": (character_profile_choices(), {"default": "manual"}),
|
||||
"rename_to": ("STRING", {"default": ""}),
|
||||
"delete_now": ("BOOLEAN", {"default": False}),
|
||||
"rename_now": ("BOOLEAN", {"default": False}),
|
||||
},
|
||||
"optional": {
|
||||
"manual_profile_name": ("STRING", {"default": ""}),
|
||||
"fallback_profile_json": ("STRING", {"default": "", "multiline": True}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING", "STRING", "STRING", "STRING", "STRING")
|
||||
RETURN_NAMES = ("character_profile", "descriptor", "profile_name", "saved_path", "status")
|
||||
FUNCTION = "build"
|
||||
CATEGORY = "prompt_builder"
|
||||
|
||||
def build(
|
||||
self,
|
||||
enabled,
|
||||
profile_name,
|
||||
rename_to,
|
||||
delete_now,
|
||||
rename_now,
|
||||
manual_profile_name="",
|
||||
fallback_profile_json="",
|
||||
):
|
||||
chosen_name = manual_profile_name.strip() if profile_name == "manual" and manual_profile_name.strip() else profile_name
|
||||
profile = load_character_profile_json(
|
||||
profile_name=chosen_name,
|
||||
fallback_profile_json=fallback_profile_json or "",
|
||||
enabled=enabled,
|
||||
delete_now=delete_now,
|
||||
rename_now=rename_now,
|
||||
rename_to=rename_to,
|
||||
)
|
||||
return profile["profile_json"], profile["descriptor"], profile["profile_name"], profile["saved_path"], profile["status"]
|
||||
|
||||
|
||||
class SxCPCaptionNaturalizer:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
@@ -428,6 +741,7 @@ class SxCPInstaOFPromptPair:
|
||||
"seed_config": ("STRING", {"default": "", "multiline": True}),
|
||||
"options_json": ("STRING", {"default": "", "multiline": True}),
|
||||
"camera_config": ("STRING", {"default": "", "multiline": True}),
|
||||
"character_profile": ("STRING", {"default": "", "multiline": True}),
|
||||
"extra_positive": ("STRING", {"default": "", "multiline": True}),
|
||||
"extra_negative": ("STRING", {"default": "", "multiline": True}),
|
||||
},
|
||||
@@ -461,6 +775,7 @@ class SxCPInstaOFPromptPair:
|
||||
seed_config="",
|
||||
options_json="",
|
||||
camera_config="",
|
||||
character_profile="",
|
||||
extra_positive="",
|
||||
extra_negative="",
|
||||
):
|
||||
@@ -477,6 +792,7 @@ class SxCPInstaOFPromptPair:
|
||||
seed_config=seed_config or "",
|
||||
options_json=options_json or "",
|
||||
camera_config=camera_config or "",
|
||||
character_profile=character_profile or "",
|
||||
extra_positive=extra_positive or "",
|
||||
extra_negative=extra_negative or "",
|
||||
)
|
||||
@@ -496,6 +812,13 @@ NODE_CLASS_MAPPINGS = {
|
||||
"SxCPPromptBuilder": SxCPPromptBuilder,
|
||||
"SxCPSeedControl": SxCPSeedControl,
|
||||
"SxCPCameraControl": SxCPCameraControl,
|
||||
"SxCPCategoryPreset": SxCPCategoryPreset,
|
||||
"SxCPCastControl": SxCPCastControl,
|
||||
"SxCPGenerationProfile": SxCPGenerationProfile,
|
||||
"SxCPAdvancedFilters": SxCPAdvancedFilters,
|
||||
"SxCPPromptBuilderFromConfigs": SxCPPromptBuilderFromConfigs,
|
||||
"SxCPCharacterProfileSave": SxCPCharacterProfileSave,
|
||||
"SxCPCharacterProfileLoad": SxCPCharacterProfileLoad,
|
||||
"SxCPCaptionNaturalizer": SxCPCaptionNaturalizer,
|
||||
"SxCPKrea2Formatter": SxCPKrea2Formatter,
|
||||
"SxCPInstaOFOptions": SxCPInstaOFOptions,
|
||||
@@ -506,8 +829,19 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"SxCPPromptBuilder": "SxCP Prompt Builder",
|
||||
"SxCPSeedControl": "SxCP Seed Control",
|
||||
"SxCPCameraControl": "SxCP Camera Control",
|
||||
"SxCPCategoryPreset": "SxCP Category Preset",
|
||||
"SxCPCastControl": "SxCP Cast Control",
|
||||
"SxCPGenerationProfile": "SxCP Generation Profile",
|
||||
"SxCPAdvancedFilters": "SxCP Advanced Filters",
|
||||
"SxCPPromptBuilderFromConfigs": "SxCP Prompt Builder From Configs",
|
||||
"SxCPCharacterProfileSave": "SxCP Character Profile Save",
|
||||
"SxCPCharacterProfileLoad": "SxCP Character Profile Load",
|
||||
"SxCPCaptionNaturalizer": "SxCP Caption Naturalizer",
|
||||
"SxCPKrea2Formatter": "SxCP Krea2 Formatter",
|
||||
"SxCPInstaOFOptions": "SxCP Insta/OF Options",
|
||||
"SxCPInstaOFPromptPair": "SxCP Insta/OF Prompt Pair",
|
||||
}
|
||||
|
||||
WEB_DIRECTORY = "./web"
|
||||
|
||||
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"]
|
||||
|
||||
Reference in New Issue
Block a user