Compare commits

...

3 Commits

7 changed files with 234 additions and 18 deletions
+16
View File
@@ -45,6 +45,22 @@ Version: `2026-06-30-generated-route-validation-positive-channel-cleanup`
code path before closing the category. Manual prompt-axis wins are not code path before closing the category. Manual prompt-axis wins are not
enough; the generated route can still drop the key contact hierarchy or add enough; the generated route can still drop the key contact hierarchy or add
limiting positive-channel wording. limiting positive-channel wording.
14. Treat the final prompt that Krea receives and the rendered generator images
as the source of truth. Tests are guardrails for known failures, not proof
that the prompt will render the intended pose. If a test passes while the
rendered image or prompt audit shows drift, update the test and the method
rather than trusting the test.
15. Atlas/catalog prompt wording must use direct visual prompt sentences. Do
not send option-list wording such as `or`, `may`, `optionally`, or `either`
in pose cues, and do not append meta instructions such as `keep the visible
partner...` or generic camera-layout prose to atlas routes. Krea2 is not an
instruction-following LLM in this loop; prompt text should describe the
image, not explain a policy.
16. Do not promote generator edits from a few isolated renders unless the final
generated prompt is structurally wrong before rendering. For pose wording
changes, collect prompt/image evidence across multiple women, source cases,
and seeds when feasible, then patch only the repeated generator-safe
hierarchy. Keep early wins as prompt-guide or provisional evidence.
## Promotion Gates ## Promotion Gates
+1
View File
@@ -12,6 +12,7 @@ METADATA_AXIS_KEYS = {
"position_key", "position_key",
"position_keys", "position_keys",
"krea2_variant_keys", "krea2_variant_keys",
"krea2_prompt_variant_indices",
"restored_prompt_axes", "restored_prompt_axes",
} }
ACTION_CONTEXT_PRIORITY = ( ACTION_CONTEXT_PRIORITY = (
+27 -1
View File
@@ -76,6 +76,33 @@ def get_variant(key: str, *, path: str | Path | None = None) -> dict[str, Any]:
return {} return {}
def _cue_list(value: Any) -> list[str]:
if isinstance(value, dict):
value = value.get("prompt_cues") or value.get("cues")
if not isinstance(value, list):
return []
return [str(cue) for cue in value if str(cue).strip()]
def prompt_cue_sets(variant_or_key: dict[str, Any] | str) -> list[list[str]]:
variant = get_variant(variant_or_key) if isinstance(variant_or_key, str) else dict(variant_or_key or {})
if not variant:
return []
cue_sets: list[list[str]] = []
baseline = _cue_list(variant.get("prompt_cues"))
if baseline:
cue_sets.append(baseline)
for cue_set in variant.get("prompt_variant_cues") or []:
cues = _cue_list(cue_set)
if cues:
cue_sets.append(cues)
if not cue_sets:
fallback = str(variant.get("canonical_geometry") or "").strip()
if fallback:
cue_sets.append([fallback])
return cue_sets
def reference_paths(key: str, *, path: str | Path | None = None) -> list[Path]: def reference_paths(key: str, *, path: str | Path | None = None) -> list[Path]:
catalog = load_catalog(path) catalog = load_catalog(path)
atlas_root = Path(str(catalog.get("atlas_root") or "")) atlas_root = Path(str(catalog.get("atlas_root") or ""))
@@ -90,4 +117,3 @@ def reference_paths(key: str, *, path: str | Path | None = None) -> list[Path]:
continue continue
paths.append(atlas_root / ref_path) paths.append(atlas_root / ref_path)
return paths return paths
+19 -6
View File
@@ -97,6 +97,16 @@ def _has_krea2_atlas_variant(row: dict[str, Any]) -> bool:
return any(krea2_pose_variant_catalog.get_variant(key) for key in _krea2_variant_keys(row)) return any(krea2_pose_variant_catalog.get_variant(key) for key in _krea2_variant_keys(row))
def _restores_krea2_prompt_axis(row: dict[str, Any], axis_name: str) -> bool:
config = row.get("hardcore_position_config") if isinstance(row.get("hardcore_position_config"), dict) else {}
axis_values = row.get("item_axis_values") if isinstance(row.get("item_axis_values"), dict) else {}
restored_axes = [
*_list_values(config.get("restore_prompt_axes")),
*_list_values(axis_values.get("restored_prompt_axes")),
]
return axis_name in restored_axes
def _has_krea2_top_down_variant(row: dict[str, Any]) -> bool: def _has_krea2_top_down_variant(row: dict[str, Any]) -> bool:
for key in _krea2_variant_keys(row): for key in _krea2_variant_keys(row):
variant = krea2_pose_variant_catalog.get_variant(key) variant = krea2_pose_variant_catalog.get_variant(key)
@@ -214,6 +224,14 @@ def format_insta_pair_result(request: KreaPairFormatRequest, deps: KreaPairForma
) )
hard_has_atlas_variant = _has_krea2_atlas_variant(hard) hard_has_atlas_variant = _has_krea2_atlas_variant(hard)
hard_output_composition = "" if hard_has_atlas_variant else deps.pov_composition_text(hard_composition, pov_labels) hard_output_composition = "" if hard_has_atlas_variant else deps.pov_composition_text(hard_composition, pov_labels)
hard_restores_clothing = hard_has_atlas_variant and _restores_krea2_prompt_axis(hard, "clothing_detail")
hard_clothing = deps.natural_label_text(
deps.filter_pov_labeled_clauses(
deps.natural_clothing_state(row.get("hardcore_clothing_state"), hard_action),
pov_labels,
),
hard_labels,
)
same_soft_cast = options.get("softcore_cast") == "same_as_hardcore" same_soft_cast = options.get("softcore_cast") == "same_as_hardcore"
soft_output_composition = deps.pov_composition_text(soft.get("composition"), pov_labels if same_soft_cast else []) soft_output_composition = deps.pov_composition_text(soft.get("composition"), pov_labels if same_soft_cast else [])
soft_cast_presence = deps.softcore_cast_presence_phrase( soft_cast_presence = deps.softcore_cast_presence_phrase(
@@ -284,12 +302,7 @@ def format_insta_pair_result(request: KreaPairFormatRequest, deps: KreaPairForma
hard_cast_prose, hard_cast_prose,
hard_action, hard_action,
deps.pov_camera_phrase(pov_labels), deps.pov_camera_phrase(pov_labels),
"" hard_clothing if (not hard_has_atlas_variant or hard_restores_clothing) else "",
if hard_has_atlas_variant
else deps.natural_label_text(
deps.filter_pov_labeled_clauses(deps.natural_clothing_state(row.get("hardcore_clothing_state"), hard_action), pov_labels),
hard_labels,
),
f"set in {hard_scene}" if hard_scene else "", f"set in {hard_scene}" if hard_scene else "",
hard_camera_scene, hard_camera_scene,
deps.expression_phrase(hard_expression), deps.expression_phrase(hard_expression),
+35 -2
View File
@@ -105,14 +105,47 @@ def _unique_texts(values: list[Any]) -> list[str]:
return texts return texts
def _restored_visible_details(axis_values: dict[str, Any]) -> list[str]:
restored_details = _list_values(axis_values.get("restored_prompt_details"))
restored_axes = _list_values(axis_values.get("restored_prompt_axes"))
if restored_axes and len(restored_axes) == len(restored_details):
return _unique_texts(
[
detail
for axis, detail in zip(restored_axes, restored_details)
if axis != "clothing_detail"
]
)
clothing_detail = _clean(axis_values.get("clothing_detail")).lower()
return _unique_texts(
[
detail
for detail in restored_details
if not clothing_detail or _clean(detail).lower() != clothing_detail
]
)
def _krea2_atlas_variant_sentence(axis_values: Any) -> str: def _krea2_atlas_variant_sentence(axis_values: Any) -> str:
variant = _selected_krea2_atlas_variant(axis_values) variant = _selected_krea2_atlas_variant(axis_values)
if not variant: if not variant:
return "" return ""
cues = _unique_texts(list(variant.get("prompt_cues") or []) or [variant.get("canonical_geometry")]) cue_sets = krea2_pose_variant_catalog.prompt_cue_sets(variant)
selected_index = 0
if isinstance(axis_values, dict):
indices = axis_values.get("krea2_prompt_variant_indices")
if isinstance(indices, dict):
try:
selected_index = int(indices.get(str(variant.get("key") or ""), 0))
except (TypeError, ValueError):
selected_index = 0
if selected_index < 0 or selected_index >= len(cue_sets):
selected_index = 0
cues = _unique_texts(cue_sets[selected_index] if cue_sets else [variant.get("canonical_geometry")])
sentence = _clean(". ".join(cues)).rstrip(".") sentence = _clean(". ".join(cues)).rstrip(".")
if isinstance(axis_values, dict): if isinstance(axis_values, dict):
restored_details = _unique_texts(_list_values(axis_values.get("restored_prompt_details"))) restored_details = _restored_visible_details(axis_values)
if restored_details: if restored_details:
sentence = f"{sentence}. Additional visible detail: {'; '.join(restored_details)}" sentence = f"{sentence}. Additional visible detail: {'; '.join(restored_details)}"
return sentence return sentence
+32
View File
@@ -27,6 +27,7 @@ try:
from . import generate_prompt_batches as g from . import generate_prompt_batches as g
from . import generation_profile_config as generation_profile_policy from . import generation_profile_config as generation_profile_policy
from . import hardcore_position_config as hardcore_position_policy from . import hardcore_position_config as hardcore_position_policy
from . import krea2_pose_variant_catalog
from . import location_config as location_policy from . import location_config as location_policy
from . import pair_builder from . import pair_builder
from . import pair_cast from . import pair_cast
@@ -76,6 +77,7 @@ except ImportError: # Allows local smoke tests with `python -c`.
import generate_prompt_batches as g import generate_prompt_batches as g
import generation_profile_config as generation_profile_policy import generation_profile_config as generation_profile_policy
import hardcore_position_config as hardcore_position_policy import hardcore_position_config as hardcore_position_policy
import krea2_pose_variant_catalog
import location_config as location_policy import location_config as location_policy
import pair_builder import pair_builder
import pair_cast import pair_cast
@@ -717,6 +719,30 @@ def _axis_values_with_krea2_variant_keys(
return merged return merged
def _axis_values_with_krea2_prompt_variant_indices(
axis_values: dict[str, Any],
*,
seed_config: dict[str, int],
seed: int,
row_number: int,
) -> dict[str, Any]:
variant_keys = axis_values.get("krea2_variant_keys") if isinstance(axis_values, dict) else []
if not isinstance(variant_keys, list) or not variant_keys:
return axis_values
rng = seed_policy.axis_rng(seed_config, "pose", seed, row_number)
indices: dict[str, int] = {}
for key in variant_keys:
variant = krea2_pose_variant_catalog.get_variant(str(key))
cue_sets = krea2_pose_variant_catalog.prompt_cue_sets(variant)
if len(cue_sets) > 1:
indices[str(key)] = rng.randrange(len(cue_sets))
if not indices:
return axis_values
merged = dict(axis_values)
merged["krea2_prompt_variant_indices"] = indices
return merged
def _axis_values_with_hardcore_route_metadata( def _axis_values_with_hardcore_route_metadata(
axis_values: dict[str, Any], axis_values: dict[str, Any],
*, *,
@@ -2387,6 +2413,12 @@ def _build_custom_row(
item_axis_values, item_axis_values,
parsed_hardcore_position_config, parsed_hardcore_position_config,
) )
item_axis_values = _axis_values_with_krea2_prompt_variant_indices(
item_axis_values,
seed_config=seed_config,
seed=seed,
row_number=row_number,
)
item_template_metadata = dict(category_route.item_template_metadata) item_template_metadata = dict(category_route.item_template_metadata)
item_formatter_hints = dict(category_route.formatter_hints) item_formatter_hints = dict(category_route.formatter_hints)
is_pose_category = category_route.is_pose_category is_pose_category = category_route.is_pose_category
+100 -5
View File
@@ -6762,8 +6762,13 @@ def smoke_krea2_pov_pose_variant_catalog() -> None:
refs = variant.get("reference_images") refs = variant.get("reference_images")
_expect(isinstance(prompt_cues, list) and prompt_cues, f"{key} has no prompt cues") _expect(isinstance(prompt_cues, list) and prompt_cues, f"{key} has no prompt cues")
_expect(isinstance(avoid_cues, list) and avoid_cues, f"{key} has no avoid cues") _expect(isinstance(avoid_cues, list) and avoid_cues, f"{key} has no avoid cues")
for cue in prompt_cues: prompt_variant_cues = variant.get("prompt_variant_cues", [])
cue_text = _expect_text(f"{key}.prompt_cue", cue, 8) _expect(isinstance(prompt_variant_cues, list), f"{key} prompt variant cue sets should be a list when present")
all_cue_sets = [prompt_cues, *prompt_variant_cues]
for cue_set_index, cue_set in enumerate(all_cue_sets):
_expect(isinstance(cue_set, list) and cue_set, f"{key} prompt cue set {cue_set_index} is empty")
for cue in cue_set:
cue_text = _expect_text(f"{key}.prompt_cue[{cue_set_index}]", cue, 8)
_expect( _expect(
not re.search(r"\b(?:may|optionally|either|or)\b", cue_text, flags=re.IGNORECASE), not re.search(r"\b(?:may|optionally|either|or)\b", cue_text, flags=re.IGNORECASE),
f"{key} prompt cue should be a direct model instruction, not an option list: {cue_text!r}", f"{key} prompt cue should be a direct model instruction, not an option list: {cue_text!r}",
@@ -6846,7 +6851,17 @@ def smoke_krea2_pov_atlas_variant_prompt_routes() -> None:
_expect(variant_keys == [key], f"{key} row lost exact variant metadata: {variant_keys}") _expect(variant_keys == [key], f"{key} row lost exact variant metadata: {variant_keys}")
krea = krea_formatter.format_krea2_prompt("", metadata_json=_json(pair), target="hardcore") krea = krea_formatter.format_krea2_prompt("", metadata_json=_json(pair), target="hardcore")
prompt = _expect_text(f"{key}.krea_prompt", krea.get("krea_prompt"), 80).lower() prompt = _expect_text(f"{key}.krea_prompt", krea.get("krea_prompt"), 80).lower()
for cue in variant.get("prompt_cues") or []: hard_axis_values = hard_row.get("item_axis_values") if isinstance(hard_row.get("item_axis_values"), dict) else {}
variant_indices = hard_axis_values.get("krea2_prompt_variant_indices") if isinstance(hard_axis_values, dict) else {}
selected_index = 0
if isinstance(variant_indices, dict):
try:
selected_index = int(variant_indices.get(key, 0))
except (TypeError, ValueError):
selected_index = 0
cue_sets = krea2_pose_variant_catalog.prompt_cue_sets(variant)
_expect(0 <= selected_index < len(cue_sets), f"{key} selected invalid prompt variant index {selected_index}")
for cue in cue_sets[selected_index]:
cue_text = _expect_text(f"{key}.prompt_cue", cue, 8).lower() cue_text = _expect_text(f"{key}.prompt_cue", cue, 8).lower()
_expect(cue_text in prompt, f"{key} final Krea prompt lost atlas cue {cue_text!r}: {prompt}") _expect(cue_text in prompt, f"{key} final Krea prompt lost atlas cue {cue_text!r}: {prompt}")
atlas_action_prompt = prompt.split(" camera is ", 1)[0] atlas_action_prompt = prompt.split(" camera is ", 1)[0]
@@ -6911,6 +6926,60 @@ def smoke_krea2_pov_atlas_variant_prompt_routes() -> None:
def smoke_krea2_pose_variant_catalog_policy() -> None: def smoke_krea2_pose_variant_catalog_policy() -> None:
catalog = krea2_pose_variant_catalog.load_catalog() catalog = krea2_pose_variant_catalog.load_catalog()
_expect(catalog.get("version") == 1, "Krea2 pose-variant loader returned wrong catalog") _expect(catalog.get("version") == 1, "Krea2 pose-variant loader returned wrong catalog")
synthetic_variant = {
"key": "pov_synthetic_seeded_variant",
"prompt_cues": ["synthetic baseline atlas cue", "synthetic baseline contact anchor"],
"prompt_variant_cues": [
["synthetic alternate atlas cue", "synthetic alternate contact anchor"],
{"prompt_cues": ["synthetic second alternate cue", "synthetic second contact anchor"]},
],
}
_expect(
krea2_pose_variant_catalog.prompt_cue_sets(synthetic_variant) == [
["synthetic baseline atlas cue", "synthetic baseline contact anchor"],
["synthetic alternate atlas cue", "synthetic alternate contact anchor"],
["synthetic second alternate cue", "synthetic second contact anchor"],
],
"Krea2 pose-variant catalog should expose baseline and optional prompt variant cue sets",
)
original_get_variant = krea2_pose_variant_catalog.get_variant
try:
def fake_get_variant(key: str, **kwargs):
if key == "pov_synthetic_seeded_variant":
return synthetic_variant
return original_get_variant(key, **kwargs)
krea2_pose_variant_catalog.get_variant = fake_get_variant
baseline_sentence = krea_pov_actions._krea2_atlas_variant_sentence(
{
"krea2_variant_keys": ["pov_synthetic_seeded_variant"],
"krea2_prompt_variant_indices": {"pov_synthetic_seeded_variant": 0},
}
)
alternate_sentence = krea_pov_actions._krea2_atlas_variant_sentence(
{
"krea2_variant_keys": ["pov_synthetic_seeded_variant"],
"krea2_prompt_variant_indices": {"pov_synthetic_seeded_variant": 1},
}
)
_expect("synthetic baseline atlas cue" in baseline_sentence, "Krea2 atlas sentence lost baseline prompt cue set")
_expect("synthetic alternate atlas cue" in alternate_sentence, "Krea2 atlas sentence lost selected prompt variant cue set")
selected_indices: set[int] = set()
for seed in range(4510, 4560):
axis_values = pb._axis_values_with_krea2_prompt_variant_indices(
{"krea2_variant_keys": ["pov_synthetic_seeded_variant"]},
seed_config={},
seed=seed,
row_number=1,
)
selected_indices.add(int(axis_values.get("krea2_prompt_variant_indices", {}).get("pov_synthetic_seeded_variant", 0)))
_expect(
len(selected_indices) >= 2,
f"Krea2 prompt variant selector should vary across pose seeds, got {sorted(selected_indices)}",
)
finally:
krea2_pose_variant_catalog.get_variant = original_get_variant
proven = krea2_pose_variant_catalog.variant_keys(status="proven") proven = krea2_pose_variant_catalog.variant_keys(status="proven")
_expect( _expect(
proven == [ proven == [
@@ -8570,9 +8639,35 @@ def smoke_pov_oral_position_routes() -> None:
clothing_only_top_krea.get("krea_prompt"), clothing_only_top_krea.get("krea_prompt"),
60, 60,
).lower() ).lower()
clothing_only_prompt_key = _clean_key(clothing_only_top_prompt)
clothing_only_state = _clean_key(clothing_only_top_pair.get("hardcore_clothing_state"))
expected_clothing_terms = [
term
for term in (
"body is fully exposed",
"bare skin unobstructed",
"pushed aside",
"partly removed",
"oral contact unobstructed",
"belt open and pants lowered below the hips",
)
if term in clothing_only_state
]
_expect( _expect(
any(str(detail).lower() in clothing_only_top_prompt for detail in clothing_only_details), expected_clothing_terms,
f"Krea2 POV Prompt Restore clothing-only final prompt did not include sampled clothing detail: {clothing_only_top_prompt}", f"Krea2 POV Prompt Restore clothing-only fixture lost softcore-derived clothing state: {clothing_only_state}",
)
_expect(
any(term in clothing_only_prompt_key for term in expected_clothing_terms),
f"Krea2 POV Prompt Restore clothing-only final prompt did not follow softcore clothing continuity: {clothing_only_top_prompt}",
)
_expect(
"clothing state:" not in clothing_only_top_prompt,
f"Krea2 POV Prompt Restore clothing-only final prompt leaked raw clothing label: {clothing_only_top_prompt}",
)
_expect(
not any(str(detail).lower() in clothing_only_top_prompt for detail in clothing_only_details),
f"Krea2 POV Prompt Restore clothing-only final prompt should not dump raw clothing_detail: {clothing_only_top_prompt}",
) )
sitting_variant_config = sxcp_nodes.NODE_CLASS_MAPPINGS["SxCPKrea2POVOralFilter"]().build( sitting_variant_config = sxcp_nodes.NODE_CLASS_MAPPINGS["SxCPKrea2POVOralFilter"]().build(