From 0c62df36de7793386507ccf0705962f971902df3 Mon Sep 17 00:00:00 2001 From: Ethanfel Date: Sat, 27 Jun 2026 17:14:03 +0200 Subject: [PATCH] Clean built-in couple formatter prose --- caption_metadata_routes.py | 19 +++++++++++-- krea_normal_formatter.py | 16 +++++++++-- tools/prompt_smoke.py | 58 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 5 deletions(-) diff --git a/caption_metadata_routes.py b/caption_metadata_routes.py index 95d7617..4d888d9 100644 --- a/caption_metadata_routes.py +++ b/caption_metadata_routes.py @@ -78,6 +78,21 @@ def couple_clothing_sentence(clothing: str, clean_text: Callable[[Any], str]) -> return f"They wear {clothing}" +def couple_subject_sentence( + subject: str, + ages: str, + cap_first: Callable[[str], str], + clean_age_phrase: Callable[[str], str], +) -> str: + subject = cap_first(subject or "adult couple") + ages = clean_age_phrase(ages) + if ages: + return f"{subject}, {ages}" + if subject.lower() == "adult couple": + return subject + return f"{subject} are adults" + + def single_from_row_result( request: CaptionMetadataRouteRequest, deps: CaptionMetadataRouteDependencies, @@ -176,9 +191,7 @@ def couple_from_row_result( camera_scene = deps.clean_text(row.get("camera_scene_directive")) style = deps.field_row_value(row, "style") if keep_style else "" - parts = [f"{deps.cap_first(subject)} are adults"] - if ages: - parts.append(f"The age detail is {deps.clean_age_phrase(ages)}") + parts = [couple_subject_sentence(subject, ages, deps.cap_first, deps.clean_age_phrase)] if body: parts.append(f"Their body types are {body}") if clothing: diff --git a/krea_normal_formatter.py b/krea_normal_formatter.py index 2c5625e..2dd7991 100644 --- a/krea_normal_formatter.py +++ b/krea_normal_formatter.py @@ -54,6 +54,19 @@ def _couple_clothing_phrase(item: str, clean: Callable[[Any], str]) -> str: return f"The couple wears {item}" +def _cap_first(text: str) -> str: + text = str(text or "").strip() + return f"{text[:1].upper()}{text[1:]}" if text else "" + + +def _couple_subject_phrase(subject: str, ages: str) -> str: + subject = _cap_first(subject or "adult couple") + ages = str(ages or "").strip() + if ages: + return f"{subject}, {ages}" + return subject + + def format_normal_row_result( request: KreaNormalRowRequest, deps: KreaNormalRowDependencies, @@ -98,8 +111,7 @@ def format_normal_row_result( ages = deps.age_detail_phrase(deps.row_value(row, "age", ("Ages",)) or row.get("age_band")) body = deps.row_value(row, "body", ("Body types",)) or deps.clean(row.get("body_type")) parts = [ - f"An adult couple: {subject}, all visibly adult", - f"Age detail: {ages}" if ages else "", + _couple_subject_phrase(subject, ages), f"Body types: {body}" if body else "", _couple_clothing_phrase(item, deps.clean) if item else "", f"The pose is {pose}" if pose else "", diff --git a/tools/prompt_smoke.py b/tools/prompt_smoke.py index 017e1d2..8876a20 100644 --- a/tools/prompt_smoke.py +++ b/tools/prompt_smoke.py @@ -638,6 +638,63 @@ def smoke_builtin_single() -> None: _expect_formatter_outputs(row, "builtin_single_woman", target="single") +def smoke_builtin_couple_metadata() -> None: + row = _prompt_row(name="builtin_couple", category="couple", subcategory="random", seed=1003, men_count=0) + _expect(row.get("source") == "built_in_generator", "builtin couple row should come from built-in generator") + _expect(row.get("subject_type") == "couple", "builtin couple row lost normalized subject_type") + _expect(row.get("women_count") + row.get("men_count") == row.get("person_count"), "builtin couple row lost count consistency") + _expect(row.get("person_count") == 2, "builtin couple row lost normalized person count") + subject = _expect_text("builtin_couple.subject_phrase", row.get("subject_phrase"), 5) + age = _expect_text("builtin_couple.age_band", row.get("age_band"), 8) + body = _expect_text("builtin_couple.body_type", row.get("body_type"), 5) + scene = _expect_text("builtin_couple.scene_text", row.get("scene_text"), 12) + item = _expect_text("builtin_couple.item", row.get("item"), 8) + pose = _expect_text("builtin_couple.pose", row.get("pose"), 8) + expression = _expect_text("builtin_couple.expression", row.get("expression"), 8) + composition = _expect_text("builtin_couple.composition", row.get("composition"), 8) + + metadata_only = dict(row) + metadata_only["prompt"] = "" + metadata_only["caption"] = "" + metadata = _json(metadata_only) + krea = krea_formatter.format_krea2_prompt("", metadata_json=metadata, target="auto") + sdxl = sdxl_formatter.format_sdxl_prompt( + "", + metadata_json=metadata, + target="auto", + trigger=SdxlTrigger, + prepend_trigger=True, + ) + caption, caption_method = caption_naturalizer.naturalize_caption( + "", + metadata_json=metadata, + target="auto", + trigger=Trigger, + include_trigger=True, + ) + + clean_age = caption_text_policy.clean_age_phrase(age) + krea_prompt = str(krea.get("krea_prompt", "")) + sdxl_prompt = str(sdxl.get("sdxl_prompt", "")).lower() + _expect("metadata(couple)" in krea.get("method", ""), "Krea built-in couple route did not use metadata") + _expect(subject.capitalize() in krea_prompt and clean_age in krea_prompt, "Krea built-in couple route lost subject or age") + _expect("all visibly adult" not in krea_prompt.lower(), "Krea built-in couple route kept redundant adult noise") + _expect("Age detail:" not in krea_prompt, "Krea built-in couple route kept age helper label") + for value in (body, scene, item, pose, expression, composition): + _expect(value in krea_prompt, f"Krea built-in couple route lost metadata value: {value}") + + _expect("2women" in sdxl_prompt or "1woman, 1man" in sdxl_prompt or "2men" in sdxl_prompt, "SDXL built-in couple route lost count tags") + for value in (body, scene, item, pose, expression, composition): + for tag in sdxl_tag_policy.split_tag_text(value): + _expect(tag.lower() in sdxl_prompt, f"SDXL built-in couple route lost metadata tag: {tag}") + + _expect(caption_method.endswith("metadata(couple)"), "Caption built-in couple route did not use metadata") + _expect(clean_age in caption and scene in caption, "Caption built-in couple route lost age or scene") + _expect("The age detail is" not in caption, "Caption built-in couple route kept age helper sentence") + for value in (body, item, pose, expression, composition): + _expect(value in caption, f"Caption built-in couple route lost metadata value: {value}") + + def smoke_camera_scene_single() -> None: row = _prompt_row( name="camera_scene_single", @@ -8022,6 +8079,7 @@ def smoke_node_profile_filter_registration() -> None: SMOKE_CASES: list[tuple[str, Callable[[], None]]] = [ ("builtin_single_woman", smoke_builtin_single), + ("builtin_couple_metadata", smoke_builtin_couple_metadata), ("camera_scene_single", smoke_camera_scene_single), ("row_camera_policy", smoke_row_camera_policy), ("config_route_location_theme", smoke_config_route_location_theme),