Add SDXL formatter profiles
This commit is contained in:
@@ -421,6 +421,22 @@ partitions, counters, or office rows are kept visible. In male-POV setups this
|
||||
becomes a first-person spatial description and the external camera sentence is
|
||||
suppressed.
|
||||
|
||||
`SxCP SDXL Formatter` rewrites prompt builder output or `metadata_json` into
|
||||
comma-tag SDXL/Pony-style prompts. Connect `metadata_json` when possible so
|
||||
character, camera, outfit, and action metadata stay available to the tag route.
|
||||
|
||||
SDXL formatter controls:
|
||||
|
||||
- `formatter_profile`: `manual_controls` keeps `style_preset` and
|
||||
`quality_preset` authoritative. `pony_flat_vector`, `sdxl_photo`, and
|
||||
`flat_vector` apply coherent formatter defaults.
|
||||
- `style_preset`: positive style anchor such as `flat_vector_pony`,
|
||||
`flat_vector`, or `photographic`.
|
||||
- `quality_preset`: quality/score tail such as `pony_high` or `sdxl_high`.
|
||||
- `trigger` and `prepend_trigger_to_prompt`: explicit model/LoRA trigger
|
||||
placement for SDXL-style workflows.
|
||||
- `custom_style` and `custom_quality`: override the selected preset text.
|
||||
|
||||
`SxCP Caption Naturalizer` rewrites tag-like captions or labeled prompts into
|
||||
more natural language. Connect the prompt builder's `metadata_json` output to
|
||||
`source_text` for the cleanest result. You can also connect `caption` or
|
||||
|
||||
@@ -301,6 +301,7 @@ NODE_INPUT_TOOLTIPS = {
|
||||
},
|
||||
"SxCPSDXLFormatter": {
|
||||
"metadata_json": "Best input for SDXL tag formatting because it preserves cast, camera, outfit, and explicit action metadata.",
|
||||
"formatter_profile": "High-level formatter defaults. manual_controls keeps style_preset and quality_preset authoritative.",
|
||||
"style_preset": "Positive style anchor preset. flat_vector_pony matches the old SDXL tag style.",
|
||||
"quality_preset": "Quality/score tag tail for SDXL or Pony-style checkpoints.",
|
||||
"custom_style": "Optional replacement for the style preset. Leave empty to use style_preset.",
|
||||
|
||||
@@ -288,10 +288,12 @@ Keep here:
|
||||
- shared formatter input parsing from `formatter_input.py`.
|
||||
- style presets, quality presets, default negative prompt, and action/position
|
||||
family tag hints from `sdxl_presets.py`.
|
||||
- formatter profiles for manual controls, Pony flat-vector, SDXL photo, and
|
||||
plain flat-vector styles live in `sdxl_presets.py` and are exposed by
|
||||
`SxCP SDXL Formatter`.
|
||||
|
||||
Improve later:
|
||||
|
||||
- add formatter profiles for Pony, SDXL photo, and flat vector;
|
||||
- make fallback cleanup use the shared field-label inventory.
|
||||
|
||||
### Naturalizer Path
|
||||
|
||||
@@ -96,7 +96,7 @@ Core helper ownership:
|
||||
| `prompt_hygiene.py` | Generic prompt, caption, and negative-prompt cleanup. |
|
||||
| `row_normalization.py` | Final prompt-row and pair metadata normalization: trigger prepending, extra-positive append, negative merge/dedupe, caption-part joining, and embedded soft/hard row sanitation. |
|
||||
| `formatter_input.py` | Shared formatter input parsing: text cleanup, metadata/source JSON detection, trigger-prefix stripping, shared prompt field-label inventory, `Avoid:` splitting, prompt-field extraction, and metadata row-value fallback. |
|
||||
| `sdxl_presets.py` | SDXL style presets, quality presets, default negative prompt, and metadata-family tag hints used by the SDXL formatter and node choice lists. |
|
||||
| `sdxl_presets.py` | SDXL formatter profiles, style presets, quality presets, default negative prompt, and metadata-family tag hints used by the SDXL formatter and node choice lists. |
|
||||
| `caption_policy.py` | Caption naturalizer policy data and helpers: caption profiles, style tails, item labels, metadata-family caption labels, detail/style-policy normalization, clothing cleanup, and composition cleanup. |
|
||||
|
||||
## Node IO Map
|
||||
@@ -651,8 +651,8 @@ not parse metadata. That is a wiring/input-hint issue, not a prompt pool issue.
|
||||
- Normal metadata row: `_row_core_tags`.
|
||||
- Plain text fallback: `_fallback_text_to_sdxl`.
|
||||
|
||||
Use this route for style triggers, weighted tag style, nude weighting, and Pony /
|
||||
SDXL quality/style presets.
|
||||
Use this route for style triggers, weighted tag style, nude weighting, formatter
|
||||
profiles, and Pony / SDXL quality/style presets.
|
||||
|
||||
SDXL field consumption:
|
||||
|
||||
|
||||
+15
-2
@@ -4,12 +4,22 @@ try:
|
||||
from .caption_naturalizer import naturalize_caption
|
||||
from .caption_policy import caption_profile_choices
|
||||
from .krea_formatter import format_krea2_prompt
|
||||
from .sdxl_formatter import format_sdxl_prompt, sdxl_quality_preset_choices, sdxl_style_preset_choices
|
||||
from .sdxl_formatter import (
|
||||
format_sdxl_prompt,
|
||||
sdxl_formatter_profile_choices,
|
||||
sdxl_quality_preset_choices,
|
||||
sdxl_style_preset_choices,
|
||||
)
|
||||
except ImportError: # Allows local smoke tests from the repository root.
|
||||
from caption_naturalizer import naturalize_caption
|
||||
from caption_policy import caption_profile_choices
|
||||
from krea_formatter import format_krea2_prompt
|
||||
from sdxl_formatter import format_sdxl_prompt, sdxl_quality_preset_choices, sdxl_style_preset_choices
|
||||
from sdxl_formatter import (
|
||||
format_sdxl_prompt,
|
||||
sdxl_formatter_profile_choices,
|
||||
sdxl_quality_preset_choices,
|
||||
sdxl_style_preset_choices,
|
||||
)
|
||||
|
||||
|
||||
class SxCPCaptionNaturalizer:
|
||||
@@ -138,6 +148,7 @@ class SxCPSDXLFormatter:
|
||||
"source_text": ("STRING", {"default": "", "multiline": True}),
|
||||
"input_hint": (["auto", "metadata_json", "prompt"], {"default": "auto"}),
|
||||
"target": (["auto", "single", "softcore", "hardcore"], {"default": "auto"}),
|
||||
"formatter_profile": (sdxl_formatter_profile_choices(), {"default": "manual_controls"}),
|
||||
"style_preset": (sdxl_style_preset_choices(), {"default": "flat_vector_pony"}),
|
||||
"quality_preset": (sdxl_quality_preset_choices(), {"default": "pony_high"}),
|
||||
"trigger": ("STRING", {"default": "mythp0rt", "multiline": False}),
|
||||
@@ -174,6 +185,7 @@ class SxCPSDXLFormatter:
|
||||
source_text,
|
||||
input_hint,
|
||||
target,
|
||||
formatter_profile,
|
||||
style_preset,
|
||||
quality_preset,
|
||||
trigger,
|
||||
@@ -195,6 +207,7 @@ class SxCPSDXLFormatter:
|
||||
negative_prompt=negative_prompt or "",
|
||||
input_hint=input_hint,
|
||||
target=target,
|
||||
formatter_profile=formatter_profile,
|
||||
style_preset=style_preset,
|
||||
quality_preset=quality_preset,
|
||||
trigger=trigger,
|
||||
|
||||
+11
-2
@@ -23,6 +23,7 @@ TRIGGER_CANDIDATES = (
|
||||
|
||||
SDXL_STYLE_PRESETS = sdxl_policy.SDXL_STYLE_PRESETS
|
||||
SDXL_QUALITY_PRESETS = sdxl_policy.SDXL_QUALITY_PRESETS
|
||||
SDXL_FORMATTER_PROFILES = sdxl_policy.SDXL_FORMATTER_PROFILES
|
||||
SDXL_DEFAULT_NEGATIVE = sdxl_policy.SDXL_DEFAULT_NEGATIVE
|
||||
SDXL_ACTION_FAMILY_TAGS = sdxl_policy.SDXL_ACTION_FAMILY_TAGS
|
||||
SDXL_POSITION_FAMILY_TAGS = sdxl_policy.SDXL_POSITION_FAMILY_TAGS
|
||||
@@ -38,6 +39,10 @@ def sdxl_quality_preset_choices() -> list[str]:
|
||||
return sdxl_policy.sdxl_quality_preset_choices()
|
||||
|
||||
|
||||
def sdxl_formatter_profile_choices() -> list[str]:
|
||||
return sdxl_policy.sdxl_formatter_profile_choices()
|
||||
|
||||
|
||||
def _clean(value: Any) -> str:
|
||||
return input_policy.clean_text(value)
|
||||
|
||||
@@ -436,9 +441,13 @@ def format_sdxl_prompt(
|
||||
custom_quality: str = "",
|
||||
extra_positive: str = "",
|
||||
extra_negative: str = "",
|
||||
formatter_profile: str = "manual_controls",
|
||||
) -> dict[str, str]:
|
||||
style_preset = sdxl_policy.normalize_style_preset(style_preset)
|
||||
quality_preset = sdxl_policy.normalize_quality_preset(quality_preset)
|
||||
style_preset, quality_preset = sdxl_policy.apply_formatter_profile(
|
||||
formatter_profile,
|
||||
style_preset=style_preset,
|
||||
quality_preset=quality_preset,
|
||||
)
|
||||
target = target if target in ("auto", "single", "softcore", "hardcore") else "auto"
|
||||
nude_weight = max(0.1, min(3.0, float(nude_weight)))
|
||||
row, method = _row_from_inputs(source_text, metadata_json, input_hint)
|
||||
|
||||
@@ -3,6 +3,7 @@ from __future__ import annotations
|
||||
|
||||
DEFAULT_STYLE_PRESET = "flat_vector_pony"
|
||||
DEFAULT_QUALITY_PRESET = "pony_high"
|
||||
DEFAULT_FORMATTER_PROFILE = "manual_controls"
|
||||
|
||||
SDXL_STYLE_PRESETS = {
|
||||
"flat_vector_pony": "(skindentation:1.25), (flat color:2.0), no lineart, no outline, Flat vector",
|
||||
@@ -21,6 +22,22 @@ SDXL_QUALITY_PRESETS = {
|
||||
"none": "",
|
||||
}
|
||||
|
||||
SDXL_FORMATTER_PROFILES = {
|
||||
"manual_controls": {},
|
||||
"pony_flat_vector": {
|
||||
"style_preset": "flat_vector_pony",
|
||||
"quality_preset": "pony_high",
|
||||
},
|
||||
"sdxl_photo": {
|
||||
"style_preset": "photographic",
|
||||
"quality_preset": "sdxl_high",
|
||||
},
|
||||
"flat_vector": {
|
||||
"style_preset": "flat_vector",
|
||||
"quality_preset": "sdxl_high",
|
||||
},
|
||||
}
|
||||
|
||||
SDXL_DEFAULT_NEGATIVE = (
|
||||
"worst quality, low quality, normal quality, lowres, bad anatomy, bad hands, "
|
||||
"extra fingers, missing fingers, fused fingers, deformed, disfigured, malformed body, "
|
||||
@@ -58,9 +75,30 @@ def sdxl_quality_preset_choices() -> list[str]:
|
||||
return list(SDXL_QUALITY_PRESETS)
|
||||
|
||||
|
||||
def sdxl_formatter_profile_choices() -> list[str]:
|
||||
return list(SDXL_FORMATTER_PROFILES)
|
||||
|
||||
|
||||
def normalize_style_preset(value: str) -> str:
|
||||
return value if value in SDXL_STYLE_PRESETS else DEFAULT_STYLE_PRESET
|
||||
|
||||
|
||||
def normalize_quality_preset(value: str) -> str:
|
||||
return value if value in SDXL_QUALITY_PRESETS else DEFAULT_QUALITY_PRESET
|
||||
|
||||
|
||||
def normalize_formatter_profile(value: str) -> str:
|
||||
return value if value in SDXL_FORMATTER_PROFILES else DEFAULT_FORMATTER_PROFILE
|
||||
|
||||
|
||||
def apply_formatter_profile(
|
||||
formatter_profile: str,
|
||||
*,
|
||||
style_preset: str,
|
||||
quality_preset: str,
|
||||
) -> tuple[str, str]:
|
||||
profile = SDXL_FORMATTER_PROFILES[normalize_formatter_profile(formatter_profile)]
|
||||
return (
|
||||
normalize_style_preset(profile.get("style_preset", style_preset)),
|
||||
normalize_quality_preset(profile.get("quality_preset", quality_preset)),
|
||||
)
|
||||
|
||||
@@ -1034,14 +1034,41 @@ def smoke_sdxl_presets_policy() -> None:
|
||||
sdxl_formatter.SDXL_QUALITY_PRESETS is sdxl_presets.SDXL_QUALITY_PRESETS,
|
||||
"SDXL formatter quality presets should delegate to sdxl_presets",
|
||||
)
|
||||
_expect(
|
||||
sdxl_formatter.SDXL_FORMATTER_PROFILES is sdxl_presets.SDXL_FORMATTER_PROFILES,
|
||||
"SDXL formatter profiles should delegate to sdxl_presets",
|
||||
)
|
||||
_expect(
|
||||
sdxl_formatter.SDXL_ACTION_FAMILY_TAGS is sdxl_presets.SDXL_ACTION_FAMILY_TAGS,
|
||||
"SDXL formatter action-family tags should delegate to sdxl_presets",
|
||||
)
|
||||
_expect("sdxl_photo" in sdxl_presets.sdxl_formatter_profile_choices(), "SDXL profile choices lost sdxl_photo")
|
||||
_expect("flat_vector_pony" in sdxl_presets.sdxl_style_preset_choices(), "SDXL style preset choices lost default")
|
||||
_expect("pony_high" in sdxl_presets.sdxl_quality_preset_choices(), "SDXL quality preset choices lost default")
|
||||
_expect(
|
||||
sdxl_presets.normalize_formatter_profile("bad") == sdxl_presets.DEFAULT_FORMATTER_PROFILE,
|
||||
"SDXL invalid profile fallback changed",
|
||||
)
|
||||
_expect(sdxl_presets.normalize_style_preset("bad") == sdxl_presets.DEFAULT_STYLE_PRESET, "SDXL invalid style fallback changed")
|
||||
_expect(sdxl_presets.normalize_quality_preset("bad") == sdxl_presets.DEFAULT_QUALITY_PRESET, "SDXL invalid quality fallback changed")
|
||||
_expect(
|
||||
sdxl_presets.apply_formatter_profile(
|
||||
"sdxl_photo",
|
||||
style_preset="flat_vector_pony",
|
||||
quality_preset="pony_high",
|
||||
)
|
||||
== ("photographic", "sdxl_high"),
|
||||
"SDXL photo profile overrides changed",
|
||||
)
|
||||
_expect(
|
||||
sdxl_presets.apply_formatter_profile(
|
||||
"manual_controls",
|
||||
style_preset="flat_vector",
|
||||
quality_preset="none",
|
||||
)
|
||||
== ("flat_vector", "none"),
|
||||
"SDXL manual profile should preserve explicit controls",
|
||||
)
|
||||
|
||||
row = _fixture_hardcore_row(
|
||||
action_family="oral",
|
||||
@@ -1063,6 +1090,18 @@ def smoke_sdxl_presets_policy() -> None:
|
||||
_expect_trigger_once("sdxl_presets.formatted_prompt", formatted.get("sdxl_prompt"), SdxlTrigger)
|
||||
_expect("Flat vector" in formatted.get("sdxl_prompt", ""), "SDXL invalid style did not fall back to default preset")
|
||||
_expect("score_9" in formatted.get("sdxl_prompt", ""), "SDXL invalid quality did not fall back to default preset")
|
||||
profiled = sdxl_formatter.format_sdxl_prompt(
|
||||
_json(row),
|
||||
input_hint="auto",
|
||||
formatter_profile="sdxl_photo",
|
||||
style_preset="flat_vector_pony",
|
||||
quality_preset="pony_high",
|
||||
trigger=SdxlTrigger,
|
||||
prepend_trigger=True,
|
||||
)
|
||||
profiled_prompt = profiled.get("sdxl_prompt", "")
|
||||
_expect("realistic photo" in profiled_prompt, "SDXL photo profile did not apply photographic style")
|
||||
_expect("score_9" not in profiled_prompt, "SDXL photo profile should switch away from Pony score quality tail")
|
||||
|
||||
|
||||
def smoke_hardcore_position_config_policy() -> None:
|
||||
@@ -2824,6 +2863,7 @@ def smoke_node_formatter_registration() -> None:
|
||||
"A woman standing by a window",
|
||||
"prompt",
|
||||
"single",
|
||||
"manual_controls",
|
||||
"flat_vector_pony",
|
||||
"pony_high",
|
||||
"mythp0rt",
|
||||
@@ -2835,6 +2875,9 @@ def smoke_node_formatter_registration() -> None:
|
||||
_expect_trigger_once("node_formatter.sdxl_prompt", sdxl_output[0], "mythp0rt")
|
||||
_expect_text("node_formatter.sdxl_negative", sdxl_output[1], 20)
|
||||
_expect(sdxl_output[6].startswith("text("), "SDXL Formatter method changed unexpectedly")
|
||||
sdxl_inputs = sxcp_nodes.NODE_CLASS_MAPPINGS["SxCPSDXLFormatter"].INPUT_TYPES().get("required") or {}
|
||||
_expect("formatter_profile" in sdxl_inputs, "SDXL Formatter lost formatter_profile input")
|
||||
_expect("tooltip" in sdxl_inputs["formatter_profile"][1], "SDXL formatter_profile tooltip injection missing")
|
||||
|
||||
|
||||
def smoke_node_insta_registration() -> None:
|
||||
|
||||
Reference in New Issue
Block a user