Extract fallback role graph wording
This commit is contained in:
@@ -180,6 +180,29 @@ def _character_cast_two_men(*, pov_first_man: bool = False) -> str:
|
||||
)["character_cast"]
|
||||
|
||||
|
||||
def _character_cast_subjects(subjects: list[str] | tuple[str, ...]) -> str:
|
||||
cast = ""
|
||||
counts = {"woman": 0, "man": 0}
|
||||
for subject in subjects:
|
||||
subject = str(subject)
|
||||
counts[subject] += 1
|
||||
label = chr(ord("A") + counts[subject] - 1)
|
||||
cast = pb.build_character_slot_json(
|
||||
subject_type=subject,
|
||||
label=label,
|
||||
age="25-year-old adult" if subject == "woman" else "40-year-old adult",
|
||||
ethnicity="western_european",
|
||||
figure="balanced",
|
||||
body="slim" if subject == "woman" else "average",
|
||||
descriptor_detail="compact",
|
||||
expression_intensity=0.55,
|
||||
softcore_expression_intensity=0.35,
|
||||
hardcore_expression_intensity=0.75,
|
||||
character_cast=cast,
|
||||
)["character_cast"]
|
||||
return cast
|
||||
|
||||
|
||||
def _action_filter(focus: str, hardcore_position_config: str | dict[str, Any] | None = "") -> str:
|
||||
kwargs = {
|
||||
"allow_toys": False,
|
||||
@@ -1325,6 +1348,128 @@ def smoke_interaction_role_graph_routes() -> None:
|
||||
_expect_formatter_outputs(row, name, target="single")
|
||||
|
||||
|
||||
def smoke_fallback_role_graph_routes() -> None:
|
||||
cases = [
|
||||
(
|
||||
"fallback_solo_woman_manual",
|
||||
("woman",),
|
||||
"Manual stimulation",
|
||||
"manual_only",
|
||||
"manual",
|
||||
"fingering",
|
||||
4401,
|
||||
1,
|
||||
0,
|
||||
("reclines with thighs open", "one hand between her legs"),
|
||||
("one hand between her legs", "fingers visibly stimulating"),
|
||||
),
|
||||
(
|
||||
"fallback_solo_man_climax",
|
||||
("man",),
|
||||
"Cumshot and climax",
|
||||
"climax_only",
|
||||
"climax",
|
||||
"open_thighs",
|
||||
4401,
|
||||
0,
|
||||
1,
|
||||
("solo visible ejaculation pose", "semen visible"),
|
||||
("solo visible ejaculation pose", "visible semen on skin"),
|
||||
),
|
||||
(
|
||||
"fallback_women_only_oral",
|
||||
("woman", "woman"),
|
||||
"Oral sex",
|
||||
"oral_only",
|
||||
"oral",
|
||||
"reclining_oral",
|
||||
4401,
|
||||
2,
|
||||
0,
|
||||
("woman a kneels between woman b", "uses tongue and fingers"),
|
||||
("woman a kneels between woman b", "uses tongue and fingers"),
|
||||
),
|
||||
(
|
||||
"fallback_women_only_threesome",
|
||||
("woman", "woman", "woman"),
|
||||
"Threesomes",
|
||||
"threesome_only",
|
||||
"threesome",
|
||||
"front_back",
|
||||
4401,
|
||||
3,
|
||||
0,
|
||||
("uses a strap-on", "gives oral contact"),
|
||||
("uses a strap-on", "gives oral contact"),
|
||||
),
|
||||
(
|
||||
"fallback_men_only_oral",
|
||||
("man", "man"),
|
||||
"Oral sex",
|
||||
"oral_only",
|
||||
"oral",
|
||||
"kneeling",
|
||||
4401,
|
||||
0,
|
||||
2,
|
||||
("man a kneels", "takes man b's penis"),
|
||||
("man a kneels", "takes man b's penis"),
|
||||
),
|
||||
(
|
||||
"fallback_men_only_threesome",
|
||||
("man", "man", "man"),
|
||||
"Threesomes",
|
||||
"threesome_only",
|
||||
"threesome",
|
||||
"front_back",
|
||||
4401,
|
||||
0,
|
||||
3,
|
||||
("penetrates man b anally", "gives oral contact"),
|
||||
("penetrates man b anally", "gives oral contact"),
|
||||
),
|
||||
(
|
||||
"fallback_mixed_threesome",
|
||||
("woman", "man", "man"),
|
||||
"Threesomes",
|
||||
"threesome_only",
|
||||
"threesome",
|
||||
"front_back",
|
||||
4401,
|
||||
1,
|
||||
2,
|
||||
("thrusts his penis into woman a", "uses mouth and hands"),
|
||||
("thrusts his penis into woman a", "uses mouth and hands"),
|
||||
),
|
||||
]
|
||||
for name, subjects, subcategory, focus, family, position_key, seed, women_count, men_count, role_terms, krea_terms in cases:
|
||||
row = _prompt_row(
|
||||
name=name,
|
||||
category="Hardcore sexual poses",
|
||||
subcategory=subcategory,
|
||||
seed=seed,
|
||||
character_cast=_character_cast_subjects(subjects),
|
||||
women_count=women_count,
|
||||
men_count=men_count,
|
||||
hardcore_position_config=_position_filter(focus, family, [position_key]),
|
||||
)
|
||||
_expect_custom_row(row, name)
|
||||
_expect(row.get("position_family") == family, f"{name} position_family mismatch: {row.get('position_family')}")
|
||||
_expect(position_key in (row.get("position_keys") or []), f"{name} lost position key {position_key!r}")
|
||||
role_graph = _expect_text(f"{name}.source_role_graph", row.get("source_role_graph"), 30).lower()
|
||||
for term in role_terms:
|
||||
_expect(term in role_graph, f"{name} role graph missing {term!r}: {role_graph}")
|
||||
krea = krea_formatter.format_krea2_prompt("", metadata_json=_json(row), target="single")
|
||||
prompt = _expect_text(f"{name}.krea_prompt", krea.get("krea_prompt"), 60).lower()
|
||||
_expect("metadata" in krea.get("method", ""), f"{name}.krea did not use metadata")
|
||||
_expect("role graph:" not in prompt and "sexual scene:" not in prompt, f"{name} Krea leaked raw labels")
|
||||
for term in krea_terms:
|
||||
_expect(term in prompt, f"{name} Krea prompt missing {term!r}: {prompt}")
|
||||
if name == "fallback_solo_man_climax":
|
||||
_expect("lower back and ass" not in prompt, f"{name} Krea kept conflicting solo male climax detail: {prompt}")
|
||||
_expect_formatter_outputs(row, name, target="single")
|
||||
|
||||
|
||||
def smoke_no_expression_fallback() -> None:
|
||||
cast = pb.build_character_slot_json(
|
||||
subject_type="woman",
|
||||
@@ -1463,6 +1608,7 @@ SMOKE_CASES: list[tuple[str, Callable[[], None]]] = [
|
||||
("double_front_back_route", smoke_double_front_back_route),
|
||||
("climax_position_routes", smoke_climax_position_routes),
|
||||
("interaction_role_graph_routes", smoke_interaction_role_graph_routes),
|
||||
("fallback_role_graph_routes", smoke_fallback_role_graph_routes),
|
||||
("expression_disabled", smoke_no_expression_fallback),
|
||||
("formatter_metadata_fixtures", smoke_formatter_metadata_fixtures),
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user