Extract builder nodes

This commit is contained in:
2026-06-26 23:32:39 +02:00
parent ef8b7f5b89
commit 30b5280da1
6 changed files with 363 additions and 237 deletions
+12 -219
View File
@@ -404,6 +404,10 @@ try:
NODE_CLASS_MAPPINGS as CAMERA_NODE_CLASS_MAPPINGS,
NODE_DISPLAY_NAME_MAPPINGS as CAMERA_NODE_DISPLAY_NAME_MAPPINGS,
)
from .node_builder import (
NODE_CLASS_MAPPINGS as BUILDER_NODE_CLASS_MAPPINGS,
NODE_DISPLAY_NAME_MAPPINGS as BUILDER_NODE_DISPLAY_NAME_MAPPINGS,
)
from .node_character import (
NODE_CLASS_MAPPINGS as CHARACTER_NODE_CLASS_MAPPINGS,
NODE_DISPLAY_NAME_MAPPINGS as CHARACTER_NODE_DISPLAY_NAME_MAPPINGS,
@@ -433,12 +437,7 @@ try:
NODE_DISPLAY_NAME_MAPPINGS as SEED_RESOLUTION_NODE_DISPLAY_NAME_MAPPINGS,
)
from .prompt_builder import (
build_prompt,
build_prompt_from_configs,
category_choices,
ethnicity_choices,
save_character_profile_payload,
subcategory_choices,
)
except ImportError:
from loop_nodes import (
@@ -453,6 +452,10 @@ except ImportError:
NODE_CLASS_MAPPINGS as CAMERA_NODE_CLASS_MAPPINGS,
NODE_DISPLAY_NAME_MAPPINGS as CAMERA_NODE_DISPLAY_NAME_MAPPINGS,
)
from node_builder import (
NODE_CLASS_MAPPINGS as BUILDER_NODE_CLASS_MAPPINGS,
NODE_DISPLAY_NAME_MAPPINGS as BUILDER_NODE_DISPLAY_NAME_MAPPINGS,
)
from node_character import (
NODE_CLASS_MAPPINGS as CHARACTER_NODE_CLASS_MAPPINGS,
NODE_DISPLAY_NAME_MAPPINGS as CHARACTER_NODE_DISPLAY_NAME_MAPPINGS,
@@ -482,12 +485,7 @@ except ImportError:
NODE_DISPLAY_NAME_MAPPINGS as SEED_RESOLUTION_NODE_DISPLAY_NAME_MAPPINGS,
)
from prompt_builder import (
build_prompt,
build_prompt_from_configs,
category_choices,
ethnicity_choices,
save_character_profile_payload,
subcategory_choices,
)
@@ -565,206 +563,8 @@ if PromptServer is not None and web is not None:
return web.json_response({"error": str(exc)}, status=400)
class SxCPPromptBuilder:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"category": (category_choices(), {"default": "auto_weighted"}),
"subcategory": (subcategory_choices(), {"default": "random"}),
"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}),
"clothing": (["random", "full", "minimal"], {"default": "random"}),
"ethnicity": (ethnicity_choices(), {"default": "any"}),
"poses": (["random", "standard", "evocative"], {"default": "random"}),
"expression_enabled": ("BOOLEAN", {"default": True}),
"expression_intensity": ("FLOAT", {"default": -1.0, "min": -1.0, "max": 1.0, "step": 0.01}),
"backside_bias": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.01}),
"figure": (["random", "curvy", "balanced", "bombshell"], {"default": "random"}),
"women_count": ("INT", {"default": 1, "min": 0, "max": 12, "step": 1}),
"men_count": ("INT", {"default": 1, "min": 0, "max": 12, "step": 1}),
"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": ("STRING", {"default": "sxcpinup_coloredpencil"}),
"prepend_trigger_to_prompt": ("BOOLEAN", {"default": True}),
},
"optional": {
"ethnicity_list": (SXCP_ETHNICITY_LIST,),
"seed_config": (SXCP_SEED_CONFIG,),
"camera_config": (SXCP_CAMERA_CONFIG,),
"location_config": (SXCP_LOCATION_CONFIG,),
"composition_config": (SXCP_COMPOSITION_CONFIG,),
"character_profile": (SXCP_CHARACTER_PROFILE,),
"character_cast": (SXCP_CHARACTER_CAST,),
"hardcore_position_config": (SXCP_HARDCORE_POSITION_CONFIG,),
"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,
category,
subcategory,
row_number,
start_index,
seed,
clothing,
ethnicity,
poses,
expression_enabled,
expression_intensity,
backside_bias,
figure,
women_count,
men_count,
minimal_clothing_ratio,
standard_pose_ratio,
trigger,
prepend_trigger_to_prompt,
seed_config="",
camera_config="",
location_config="",
composition_config="",
character_profile="",
character_cast="",
hardcore_position_config="",
extra_positive="",
extra_negative="",
no_plus_women=False,
no_black=False,
ethnicity_list="",
):
row = build_prompt(
category=category,
subcategory=subcategory,
row_number=row_number,
start_index=start_index,
seed=seed,
clothing=clothing,
ethnicity=ethnicity_list or ethnicity,
poses=poses,
expression_enabled=expression_enabled,
expression_intensity=expression_intensity,
backside_bias=backside_bias,
figure=figure,
no_plus_women=no_plus_women,
no_black=no_black,
women_count=women_count,
men_count=men_count,
minimal_clothing_ratio=minimal_clothing_ratio,
standard_pose_ratio=standard_pose_ratio,
trigger=trigger,
prepend_trigger_to_prompt=prepend_trigger_to_prompt,
extra_positive=extra_positive or "",
extra_negative=extra_negative or "",
seed_config=seed_config or "",
camera_config=camera_config or "",
location_config=location_config or "",
composition_config=composition_config or "",
character_profile=character_profile or "",
character_cast=character_cast or "",
hardcore_position_config=hardcore_position_config or "",
)
return (
row["prompt"],
row["negative_prompt"],
row["caption"],
json.dumps(row, ensure_ascii=True, sort_keys=True),
row.get("main_category", category),
row.get("subcategory", subcategory),
)
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": (SXCP_CATEGORY_CONFIG,),
"cast_config": (SXCP_CAST_CONFIG,),
"generation_profile": (SXCP_GENERATION_PROFILE,),
"filter_config": (SXCP_FILTER_CONFIG,),
"ethnicity_list": (SXCP_ETHNICITY_LIST,),
"seed_config": (SXCP_SEED_CONFIG,),
"camera_config": (SXCP_CAMERA_CONFIG,),
"location_config": (SXCP_LOCATION_CONFIG,),
"composition_config": (SXCP_COMPOSITION_CONFIG,),
"character_profile": (SXCP_CHARACTER_PROFILE,),
"character_cast": (SXCP_CHARACTER_CAST,),
"hardcore_position_config": (SXCP_HARDCORE_POSITION_CONFIG,),
"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="",
ethnicity_list="",
seed_config="",
camera_config="",
location_config="",
composition_config="",
character_profile="",
character_cast="",
hardcore_position_config="",
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=ethnicity_list or filter_config or "",
seed_config=seed_config or "",
camera_config=camera_config or "",
location_config=location_config or "",
composition_config=composition_config or "",
character_profile=character_profile or "",
character_cast=character_cast or "",
hardcore_position_config=hardcore_position_config 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", ""),
)
NODE_CLASS_MAPPINGS = {
"SxCPPromptBuilder": SxCPPromptBuilder,
}
NODE_CLASS_MAPPINGS = {}
NODE_CLASS_MAPPINGS.update(BUILDER_NODE_CLASS_MAPPINGS)
NODE_CLASS_MAPPINGS.update(SEED_RESOLUTION_NODE_CLASS_MAPPINGS)
NODE_CLASS_MAPPINGS.update(CAMERA_NODE_CLASS_MAPPINGS)
NODE_CLASS_MAPPINGS.update(CHARACTER_NODE_CLASS_MAPPINGS)
@@ -773,15 +573,11 @@ NODE_CLASS_MAPPINGS.update(FORMATTER_NODE_CLASS_MAPPINGS)
NODE_CLASS_MAPPINGS.update(INSTA_NODE_CLASS_MAPPINGS)
NODE_CLASS_MAPPINGS.update(ROUTE_CONFIG_NODE_CLASS_MAPPINGS)
NODE_CLASS_MAPPINGS.update(PROFILE_FILTER_NODE_CLASS_MAPPINGS)
NODE_CLASS_MAPPINGS.update({
"SxCPPromptBuilderFromConfigs": SxCPPromptBuilderFromConfigs,
})
NODE_CLASS_MAPPINGS.update(LOOP_NODE_CLASS_MAPPINGS)
_install_input_tooltips(NODE_CLASS_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS = {
"SxCPPromptBuilder": "SxCP Prompt Builder",
}
NODE_DISPLAY_NAME_MAPPINGS = {}
NODE_DISPLAY_NAME_MAPPINGS.update(BUILDER_NODE_DISPLAY_NAME_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS.update(SEED_RESOLUTION_NODE_DISPLAY_NAME_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS.update(CAMERA_NODE_DISPLAY_NAME_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS.update(CHARACTER_NODE_DISPLAY_NAME_MAPPINGS)
@@ -790,9 +586,6 @@ NODE_DISPLAY_NAME_MAPPINGS.update(FORMATTER_NODE_DISPLAY_NAME_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS.update(INSTA_NODE_DISPLAY_NAME_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS.update(ROUTE_CONFIG_NODE_DISPLAY_NAME_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS.update(PROFILE_FILTER_NODE_DISPLAY_NAME_MAPPINGS)
NODE_DISPLAY_NAME_MAPPINGS.update({
"SxCPPromptBuilderFromConfigs": "SxCP Prompt Builder From Configs",
})
NODE_DISPLAY_NAME_MAPPINGS.update(LOOP_NODE_DISPLAY_NAME_MAPPINGS)
WEB_DIRECTORY = "./web"