From f110ee6a890e30ac489ca854b0ba273c005b342c Mon Sep 17 00:00:00 2001 From: Ethanfel Date: Sat, 27 Jun 2026 17:22:13 +0200 Subject: [PATCH] Keep SDXL character tags metadata driven --- docs/prompt-pool-routing-map.md | 4 +-- sdxl_tag_policy.py | 6 +--- tools/prompt_smoke.py | 49 +++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/docs/prompt-pool-routing-map.md b/docs/prompt-pool-routing-map.md index 92e64cb..af39fd4 100644 --- a/docs/prompt-pool-routing-map.md +++ b/docs/prompt-pool-routing-map.md @@ -802,10 +802,10 @@ SDXL field consumption: | Branch | Reads most from | Key functions | | --- | --- | --- | -| Normal metadata | cast descriptors, age/body/skin/hair/eyes, `action_family`, `position_family`, `position_keys`, item, role graph, clothing/body exposure state, scene, camera config/directive | `sdxl_tag_routes.row_core_tags_result`, `sdxl_tag_policy.metadata_family_tags`, `sdxl_tag_policy.camera_tags` | +| Normal metadata | `cast_descriptor_text` or structured age/body/skin/hair/eyes, `action_family`, `position_family`, `position_keys`, item, role graph, clothing/body exposure state, scene, camera config/directive | `sdxl_tag_routes.row_core_tags_result`, `sdxl_tag_policy.normal_character_tags`, `sdxl_tag_policy.metadata_family_tags`, `sdxl_tag_policy.camera_tags` | | Pair softcore | `softcore_row`, pair partner styling, root soft camera config | `sdxl_tag_routes.soft_tags_result` | | Pair hardcore | `hardcore_row`, `action_family`, `position_family`, `position_keys`, role graph, item, `hardcore_clothing_state`, expression/composition, hard camera fields | `sdxl_tag_routes.hard_tags_result`, `sdxl_tag_policy.metadata_family_tags` | -| Text fallback | `source_text`, preserve-trigger setting, shared field-label stripping | `_fallback_text_to_sdxl` | +| Text fallback | `source_text`, preserve-trigger setting, shared field-label stripping, prompt labels such as `Characters:` | `_fallback_text_to_sdxl` | SDXL is the right place for model trigger handling, tag ordering, weight syntax, quality/style preset changes, and nude-weight defaults. Do not solve those in diff --git a/sdxl_tag_policy.py b/sdxl_tag_policy.py index c8db2ff..3aa2aa5 100644 --- a/sdxl_tag_policy.py +++ b/sdxl_tag_policy.py @@ -162,11 +162,7 @@ def character_tags_from_descriptor(descriptor: Any) -> list[str]: def normal_character_tags(row: dict[str, Any]) -> list[str]: - descriptor = ( - clean(row.get("cast_descriptor_text")) - or prompt_field(row.get("prompt", ""), "Characters") - or prompt_field(row.get("prompt", ""), "Cast descriptors") - ) + descriptor = clean(row.get("cast_descriptor_text")) if descriptor: return character_tags_from_descriptor(descriptor) diff --git a/tools/prompt_smoke.py b/tools/prompt_smoke.py index 676230b..73ca695 100644 --- a/tools/prompt_smoke.py +++ b/tools/prompt_smoke.py @@ -4417,6 +4417,32 @@ def smoke_sdxl_tag_policy() -> None: _expect(deps.explicit_tags is sdxl_tag_policy.explicit_tags, "SDXL route deps lost explicit tag policy") _expect(deps.softcore_pair_tags is sdxl_tag_policy.softcore_pair_tags, "SDXL route deps lost softcore pair tag policy") + stale_character_row = { + "prompt": "Characters: 99-year-old adult man, stale body, stale skin, stale hair, stale eyes.", + "age_band": "27-year-old adult", + "subject_phrase": "woman", + "body_phrase": "athletic figure", + "skin": "warm olive skin", + "hair": "short black hair", + "eyes": "green eyes", + } + stale_character_tags = sdxl_tag_policy.normal_character_tags(stale_character_row) + _expect("27-year-old adult" in stale_character_tags, "SDXL character tags lost structured age") + _expect("warm olive skin" in stale_character_tags, "SDXL character tags lost structured skin") + _expect( + all("stale" not in tag for tag in stale_character_tags), + "SDXL character tags should not parse stale raw prompt character labels", + ) + descriptor_tags = sdxl_tag_policy.normal_character_tags( + { + "prompt": "Characters: stale prompt descriptor.", + "cast_descriptor_text": "Woman A: 30-year-old adult woman, toned figure, fair skin, red hair, gray eyes", + } + ) + _expect("30-year-old adult woman" in descriptor_tags, "SDXL character tags lost cast descriptor metadata") + _expect("toned build" in descriptor_tags, "SDXL character tags did not normalize descriptor figure tag") + _expect(all("stale" not in tag for tag in descriptor_tags), "SDXL cast descriptor metadata should beat stale prompt labels") + def smoke_sdxl_tag_routes() -> None: row = _fixture_hardcore_row( @@ -4435,6 +4461,29 @@ def smoke_sdxl_tag_routes() -> None: "Typed SDXL row tag route should match legacy wrapper output", ) _expect("sdxl route tag" in typed_row.as_text(), "Typed SDXL row tag route lost route-specific formatter hint") + stale_character_route_row = _fixture_hardcore_row( + prompt="Characters: stale prompt subject, stale body, stale skin, stale hair, stale eyes.", + cast_descriptor_text="", + cast_descriptors=[], + subject_type="woman", + subject_phrase="woman", + primary_subject="woman", + age_band="27-year-old adult", + body_phrase="athletic figure", + skin="warm olive skin", + hair="short black hair", + eyes="green eyes", + women_count=1, + men_count=0, + person_count=1, + ) + stale_character_route_tags = sdxl_tag_routes.row_core_tags_result( + sdxl_tag_routes.SDXLRowTagRequest(stale_character_route_row, 1.29), + deps, + ).as_text() + _expect("27-year-old adult" in stale_character_route_tags, "SDXL route lost structured character age") + _expect("warm olive skin" in stale_character_route_tags, "SDXL route lost structured character skin") + _expect("stale" not in stale_character_route_tags, "SDXL route should not parse stale prompt character labels") stale_prompt_row = _fixture_hardcore_row( prompt="stale raw prompt mentions fully nude naked pussy penis oral anal semen penetration", item="standing portrait setup",