Centralize formatter detail levels
This commit is contained in:
+5
-6
@@ -4,9 +4,11 @@ import re
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
from . import formatter_detail as detail_policy
|
||||||
from . import formatter_input as input_policy
|
from . import formatter_input as input_policy
|
||||||
from . import route_metadata as route_metadata_policy
|
from . import route_metadata as route_metadata_policy
|
||||||
except ImportError: # Allows local smoke tests with `python tools/prompt_smoke.py`.
|
except ImportError: # Allows local smoke tests with `python tools/prompt_smoke.py`.
|
||||||
|
import formatter_detail as detail_policy
|
||||||
import formatter_input as input_policy
|
import formatter_input as input_policy
|
||||||
import route_metadata as route_metadata_policy
|
import route_metadata as route_metadata_policy
|
||||||
|
|
||||||
@@ -14,7 +16,7 @@ except ImportError: # Allows local smoke tests with `python tools/prompt_smoke.
|
|||||||
OLD_TRIGGER = "sxcpinup_coloredpencil"
|
OLD_TRIGGER = "sxcpinup_coloredpencil"
|
||||||
DEFAULT_TRIGGER = "sxcppnl7"
|
DEFAULT_TRIGGER = "sxcppnl7"
|
||||||
|
|
||||||
DETAIL_LEVELS = ("balanced", "concise", "dense")
|
DETAIL_LEVELS = detail_policy.DETAIL_LEVELS
|
||||||
STYLE_POLICIES = ("drop_style_tail", "keep_style_terms")
|
STYLE_POLICIES = ("drop_style_tail", "keep_style_terms")
|
||||||
CAPTION_PROFILE_DEFAULT = "manual_controls"
|
CAPTION_PROFILE_DEFAULT = "manual_controls"
|
||||||
|
|
||||||
@@ -72,7 +74,7 @@ POSITION_FAMILY_CAPTION_LABELS = {
|
|||||||
|
|
||||||
|
|
||||||
def normalize_detail_level(value: str) -> str:
|
def normalize_detail_level(value: str) -> str:
|
||||||
return value if value in DETAIL_LEVELS else "balanced"
|
return detail_policy.normalize_detail_level(value)
|
||||||
|
|
||||||
|
|
||||||
def normalize_style_policy(value: str) -> str:
|
def normalize_style_policy(value: str) -> str:
|
||||||
@@ -107,10 +109,7 @@ def keep_style_terms(style_policy: str) -> bool:
|
|||||||
|
|
||||||
|
|
||||||
def detail_allows(level: str, dense_only: bool = False) -> bool:
|
def detail_allows(level: str, dense_only: bool = False) -> bool:
|
||||||
level = normalize_detail_level((level or "balanced").strip().lower())
|
return detail_policy.detail_allows(level, dense_only=dense_only)
|
||||||
if dense_only:
|
|
||||||
return level == "dense"
|
|
||||||
return level != "concise"
|
|
||||||
|
|
||||||
|
|
||||||
def strip_style_tail(text: str) -> str:
|
def strip_style_tail(text: str) -> str:
|
||||||
|
|||||||
@@ -84,6 +84,15 @@ routes:
|
|||||||
It must not make formatter-style decisions. Krea prose, SDXL tags, and training
|
It must not make formatter-style decisions. Krea prose, SDXL tags, and training
|
||||||
caption sentence shape stay in their formatter modules.
|
caption sentence shape stay in their formatter modules.
|
||||||
|
|
||||||
|
Formatter detail-level handling now has one home:
|
||||||
|
|
||||||
|
- `formatter_detail.py`
|
||||||
|
|
||||||
|
It owns route-neutral prose detail levels, node choice lists, normalization, and
|
||||||
|
the concise/balanced/dense inclusion gate used by Krea2 and natural-caption
|
||||||
|
routes. It must not own route-specific style controls such as Krea photographic
|
||||||
|
mode or caption style-tail policy.
|
||||||
|
|
||||||
Formatter target handling now has one home:
|
Formatter target handling now has one home:
|
||||||
|
|
||||||
- `formatter_target.py`
|
- `formatter_target.py`
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ Core helper ownership:
|
|||||||
| `krea_cast.py` | Shared formatter cast descriptor parsing, cast labels, cast prose, natural cast descriptor text, and label replacement used by Krea2 and caption routes. |
|
| `krea_cast.py` | Shared formatter cast descriptor parsing, cast labels, cast prose, natural cast descriptor text, and label replacement used by Krea2 and caption routes. |
|
||||||
| `prompt_hygiene.py` | Generic prompt, caption, and negative-prompt cleanup. |
|
| `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, embedded soft/hard row output and side-metadata synchronization, and embedded row sanitation. |
|
| `row_normalization.py` | Final prompt-row and pair metadata normalization: trigger prepending, extra-positive append, negative merge/dedupe, caption-part joining, embedded soft/hard row output and side-metadata synchronization, and embedded row sanitation. |
|
||||||
|
| `formatter_detail.py` | Shared formatter detail-level choices, normalization, and concise/balanced/dense gates used by Krea2 and caption routes. |
|
||||||
| `formatter_input.py` | Shared formatter input parsing: text cleanup, metadata/source JSON detection, trigger-prefix stripping, shared prompt field-label inventory, fallback field-label stripping, `Avoid:` splitting, prompt-field extraction, and metadata row-value fallback. |
|
| `formatter_input.py` | Shared formatter input parsing: text cleanup, metadata/source JSON detection, trigger-prefix stripping, shared prompt field-label inventory, fallback field-label stripping, `Avoid:` splitting, prompt-field extraction, and metadata row-value fallback. |
|
||||||
| `formatter_target.py` | Shared formatter target choices and normalization for `auto`, `single`, `softcore`, and `hardcore`, including pair-side selection and combined-caption inclusion policy. |
|
| `formatter_target.py` | Shared formatter target choices and normalization for `auto`, `single`, `softcore`, and `hardcore`, including pair-side selection and combined-caption inclusion policy. |
|
||||||
| `node_tooltips.py` | Node input tooltip inventory, node-specific overrides, dynamic-input fallback rules, and tooltip injection installer used by `__init__.py`. |
|
| `node_tooltips.py` | Node input tooltip inventory, node-specific overrides, dynamic-input fallback rules, and tooltip injection installer used by `__init__.py`. |
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
DETAIL_LEVELS = ("balanced", "concise", "dense")
|
||||||
|
DEFAULT_DETAIL_LEVEL = "balanced"
|
||||||
|
|
||||||
|
|
||||||
|
def detail_level_choices() -> list[str]:
|
||||||
|
return list(DETAIL_LEVELS)
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_detail_level(value: Any) -> str:
|
||||||
|
level = str(value or "").strip().lower().replace("-", "_").replace(" ", "_")
|
||||||
|
return level if level in DETAIL_LEVELS else DEFAULT_DETAIL_LEVEL
|
||||||
|
|
||||||
|
|
||||||
|
def detail_allows(level: Any, dense_only: bool = False) -> bool:
|
||||||
|
level = normalize_detail_level(level)
|
||||||
|
if dense_only:
|
||||||
|
return level == "dense"
|
||||||
|
return level != "concise"
|
||||||
@@ -4,8 +4,10 @@ from dataclasses import dataclass
|
|||||||
from typing import Any, Callable
|
from typing import Any, Callable
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
from . import formatter_detail as detail_policy
|
||||||
from . import formatter_target as target_policy
|
from . import formatter_target as target_policy
|
||||||
except ImportError: # pragma: no cover - plain-script smoke tests
|
except ImportError: # pragma: no cover - plain-script smoke tests
|
||||||
|
import formatter_detail as detail_policy
|
||||||
import formatter_target as target_policy
|
import formatter_target as target_policy
|
||||||
|
|
||||||
|
|
||||||
@@ -48,7 +50,7 @@ class KreaFormatDependencies:
|
|||||||
|
|
||||||
|
|
||||||
def format_krea2_prompt_result(request: KreaFormatRequest, deps: KreaFormatDependencies) -> KreaFormatRoute:
|
def format_krea2_prompt_result(request: KreaFormatRequest, deps: KreaFormatDependencies) -> KreaFormatRoute:
|
||||||
detail_level = request.detail_level if request.detail_level in ("concise", "balanced", "dense") else "balanced"
|
detail_level = detail_policy.normalize_detail_level(request.detail_level)
|
||||||
style_mode = request.style_mode if request.style_mode in ("preserve", "photographic", "minimal") else "preserve"
|
style_mode = request.style_mode if request.style_mode in ("preserve", "photographic", "minimal") else "preserve"
|
||||||
target = target_policy.normalize_target(request.target)
|
target = target_policy.normalize_target(request.target)
|
||||||
row, method = deps.row_from_inputs(request.source_text, request.metadata_json, request.input_hint)
|
row, method = deps.row_from_inputs(request.source_text, request.metadata_json, request.input_hint)
|
||||||
|
|||||||
+4
-2
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|||||||
try:
|
try:
|
||||||
from .caption_naturalizer import naturalize_caption
|
from .caption_naturalizer import naturalize_caption
|
||||||
from .caption_policy import caption_profile_choices
|
from .caption_policy import caption_profile_choices
|
||||||
|
from .formatter_detail import detail_level_choices
|
||||||
from .formatter_input import INPUT_HINT_CAPTION_OR_PROMPT, INPUT_HINT_PROMPT, input_hint_choices
|
from .formatter_input import INPUT_HINT_CAPTION_OR_PROMPT, INPUT_HINT_PROMPT, input_hint_choices
|
||||||
from .formatter_target import target_choices
|
from .formatter_target import target_choices
|
||||||
from .krea_formatter import format_krea2_prompt
|
from .krea_formatter import format_krea2_prompt
|
||||||
@@ -15,6 +16,7 @@ try:
|
|||||||
except ImportError: # Allows local smoke tests from the repository root.
|
except ImportError: # Allows local smoke tests from the repository root.
|
||||||
from caption_naturalizer import naturalize_caption
|
from caption_naturalizer import naturalize_caption
|
||||||
from caption_policy import caption_profile_choices
|
from caption_policy import caption_profile_choices
|
||||||
|
from formatter_detail import detail_level_choices
|
||||||
from formatter_input import INPUT_HINT_CAPTION_OR_PROMPT, INPUT_HINT_PROMPT, input_hint_choices
|
from formatter_input import INPUT_HINT_CAPTION_OR_PROMPT, INPUT_HINT_PROMPT, input_hint_choices
|
||||||
from formatter_target import target_choices
|
from formatter_target import target_choices
|
||||||
from krea_formatter import format_krea2_prompt
|
from krea_formatter import format_krea2_prompt
|
||||||
@@ -34,7 +36,7 @@ class SxCPCaptionNaturalizer:
|
|||||||
"source_text": ("STRING", {"default": "", "multiline": True}),
|
"source_text": ("STRING", {"default": "", "multiline": True}),
|
||||||
"input_hint": (input_hint_choices(text_hint=INPUT_HINT_CAPTION_OR_PROMPT), {"default": "auto"}),
|
"input_hint": (input_hint_choices(text_hint=INPUT_HINT_CAPTION_OR_PROMPT), {"default": "auto"}),
|
||||||
"caption_profile": (caption_profile_choices(), {"default": "manual_controls"}),
|
"caption_profile": (caption_profile_choices(), {"default": "manual_controls"}),
|
||||||
"detail_level": (["balanced", "concise", "dense"], {"default": "balanced"}),
|
"detail_level": (detail_level_choices(), {"default": "balanced"}),
|
||||||
"style_policy": (["drop_style_tail", "keep_style_terms"], {"default": "drop_style_tail"}),
|
"style_policy": (["drop_style_tail", "keep_style_terms"], {"default": "drop_style_tail"}),
|
||||||
"trigger": ("STRING", {"default": "sxcppnl7"}),
|
"trigger": ("STRING", {"default": "sxcppnl7"}),
|
||||||
"include_trigger": ("BOOLEAN", {"default": True}),
|
"include_trigger": ("BOOLEAN", {"default": True}),
|
||||||
@@ -86,7 +88,7 @@ class SxCPKrea2Formatter:
|
|||||||
"source_text": ("STRING", {"default": "", "multiline": True}),
|
"source_text": ("STRING", {"default": "", "multiline": True}),
|
||||||
"input_hint": (input_hint_choices(text_hint=INPUT_HINT_PROMPT), {"default": "auto"}),
|
"input_hint": (input_hint_choices(text_hint=INPUT_HINT_PROMPT), {"default": "auto"}),
|
||||||
"target": (target_choices(), {"default": "auto"}),
|
"target": (target_choices(), {"default": "auto"}),
|
||||||
"detail_level": (["balanced", "concise", "dense"], {"default": "balanced"}),
|
"detail_level": (detail_level_choices(), {"default": "balanced"}),
|
||||||
"style_mode": (["preserve", "photographic", "minimal"], {"default": "preserve"}),
|
"style_mode": (["preserve", "photographic", "minimal"], {"default": "preserve"}),
|
||||||
"preserve_trigger": ("BOOLEAN", {"default": False}),
|
"preserve_trigger": ("BOOLEAN", {"default": False}),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ CRITICAL_ROUTE_MODULES: tuple[tuple[str, str], ...] = (
|
|||||||
("krea_format_route.py", "krea_format_route_policy"),
|
("krea_format_route.py", "krea_format_route_policy"),
|
||||||
("sdxl_format_route.py", "sdxl_format_route_policy"),
|
("sdxl_format_route.py", "sdxl_format_route_policy"),
|
||||||
("caption_format_route.py", "caption_format_route_policy"),
|
("caption_format_route.py", "caption_format_route_policy"),
|
||||||
|
("formatter_detail.py", "formatter_detail_policy"),
|
||||||
("formatter_input.py", "formatter_input_policy"),
|
("formatter_input.py", "formatter_input_policy"),
|
||||||
("formatter_target.py", "formatter_target_policy"),
|
("formatter_target.py", "formatter_target_policy"),
|
||||||
("pair_builder.py", "pair_builder_policy"),
|
("pair_builder.py", "pair_builder_policy"),
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import character_slot # noqa: E402
|
|||||||
import category_cast_config # noqa: E402
|
import category_cast_config # noqa: E402
|
||||||
import category_library # noqa: E402
|
import category_library # noqa: E402
|
||||||
import filter_config # noqa: E402
|
import filter_config # noqa: E402
|
||||||
|
import formatter_detail # noqa: E402
|
||||||
import formatter_input # noqa: E402
|
import formatter_input # noqa: E402
|
||||||
import formatter_target # noqa: E402
|
import formatter_target # noqa: E402
|
||||||
import hardcore_position_config # noqa: E402
|
import hardcore_position_config # noqa: E402
|
||||||
@@ -2842,6 +2843,26 @@ def smoke_formatter_target_policy() -> None:
|
|||||||
_expect(not hard_pair.include_softcore and hard_pair.include_hardcore, "Pair hardcore should include only hard side")
|
_expect(not hard_pair.include_softcore and hard_pair.include_hardcore, "Pair hardcore should include only hard side")
|
||||||
|
|
||||||
|
|
||||||
|
def smoke_formatter_detail_policy() -> None:
|
||||||
|
_expect(
|
||||||
|
formatter_detail.detail_level_choices() == ["balanced", "concise", "dense"],
|
||||||
|
"Formatter detail choices changed",
|
||||||
|
)
|
||||||
|
_expect(formatter_detail.normalize_detail_level("dense") == "dense", "Formatter detail lost dense")
|
||||||
|
_expect(formatter_detail.normalize_detail_level("BAD") == "balanced", "Formatter detail should normalize invalid values")
|
||||||
|
_expect(formatter_detail.detail_allows("concise") is False, "Formatter detail concise gate changed")
|
||||||
|
_expect(formatter_detail.detail_allows("dense", dense_only=True) is True, "Formatter detail dense-only gate changed")
|
||||||
|
_expect(caption_policy.DETAIL_LEVELS is formatter_detail.DETAIL_LEVELS, "Caption detail levels should delegate")
|
||||||
|
_expect(
|
||||||
|
caption_policy.normalize_detail_level("bad") == formatter_detail.normalize_detail_level("bad"),
|
||||||
|
"Caption detail normalization should delegate",
|
||||||
|
)
|
||||||
|
_expect(
|
||||||
|
caption_policy.detail_allows("dense", dense_only=True) == formatter_detail.detail_allows("dense", dense_only=True),
|
||||||
|
"Caption detail gate should delegate",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def smoke_krea_format_route_policy() -> None:
|
def smoke_krea_format_route_policy() -> None:
|
||||||
row = _prompt_row(
|
row = _prompt_row(
|
||||||
name="krea_format_route_single",
|
name="krea_format_route_single",
|
||||||
@@ -6264,8 +6285,10 @@ def smoke_node_formatter_registration() -> None:
|
|||||||
_expect("caption_profile" in caption_inputs, "Caption Naturalizer lost caption_profile input")
|
_expect("caption_profile" in caption_inputs, "Caption Naturalizer lost caption_profile input")
|
||||||
_expect("target" in caption_inputs, "Caption Naturalizer lost target input")
|
_expect("target" in caption_inputs, "Caption Naturalizer lost target input")
|
||||||
_expect(caption_inputs["target"][0] == formatter_target.target_choices(), "Caption Naturalizer target choices drifted")
|
_expect(caption_inputs["target"][0] == formatter_target.target_choices(), "Caption Naturalizer target choices drifted")
|
||||||
|
_expect(caption_inputs["detail_level"][0] == formatter_detail.detail_level_choices(), "Caption Naturalizer detail choices drifted")
|
||||||
_expect("tooltip" in caption_inputs["caption_profile"][1], "Caption profile tooltip injection missing")
|
_expect("tooltip" in caption_inputs["caption_profile"][1], "Caption profile tooltip injection missing")
|
||||||
_expect(krea_inputs["target"][0] == formatter_target.target_choices(), "Krea2 Formatter target choices drifted")
|
_expect(krea_inputs["target"][0] == formatter_target.target_choices(), "Krea2 Formatter target choices drifted")
|
||||||
|
_expect(krea_inputs["detail_level"][0] == formatter_detail.detail_level_choices(), "Krea2 Formatter detail choices drifted")
|
||||||
|
|
||||||
krea_output = krea_node().build(
|
krea_output = krea_node().build(
|
||||||
"sxcppnl7 A woman standing by a window",
|
"sxcppnl7 A woman standing by a window",
|
||||||
@@ -6644,6 +6667,7 @@ SMOKE_CASES: list[tuple[str, Callable[[], None]]] = [
|
|||||||
("row_assembly_policy", smoke_row_assembly_policy),
|
("row_assembly_policy", smoke_row_assembly_policy),
|
||||||
("formatter_input_policy", smoke_formatter_input_policy),
|
("formatter_input_policy", smoke_formatter_input_policy),
|
||||||
("formatter_target_policy", smoke_formatter_target_policy),
|
("formatter_target_policy", smoke_formatter_target_policy),
|
||||||
|
("formatter_detail_policy", smoke_formatter_detail_policy),
|
||||||
("krea_format_route_policy", smoke_krea_format_route_policy),
|
("krea_format_route_policy", smoke_krea_format_route_policy),
|
||||||
("formatter_cast_policy", smoke_formatter_cast_policy),
|
("formatter_cast_policy", smoke_formatter_cast_policy),
|
||||||
("caption_policy", smoke_caption_policy),
|
("caption_policy", smoke_caption_policy),
|
||||||
|
|||||||
Reference in New Issue
Block a user