Improve same-cast softcore and solo hardcore prompts
This commit is contained in:
@@ -110,7 +110,10 @@ When the hardcore cast includes partners, pair mode also creates deterministic
|
|||||||
shared cast descriptors such as `woman A / primary creator` and `man A`. Use
|
shared cast descriptors such as `woman A / primary creator` and `man A`. Use
|
||||||
`softcore_cast=same_as_hardcore`, `hardcore_cast=couple`, and
|
`softcore_cast=same_as_hardcore`, `hardcore_cast=couple`, and
|
||||||
`continuity=same_creator_same_room` when you want a soft prompt with the same
|
`continuity=same_creator_same_room` when you want a soft prompt with the same
|
||||||
woman, man, and location as the hardcore prompt.
|
woman, man, and location as the hardcore prompt. In that setup, the softcore
|
||||||
|
prompt keeps the same listed adult cast physically present together in a
|
||||||
|
non-explicit teaser pose, with deterministic non-explicit partner outfits and a
|
||||||
|
shared cast pose.
|
||||||
|
|
||||||
It outputs:
|
It outputs:
|
||||||
|
|
||||||
|
|||||||
+19
-2
@@ -485,17 +485,34 @@ def _insta_of_pair_from_row(row: dict[str, Any], detail_level: str, keep_style:
|
|||||||
soft_text, _soft_method = _metadata_to_prose(soft_row, detail_level, keep_style)
|
soft_text, _soft_method = _metadata_to_prose(soft_row, detail_level, keep_style)
|
||||||
hard_text, _hard_method = _metadata_to_prose(hard_row_for_text, detail_level, keep_style)
|
hard_text, _hard_method = _metadata_to_prose(hard_row_for_text, detail_level, keep_style)
|
||||||
descriptor = _clean_text(row.get("shared_descriptor"))
|
descriptor = _clean_text(row.get("shared_descriptor"))
|
||||||
|
options = row.get("options") if isinstance(row.get("options"), dict) else {}
|
||||||
cast_descriptors = row.get("shared_cast_descriptors")
|
cast_descriptors = row.get("shared_cast_descriptors")
|
||||||
if isinstance(cast_descriptors, list):
|
if isinstance(cast_descriptors, list):
|
||||||
cast_descriptor_text = _human_join([_clean_text(item) for item in cast_descriptors if _clean_text(item)])
|
cast_descriptor_text = _human_join([_clean_text(item) for item in cast_descriptors if _clean_text(item)])
|
||||||
else:
|
else:
|
||||||
cast_descriptor_text = _clean_text(cast_descriptors)
|
cast_descriptor_text = _clean_text(cast_descriptors)
|
||||||
|
|
||||||
|
same_soft_cast = options.get("softcore_cast") == "same_as_hardcore"
|
||||||
|
|
||||||
parts = []
|
parts = []
|
||||||
if cast_descriptor_text:
|
if cast_descriptor_text and same_soft_cast:
|
||||||
parts.append(f"The shared cast descriptors are {cast_descriptor_text}")
|
parts.append(f"The shared cast descriptors are {cast_descriptor_text}")
|
||||||
elif descriptor:
|
elif descriptor:
|
||||||
parts.append(f"The shared creator descriptor is {descriptor}")
|
parts.append(f"The softcore primary creator descriptor is {descriptor}")
|
||||||
|
if cast_descriptor_text and not same_soft_cast:
|
||||||
|
parts.append(f"The hardcore cast descriptors are {cast_descriptor_text}")
|
||||||
|
if same_soft_cast:
|
||||||
|
parts.append("The softcore version keeps the same adult cast present together in a non-explicit teaser setup")
|
||||||
|
partner_styling = row.get("softcore_partner_styling")
|
||||||
|
if isinstance(partner_styling, dict):
|
||||||
|
outfits = partner_styling.get("outfits")
|
||||||
|
if isinstance(outfits, list):
|
||||||
|
outfit_text = _human_join([_clean_text(item) for item in outfits if _clean_text(item)])
|
||||||
|
if outfit_text:
|
||||||
|
parts.append(f"Softcore partner styling: {outfit_text}")
|
||||||
|
pose = _clean_text(partner_styling.get("pose"))
|
||||||
|
if pose:
|
||||||
|
parts.append(f"The shared softcore cast pose is {pose}")
|
||||||
if soft_text:
|
if soft_text:
|
||||||
parts.append(f"Softcore version: {soft_text}")
|
parts.append(f"Softcore version: {soft_text}")
|
||||||
if hard_text:
|
if hard_text:
|
||||||
|
|||||||
@@ -986,6 +986,10 @@
|
|||||||
"bed-level"
|
"bed-level"
|
||||||
],
|
],
|
||||||
"body_contact": [
|
"body_contact": [
|
||||||
|
"one hand gripping the sheets",
|
||||||
|
"hips lifted toward the camera",
|
||||||
|
"body arched on rumpled sheets",
|
||||||
|
"thighs tense against the bedding",
|
||||||
"bodies still pressed together",
|
"bodies still pressed together",
|
||||||
"hands gripping hips",
|
"hands gripping hips",
|
||||||
"thighs spread open",
|
"thighs spread open",
|
||||||
@@ -1015,7 +1019,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"text": "wet orgasm during strap-on penetration",
|
"text": "wet orgasm during strap-on penetration",
|
||||||
"cast": "women_only"
|
"cast": "women_only",
|
||||||
|
"min_people": 2
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"text": "post-orgasm dripping arousal",
|
"text": "post-orgasm dripping arousal",
|
||||||
@@ -1024,10 +1029,16 @@
|
|||||||
"external cumshot",
|
"external cumshot",
|
||||||
"visible external ejaculation",
|
"visible external ejaculation",
|
||||||
"messy post-climax release",
|
"messy post-climax release",
|
||||||
"orgasm during penetration",
|
{
|
||||||
|
"text": "orgasm during penetration",
|
||||||
|
"min_people": 2
|
||||||
|
},
|
||||||
"post-orgasm hardcore climax",
|
"post-orgasm hardcore climax",
|
||||||
"visible orgasm aftermath",
|
"visible orgasm aftermath",
|
||||||
"shared climax after penetration",
|
{
|
||||||
|
"text": "shared climax after penetration",
|
||||||
|
"min_people": 2
|
||||||
|
},
|
||||||
"hardcore ejaculation scene"
|
"hardcore ejaculation scene"
|
||||||
],
|
],
|
||||||
"expression_detail": [
|
"expression_detail": [
|
||||||
|
|||||||
+20
-2
@@ -299,10 +299,28 @@ def _insta_pair_to_krea(row: dict[str, Any], detail_level: str, style_mode: str)
|
|||||||
if options.get("softcore_cast") == "same_as_hardcore"
|
if options.get("softcore_cast") == "same_as_hardcore"
|
||||||
else f"Woman A / primary creator: {descriptor}"
|
else f"Woman A / primary creator: {descriptor}"
|
||||||
)
|
)
|
||||||
|
same_soft_cast = options.get("softcore_cast") == "same_as_hardcore"
|
||||||
|
soft_cast_presence = (
|
||||||
|
"The same listed adult cast is present together in this softcore version in a non-explicit teaser pose, with no sex act or genital contact"
|
||||||
|
if same_soft_cast
|
||||||
|
else "The softcore version focuses on Woman A alone"
|
||||||
|
)
|
||||||
|
partner_styling = row.get("softcore_partner_styling")
|
||||||
|
if isinstance(partner_styling, dict):
|
||||||
|
outfits = partner_styling.get("outfits")
|
||||||
|
partner_outfit_text = "; ".join(_clean(item) for item in outfits if _clean(item)) if isinstance(outfits, list) else ""
|
||||||
|
partner_pose = _clean(partner_styling.get("pose"))
|
||||||
|
else:
|
||||||
|
partner_outfit_text = ""
|
||||||
|
partner_pose = ""
|
||||||
|
|
||||||
soft_parts = [
|
soft_parts = [
|
||||||
f"A visibly adult creator, {descriptor}",
|
f"A visibly adult creator, {descriptor}",
|
||||||
f"Shared cast descriptors: {soft_cast_descriptor_text}" if soft_cast_descriptor_text else "",
|
f"Shared cast descriptors: {soft_cast_descriptor_text}" if same_soft_cast and soft_cast_descriptor_text else "",
|
||||||
|
f"Softcore primary creator descriptor: {soft_cast_descriptor_text}" if not same_soft_cast and soft_cast_descriptor_text else "",
|
||||||
|
soft_cast_presence,
|
||||||
|
f"Partner softcore styling: {partner_outfit_text}" if partner_outfit_text else "",
|
||||||
|
f"The shared softcore cast pose is {partner_pose}" if partner_pose else "",
|
||||||
f"shown in a {soft_level or 'softcore'} Insta/OF creator image",
|
f"shown in a {soft_level or 'softcore'} Insta/OF creator image",
|
||||||
f"wearing {soft.get('item')}" if soft.get("item") else "",
|
f"wearing {soft.get('item')}" if soft.get("item") else "",
|
||||||
f"{soft.get('pose')}" if soft.get("pose") else "",
|
f"{soft.get('pose')}" if soft.get("pose") else "",
|
||||||
@@ -314,7 +332,7 @@ def _insta_pair_to_krea(row: dict[str, Any], detail_level: str, style_mode: str)
|
|||||||
]
|
]
|
||||||
hard_parts = [
|
hard_parts = [
|
||||||
f"The same visibly adult creator, {descriptor}, is the visually central woman in a consensual explicit adult {hard_level or 'hardcore'} scene",
|
f"The same visibly adult creator, {descriptor}, is the visually central woman in a consensual explicit adult {hard_level or 'hardcore'} scene",
|
||||||
f"Shared cast descriptors: {cast_descriptor_text}" if cast_descriptor_text else "",
|
f"{'Shared' if same_soft_cast else 'Hardcore'} cast descriptors: {cast_descriptor_text}" if cast_descriptor_text else "",
|
||||||
f"all participants are 21+ and visibly adult; the cast includes {hard_cast_text}" if hard_cast_text else "all participants are 21+ and visibly adult",
|
f"all participants are 21+ and visibly adult; the cast includes {hard_cast_text}" if hard_cast_text else "all participants are 21+ and visibly adult",
|
||||||
_clean(hard.get("role_graph")),
|
_clean(hard.get("role_graph")),
|
||||||
f"The sexual action is {hard.get('item')}" if hard.get("item") else "",
|
f"The sexual action is {hard.get('item')}" if hard.get("item") else "",
|
||||||
|
|||||||
+105
-5
@@ -343,6 +343,29 @@ def _heuristic_cast_compatible(text: str, women_count: int, men_count: int) -> b
|
|||||||
if not text:
|
if not text:
|
||||||
return True
|
return True
|
||||||
total = women_count + men_count
|
total = women_count + men_count
|
||||||
|
if total == 1:
|
||||||
|
solo_blocked_terms = (
|
||||||
|
"partner",
|
||||||
|
"partners",
|
||||||
|
"two bodies",
|
||||||
|
"three bodies",
|
||||||
|
"bodies still pressed",
|
||||||
|
"bodies pressed",
|
||||||
|
"bodies tangled",
|
||||||
|
"wet bodies",
|
||||||
|
"chests heaving together",
|
||||||
|
"straddling a partner",
|
||||||
|
"shared climax",
|
||||||
|
"between two",
|
||||||
|
"from both sides",
|
||||||
|
"front-and-back",
|
||||||
|
"body contact",
|
||||||
|
)
|
||||||
|
if any(term in text for term in solo_blocked_terms):
|
||||||
|
return False
|
||||||
|
solo_toy_terms = ("toy", "dildo", "finger", "fingers", "self")
|
||||||
|
if "penetration" in text and not any(term in text for term in solo_toy_terms):
|
||||||
|
return False
|
||||||
if total < 3 and "threesome" in text:
|
if total < 3 and "threesome" in text:
|
||||||
return False
|
return False
|
||||||
if total != 3 and ("centered threesome" in text or "three-way" in text):
|
if total != 3 and ("centered threesome" in text or "three-way" in text):
|
||||||
@@ -395,6 +418,7 @@ def _heuristic_cast_compatible(text: str, women_count: int, men_count: int) -> b
|
|||||||
"blowjob",
|
"blowjob",
|
||||||
"fellatio",
|
"fellatio",
|
||||||
"deepthroat",
|
"deepthroat",
|
||||||
|
"ejaculation",
|
||||||
"semen",
|
"semen",
|
||||||
)
|
)
|
||||||
if any(term in text for term in male_terms) and not any(term in text for term in toy_terms):
|
if any(term in text for term in male_terms) and not any(term in text for term in toy_terms):
|
||||||
@@ -1270,6 +1294,16 @@ def _role_graph(
|
|||||||
]
|
]
|
||||||
return f" {extra} {rng.choice(actions)}."
|
return f" {extra} {rng.choice(actions)}."
|
||||||
|
|
||||||
|
if people_count == 1:
|
||||||
|
solo = people[0]
|
||||||
|
if women_count == 1:
|
||||||
|
if "cumshot" in slug or "climax" in slug:
|
||||||
|
return f"{solo} is shown in a solo explicit climax pose with thighs open, one hand on her body, and visible arousal on skin and sheets."
|
||||||
|
return f"{solo} is shown in a solo explicit adult pose with self-touch, open body framing, and direct camera awareness."
|
||||||
|
if "cumshot" in slug or "climax" in slug:
|
||||||
|
return f"{solo} is shown in a solo explicit climax pose with one hand on his cock, body angled toward the camera, and visible ejaculation detail."
|
||||||
|
return f"{solo} is shown in a solo explicit adult pose with direct camera awareness and clear body framing."
|
||||||
|
|
||||||
if women_count > 0 and men_count == 0:
|
if women_count > 0 and men_count == 0:
|
||||||
a, b = _pick_distinct(rng, women, 2)
|
a, b = _pick_distinct(rng, women, 2)
|
||||||
c = any_woman({a, b}) if len(women) >= 3 else ""
|
c = any_woman({a, b}) if len(women) >= 3 else ""
|
||||||
@@ -2074,6 +2108,40 @@ def _insta_of_cast_phrase(women_count: int, men_count: int) -> str:
|
|||||||
return context["cast_summary"]
|
return context["cast_summary"]
|
||||||
|
|
||||||
|
|
||||||
|
SOFTCORE_CAST_POSES = [
|
||||||
|
"standing together for a mirror selfie with bodies close but no sexual contact",
|
||||||
|
"posing shoulder-to-shoulder in a creator-shot group teaser",
|
||||||
|
"leaning together on the bed in a non-explicit subscriber preview",
|
||||||
|
"sitting close together with hands kept above clothing",
|
||||||
|
"arranged around Woman A in a flirtatious non-explicit teaser pose",
|
||||||
|
"posing in the same room as a coordinated adult creator set",
|
||||||
|
"standing near the phone tripod with relaxed teasing body language",
|
||||||
|
"framed together in a softcore cast reveal with no sex act",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def _insta_of_partner_styling(
|
||||||
|
seed_config: dict[str, int],
|
||||||
|
seed: int,
|
||||||
|
row_number: int,
|
||||||
|
women_count: int,
|
||||||
|
men_count: int,
|
||||||
|
) -> dict[str, Any]:
|
||||||
|
content_rng = _axis_rng(seed_config, "content", seed, row_number + 421)
|
||||||
|
pose_rng = _axis_rng(seed_config, "pose", seed, row_number + 421)
|
||||||
|
outfits: list[str] = []
|
||||||
|
for index in range(max(0, women_count - 1)):
|
||||||
|
label = chr(ord("B") + index)
|
||||||
|
outfits.append(f"Woman {label} wears {g.choose(content_rng, g.WOMEN_CLOTHES_MINIMAL)}")
|
||||||
|
for index in range(max(0, men_count)):
|
||||||
|
label = chr(ord("A") + index)
|
||||||
|
outfits.append(f"Man {label} wears {g.choose(content_rng, g.MEN_CLOTHES_MINIMAL)}")
|
||||||
|
return {
|
||||||
|
"outfits": outfits,
|
||||||
|
"pose": g.choose(pose_rng, SOFTCORE_CAST_POSES),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def _insta_of_active_trigger(prompt: str, trigger: str, enabled: bool) -> str:
|
def _insta_of_active_trigger(prompt: str, trigger: str, enabled: bool) -> str:
|
||||||
return _prepend_trigger(prompt, trigger, enabled)
|
return _prepend_trigger(prompt, trigger, enabled)
|
||||||
|
|
||||||
@@ -2167,6 +2235,16 @@ def build_insta_of_pair(
|
|||||||
if options["softcore_cast"] == "same_as_hardcore"
|
if options["softcore_cast"] == "same_as_hardcore"
|
||||||
else f"Woman A / primary creator: {descriptor}"
|
else f"Woman A / primary creator: {descriptor}"
|
||||||
)
|
)
|
||||||
|
soft_partner_styling = _insta_of_partner_styling(
|
||||||
|
parsed_seed_config,
|
||||||
|
seed,
|
||||||
|
row_number,
|
||||||
|
hard_women_count if options["softcore_cast"] == "same_as_hardcore" else 1,
|
||||||
|
hard_men_count if options["softcore_cast"] == "same_as_hardcore" else 0,
|
||||||
|
)
|
||||||
|
if options["softcore_cast"] != "same_as_hardcore":
|
||||||
|
soft_partner_styling = {"outfits": [], "pose": ""}
|
||||||
|
soft_partner_outfit_text = "; ".join(soft_partner_styling["outfits"])
|
||||||
platform_style = INSTA_OF_PLATFORM_STYLES[options["platform_style"]]
|
platform_style = INSTA_OF_PLATFORM_STYLES[options["platform_style"]]
|
||||||
soft_level = INSTA_OF_SOFT_LEVELS[options["softcore_level"]]
|
soft_level = INSTA_OF_SOFT_LEVELS[options["softcore_level"]]
|
||||||
hard_level = INSTA_OF_HARDCORE_LEVELS[options["hardcore_level"]]
|
hard_level = INSTA_OF_HARDCORE_LEVELS[options["hardcore_level"]]
|
||||||
@@ -2186,12 +2264,24 @@ def build_insta_of_pair(
|
|||||||
if options["softcore_cast"] == "solo"
|
if options["softcore_cast"] == "solo"
|
||||||
else f"non-explicit teaser setup with the same adult cast as the hardcore version: {_insta_of_cast_phrase(hard_women_count, hard_men_count)}"
|
else f"non-explicit teaser setup with the same adult cast as the hardcore version: {_insta_of_cast_phrase(hard_women_count, hard_men_count)}"
|
||||||
)
|
)
|
||||||
|
soft_cast_presence = (
|
||||||
|
"Show the same listed adult cast together in the softcore version, present in the same location in a non-explicit teaser pose with no sex act or genital contact. "
|
||||||
|
if options["softcore_cast"] == "same_as_hardcore"
|
||||||
|
else "Keep the softcore version focused on Woman A alone. "
|
||||||
|
)
|
||||||
|
soft_cast_styling_sentence = (
|
||||||
|
f"Partner softcore styling: {soft_partner_outfit_text}. Shared softcore cast pose: {soft_partner_styling['pose']}. "
|
||||||
|
if options["softcore_cast"] == "same_as_hardcore" and soft_partner_outfit_text
|
||||||
|
else ""
|
||||||
|
)
|
||||||
hard_cast = _insta_of_cast_phrase(hard_women_count, hard_men_count)
|
hard_cast = _insta_of_cast_phrase(hard_women_count, hard_men_count)
|
||||||
|
|
||||||
soft_prompt = (
|
soft_prompt = (
|
||||||
f"Insta/OF softcore mode: {platform_style}. Shared primary creator descriptor: {descriptor}. "
|
f"Insta/OF softcore mode: {platform_style}. Shared primary creator descriptor: {descriptor}. "
|
||||||
f"Softcore setup: {soft_level}. Cast continuity: {soft_cast}. "
|
f"Softcore setup: {soft_level}. Cast continuity: {soft_cast}. "
|
||||||
f"Shared cast descriptors: {soft_cast_descriptor_text}. "
|
f"Shared cast descriptors: {soft_cast_descriptor_text}. "
|
||||||
|
f"{soft_cast_presence}"
|
||||||
|
f"{soft_cast_styling_sentence}"
|
||||||
f"Outfit: {soft_row['item']}. Pose: {soft_row['pose']}. Setting: {soft_row['scene_text']}. "
|
f"Outfit: {soft_row['item']}. Pose: {soft_row['pose']}. Setting: {soft_row['scene_text']}. "
|
||||||
f"Facial expression: {soft_row['expression']}. Composition: {soft_row['composition']}. "
|
f"Facial expression: {soft_row['expression']}. Composition: {soft_row['composition']}. "
|
||||||
f"{soft_camera_sentence}"
|
f"{soft_camera_sentence}"
|
||||||
@@ -2217,11 +2307,20 @@ def build_insta_of_pair(
|
|||||||
hard_prompt = _insta_of_active_trigger(hard_prompt, active_trigger, bool(prepend_trigger_to_prompt))
|
hard_prompt = _insta_of_active_trigger(hard_prompt, active_trigger, bool(prepend_trigger_to_prompt))
|
||||||
soft_negative = _combined_negative(INSTA_OF_SOFT_NEGATIVE, extra_negative)
|
soft_negative = _combined_negative(INSTA_OF_SOFT_NEGATIVE, extra_negative)
|
||||||
hard_negative = _combined_negative(INSTA_OF_NEGATIVE, extra_negative)
|
hard_negative = _combined_negative(INSTA_OF_NEGATIVE, extra_negative)
|
||||||
soft_caption = (
|
soft_caption_parts = [
|
||||||
f"{active_trigger}, Insta/OF softcore mode, {descriptor}, {soft_level}, "
|
active_trigger,
|
||||||
f"{soft_row['item']}, {soft_row['pose']}, {soft_row['scene_text']}, {soft_row['composition']}, "
|
"Insta/OF softcore mode",
|
||||||
f"{soft_camera_config['camera_mode'].replace('_', ' ')} camera"
|
descriptor,
|
||||||
)
|
soft_level,
|
||||||
|
soft_row["item"],
|
||||||
|
soft_row["pose"],
|
||||||
|
soft_partner_outfit_text,
|
||||||
|
soft_partner_styling["pose"],
|
||||||
|
soft_row["scene_text"],
|
||||||
|
soft_row["composition"],
|
||||||
|
f"{soft_camera_config['camera_mode'].replace('_', ' ')} camera",
|
||||||
|
]
|
||||||
|
soft_caption = ", ".join(str(part).strip() for part in soft_caption_parts if str(part).strip())
|
||||||
hard_caption = (
|
hard_caption = (
|
||||||
f"{active_trigger}, Insta/OF hardcore mode, same primary creator descriptor, {descriptor}, "
|
f"{active_trigger}, Insta/OF hardcore mode, same primary creator descriptor, {descriptor}, "
|
||||||
f"{hard_cast}, {hard_row['role_graph']}, {hard_row['item']}, {hard_scene}, {hard_composition}, "
|
f"{hard_cast}, {hard_row['role_graph']}, {hard_row['item']}, {hard_scene}, {hard_composition}, "
|
||||||
@@ -2232,6 +2331,7 @@ def build_insta_of_pair(
|
|||||||
"options": options,
|
"options": options,
|
||||||
"shared_descriptor": descriptor,
|
"shared_descriptor": descriptor,
|
||||||
"shared_cast_descriptors": cast_descriptors,
|
"shared_cast_descriptors": cast_descriptors,
|
||||||
|
"softcore_partner_styling": soft_partner_styling,
|
||||||
"softcore_prompt": soft_prompt,
|
"softcore_prompt": soft_prompt,
|
||||||
"hardcore_prompt": hard_prompt,
|
"hardcore_prompt": hard_prompt,
|
||||||
"softcore_negative_prompt": soft_negative,
|
"softcore_negative_prompt": soft_negative,
|
||||||
|
|||||||
Reference in New Issue
Block a user