Normalize built-in row scene metadata

This commit is contained in:
2026-06-27 16:58:12 +02:00
parent 7cd2d48e6a
commit 83d661919f
3 changed files with 26 additions and 3 deletions
+1 -1
View File
@@ -132,7 +132,7 @@ Core helper ownership:
| `krea_row_fields.py` | Shared Krea normal-row field extraction for item, scene, pose, expression, composition/source-composition, camera, and style used by normal and configured-cast 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, including route-agnostic negative-prompt merge/dedupe. |
| `row_normalization.py` | Final prompt-row and pair metadata normalization: legacy built-in subject/count metadata enrichment, 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: legacy built-in subject/count/scene metadata enrichment, 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_target.py` | Shared formatter target choices and normalization for `auto`, `single`, `softcore`, and `hardcore`, including pair-side selection and combined-caption inclusion policy. |
+10 -2
View File
@@ -3,8 +3,10 @@ from __future__ import annotations
from typing import Any
try:
from . import row_location as row_location_policy
from .prompt_hygiene import combine_negative_text, sanitize_caption_text, sanitize_negative_text, sanitize_prompt_text
except ImportError: # Allows local smoke tests with `python tools/prompt_smoke.py`.
import row_location as row_location_policy
from prompt_hygiene import combine_negative_text, sanitize_caption_text, sanitize_negative_text, sanitize_prompt_text
@@ -77,8 +79,14 @@ def enrich_legacy_row_metadata(row: dict[str, Any]) -> dict[str, Any]:
_setdefault_count(row, "men_count", men_count)
if women_count is not None and men_count is not None and not str(row.get("person_count") or "").strip():
row["person_count"] = int(women_count) + int(men_count)
if str(row.get("scene") or "").strip() and not str(row.get("scene_slug") or "").strip():
row["scene_slug"] = row.get("scene")
scene_slug = str(row.get("scene") or row.get("scene_slug") or "").strip()
if scene_slug and not str(row.get("scene_slug") or "").strip():
row["scene_slug"] = scene_slug
if scene_slug and not str(row.get("scene_text") or "").strip():
scene_text = row_location_policy.legacy_scene_text_for_slug(scene_slug)
if scene_text:
row["scene_text"] = scene_text
row.setdefault("scene_entry", {"slug": scene_slug, "prompt": scene_text})
return row
+15
View File
@@ -575,13 +575,24 @@ def smoke_builtin_single() -> None:
_expect(row.get("subject_phrase") == "woman", "builtin single row lost normalized subject_phrase")
_expect(row.get("women_count") == 1 and row.get("men_count") == 0, "builtin single row lost normalized cast counts")
_expect(row.get("person_count") == 1, "builtin single row lost normalized person count")
_expect_text("builtin_single_woman.scene_text", row.get("scene_text"), 12)
_expect(row.get("scene_slug") == row.get("scene"), "builtin single row lost legacy scene slug metadata")
_expect(row.get("scene_entry", {}).get("slug") == row.get("scene"), "builtin single row lost scene_entry slug")
_expect("cast_summary" not in row, "builtin single row should not masquerade as configured cast")
_expect_trigger_once("builtin_single_woman.prompt", row.get("prompt"), Trigger)
krea = krea_formatter.format_krea2_prompt("", metadata_json=_json(row), target="single")
_expect(row.get("scene_text") in str(krea.get("krea_prompt", "")), "builtin single Krea route used scene slug instead of scene text")
sdxl = sdxl_formatter.format_sdxl_prompt("", metadata_json=_json(row), target="single", trigger=SdxlTrigger, prepend_trigger=True)
_expect("1woman" in str(sdxl.get("sdxl_prompt", "")).lower(), "builtin single SDXL route lost normalized woman count")
sdxl_scene_text = str(sdxl.get("sdxl_prompt", "")).lower()
scene_words = re.findall(r"[a-z0-9]+", str(row.get("scene_text", "")).split(",", 1)[0].lower())
scene_anchor = " ".join(scene_words[:2])
_expect(scene_anchor in sdxl_scene_text, "builtin single SDXL route lost readable scene text")
_expect(str(row.get("scene_slug", "")).lower() not in sdxl_scene_text, "builtin single SDXL route leaked raw scene slug")
caption, caption_method = caption_naturalizer.naturalize_caption("", metadata_json=_json(row), target="single", trigger=Trigger, include_trigger=True)
_expect(caption_method.endswith("metadata(single)"), "builtin single caption route did not use single metadata branch")
_expect("woman" in caption.lower(), "builtin single caption route lost normalized subject")
_expect(row.get("scene_text") in caption, "builtin single caption route used scene slug instead of scene text")
_expect_formatter_outputs(row, "builtin_single_woman", target="single")
@@ -2814,6 +2825,7 @@ def smoke_row_normalization_policy() -> None:
{
"source": "built_in_generator",
"primary_subject": "two women",
"scene": "office",
"prompt": "Two adults in a clean legacy prompt.",
"caption": "legacy couple caption",
"negative_prompt": "bad anatomy",
@@ -2824,6 +2836,9 @@ def smoke_row_normalization_policy() -> None:
_expect(legacy_couple.get("subject_type") == "couple", "Legacy couple row lost normalized subject_type")
_expect(legacy_couple.get("women_count") == 2 and legacy_couple.get("men_count") == 0, "Legacy couple row lost normalized counts")
_expect(legacy_couple.get("person_count") == 2, "Legacy couple row lost normalized person count")
_expect(legacy_couple.get("scene_slug") == "office", "Legacy couple row lost scene slug")
_expect("cozy office desk" in str(legacy_couple.get("scene_text", "")), "Legacy couple row lost readable scene text")
_expect(legacy_couple.get("scene_entry", {}).get("slug") == "office", "Legacy couple row lost scene entry")
_expect("cast_summary" not in legacy_couple, "Legacy couple row should not gain configured-cast summary")
legacy_group = row_normalization.normalize_prompt_row(