Improve hardcore prompt wording QA
This commit is contained in:
+109
-15
@@ -292,9 +292,24 @@ def _natural_label_text(text: Any, labels: list[str]) -> str:
|
||||
text = re.sub(r"\bWoman A\b", "the woman", text)
|
||||
elif labels == ["Man A"]:
|
||||
text = re.sub(r"\bMan A\b", "the man", text)
|
||||
text = re.sub(
|
||||
r"(^|[.!?]\s+)(the woman|the man)\b",
|
||||
lambda match: match.group(1) + match.group(2).capitalize(),
|
||||
text,
|
||||
flags=re.IGNORECASE,
|
||||
)
|
||||
return text
|
||||
|
||||
|
||||
def _lowercase_for_inline_join(text: str) -> str:
|
||||
return re.sub(
|
||||
r"^(The woman|The man|The viewer|The named adults)\b",
|
||||
lambda match: match.group(1).lower(),
|
||||
_clean(text),
|
||||
flags=re.IGNORECASE,
|
||||
)
|
||||
|
||||
|
||||
def _cast_prose(
|
||||
text: str,
|
||||
central_label: str = "Woman A",
|
||||
@@ -446,10 +461,40 @@ def _pov_hardcore_pose_sentence(
|
||||
action_lower = action_text.lower()
|
||||
if not context:
|
||||
context = action_lower
|
||||
|
||||
def sentence(base: str) -> str:
|
||||
details = ""
|
||||
if ";" in action_text:
|
||||
details = _pov_clean_detail(action_text.split(";", 1)[1], f"{context} {base}", detail_density)
|
||||
return f"{base}; {details}" if details else base
|
||||
|
||||
if _is_outercourse_text(context, action_lower):
|
||||
if any(term in context for term in ("boobjob", "titjob", "breast sex", "breast-sex")):
|
||||
return sentence(
|
||||
"POV breast-sex position: the viewer reclines with his hips in the foreground while the woman kneels between his thighs; "
|
||||
"her hands press both breasts around the viewer's penis with the glans near her mouth"
|
||||
)
|
||||
if any(term in context for term in ("testicle", "balls licking", "balls-licking", "balls and mouth")):
|
||||
return sentence(
|
||||
"POV testicle-sucking position: the viewer reclines with thighs open while the woman kneels low between his legs; "
|
||||
"her mouth and tongue stay at the viewer's balls with his penis visible above her face"
|
||||
)
|
||||
if any(term in context for term in ("penis licking", "penis-licking", "tongue along", "tongue licking")):
|
||||
return sentence(
|
||||
"POV penis-licking position: the viewer's hips and penis are in the foreground while the woman kneels close; "
|
||||
"her tongue moves along the shaft and glans with her hands steadying the base"
|
||||
)
|
||||
if any(term in context for term in ("footjob", "soles", "toes curled", "feet stroking")):
|
||||
return sentence(
|
||||
"POV footjob position: the viewer reclines with his penis in the foreground while the woman faces him; "
|
||||
"her soles wrap around the shaft and stroke it with the contact point centered"
|
||||
)
|
||||
return sentence(
|
||||
"POV non-penetrative outercourse position: the viewer's hips stay in the foreground while the woman keeps the visible contact point centered"
|
||||
)
|
||||
penetrative_tokens = (
|
||||
"penetrat",
|
||||
"thrust",
|
||||
"penis",
|
||||
"anal",
|
||||
"cowgirl",
|
||||
"missionary",
|
||||
@@ -472,12 +517,6 @@ def _pov_hardcore_pose_sentence(
|
||||
|
||||
contact = _pov_contact_clause(action, role_graph, hard_item, axis_values, context)
|
||||
|
||||
def sentence(base: str) -> str:
|
||||
details = ""
|
||||
if ";" in action_text:
|
||||
details = _pov_clean_detail(action_text.split(";", 1)[1], f"{context} {base}", detail_density)
|
||||
return f"{base}; {details}" if details else base
|
||||
|
||||
if "reverse cowgirl" in context:
|
||||
return sentence(
|
||||
"POV reverse cowgirl position: the viewer lies on his back while the woman straddles his hips facing away; "
|
||||
@@ -644,11 +683,31 @@ def _sanitize_scene_text_for_cast(text: Any, labels: list[str]) -> str:
|
||||
return text
|
||||
|
||||
|
||||
def _natural_clothing_state(text: Any) -> str:
|
||||
def _clothing_access_phrase(action_text: Any) -> str:
|
||||
text = _clean(action_text).lower()
|
||||
if any(term in text for term in ("cumshot", "ejaculat", "semen", "cum on", "cum across", "post-orgasm", "aftermath")):
|
||||
return "leaving the body exposed for visible semen and aftermath"
|
||||
if any(term in text for term in ("boobjob", "titjob", "breast sex", "footjob", "testicle", "balls", "penis licking", "non-penetrative")):
|
||||
return "leaving the contact point unobstructed"
|
||||
if any(term in text for term in ("oral", "blowjob", "fellatio", "mouth", "tongue")):
|
||||
return "leaving the oral contact unobstructed"
|
||||
if any(term in text for term in ("penetrat", "thrust", "penis entering", "vaginal", "anal")):
|
||||
return "leaving the penetration point unobstructed"
|
||||
return "leaving skin and body contact readable"
|
||||
|
||||
|
||||
def _natural_clothing_state(text: Any, action_text: Any = "") -> str:
|
||||
text = _clean(text)
|
||||
if not text:
|
||||
return ""
|
||||
text = re.sub(r"^Clothing state:\s*", "", text, flags=re.IGNORECASE)
|
||||
if re.search(r";\s*(?=(?:Woman|Man) [A-Z]\b)", text):
|
||||
parts = [
|
||||
_natural_clothing_state(part, action_text).rstrip(".")
|
||||
for part in re.split(r";\s*(?=(?:Woman|Man) [A-Z]\b)", text)
|
||||
if _clean(part)
|
||||
]
|
||||
return ". ".join(part for part in parts if part)
|
||||
body_exposure = re.match(r"^Body exposure:\s*(.*?)\.?$", text, flags=re.IGNORECASE)
|
||||
if body_exposure:
|
||||
return _clean(body_exposure.group(1)).rstrip(".")
|
||||
@@ -672,9 +731,9 @@ def _natural_clothing_state(text: Any) -> str:
|
||||
if "nude-adjacent" in state:
|
||||
return f"{owner.capitalize()}'s body is partly exposed"
|
||||
if "partially removed" in state or "pushed aside" in state:
|
||||
return f"{owner.capitalize()}'s {outfit} is pushed aside and partly removed, exposing the sexual contact clearly"
|
||||
return f"{owner.capitalize()}'s {outfit} is pushed aside or partly removed where needed, {_clothing_access_phrase(action_text)}"
|
||||
if "keeps" in state:
|
||||
return f"{owner.capitalize()} keeps the {outfit} on while the sexual contact stays visible"
|
||||
return f"{owner.capitalize()} keeps the {outfit} on while {_clothing_access_phrase(action_text)}"
|
||||
text = re.sub(r";\s*(?:softcore visual reference|teaser outfit detail):\s*", ". Visual clothing state: ", text, flags=re.IGNORECASE)
|
||||
text = text.replace("softcore outfit", "outfit")
|
||||
text = text.replace("teaser outfit", "outfit")
|
||||
@@ -715,6 +774,31 @@ def _position_context_text(role_graph: str, hard_item: str, composition: str = "
|
||||
)
|
||||
|
||||
|
||||
def _is_outercourse_text(*parts: Any) -> bool:
|
||||
text = " ".join(_clean(part).lower() for part in parts if _clean(part))
|
||||
return any(
|
||||
term in text
|
||||
for term in (
|
||||
"outercourse",
|
||||
"non-penetrative",
|
||||
"boobjob",
|
||||
"titjob",
|
||||
"breast sex",
|
||||
"breast-sex",
|
||||
"testicle",
|
||||
"balls licking",
|
||||
"balls-licking",
|
||||
"penis licking",
|
||||
"penis-licking",
|
||||
"tongue along",
|
||||
"footjob",
|
||||
"soles",
|
||||
"toes curled",
|
||||
"feet stroking",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def _is_toy_assisted_double_text(*parts: Any) -> bool:
|
||||
text = " ".join(_clean(part).lower() for part in parts if _clean(part))
|
||||
if "toy" not in text:
|
||||
@@ -758,6 +842,16 @@ def _hardcore_pose_anchor(role_graph: str, hard_item: str, composition: str = ""
|
||||
position_text = _clean(axis_values.get("position", "")).lower()
|
||||
if not text:
|
||||
return ""
|
||||
if _is_outercourse_text(role_graph, hard_item, composition, _axis_values_text(axis_values)):
|
||||
if any(term in text for term in ("boobjob", "titjob", "breast sex", "breast-sex")):
|
||||
return "breast-sex outercourse pose"
|
||||
if any(term in text for term in ("testicle", "balls licking", "balls-licking", "balls and mouth")):
|
||||
return "testicle-sucking outercourse pose"
|
||||
if any(term in text for term in ("penis licking", "penis-licking", "tongue along", "tongue licking")):
|
||||
return "penis-licking outercourse pose"
|
||||
if any(term in text for term in ("footjob", "soles", "toes curled", "feet stroking")):
|
||||
return "footjob outercourse pose"
|
||||
return "non-penetrative outercourse pose"
|
||||
if _is_toy_assisted_double_text(role_graph, hard_item, composition, _axis_values_text(axis_values)):
|
||||
if "face-down ass-up" in text or "face-down" in text:
|
||||
return "toy-assisted face-down rear-entry double-penetration pose"
|
||||
@@ -887,7 +981,7 @@ def _hardcore_pose_anchor(role_graph: str, hard_item: str, composition: str = ""
|
||||
return "three-body explicit sex pose"
|
||||
if "group" in text or "orgy" in text:
|
||||
return "multi-body explicit sex pose"
|
||||
if "penetrat" in text or "thrust" in text:
|
||||
if re.search(r"(?<!non-)penetrat|thrust", text):
|
||||
return "hip-aligned penetrative sex pose"
|
||||
return ""
|
||||
|
||||
@@ -1085,7 +1179,7 @@ def _hardcore_pose_arrangement(anchor: str, role_graph: str, hard_item: str, com
|
||||
return "with all three adult bodies clearly placed around the central subject"
|
||||
if "group" in text or "orgy" in text:
|
||||
return "with each adult body readable in the shared sex act"
|
||||
if "penetrat" in text or "thrust" in text:
|
||||
if re.search(r"(?<!non-)penetrat|thrust", text):
|
||||
return "with hips aligned and legs open around the contact point"
|
||||
return ""
|
||||
|
||||
@@ -1158,7 +1252,7 @@ def _hardcore_item_detail(hard_item: str) -> str:
|
||||
r"face-sitting cunnilingus",
|
||||
r"pussy licking with thighs spread",
|
||||
r"oral sex with tongue and fingers",
|
||||
r"mouth on genitals with explicit contact",
|
||||
r"oral contact with mouth on the visible genitals",
|
||||
r"sixty-nine oral sex",
|
||||
)
|
||||
act_pattern = "|".join(act_patterns)
|
||||
@@ -1621,7 +1715,7 @@ def _hardcore_action_sentence(
|
||||
if arrangement and anchor_phrase and not _arrangement_duplicates_role(arrangement, role_graph):
|
||||
anchor_phrase = f"{anchor_phrase} {arrangement}"
|
||||
if role_graph and anchor_phrase:
|
||||
sentence = f"In {anchor_phrase}, {role_graph}"
|
||||
sentence = f"In {anchor_phrase}, {_lowercase_for_inline_join(role_graph)}"
|
||||
elif role_graph:
|
||||
sentence = role_graph
|
||||
elif detail and anchor_phrase:
|
||||
@@ -2063,7 +2157,7 @@ def _insta_pair_to_krea(row: dict[str, Any], detail_level: str, style_mode: str)
|
||||
hard_action,
|
||||
_pov_camera_phrase(pov_labels),
|
||||
_natural_label_text(
|
||||
_filter_pov_labeled_clauses(_natural_clothing_state(row.get("hardcore_clothing_state")), pov_labels),
|
||||
_filter_pov_labeled_clauses(_natural_clothing_state(row.get("hardcore_clothing_state"), hard_action), pov_labels),
|
||||
hard_labels,
|
||||
),
|
||||
hard_cast_prose,
|
||||
|
||||
Reference in New Issue
Block a user