Route pair metadata structurally
This commit is contained in:
@@ -5,8 +5,10 @@ from dataclasses import dataclass
|
|||||||
from typing import Any, Callable
|
from typing import Any, Callable
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
from . import formatter_input as input_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_input as input_policy
|
||||||
import formatter_target as target_policy
|
import formatter_target as target_policy
|
||||||
|
|
||||||
|
|
||||||
@@ -308,7 +310,7 @@ def insta_of_pair_from_row_result(
|
|||||||
keep_style = request.keep_style
|
keep_style = request.keep_style
|
||||||
pair_target = target_policy.pair_policy(request.target)
|
pair_target = target_policy.pair_policy(request.target)
|
||||||
target = pair_target.pair_target
|
target = pair_target.pair_target
|
||||||
if deps.clean_text(row.get("mode")).lower() != "insta/of":
|
if not input_policy.is_pair_metadata(row):
|
||||||
return None
|
return None
|
||||||
soft_row = row.get("softcore_row")
|
soft_row = row.get("softcore_row")
|
||||||
hard_row = row.get("hardcore_row")
|
hard_row = row.get("hardcore_row")
|
||||||
|
|||||||
@@ -698,6 +698,13 @@ Important POV rule:
|
|||||||
|
|
||||||
## Formatter Routes
|
## Formatter Routes
|
||||||
|
|
||||||
|
Formatter metadata input is normalized by `formatter_input.py`. Pair routing is
|
||||||
|
structural: metadata with both a softcore side and a hardcore side
|
||||||
|
(`softcore_row`/`hardcore_row` or root soft/hard prompt/caption fields) is
|
||||||
|
treated as pair metadata even if the UI `mode` label is absent. Krea2, SDXL, and
|
||||||
|
caption routes share this detection to avoid hidden drift between formatter
|
||||||
|
paths.
|
||||||
|
|
||||||
### Krea2
|
### Krea2
|
||||||
|
|
||||||
`format_krea2_prompt` chooses between three roads:
|
`format_krea2_prompt` chooses between three roads:
|
||||||
|
|||||||
+17
-1
@@ -81,11 +81,27 @@ def maybe_json(text: Any) -> dict[str, Any] | None:
|
|||||||
def normalize_input_metadata(row: dict[str, Any]) -> dict[str, Any]:
|
def normalize_input_metadata(row: dict[str, Any]) -> dict[str, Any]:
|
||||||
row = dict(row)
|
row = dict(row)
|
||||||
trigger = str(row.get("trigger") or "").strip()
|
trigger = str(row.get("trigger") or "").strip()
|
||||||
if row.get("mode") == "Insta/OF":
|
if is_pair_metadata(row):
|
||||||
return row_normalization_policy.normalize_pair_metadata(row, active_trigger=trigger)
|
return row_normalization_policy.normalize_pair_metadata(row, active_trigger=trigger)
|
||||||
return row_normalization_policy.sanitize_metadata_row_text(row, active_trigger=trigger)
|
return row_normalization_policy.sanitize_metadata_row_text(row, active_trigger=trigger)
|
||||||
|
|
||||||
|
|
||||||
|
def is_pair_metadata(row: Any) -> bool:
|
||||||
|
if not isinstance(row, dict):
|
||||||
|
return False
|
||||||
|
soft_side = (
|
||||||
|
isinstance(row.get("softcore_row"), dict)
|
||||||
|
or bool(clean_text(row.get("softcore_prompt")))
|
||||||
|
or bool(clean_text(row.get("softcore_caption")))
|
||||||
|
)
|
||||||
|
hard_side = (
|
||||||
|
isinstance(row.get("hardcore_row"), dict)
|
||||||
|
or bool(clean_text(row.get("hardcore_prompt")))
|
||||||
|
or bool(clean_text(row.get("hardcore_caption")))
|
||||||
|
)
|
||||||
|
return soft_side and hard_side
|
||||||
|
|
||||||
|
|
||||||
def normalize_input_hint(value: Any, *, text_hint: str = INPUT_HINT_PROMPT) -> str:
|
def normalize_input_hint(value: Any, *, text_hint: str = INPUT_HINT_PROMPT) -> str:
|
||||||
hint = clean_text(value).lower().replace("-", "_")
|
hint = clean_text(value).lower().replace("-", "_")
|
||||||
hint = _INPUT_HINT_ALIASES.get(hint, hint)
|
hint = _INPUT_HINT_ALIASES.get(hint, hint)
|
||||||
|
|||||||
@@ -5,9 +5,11 @@ from typing import Any, Callable
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
from . import formatter_detail as detail_policy
|
from . import formatter_detail as detail_policy
|
||||||
|
from . import formatter_input as input_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_detail as detail_policy
|
||||||
|
import formatter_input as input_policy
|
||||||
import formatter_target as target_policy
|
import formatter_target as target_policy
|
||||||
|
|
||||||
|
|
||||||
@@ -68,7 +70,7 @@ def format_krea2_prompt_result(request: KreaFormatRequest, deps: KreaFormatDepen
|
|||||||
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)
|
||||||
|
|
||||||
if row and row.get("mode") == "Insta/OF":
|
if row and input_policy.is_pair_metadata(row):
|
||||||
pair_target = target_policy.pair_policy(target)
|
pair_target = target_policy.pair_policy(target)
|
||||||
soft_prompt, soft_negative, hard_prompt, hard_negative = deps.insta_pair_to_krea(
|
soft_prompt, soft_negative, hard_prompt, hard_negative = deps.insta_pair_to_krea(
|
||||||
row,
|
row,
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ from dataclasses import dataclass
|
|||||||
from typing import Any, Callable
|
from typing import Any, Callable
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
from . import formatter_input as input_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_input as input_policy
|
||||||
import formatter_target as target_policy
|
import formatter_target as target_policy
|
||||||
|
|
||||||
|
|
||||||
@@ -65,7 +67,7 @@ def format_sdxl_prompt_result(request: SDXLFormatRequest, deps: SDXLFormatDepend
|
|||||||
nude_weight = max(0.1, min(3.0, float(request.nude_weight)))
|
nude_weight = max(0.1, min(3.0, float(request.nude_weight)))
|
||||||
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)
|
||||||
|
|
||||||
if row and row.get("mode") == "Insta/OF":
|
if row and input_policy.is_pair_metadata(row):
|
||||||
pair_target = target_policy.pair_policy(target)
|
pair_target = target_policy.pair_policy(target)
|
||||||
soft_row = row.get("softcore_row") if isinstance(row.get("softcore_row"), dict) else {}
|
soft_row = row.get("softcore_row") if isinstance(row.get("softcore_row"), dict) else {}
|
||||||
hard_row = row.get("hardcore_row") if isinstance(row.get("hardcore_row"), dict) else {}
|
hard_row = row.get("hardcore_row") if isinstance(row.get("hardcore_row"), dict) else {}
|
||||||
|
|||||||
@@ -2932,7 +2932,6 @@ def smoke_formatter_input_policy() -> None:
|
|||||||
row, method = formatter_input.row_from_inputs(source_json, "", "prompt")
|
row, method = formatter_input.row_from_inputs(source_json, "", "prompt")
|
||||||
_expect(row is None and method == "text", "Formatter input parser should not parse source JSON in explicit prompt mode")
|
_expect(row is None and method == "text", "Formatter input parser should not parse source JSON in explicit prompt mode")
|
||||||
pair_metadata = {
|
pair_metadata = {
|
||||||
"mode": "Insta/OF",
|
|
||||||
"trigger": Trigger,
|
"trigger": Trigger,
|
||||||
"softcore_row": {
|
"softcore_row": {
|
||||||
"prompt": f"{Trigger}, {Trigger}, embedded-only soft.",
|
"prompt": f"{Trigger}, {Trigger}, embedded-only soft.",
|
||||||
@@ -2952,8 +2951,10 @@ def smoke_formatter_input_policy() -> None:
|
|||||||
"camera_scene_directive": "Row hard scene camera layout.",
|
"camera_scene_directive": "Row hard scene camera layout.",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
_expect(formatter_input.is_pair_metadata(pair_metadata), "Formatter input policy should detect structural pair metadata")
|
||||||
parsed_pair, pair_method = formatter_input.row_from_inputs("", _json(pair_metadata), "metadata_json")
|
parsed_pair, pair_method = formatter_input.row_from_inputs("", _json(pair_metadata), "metadata_json")
|
||||||
_expect(pair_method == "metadata_json", "Formatter input parser should read pair metadata JSON")
|
_expect(pair_method == "metadata_json", "Formatter input parser should read pair metadata JSON")
|
||||||
|
_expect(formatter_input.is_pair_metadata(parsed_pair), "Formatter input parser should preserve structural pair metadata")
|
||||||
_expect_trigger_once("formatter_input.pair.soft_prompt", parsed_pair.get("softcore_prompt"), Trigger)
|
_expect_trigger_once("formatter_input.pair.soft_prompt", parsed_pair.get("softcore_prompt"), Trigger)
|
||||||
_expect(
|
_expect(
|
||||||
parsed_pair.get("softcore_partner_styling") == parsed_pair["softcore_row"].get("softcore_partner_styling"),
|
parsed_pair.get("softcore_partner_styling") == parsed_pair["softcore_row"].get("softcore_partner_styling"),
|
||||||
@@ -6107,7 +6108,6 @@ def smoke_formatter_metadata_fixtures() -> None:
|
|||||||
_expect("sdxl route tag" not in caption_text, "Caption naturalizer leaked SDXL formatter hint")
|
_expect("sdxl route tag" not in caption_text, "Caption naturalizer leaked SDXL formatter hint")
|
||||||
|
|
||||||
external_pair = {
|
external_pair = {
|
||||||
"mode": "Insta/OF",
|
|
||||||
"trigger": Trigger,
|
"trigger": Trigger,
|
||||||
"shared_descriptor": "25-year-old adult woman, slim figure, fair skin, blonde hair, blue eyes",
|
"shared_descriptor": "25-year-old adult woman, slim figure, fair skin, blonde hair, blue eyes",
|
||||||
"shared_cast_descriptors": [
|
"shared_cast_descriptors": [
|
||||||
|
|||||||
Reference in New Issue
Block a user