Clean built-in couple formatter prose

This commit is contained in:
2026-06-27 17:14:03 +02:00
parent ed67c9ba7b
commit 0c62df36de
3 changed files with 88 additions and 5 deletions
+16 -3
View File
@@ -78,6 +78,21 @@ def couple_clothing_sentence(clothing: str, clean_text: Callable[[Any], str]) ->
return f"They wear {clothing}" 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( def single_from_row_result(
request: CaptionMetadataRouteRequest, request: CaptionMetadataRouteRequest,
deps: CaptionMetadataRouteDependencies, deps: CaptionMetadataRouteDependencies,
@@ -176,9 +191,7 @@ def couple_from_row_result(
camera_scene = deps.clean_text(row.get("camera_scene_directive")) camera_scene = deps.clean_text(row.get("camera_scene_directive"))
style = deps.field_row_value(row, "style") if keep_style else "" style = deps.field_row_value(row, "style") if keep_style else ""
parts = [f"{deps.cap_first(subject)} are adults"] parts = [couple_subject_sentence(subject, ages, deps.cap_first, deps.clean_age_phrase)]
if ages:
parts.append(f"The age detail is {deps.clean_age_phrase(ages)}")
if body: if body:
parts.append(f"Their body types are {body}") parts.append(f"Their body types are {body}")
if clothing: if clothing:
+14 -2
View File
@@ -54,6 +54,19 @@ def _couple_clothing_phrase(item: str, clean: Callable[[Any], str]) -> str:
return f"The couple wears {item}" 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( def format_normal_row_result(
request: KreaNormalRowRequest, request: KreaNormalRowRequest,
deps: KreaNormalRowDependencies, 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")) 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")) body = deps.row_value(row, "body", ("Body types",)) or deps.clean(row.get("body_type"))
parts = [ parts = [
f"An adult couple: {subject}, all visibly adult", _couple_subject_phrase(subject, ages),
f"Age detail: {ages}" if ages else "",
f"Body types: {body}" if body else "", f"Body types: {body}" if body else "",
_couple_clothing_phrase(item, deps.clean) if item else "", _couple_clothing_phrase(item, deps.clean) if item else "",
f"The pose is {pose}" if pose else "", f"The pose is {pose}" if pose else "",
+58
View File
@@ -638,6 +638,63 @@ def smoke_builtin_single() -> None:
_expect_formatter_outputs(row, "builtin_single_woman", target="single") _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: def smoke_camera_scene_single() -> None:
row = _prompt_row( row = _prompt_row(
name="camera_scene_single", name="camera_scene_single",
@@ -8022,6 +8079,7 @@ def smoke_node_profile_filter_registration() -> None:
SMOKE_CASES: list[tuple[str, Callable[[], None]]] = [ SMOKE_CASES: list[tuple[str, Callable[[], None]]] = [
("builtin_single_woman", smoke_builtin_single), ("builtin_single_woman", smoke_builtin_single),
("builtin_couple_metadata", smoke_builtin_couple_metadata),
("camera_scene_single", smoke_camera_scene_single), ("camera_scene_single", smoke_camera_scene_single),
("row_camera_policy", smoke_row_camera_policy), ("row_camera_policy", smoke_row_camera_policy),
("config_route_location_theme", smoke_config_route_location_theme), ("config_route_location_theme", smoke_config_route_location_theme),