from __future__ import annotations from typing import Any, Callable try: from .prompt_hygiene import sanitize_caption_text, sanitize_negative_text, sanitize_prompt_text except ImportError: # Allows local smoke tests with `python tools/prompt_smoke.py`. from prompt_hygiene import sanitize_caption_text, sanitize_negative_text, sanitize_prompt_text def _labeled_expression_sentence(label: str, expression: Any) -> str: expression = str(expression or "").strip() if not expression: return "" return f"{label}: {expression}. " def _prepend_trigger(prompt: str, trigger: str, enabled: bool) -> str: trigger = trigger.strip() if not enabled or not trigger: return prompt if prompt.lower().startswith(trigger.lower()): return prompt return f"{trigger}, {prompt}" def _combined_negative(base: str, extra: str) -> str: parts = [part.strip() for part in (base, extra) if part and part.strip()] return ", ".join(parts) def assemble_insta_pair_metadata( *, active_trigger: str, prepend_trigger_to_prompt: bool, extra_positive: str, extra_negative: str, soft_negative_base: str, hard_negative_base: str, options: dict[str, Any], platform_style: str, soft_descriptor_sentence: str, soft_level: str, soft_cast: str, soft_cast_presence: str, soft_cast_styling_sentence: str, soft_row: dict[str, Any], soft_camera_scene_sentence: str, soft_camera_sentence: str, hard_level: str, hard_cast: str, cast_descriptor_text: str, pov_directive: str, pov_character_labels: list[str], hard_clothing_sentence: str, hard_row: dict[str, Any], hard_scene: str, hard_camera_scene_sentence: str, hard_composition: str, hard_detail_directive: str, hard_camera_sentence: str, descriptor: str, soft_partner_outfit_text: str, soft_partner_styling: dict[str, Any], soft_camera_scene_directive: str, soft_camera_config: dict[str, Any], soft_camera_directive: str, hard_camera_scene_directive: str, hard_camera_config: dict[str, Any], hard_camera_directive: str, camera_caption_text: Callable[[dict[str, Any]], str], cast_descriptors: list[str], character_hardcore_clothing_entries: list[str], default_man_hardcore_clothing_entries: list[str], hard_clothing_state: str, hard_detail_density: str, hard_women_count: int, hard_men_count: int, character_slots: list[dict[str, Any]], character_slot_map: dict[str, dict[str, Any]], ) -> dict[str, Any]: soft_prompt = ( f"Insta/OF softcore mode: {platform_style}. " f"{soft_descriptor_sentence}" f"Softcore setup: {soft_level}. Cast: {soft_cast}. " f"{soft_cast_presence}" f"{soft_cast_styling_sentence}" f"{soft_row['softcore_item_prompt_label']}: {soft_row['item']}. Pose: {soft_row['pose']}. Setting: {soft_row['scene_text']}. " f"{soft_camera_scene_sentence}" f"{_labeled_expression_sentence('Facial expression', soft_row.get('expression'))}" f"Composition: {soft_row['composition']}. " f"{soft_camera_sentence}" "Keep the softcore version seductive, creator-shot, and styled as a soft teaser. " f"{soft_row['positive_suffix']}." ) hard_prompt = ( f"Insta/OF hardcore mode: {platform_style}. " f"Hardcore setup: {hard_level}. Cast: {hard_cast}. " f"Cast descriptors: {cast_descriptor_text}. " f"{pov_directive + ' ' if pov_directive else ''}" f"{'Keep Woman A visually central from the POV camera. ' if pov_character_labels else 'Keep Woman A visually central. '}" f"{hard_clothing_sentence}" f"Role graph: {hard_row['role_graph']} Sexual scene: {hard_row['item']}. " f"Setting: {hard_scene}. " f"{hard_camera_scene_sentence}" f"{_labeled_expression_sentence('Facial expressions', hard_row.get('expression'))}" f"Composition: {hard_composition}. " f"{hard_detail_directive}" f"{hard_camera_sentence}" f"{hard_row['positive_suffix']}." ) if extra_positive.strip(): soft_prompt = f"{soft_prompt.rstrip()} {extra_positive.strip()}" hard_prompt = f"{hard_prompt.rstrip()} {extra_positive.strip()}" soft_prompt = _prepend_trigger(soft_prompt, active_trigger, bool(prepend_trigger_to_prompt)) hard_prompt = _prepend_trigger(hard_prompt, active_trigger, bool(prepend_trigger_to_prompt)) soft_prompt = sanitize_prompt_text(soft_prompt, triggers=(active_trigger,)) hard_prompt = sanitize_prompt_text(hard_prompt, triggers=(active_trigger,)) soft_negative = sanitize_negative_text(_combined_negative(soft_negative_base, extra_negative)) hard_negative = sanitize_negative_text(_combined_negative(hard_negative_base, extra_negative)) soft_caption_parts = [ active_trigger, "Insta/OF softcore mode", descriptor, soft_level, soft_row["item"], soft_row["pose"], soft_partner_outfit_text, soft_partner_styling["pose"], soft_row["scene_text"], soft_camera_scene_directive, soft_row["composition"], camera_caption_text(soft_camera_config) if soft_camera_directive else "", ] soft_caption = sanitize_caption_text( ", ".join(str(part).strip() for part in soft_caption_parts if str(part).strip()), triggers=(active_trigger,), ) hard_caption_parts = [ active_trigger, "Insta/OF hardcore mode", "Woman A", descriptor, hard_cast, hard_row["role_graph"], hard_row["item"], hard_scene, hard_camera_scene_directive, hard_composition, camera_caption_text(hard_camera_config) if hard_camera_directive else "", ] hard_caption = sanitize_caption_text( ", ".join(str(part).strip() for part in hard_caption_parts if str(part).strip()), triggers=(active_trigger,), ) return { "mode": "Insta/OF", "options": options, "shared_descriptor": descriptor, "shared_cast_descriptors": cast_descriptors, "pov_character_labels": pov_character_labels, "pov_prompt_directive": pov_directive, "softcore_partner_styling": soft_partner_styling, "character_hardcore_clothing": character_hardcore_clothing_entries, "default_man_hardcore_clothing": default_man_hardcore_clothing_entries, "hardcore_clothing_state": hard_clothing_state, "hardcore_detail_density": hard_detail_density, "hardcore_position_config": hard_row.get("hardcore_position_config", {}), "softcore_prompt": soft_prompt, "hardcore_prompt": hard_prompt, "softcore_negative_prompt": soft_negative, "hardcore_negative_prompt": hard_negative, "softcore_caption": soft_caption, "hardcore_caption": hard_caption, "softcore_row": soft_row, "hardcore_row": hard_row, "hardcore_women_count": hard_women_count, "hardcore_men_count": hard_men_count, "character_cast_slots": character_slots, "character_slot_labels": sorted(character_slot_map), "softcore_camera_config": soft_camera_config, "hardcore_camera_config": hard_camera_config, "softcore_camera_directive": soft_camera_directive, "hardcore_camera_directive": hard_camera_directive, "softcore_camera_scene_directive": soft_camera_scene_directive, "hardcore_camera_scene_directive": hard_camera_scene_directive, }