Centralize exact subcategory selectors

This commit is contained in:
2026-06-27 15:09:36 +02:00
parent 5ae2f31a20
commit 728d3e559c
5 changed files with 131 additions and 8 deletions
+84 -2
View File
@@ -285,7 +285,7 @@ def _character_cast_subjects(subjects: list[str] | tuple[str, ...]) -> str:
def _exact_subcategory_selector(category: dict[str, Any], subcategory: dict[str, Any]) -> str:
return f"{category.get('name')} / {subcategory.get('name')}"
return category_library.exact_subcategory_selector(category, subcategory)
def _matrix_cast_for_route(category: dict[str, Any], subcategory: dict[str, Any]) -> tuple[int, int, str]:
@@ -1878,7 +1878,24 @@ def smoke_category_extensions_policy() -> None:
"compositions": ["centered catalog frame"],
}
},
}
},
"Dev / Test Wear": {
"prompt_template": (
"{subject_phrase}: slash-name test style. {item_label}: {item}. "
"Scene: {scene}. Pose: {pose}. Facial expression: {expression}. "
"Composition: {composition}."
),
"caption_template": "{subject_phrase}, {item}, {scene}, {composition}",
"subcategories": {
"Layered / Office": {
"items": ["slash-safe structured blazer over tailored trousers"],
"scenes": ["slash-safe showroom with glass shelving"],
"poses": ["standing beside a mirrored divider"],
"expressions": ["focused exact-route look"],
"compositions": ["slash-safe centered catalog frame"],
}
},
},
}
},
ensure_ascii=True,
@@ -1890,6 +1907,12 @@ def smoke_category_extensions_policy() -> None:
"Dev Test Wear / Layered Office" in pb.subcategory_choices(),
"User-added JSON subcategory did not reach subcategory choices",
)
slash_selector = "Dev / Test Wear / Layered / Office"
_expect("Dev / Test Wear" in pb.category_choices(), "Slash-bearing user category did not reach category choices")
_expect(
slash_selector in pb.subcategory_choices(),
"Slash-bearing user subcategory did not reach subcategory choices",
)
row = pb.build_prompt(
category="Dev Test Wear",
subcategory="Dev Test Wear / Layered Office",
@@ -1922,6 +1945,36 @@ def smoke_category_extensions_policy() -> None:
_expect(row.get("expression") == "focused calm look", "User-added JSON expression did not generate")
_expect(row.get("composition") == "centered catalog frame", "User-added JSON composition did not generate")
_expect_formatter_outputs(row, "category_extensions_user_added_json", target="single")
slash_row = pb.build_prompt(
category="Dev / Test Wear",
subcategory=slash_selector,
row_number=1,
start_index=1,
seed=4110,
clothing="random",
ethnicity="any",
poses="random",
backside_bias=0.0,
figure="random",
no_plus_women=False,
no_black=False,
minimal_clothing_ratio=0.0,
standard_pose_ratio=1.0,
trigger=Trigger,
prepend_trigger_to_prompt=True,
extra_positive="",
extra_negative="",
women_count=1,
men_count=0,
)
_expect_row_base(slash_row, "category_extensions_slash_named_json")
_expect(slash_row.get("main_category") == "Dev / Test Wear", "Slash-bearing JSON category name drifted")
_expect(slash_row.get("subcategory") == "Layered / Office", "Slash-bearing JSON subcategory name drifted")
_expect(
slash_row.get("item") == "slash-safe structured blazer over tailored trousers",
"Slash-bearing JSON exact subcategory did not generate the intended item",
)
_expect_formatter_outputs(slash_row, "category_extensions_slash_named_json", target="single")
finally:
category_library.CATEGORY_DIR = previous_category_dir
category_extensions._EXTENSIONS_APPLIED = previous_extensions_applied
@@ -4324,6 +4377,35 @@ def smoke_category_library_route() -> None:
_expect(subcategory.get("slug") == "oral_sex", "exact subcategory lookup selected wrong subcategory")
_expect((women_count, men_count) == (1, 1), "exact subcategory lookup changed compatible cast counts")
slash_categories = [
{"name": "Dev", "slug": "dev", "subcategories": [{"name": "Wrong Route", "slug": "wrong_route", "items": ["wrong item"]}]},
{
"name": "Dev / Test Wear",
"slug": "dev_test_wear",
"subcategories": [{"name": "Layered / Office", "slug": "layered_office", "items": ["structured test item"]}],
},
]
slash_selector = category_library.exact_subcategory_selector(
slash_categories[1],
slash_categories[1]["subcategories"][0],
)
slash_choice = category_library.split_exact_subcategory_choice(slash_categories, slash_selector)
_expect(slash_choice is not None, "Exact selector parser did not accept slash-bearing category/subcategory names")
if slash_choice is not None:
_expect(slash_choice[0].get("slug") == "dev_test_wear", "Exact selector parser did not prefer longest category prefix")
_expect(slash_choice[1] == "Layered / Office", "Exact selector parser trimmed slash-bearing subcategory incorrectly")
slash_category, slash_subcategory, _slash_women, _slash_men = category_library.find_subcategory(
slash_categories,
"custom_random",
slash_selector,
random.Random(201),
random.Random(202),
women_count=1,
men_count=0,
)
_expect(slash_category.get("slug") == "dev_test_wear", "Exact subcategory lookup failed slash-bearing category")
_expect(slash_subcategory.get("slug") == "layered_office", "Exact subcategory lookup failed slash-bearing subcategory")
item = category_library.compatible_entries(list(subcategory.get("items") or []), women_count, men_count)[0]
scenes = category_library.configured_pool(
category,