From 0a9a82991e5e37be6a3fbdafd64e08eb0a7a65ab Mon Sep 17 00:00:00 2001 From: Ethanfel Date: Fri, 26 Jun 2026 12:25:12 +0200 Subject: [PATCH] Reduce split-view cues in POV prompts --- krea_formatter.py | 63 +++++++++++++++++++++++++++++++++++++++++++++-- prompt_builder.py | 6 ++--- 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/krea_formatter.py b/krea_formatter.py index e75697c..65fe847 100644 --- a/krea_formatter.py +++ b/krea_formatter.py @@ -675,10 +675,10 @@ def _pov_camera_phrase(pov_labels: list[str], softcore: bool = False) -> str: return "" if softcore: return ( - "Camera is the male participant's first-person creator view, with him implied by perspective or foreground cues" + "Camera is the male participant's first-person creator view in one continuous frame, with him implied by perspective or foreground cues" ) return ( - "Camera is the male participant's first-person view; only his foreground hands or body cues appear" + "Camera is the male participant's first-person view in one continuous frame; only his foreground hands or body cues appear" ) @@ -908,6 +908,57 @@ def _is_foreplay_text(*parts: Any) -> bool: ) +def _is_close_foreplay_text(*parts: Any) -> bool: + text = " ".join(_clean(part).lower() for part in parts if _clean(part)) + if not text or not _is_foreplay_text(text): + return False + return any( + term in text + for term in ( + "stand close", + "stand face-to-face", + "press their bodies", + "bodies pressed close", + "hips pressed close", + "mouth-to-mouth", + "deep kissing", + "heated kiss", + "hands pull clothing", + "pull clothing aside", + "clothing being removed", + ) + ) + + +def _sanitize_foreplay_detail(detail: str, role_graph: str = "", composition: str = "") -> str: + detail = _clean(detail) + if not detail: + return "" + if not _is_close_foreplay_text(role_graph, detail, composition): + return detail + detail = re.sub( + r"\b(?:raised edge|edge-supported|edge-of-bed|bed-edge)\s+undressing position\s+(?:featuring|while|with)\s+", + "", + detail, + flags=re.IGNORECASE, + ) + detail = re.sub( + r"\b(?:standing kissing|wall-pressed kissing|mirror undressing)\s+position\s+(?:featuring|while|with)\s+", + "", + detail, + flags=re.IGNORECASE, + ) + detail = re.sub( + r"\b(?:raised edge|edge-supported|edge-of-bed|bed-edge)\s+undressing position\b", + "close standing undressing", + detail, + flags=re.IGNORECASE, + ) + detail = re.sub(r"\braised-edge open-thigh position\b", "close-body first-person position", detail, flags=re.IGNORECASE) + detail = re.sub(r"\s*,\s*", ", ", detail).strip(" ,;") + return _clean(detail) + + def _is_vaginal_penetration_text(*parts: Any) -> bool: text = " ".join(_clean(part).lower() for part in parts if _clean(part)) if not text or _is_outercourse_text(text) or _is_oral_text(text) or _is_foreplay_text(text): @@ -1695,6 +1746,8 @@ def _join_detail_clauses(clauses: list[str]) -> str: def _action_position_phrase(action: str) -> str: action = _clean(action).lower() + if _is_close_foreplay_text(action): + return "single-frame close-body first-person position" if "pov reverse cowgirl" in action: return "reverse-cowgirl first-person position" if "pov cowgirl" in action: @@ -2013,6 +2066,10 @@ def _hardcore_action_sentence( if is_climax: anchor = "" detail = _dedupe_climax_detail(detail, role_graph, detail_density) + elif _is_foreplay_text(role_graph, hard_item, composition, _axis_values_text(axis_values)): + anchor = "" + detail = _sanitize_foreplay_detail(detail, role_graph, composition) + detail = _limit_detail_for_density(detail, detail_density, False) elif is_outercourse: anchor = "" detail = _dedupe_outercourse_detail(detail, role_graph, hard_item, axis_values) @@ -2097,6 +2154,8 @@ def _composition_phrase( token in composition_lower for token in ("close-up", "close crop", "tight", "direct-flash", "subscriber-view", "post-ejaculation", "aftermath") ) + if _is_close_foreplay_text(action_lower) and close_or_aftermath: + return f"{prefix} {composition}, in one continuous first-person close-body frame" if position and close_or_aftermath: if detail_density == "compact": return f"{prefix} {composition}, with the {position} still readable" diff --git a/prompt_builder.py b/prompt_builder.py index 63ee53c..d99b526 100644 --- a/prompt_builder.py +++ b/prompt_builder.py @@ -3628,7 +3628,7 @@ def _coworking_direction_detail( if "left side" in direction: return f"{subject} is in left-side profile; {midground} run behind {pronoun} toward {background}, with coworking details kept at the frame edges" if "back-right" in direction or "back-left" in direction: - return f"{subject} is seen from a rear-quarter angle, turning back over one shoulder; {midground} and {background} stay beyond {pronoun}, not in the lower foreground" + return f"{subject} stays close in one continuous diagonal first-person body angle; {midground} lead toward {background} behind {pronoun} at the edges, not in the lower foreground" if direction == "back view": return f"the viewer looks past {subject}'s back toward {midground}, then into {background}; only POV body cues sit low in frame" if "front-right" in direction or "front-left" in direction: @@ -3663,12 +3663,12 @@ def _coworking_distance_detail(distance: str, profile: dict[str, str], subject_k def _coworking_elevation_detail(elevation: str, profile: dict[str, str], subject_kind: str, pov_labels: list[str] | None = None) -> str: elevation = str(elevation or "").strip().lower() - _subject, pronoun = _coworking_subject_terms(subject_kind, pov_labels) + subject, pronoun = _coworking_subject_terms(subject_kind, pov_labels) if pov_labels: if "low-angle" in elevation: return f"low angle keeps POV body cues low while windows and partition lines rise behind {pronoun}" if "elevated" in elevation: - return f"elevated angle shows {pronoun} from above with tabletop and glass lines only behind or beside the action" + return f"elevated POV keeps the viewer's eye line slightly higher than {subject}, with tabletop and glass lines only behind or at the side edges" if "high-angle" in elevation: return f"high angle looks down from the viewer's position with desks and aisle only in the background" return f"eye-level angle keeps tabletop lines and glass seams behind {pronoun}"