Cover Krea action POV smoke routes
This commit is contained in:
@@ -57,7 +57,9 @@ It should only handle route-agnostic cleanup:
|
|||||||
|
|
||||||
It must not make semantic decisions such as sexual action positioning, POV
|
It must not make semantic decisions such as sexual action positioning, POV
|
||||||
geometry, clothing state, or model-specific tag weighting. Those stay in the
|
geometry, clothing state, or model-specific tag weighting. Those stay in the
|
||||||
route-specific owner.
|
route-specific owner. It also preserves ordinary words such as `composition`
|
||||||
|
inside normal sentences; empty field-label cleanup is limited to standalone
|
||||||
|
labels.
|
||||||
|
|
||||||
Current integration points:
|
Current integration points:
|
||||||
|
|
||||||
@@ -93,6 +95,8 @@ Already isolated:
|
|||||||
- camera-scene prose and coworking composition adaptation live in
|
- camera-scene prose and coworking composition adaptation live in
|
||||||
`scene_camera_adapters.py`; `prompt_builder.py` still owns camera config
|
`scene_camera_adapters.py`; `prompt_builder.py` still owns camera config
|
||||||
parsing and row mutation.
|
parsing and row mutation.
|
||||||
|
- shared hardcore environment-anchor cleanup normalizes malformed pool joins
|
||||||
|
such as `on against a wall` before metadata reaches formatter routes.
|
||||||
|
|
||||||
### Pair / Adapter Layer
|
### Pair / Adapter Layer
|
||||||
|
|
||||||
@@ -248,10 +252,12 @@ Near-term:
|
|||||||
formatting across built-in rows, hardcore rows, same-cast pairs, and POV
|
formatting across built-in rows, hardcore rows, same-cast pairs, and POV
|
||||||
pairs.
|
pairs.
|
||||||
- Cover camera-scene preservation through `tools/prompt_smoke.py` for single
|
- Cover camera-scene preservation through `tools/prompt_smoke.py` for single
|
||||||
rows, split soft/hard pair cameras, and POV camera-scene routing. Expand it
|
rows, split soft/hard pair cameras, and POV camera-scene routing.
|
||||||
- Cover config-node routing through `tools/prompt_smoke.py` for category, cast,
|
- Cover config-node routing through `tools/prompt_smoke.py` for category, cast,
|
||||||
generation profile, seed lock, camera, location theme, and composition config.
|
generation profile, seed lock, camera, location theme, and composition config.
|
||||||
Expand it next for close foreplay and POV penetration.
|
- Cover close foreplay and POV penetration Krea routes so raw labels, invalid
|
||||||
|
surface grammar, normal third-person camera text, and composition punctuation
|
||||||
|
drift are caught.
|
||||||
|
|
||||||
Medium-term:
|
Medium-term:
|
||||||
|
|
||||||
@@ -310,8 +316,8 @@ Medium-term:
|
|||||||
|
|
||||||
## Recommended Next Passes
|
## Recommended Next Passes
|
||||||
|
|
||||||
1. Expand `tools/prompt_smoke.py` with close foreplay and POV penetration
|
1. Split Krea action/POV/clothing helpers into separate modules.
|
||||||
fixtures.
|
2. Split `__init__.py` node classes by family after behavior is covered by smoke
|
||||||
2. Split Krea action/POV/clothing helpers into separate modules.
|
|
||||||
3. Split `__init__.py` node classes by family after behavior is covered by smoke
|
|
||||||
checks.
|
checks.
|
||||||
|
3. Add metadata fields such as `action_family` / `position_family` to reduce
|
||||||
|
keyword guessing in hardcore filters and formatter dispatch.
|
||||||
|
|||||||
@@ -687,6 +687,11 @@ pair metadata through the core Python APIs, then verifies:
|
|||||||
collapsing to the same camera phrase;
|
collapsing to the same camera phrase;
|
||||||
- POV camera-scene directives suppress normal third-person camera text while
|
- POV camera-scene directives suppress normal third-person camera text while
|
||||||
preserving first-person spatial layout;
|
preserving first-person spatial layout;
|
||||||
|
- Krea close-interaction routes keep rewritten action wording, avoid raw
|
||||||
|
builder labels, and catch invalid surface joins such as `on against a wall`;
|
||||||
|
- Krea POV penetration routes keep first-person position anchors, suppress
|
||||||
|
normal camera text, and preserve composition punctuation before the style
|
||||||
|
suffix;
|
||||||
- expression-disabled rows do not fall back to generated expression text.
|
- expression-disabled rows do not fall back to generated expression text.
|
||||||
|
|
||||||
## Editing Cheatsheet
|
## Editing Cheatsheet
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ def _clean(value: Any) -> str:
|
|||||||
|
|
||||||
|
|
||||||
HARDCORE_ENVIRONMENT_ANCHOR_REPLACEMENTS = (
|
HARDCORE_ENVIRONMENT_ANCHOR_REPLACEMENTS = (
|
||||||
|
(r"\bon against a wall\b", "against a wall"),
|
||||||
(r"\bstacked bodies on the bed\b", "close body alignment"),
|
(r"\bstacked bodies on the bed\b", "close body alignment"),
|
||||||
(r"\bstacked bodies with close body alignment\b", "close body alignment"),
|
(r"\bstacked bodies with close body alignment\b", "close body alignment"),
|
||||||
(r"\boverhead tangled-body anal frame\b", "overhead rear-entry anal frame"),
|
(r"\boverhead tangled-body anal frame\b", "overhead rear-entry anal frame"),
|
||||||
|
|||||||
@@ -966,6 +966,7 @@ def _heuristic_cast_compatible(text: str, women_count: int, men_count: int) -> b
|
|||||||
|
|
||||||
|
|
||||||
HARDCORE_ENVIRONMENT_ANCHOR_REPLACEMENTS = (
|
HARDCORE_ENVIRONMENT_ANCHOR_REPLACEMENTS = (
|
||||||
|
(r"\bon against a wall\b", "against a wall"),
|
||||||
(r"\bstacked bodies on the bed\b", "close body alignment"),
|
(r"\bstacked bodies on the bed\b", "close body alignment"),
|
||||||
(r"\bstacked bodies with close body alignment\b", "close body alignment"),
|
(r"\bstacked bodies with close body alignment\b", "close body alignment"),
|
||||||
(r"\boverhead tangled-body anal frame\b", "overhead rear-entry anal frame"),
|
(r"\boverhead tangled-body anal frame\b", "overhead rear-entry anal frame"),
|
||||||
|
|||||||
+1
-1
@@ -51,7 +51,7 @@ def _strip_empty_fields(text: str) -> str:
|
|||||||
labels = "|".join(re.escape(label) for label in EMPTY_FIELD_LABELS)
|
labels = "|".join(re.escape(label) for label in EMPTY_FIELD_LABELS)
|
||||||
text = re.sub(rf"\b(?:{labels})\s*:\s*[.,;]", "", text, flags=re.IGNORECASE)
|
text = re.sub(rf"\b(?:{labels})\s*:\s*[.,;]", "", text, flags=re.IGNORECASE)
|
||||||
text = re.sub(rf"\b(?:{labels}):\s*(?=\.|,|;|$)", "", text, flags=re.IGNORECASE)
|
text = re.sub(rf"\b(?:{labels}):\s*(?=\.|,|;|$)", "", text, flags=re.IGNORECASE)
|
||||||
text = re.sub(rf"\b(?:{labels})\.(?=\s|$)", "", text, flags=re.IGNORECASE)
|
text = re.sub(rf"(^|(?<=[.!?])\s+)(?:{labels})\.(?=\s|$)", r"\1", text, flags=re.IGNORECASE)
|
||||||
text = re.sub(rf"\b(?:{labels}):\s*(?:none|null|n/a)\b[.,;]?", "", text, flags=re.IGNORECASE)
|
text = re.sub(rf"\b(?:{labels}):\s*(?:none|null|n/a)\b[.,;]?", "", text, flags=re.IGNORECASE)
|
||||||
return clean_spacing(text)
|
return clean_spacing(text)
|
||||||
|
|
||||||
|
|||||||
@@ -387,6 +387,32 @@ def smoke_hardcore_category_routes() -> None:
|
|||||||
_expect_formatter_outputs(row, name, target="single")
|
_expect_formatter_outputs(row, name, target="single")
|
||||||
|
|
||||||
|
|
||||||
|
def smoke_krea_close_foreplay_route() -> None:
|
||||||
|
row = _prompt_row(
|
||||||
|
name="krea_close_foreplay_route",
|
||||||
|
category="Hardcore sexual poses",
|
||||||
|
subcategory="Foreplay and teasing",
|
||||||
|
seed=3401,
|
||||||
|
character_cast=_character_cast(),
|
||||||
|
women_count=1,
|
||||||
|
men_count=1,
|
||||||
|
hardcore_position_config=_action_filter("foreplay_only"),
|
||||||
|
)
|
||||||
|
_expect_custom_row(row, "krea_close_foreplay_route")
|
||||||
|
krea = krea_formatter.format_krea2_prompt("", metadata_json=_json(row), target="single")
|
||||||
|
prompt = _expect_text("krea_close_foreplay_route.krea_prompt", krea.get("krea_prompt"), 40)
|
||||||
|
lower = prompt.lower()
|
||||||
|
_expect("metadata" in krea.get("method", ""), "close foreplay route did not use metadata")
|
||||||
|
_expect("role graph:" not in lower, "close foreplay leaked raw role label")
|
||||||
|
_expect("foreplay action:" not in lower, "close foreplay leaked raw item label")
|
||||||
|
_expect("on against" not in lower, "close foreplay kept invalid surface grammar")
|
||||||
|
_expect(
|
||||||
|
any(term in lower for term in ("clothing", "hands", "kiss", "bodies press", "body contact")),
|
||||||
|
"close foreplay lost close-contact action wording",
|
||||||
|
)
|
||||||
|
_expect_formatter_outputs(row, "krea_close_foreplay_route", target="single")
|
||||||
|
|
||||||
|
|
||||||
def _insta_options(**overrides: Any) -> str:
|
def _insta_options(**overrides: Any) -> str:
|
||||||
options = pb.build_insta_of_options_json(
|
options = pb.build_insta_of_options_json(
|
||||||
softcore_cast="same_as_hardcore",
|
softcore_cast="same_as_hardcore",
|
||||||
@@ -553,6 +579,48 @@ def smoke_pov_camera_scene() -> None:
|
|||||||
_expect("Camera:" not in prompt, "Krea POV prompt should not emit normal third-person camera directive")
|
_expect("Camera:" not in prompt, "Krea POV prompt should not emit normal third-person camera directive")
|
||||||
|
|
||||||
|
|
||||||
|
def smoke_krea_pov_penetration_route() -> None:
|
||||||
|
pair = pb.build_insta_of_pair(
|
||||||
|
row_number=1,
|
||||||
|
start_index=1,
|
||||||
|
seed=3411,
|
||||||
|
ethnicity="any",
|
||||||
|
figure="random",
|
||||||
|
no_plus_women=False,
|
||||||
|
no_black=False,
|
||||||
|
trigger=Trigger,
|
||||||
|
prepend_trigger_to_prompt=True,
|
||||||
|
options_json=_insta_options(
|
||||||
|
softcore_camera_mode="from_camera_config",
|
||||||
|
hardcore_camera_mode="from_camera_config",
|
||||||
|
camera_detail="compact",
|
||||||
|
),
|
||||||
|
character_cast=_character_cast(pov_man=True),
|
||||||
|
hardcore_position_config=_action_filter("penetration_only"),
|
||||||
|
location_config=_coworking_location_config(),
|
||||||
|
hardcore_camera_config=_orbit_camera(
|
||||||
|
horizontal_angle=45,
|
||||||
|
vertical_angle=0,
|
||||||
|
zoom=5.5,
|
||||||
|
subject_focus="action",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
_expect_pair(pair, "krea_pov_penetration_route")
|
||||||
|
hard_row = pair.get("hardcore_row") or {}
|
||||||
|
_expect("Man A" in (hard_row.get("pov_character_labels") or []), "POV penetration hard row lost Man A POV label")
|
||||||
|
_expect(not hard_row.get("camera_directive"), "POV penetration should suppress normal camera directive")
|
||||||
|
krea = krea_formatter.format_krea2_prompt("", metadata_json=_json(pair), target="hardcore")
|
||||||
|
prompt = _expect_text("krea_pov_penetration_route.krea_prompt", krea.get("krea_prompt"), 60)
|
||||||
|
lower = prompt.lower()
|
||||||
|
_expect("metadata" in krea.get("method", ""), "POV penetration route did not use metadata")
|
||||||
|
_expect("viewer" in lower and "first-person" in lower, "POV penetration lost first-person wording")
|
||||||
|
_expect("penetrates" in lower or "penetration" in lower, "POV penetration lost penetration action wording")
|
||||||
|
_expect("woman" in lower and "thigh" in lower, "POV penetration lost body-position anchors")
|
||||||
|
_expect("camera:" not in prompt, "POV penetration emitted normal third-person camera directive")
|
||||||
|
_expect("role graph:" not in lower and "sexual scene:" not in lower, "POV penetration leaked raw prompt labels")
|
||||||
|
_expect("composition. explicit" in lower, "POV penetration composition sentence should keep punctuation before style suffix")
|
||||||
|
|
||||||
|
|
||||||
def smoke_no_expression_fallback() -> None:
|
def smoke_no_expression_fallback() -> None:
|
||||||
cast = pb.build_character_slot_json(
|
cast = pb.build_character_slot_json(
|
||||||
subject_type="woman",
|
subject_type="woman",
|
||||||
@@ -584,10 +652,12 @@ SMOKE_CASES: list[tuple[str, Callable[[], None]]] = [
|
|||||||
("camera_scene_single", smoke_camera_scene_single),
|
("camera_scene_single", smoke_camera_scene_single),
|
||||||
("config_route_location_theme", smoke_config_route_location_theme),
|
("config_route_location_theme", smoke_config_route_location_theme),
|
||||||
("hardcore_category_routes", smoke_hardcore_category_routes),
|
("hardcore_category_routes", smoke_hardcore_category_routes),
|
||||||
|
("krea_close_foreplay_route", smoke_krea_close_foreplay_route),
|
||||||
("insta_pair_same_cast", smoke_insta_pair),
|
("insta_pair_same_cast", smoke_insta_pair),
|
||||||
("insta_pair_pov_man", smoke_insta_pair_pov),
|
("insta_pair_pov_man", smoke_insta_pair_pov),
|
||||||
("insta_pair_camera_split", smoke_insta_pair_camera_split),
|
("insta_pair_camera_split", smoke_insta_pair_camera_split),
|
||||||
("pov_camera_scene", smoke_pov_camera_scene),
|
("pov_camera_scene", smoke_pov_camera_scene),
|
||||||
|
("krea_pov_penetration_route", smoke_krea_pov_penetration_route),
|
||||||
("expression_disabled", smoke_no_expression_fallback),
|
("expression_disabled", smoke_no_expression_fallback),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user