from __future__ import annotations import random from pathlib import Path from typing import Any try: from . import builder_config_route as builder_config_route_policy from . import builder_prompt_route as builder_prompt_route_policy from .category_library import ( compatible_entries as _compatible_entries, compatible_entry as _compatible_entry, find_subcategory as _find_subcategory, load_category_library, merged_field as _merged_field, ) from . import camera_config as camera_policy from . import cast_context as cast_context_policy from . import category_extensions as category_extensions_policy from . import category_template_metadata as item_template_policy from . import character_appearance as character_appearance_policy from . import character_config as character_policy from . import character_profile as character_profile_policy from . import character_slot as character_slot_policy from . import category_cast_config as category_cast_policy from . import filter_config as filter_policy from . import generate_prompt_batches as g from . import generation_profile_config as generation_profile_policy from . import hardcore_position_config as hardcore_position_policy from . import location_config as location_policy from . import pair_builder from . import pair_cast from . import pair_options from . import pov_policy from . import row_normalization as row_policy from . import row_assembly as row_assembly_policy from . import row_camera as row_camera_policy from . import row_category_route as row_category_route_policy from . import row_expression as row_expression_policy from . import row_generation as row_generation_policy from . import row_item as row_item_policy from . import row_location as row_location_policy from . import row_prompt_axes as row_prompt_axes_policy from . import row_pools as row_pool_policy from . import row_rendering as row_rendering_policy from . import row_role_graph as row_role_graph_policy from . import row_route_metadata as row_route_policy from . import row_subject_route as row_subject_route_policy from . import seed_config as seed_policy from . import style_config as style_policy from . import subject_context as subject_context_policy from .hardcore_text_cleanup import ( sanitize_hardcore_axis_values as _sanitize_hardcore_axis_values, sanitize_hardcore_environment_anchors as _sanitize_hardcore_environment_anchors, ) except ImportError: # Allows local smoke tests with `python -c`. import builder_config_route as builder_config_route_policy import builder_prompt_route as builder_prompt_route_policy from category_library import ( compatible_entries as _compatible_entries, compatible_entry as _compatible_entry, find_subcategory as _find_subcategory, load_category_library, merged_field as _merged_field, ) import camera_config as camera_policy import cast_context as cast_context_policy import category_extensions as category_extensions_policy import category_template_metadata as item_template_policy import character_appearance as character_appearance_policy import character_config as character_policy import character_profile as character_profile_policy import character_slot as character_slot_policy import category_cast_config as category_cast_policy import filter_config as filter_policy import generate_prompt_batches as g import generation_profile_config as generation_profile_policy import hardcore_position_config as hardcore_position_policy import location_config as location_policy import pair_builder import pair_cast import pair_options import pov_policy import row_normalization as row_policy import row_assembly as row_assembly_policy import row_camera as row_camera_policy import row_category_route as row_category_route_policy import row_expression as row_expression_policy import row_generation as row_generation_policy import row_item as row_item_policy import row_location as row_location_policy import row_prompt_axes as row_prompt_axes_policy import row_pools as row_pool_policy import row_rendering as row_rendering_policy import row_role_graph as row_role_graph_policy import row_route_metadata as row_route_policy import row_subject_route as row_subject_route_policy import seed_config as seed_policy import style_config as style_policy import subject_context as subject_context_policy from hardcore_text_cleanup import ( sanitize_hardcore_axis_values as _sanitize_hardcore_axis_values, sanitize_hardcore_environment_anchors as _sanitize_hardcore_environment_anchors, ) ROOT_DIR = Path(__file__).resolve().parent PROFILE_DIR = character_profile_policy.PROFILE_DIR BUILTIN_CATEGORIES = category_extensions_policy.BUILTIN_CATEGORIES RANDOM_SUBCATEGORY = "random" SEED_AXIS_SALTS = seed_policy.SEED_AXIS_SALTS SEED_AXIS_ALIASES = seed_policy.SEED_AXIS_ALIASES SEED_LOCK_AXES = seed_policy.SEED_LOCK_AXES SEED_MODE_CHOICES = seed_policy.SEED_MODE_CHOICES ETHNICITY_FILTER_CHOICES = filter_policy.ETHNICITY_FILTER_CHOICES ETHNICITY_LIST_KEYS = filter_policy.ETHNICITY_LIST_KEYS ETHNICITY_BASE_LIST_KEYS = filter_policy.ETHNICITY_BASE_LIST_KEYS EUROPEAN_REGIONAL_LIST_KEYS = filter_policy.EUROPEAN_REGIONAL_LIST_KEYS MEDITERRANEAN_REGIONAL_LIST_KEYS = filter_policy.MEDITERRANEAN_REGIONAL_LIST_KEYS CHARACTER_LABEL_CHOICES = character_policy.CHARACTER_LABEL_CHOICES CHARACTER_AGE_CHOICES = character_policy.CHARACTER_AGE_CHOICES CHARACTER_BODY_CHOICES = character_policy.CHARACTER_BODY_CHOICES CHARACTER_WOMAN_BODY_CHOICES = character_policy.CHARACTER_WOMAN_BODY_CHOICES CHARACTER_MAN_BODY_CHOICES = character_policy.CHARACTER_MAN_BODY_CHOICES CHARACTER_DESCRIPTOR_DETAIL_CHOICES = character_policy.CHARACTER_DESCRIPTOR_DETAIL_CHOICES CHARACTER_PRESENCE_CHOICES = character_policy.CHARACTER_PRESENCE_CHOICES CHARACTER_RANDOM_TOKENS = character_policy.CHARACTER_RANDOM_TOKENS CHARACTER_SLOT_SEED_MAX = character_policy.CHARACTER_SLOT_SEED_MAX CHARACTER_HAIR_COLOR_CHOICES = character_policy.CHARACTER_HAIR_COLOR_CHOICES CHARACTER_HAIR_LENGTH_CHOICES = character_policy.CHARACTER_HAIR_LENGTH_CHOICES CHARACTER_HAIR_STYLE_CHOICES = character_policy.CHARACTER_HAIR_STYLE_CHOICES CHARACTER_EYE_COLOR_CHOICES = character_policy.CHARACTER_EYE_COLOR_CHOICES CAMERA_DETAIL_CHOICES = camera_policy.CAMERA_DETAIL_CHOICES HARDCORE_DETAIL_DENSITY_CHOICES = pair_options.HARDCORE_DETAIL_DENSITY_CHOICES HARDCORE_POSITION_FAMILY_CHOICES = hardcore_position_policy.HARDCORE_POSITION_FAMILY_CHOICES HARDCORE_POSITION_FOCUS_CHOICES = hardcore_position_policy.HARDCORE_POSITION_FOCUS_CHOICES HARDCORE_POSITION_KEY_CHOICES = hardcore_position_policy.HARDCORE_POSITION_KEY_CHOICES HARDCORE_POSITION_FAMILY_SUBCATEGORIES = hardcore_position_policy.HARDCORE_POSITION_FAMILY_SUBCATEGORIES HARDCORE_SOURCE_FAMILY_BY_SUBCATEGORY = hardcore_position_policy.HARDCORE_SOURCE_FAMILY_BY_SUBCATEGORY def _hardcore_source_position_family(subcategory: dict[str, Any], config: dict[str, Any] | None = None) -> str: return hardcore_position_policy.hardcore_source_position_family(subcategory, config) def _hardcore_position_keys(*parts: Any, axis_values: dict[str, Any] | None = None) -> list[str]: return hardcore_position_policy.hardcore_position_keys(*parts, axis_values=axis_values) CAMERA_ORBIT_FRAMING_CHOICES = camera_policy.CAMERA_ORBIT_FRAMING_CHOICES CAMERA_ORBIT_FOCUS_CHOICES = camera_policy.CAMERA_ORBIT_FOCUS_CHOICES GENERIC_POSITIVE_SUFFIX = row_rendering_policy.GENERIC_POSITIVE_SUFFIX SINGLE_TEMPLATE = row_rendering_policy.SINGLE_TEMPLATE COUPLE_TEMPLATE = row_rendering_policy.COUPLE_TEMPLATE GROUP_TEMPLATE = row_rendering_policy.GROUP_TEMPLATE LAYOUT_TEMPLATE = row_rendering_policy.LAYOUT_TEMPLATE CAMERA_MODE_PROMPTS = camera_policy.CAMERA_MODE_PROMPTS CAMERA_COMPACT_LABELS = camera_policy.CAMERA_COMPACT_LABELS CAMERA_SHOT_PROMPTS = camera_policy.CAMERA_SHOT_PROMPTS CAMERA_ANGLE_PROMPTS = camera_policy.CAMERA_ANGLE_PROMPTS CAMERA_LENS_PROMPTS = camera_policy.CAMERA_LENS_PROMPTS CAMERA_DISTANCE_PROMPTS = camera_policy.CAMERA_DISTANCE_PROMPTS CAMERA_ORIENTATION_PROMPTS = camera_policy.CAMERA_ORIENTATION_PROMPTS CAMERA_PHONE_PROMPTS = camera_policy.CAMERA_PHONE_PROMPTS CAMERA_PRIORITY_PROMPTS = camera_policy.CAMERA_PRIORITY_PROMPTS SafeFormatDict = row_rendering_policy.SafeFormatDict def _slug(value: str) -> str: return row_item_policy.slug(value) def _list_from(value: Any) -> list[Any]: if value is None: return [] if isinstance(value, list): return value return [value] def _is_false(value: Any) -> bool: if isinstance(value, bool): return value is False if isinstance(value, str): return value.strip().lower() in ("false", "0", "no", "off") return False def _unique_extend(target: list[Any], additions: list[Any]) -> None: category_extensions_policy.unique_extend(target, additions) def _pair_from(value: Any) -> tuple[str, str]: return row_item_policy.pair_from(value) def _weighted_choice(rng: random.Random, items: list[Any]) -> Any: return row_item_policy.weighted_choice(rng, items) def _entry_text(item: Any) -> str: return row_item_policy.entry_text(item) def _item_text(item: Any) -> str: return row_item_policy.item_text(item) def _item_name(item: Any) -> str: return row_item_policy.item_name(item) def _template_metadata(item: Any) -> dict[str, Any]: return item_template_policy.template_metadata(item) def _template_position_family(metadata: dict[str, Any]) -> str: return item_template_policy.template_position_family(metadata) def _template_position_keys(metadata: dict[str, Any]) -> list[str]: return item_template_policy.template_position_keys(metadata) def _template_action_family(metadata: dict[str, Any]) -> str: return item_template_policy.template_action_family(metadata) def _template_formatter_hints(metadata: dict[str, Any]) -> dict[str, list[str]]: return item_template_policy.formatter_hints(metadata) def _merge_position_keys(primary: list[str], fallback: list[str]) -> list[str]: return item_template_policy.merge_position_keys(primary, fallback) def _action_position_route_metadata( *, is_pose_category: bool, subcategory: dict[str, Any], hardcore_position_config: dict[str, Any] | None, item_template_metadata: dict[str, Any] | None, item_text: Any, source_role_graph: Any, source_composition: Any, pose: Any, item_axis_values: dict[str, Any] | None = None, ) -> dict[str, Any]: return row_route_policy.resolve_action_position_route( is_pose_category=is_pose_category, subcategory=subcategory, hardcore_position_config=hardcore_position_config, item_template_metadata=item_template_metadata, item_text=item_text, source_role_graph=source_role_graph, source_composition=source_composition, pose=pose, item_axis_values=item_axis_values, ) def _action_position_route( *, is_pose_category: bool, subcategory: dict[str, Any], hardcore_position_config: dict[str, Any] | None, item_template_metadata: dict[str, Any] | None, item_text: Any, source_role_graph: Any, source_composition: Any, pose: Any, item_axis_values: dict[str, Any] | None = None, ) -> row_route_policy.ActionPositionRoute: return row_route_policy.resolve_action_position_route_result( is_pose_category=is_pose_category, subcategory=subcategory, hardcore_position_config=hardcore_position_config, item_template_metadata=item_template_metadata, item_text=item_text, source_role_graph=source_role_graph, source_composition=source_composition, pose=pose, item_axis_values=item_axis_values, ) def _oral_acts_for_position(values: list[Any], position: str) -> list[Any]: return row_item_policy.oral_acts_for_position(values, position) def _oral_axis_values_for_context(values: list[Any], position: str, oral_act: str, axis_name: str) -> list[Any]: return row_item_policy.oral_axis_values_for_context(values, position, oral_act, axis_name) def _outercourse_acts_for_position(values: list[Any], position: str) -> list[Any]: return row_item_policy.outercourse_acts_for_position(values, position) def _outercourse_axis_values_for_position(values: list[Any], position: str, axis_name: str) -> list[Any]: return row_item_policy.outercourse_axis_values_for_position(values, position, axis_name) def _anal_axis_values_for_position(values: list[Any], position: str, axis_name: str) -> list[Any]: return row_item_policy.anal_axis_values_for_position(values, position, axis_name) def _compose_item( rng: random.Random, category: dict[str, Any], subcategory: dict[str, Any], item: Any, women_count: int = 1, men_count: int = 1, ) -> tuple[str, str, dict[str, str], dict[str, Any]]: return row_item_policy.compose_item( rng, category, subcategory, item, women_count, men_count, ) def _choose_text(rng: random.Random, items: list[Any]) -> str: return row_item_policy.choose_text(rng, items) def _choose_distinct_text(rng: random.Random, items: list[Any], first_text: str) -> str: return row_item_policy.choose_distinct_text(rng, items, first_text) def _choose_pair(rng: random.Random, items: list[Any]) -> tuple[str, str]: return row_item_policy.choose_pair(rng, items) def _extension_targets() -> dict[str, tuple[list[Any], bool]]: return category_extensions_policy.extension_targets() def apply_pool_extensions() -> None: category_extensions_policy.apply_pool_extensions() def category_choices() -> list[str]: return category_extensions_policy.category_choices() def subcategory_choices() -> list[str]: return category_extensions_policy.subcategory_choices() def seed_mode_choices() -> list[str]: return seed_policy.seed_mode_choices() def seed_reroll_axis_choices() -> list[str]: return seed_policy.seed_reroll_axis_choices() def normalize_seed_mode(value: Any) -> str: return seed_policy.normalize_seed_mode(value) def normalize_reroll_axis(value: Any) -> str: return seed_policy.normalize_reroll_axis(value) CATEGORY_PRESETS = category_cast_policy.CATEGORY_PRESETS CAST_PRESETS = category_cast_policy.CAST_PRESETS GENERATION_PROFILE_PRESETS = generation_profile_policy.GENERATION_PROFILE_PRESETS STYLE_PRESETS = style_policy.STYLE_PRESETS def category_preset_choices() -> list[str]: return category_cast_policy.category_preset_choices() def cast_preset_choices() -> list[str]: return category_cast_policy.cast_preset_choices() def generation_profile_choices() -> list[str]: return generation_profile_policy.generation_profile_choices() def style_pool_preset_choices() -> list[str]: return style_policy.style_pool_preset_choices() def style_combine_mode_choices() -> list[str]: return style_policy.style_combine_mode_choices() def build_category_config_json(preset: str = "auto_weighted", subcategory: str = RANDOM_SUBCATEGORY) -> str: return category_cast_policy.build_category_config_json(preset=preset, subcategory=subcategory) def _parse_category_config(category_config: str | dict[str, Any] | None) -> tuple[str, str]: return category_cast_policy.parse_category_config(category_config) def build_cast_config_json(cast_mode: str = "mixed_couple", women_count: int = 1, men_count: int = 1) -> str: return category_cast_policy.build_cast_config_json(cast_mode=cast_mode, women_count=women_count, men_count=men_count) def _parse_cast_config(cast_config: str | dict[str, Any] | None) -> dict[str, int | str]: return category_cast_policy.parse_cast_config(cast_config) def build_generation_profile_json( profile: str = "balanced", clothing_override: str = "profile_default", poses_override: str = "profile_default", expression_intensity_mode: str = "profile_default", expression_intensity: float = -1.0, backside_bias: float = -1.0, minimal_clothing_ratio: float = -1.0, standard_pose_ratio: float = -1.0, trigger_policy: str = "profile_default", expression_enabled: bool = True, ) -> str: return generation_profile_policy.build_generation_profile_json( profile=profile, clothing_override=clothing_override, poses_override=poses_override, expression_intensity_mode=expression_intensity_mode, expression_intensity=expression_intensity, backside_bias=backside_bias, minimal_clothing_ratio=minimal_clothing_ratio, standard_pose_ratio=standard_pose_ratio, trigger_policy=trigger_policy, expression_enabled=expression_enabled, ) def _parse_generation_profile(profile_config: str | dict[str, Any] | None) -> dict[str, Any]: return generation_profile_policy.parse_generation_profile(profile_config) def build_style_config_json( enabled: bool = True, combine_mode: str = "replace", preset: str = "category_default", custom_style: str = "", custom_positive_suffix: str = "", custom_negative: str = "", style_config: str | dict[str, Any] | None = "", ) -> str: return style_policy.build_style_config_json( enabled=enabled, combine_mode=combine_mode, preset=preset, custom_style=custom_style, custom_positive_suffix=custom_positive_suffix, custom_negative=custom_negative, style_config=style_config, ) def _parse_style_config(style_config: str | dict[str, Any] | None) -> dict[str, Any]: return style_policy.parse_style_config(style_config) def build_filter_config_json( ethnicity: str = "any", figure: str = "curvy", no_plus_women: bool = False, no_black: bool = False, include_european: bool = True, include_mediterranean_mena: bool = True, include_latina: bool = True, include_east_asian: bool = True, include_southeast_asian: bool = True, include_south_asian: bool = True, include_black_african: bool = True, include_indigenous: bool = True, include_mixed: bool = True, include_plus_size: bool = True, ) -> str: return filter_policy.build_filter_config_json( ethnicity=ethnicity, figure=figure, no_plus_women=no_plus_women, no_black=no_black, include_european=include_european, include_mediterranean_mena=include_mediterranean_mena, include_latina=include_latina, include_east_asian=include_east_asian, include_southeast_asian=include_southeast_asian, include_south_asian=include_south_asian, include_black_african=include_black_african, include_indigenous=include_indigenous, include_mixed=include_mixed, include_plus_size=include_plus_size, ) LOCATION_POOL_PRESETS = location_policy.LOCATION_POOL_PRESETS COMPOSITION_POOL_PRESETS = location_policy.COMPOSITION_POOL_PRESETS COMPOSITION_INLINE_PRESETS = location_policy.COMPOSITION_INLINE_PRESETS THEMATIC_LOCATION_PRESETS = location_policy.THEMATIC_LOCATION_PRESETS def location_pool_preset_choices() -> list[str]: return location_policy.location_pool_preset_choices() def composition_pool_preset_choices() -> list[str]: return location_policy.composition_pool_preset_choices() def location_theme_choices() -> list[str]: return location_policy.location_theme_choices() def _location_pool_names_for_preset(preset: str) -> list[str]: return location_policy.location_pool_names_for_preset(preset) def _custom_location_entries(custom_locations: str) -> list[dict[str, str]]: return location_policy.custom_location_entries(custom_locations) def _scene_entries_for_pool_names(pool_names: list[str]) -> list[Any]: return location_policy.scene_entries_for_pool_names(pool_names) def build_location_pool_json( enabled: bool = True, combine_mode: str = "replace", preset: str = "custom_only", custom_locations: str = "", location_config: str | dict[str, Any] | None = "", ) -> str: return location_policy.build_location_pool_json( enabled=enabled, combine_mode=combine_mode, preset=preset, custom_locations=custom_locations, location_config=location_config, ) def _parse_location_config(location_config: str | dict[str, Any] | None) -> dict[str, Any]: return location_policy.parse_location_config(location_config) def _location_config_active(location_config: dict[str, Any]) -> bool: return location_policy.location_config_active(location_config) def _composition_pool_names_for_preset(preset: str) -> list[str]: return location_policy.composition_pool_names_for_preset(preset) def _custom_composition_entries(custom_compositions: str) -> list[str]: return location_policy.custom_composition_entries(custom_compositions) def _composition_entries_for_pool_names(pool_names: list[str]) -> list[Any]: return location_policy.composition_entries_for_pool_names(pool_names) def build_composition_pool_json( enabled: bool = True, combine_mode: str = "replace", preset: str = "custom_only", custom_compositions: str = "", composition_config: str | dict[str, Any] | None = "", ) -> str: return location_policy.build_composition_pool_json( enabled=enabled, combine_mode=combine_mode, preset=preset, custom_compositions=custom_compositions, composition_config=composition_config, ) def _parse_composition_config(composition_config: str | dict[str, Any] | None) -> dict[str, Any]: return location_policy.parse_composition_config(composition_config) def _composition_config_active(composition_config: dict[str, Any]) -> bool: return location_policy.composition_config_active(composition_config) def build_thematic_location_json( enabled: bool = True, combine_mode: str = "replace", theme: str = "semi_public_affair", custom_locations: str = "", custom_compositions: str = "", location_config: str | dict[str, Any] | None = "", composition_config: str | dict[str, Any] | None = "", ) -> tuple[str, str, str]: return location_policy.build_thematic_location_json( enabled=enabled, combine_mode=combine_mode, theme=theme, custom_locations=custom_locations, custom_compositions=custom_compositions, location_config=location_config, composition_config=composition_config, ) def _ethnicity_text_from_value(value: Any) -> str: return filter_policy.ethnicity_text_from_value(value) def _is_valid_ethnicity_filter(value: Any) -> bool: return filter_policy.is_valid_ethnicity_filter(value) def normalize_ethnicity_filter(value: Any, default: str = "any", allow_random: bool = False) -> str: return filter_policy.normalize_ethnicity_filter(value, default, allow_random) def build_ethnicity_list_json( include_european: bool = False, include_mediterranean_mena: bool = False, include_latina: bool = False, include_east_asian: bool = False, include_southeast_asian: bool = False, include_south_asian: bool = False, include_black_african: bool = False, include_indigenous: bool = False, include_mixed: bool = False, include_asian: bool = False, include_white_asian: bool = False, include_western_european: bool = False, include_french_european: bool = False, include_germanic_european: bool = False, include_nordic_european: bool = False, include_celtic_european: bool = False, include_slavic_european: bool = False, include_baltic_european: bool = False, include_alpine_european: bool = False, include_balkan_european: bool = False, include_greek_mediterranean: bool = False, include_italian_mediterranean: bool = False, include_iberian_mediterranean: bool = False, strict_excludes: bool = True, ) -> dict[str, str]: return filter_policy.build_ethnicity_list_json( include_european=include_european, include_mediterranean_mena=include_mediterranean_mena, include_latina=include_latina, include_east_asian=include_east_asian, include_southeast_asian=include_southeast_asian, include_south_asian=include_south_asian, include_black_african=include_black_african, include_indigenous=include_indigenous, include_mixed=include_mixed, include_asian=include_asian, include_white_asian=include_white_asian, include_western_european=include_western_european, include_french_european=include_french_european, include_germanic_european=include_germanic_european, include_nordic_european=include_nordic_european, include_celtic_european=include_celtic_european, include_slavic_european=include_slavic_european, include_baltic_european=include_baltic_european, include_alpine_european=include_alpine_european, include_balkan_european=include_balkan_european, include_greek_mediterranean=include_greek_mediterranean, include_italian_mediterranean=include_italian_mediterranean, include_iberian_mediterranean=include_iberian_mediterranean, strict_excludes=strict_excludes, ) def _parse_filter_config(filter_config: str | dict[str, Any] | None) -> dict[str, Any]: return filter_policy.parse_filter_config(filter_config) def _normalize_hardcore_position_family(value: Any, default: str = "any") -> str: return hardcore_position_policy.normalize_hardcore_position_family(value, default) def _normalize_hardcore_position_values(values: Any) -> list[str]: return hardcore_position_policy.normalize_hardcore_position_values(values) def _empty_hardcore_position_config() -> dict[str, Any]: return hardcore_position_policy.empty_hardcore_position_config() def _parse_hardcore_position_config(value: str | dict[str, Any] | None) -> dict[str, Any]: return hardcore_position_policy.parse_hardcore_position_config(value) def _hardcore_position_summary(config: dict[str, Any]) -> str: return hardcore_position_policy.hardcore_position_summary(config) def _axis_values_with_krea2_variant_keys( axis_values: dict[str, Any], hardcore_position_config: dict[str, Any], ) -> dict[str, Any]: variant_keys = hardcore_position_config.get("krea2_variant_keys") if isinstance(hardcore_position_config, dict) else [] if not isinstance(variant_keys, list) or not variant_keys: return axis_values merged = dict(axis_values) merged["krea2_variant_keys"] = [str(key) for key in variant_keys if str(key).strip()] return merged def build_hardcore_position_pool_json( hardcore_position_config: str | dict[str, Any] | None = "", combine_mode: str = "replace", family: str = "any", selected_positions: list[str] | tuple[str, ...] | str | None = None, ) -> str: return hardcore_position_policy.build_hardcore_position_pool_json( hardcore_position_config=hardcore_position_config, combine_mode=combine_mode, family=family, selected_positions=selected_positions, ) def build_hardcore_action_filter_json( hardcore_position_config: str | dict[str, Any] | None = "", focus: str = "keep_pool", allow_toys: bool = False, allow_double: bool = False, allow_penetration: bool = True, allow_foreplay: bool = True, allow_interaction: bool = True, allow_manual: bool = True, allow_oral: bool = True, allow_outercourse: bool = True, allow_anal: bool = True, allow_climax: bool = True, ) -> str: return hardcore_position_policy.build_hardcore_action_filter_json( hardcore_position_config=hardcore_position_config, focus=focus, allow_toys=allow_toys, allow_double=allow_double, allow_penetration=allow_penetration, allow_foreplay=allow_foreplay, allow_interaction=allow_interaction, allow_manual=allow_manual, allow_oral=allow_oral, allow_outercourse=allow_outercourse, allow_anal=allow_anal, allow_climax=allow_climax, ) def _hardcore_position_config_active(config: dict[str, Any]) -> bool: return hardcore_position_policy.hardcore_position_config_active(config) def _is_hardcore_sexual_category(category: dict[str, Any]) -> bool: return hardcore_position_policy.is_hardcore_sexual_category(category) def _filter_hardcore_categories_for_position( categories: list[dict[str, Any]], config: dict[str, Any], women_count: int, men_count: int, ) -> list[dict[str, Any]]: return hardcore_position_policy.filter_hardcore_categories_for_position( categories, config, women_count, men_count, _compatible_entry, ) def _apply_hardcore_position_config_to_subcategory( subcategory: dict[str, Any], config: dict[str, Any], ) -> dict[str, Any]: return hardcore_position_policy.apply_hardcore_position_config_to_subcategory(subcategory, config) def _ratio_or_none(value: float) -> float | None: return row_generation_policy.ratio_or_none(value) def _clamped_float(value: Any, default: float = 0.5, min_value: float = 0.0, max_value: float = 1.0) -> float: return row_generation_policy.clamped_float(value, default, min_value, max_value) def build_seed_config_json( category_seed: int = -1, subcategory_seed: int = -1, content_seed: int = -1, person_seed: int = -1, scene_seed: int = -1, pose_seed: int = -1, role_seed: int = -1, expression_seed: int = -1, composition_seed: int = -1, category_seed_mode: str = "auto", subcategory_seed_mode: str = "auto", content_seed_mode: str = "auto", person_seed_mode: str = "auto", scene_seed_mode: str = "auto", pose_seed_mode: str = "auto", role_seed_mode: str = "auto", expression_seed_mode: str = "auto", composition_seed_mode: str = "auto", ) -> str: return seed_policy.build_seed_config_json( category_seed=category_seed, subcategory_seed=subcategory_seed, content_seed=content_seed, person_seed=person_seed, scene_seed=scene_seed, pose_seed=pose_seed, role_seed=role_seed, expression_seed=expression_seed, composition_seed=composition_seed, category_seed_mode=category_seed_mode, subcategory_seed_mode=subcategory_seed_mode, content_seed_mode=content_seed_mode, person_seed_mode=person_seed_mode, scene_seed_mode=scene_seed_mode, pose_seed_mode=pose_seed_mode, role_seed_mode=role_seed_mode, expression_seed_mode=expression_seed_mode, composition_seed_mode=composition_seed_mode, ) def build_seed_lock_config_json( base_seed: int = 20260614, reroll_axis: str = "none", reroll_seed: int = -1, ) -> str: return seed_policy.build_seed_lock_config_json( base_seed=base_seed, reroll_axis=reroll_axis, reroll_seed=reroll_seed, ) def _parse_seed_config(seed_config: str | dict[str, Any] | None) -> dict[str, int]: return seed_policy.parse_seed_config(seed_config) def _configured_axis_seed(seed_config: dict[str, int], axis: str) -> int | None: return seed_policy.configured_axis_seed(seed_config, axis) def _axis_rng(seed_config: dict[str, int], axis: str, base_seed: int, row_number: int) -> random.Random: return seed_policy.axis_rng(seed_config, axis, base_seed, row_number) def _is_pose_content_category(category: dict[str, Any], subcategory: dict[str, Any]) -> bool: return row_category_route_policy.is_pose_content_category(category, subcategory) def _select_category_item_route( *, category_choice: str, subcategory_choice: str, seed_config: dict[str, int], seed: int, row_number: int, women_count: int, men_count: int, hardcore_position_config: dict[str, Any] | None = None, categories: list[dict[str, Any]] | None = None, ) -> dict[str, Any]: return row_category_route_policy.select_category_item_route( category_choice=category_choice, subcategory_choice=subcategory_choice, seed_config=seed_config, seed=seed, row_number=row_number, women_count=women_count, men_count=men_count, hardcore_position_config=hardcore_position_config, categories=categories, ) def _select_category_item_route_result( *, category_choice: str, subcategory_choice: str, seed_config: dict[str, int], seed: int, row_number: int, women_count: int, men_count: int, hardcore_position_config: dict[str, Any] | None = None, categories: list[dict[str, Any]] | None = None, ) -> row_category_route_policy.CategoryItemRoute: return row_category_route_policy.select_category_item_route_result( category_choice=category_choice, subcategory_choice=subcategory_choice, seed_config=seed_config, seed=seed, row_number=row_number, women_count=women_count, men_count=men_count, hardcore_position_config=hardcore_position_config, categories=categories, ) def _format(template: str, context: dict[str, Any]) -> str: return row_rendering_policy.format_template(template, context) def _row_text_fields( category: dict[str, Any], subcategory: dict[str, Any], item: Any, style_config: str | dict[str, Any] | None = None, ) -> row_rendering_policy.RowTextFields: return row_rendering_policy.resolve_row_text_fields(category, subcategory, item, style_config) def _clean_prompt_punctuation(text: str) -> str: return row_expression_policy.clean_prompt_punctuation(text) def _strip_expression_text(text: str, expression: Any = "") -> str: return row_expression_policy.strip_expression_text(text, expression) def _disable_row_expression(row: dict[str, Any], source: str = "disabled") -> dict[str, Any]: return row_expression_policy.disable_row_expression(row, source) def _prepend_trigger(prompt: str, trigger: str, enabled: bool) -> str: return row_policy.prepend_trigger(prompt, trigger, enabled) def _combined_negative(base: str, extra: str) -> str: return row_policy.combined_negative(base, extra) def camera_mode_choices() -> list[str]: return camera_policy.camera_mode_choices() def ethnicity_choices() -> list[str]: return list(ETHNICITY_FILTER_CHOICES) def character_label_choices() -> list[str]: return character_policy.character_label_choices() def character_age_choices() -> list[str]: return character_policy.character_age_choices() def character_body_choices() -> list[str]: return character_policy.character_body_choices() def character_woman_body_choices() -> list[str]: return character_policy.character_woman_body_choices() def character_man_body_choices() -> list[str]: return character_policy.character_man_body_choices() def character_descriptor_detail_choices() -> list[str]: return character_policy.character_descriptor_detail_choices() def character_presence_choices() -> list[str]: return character_policy.character_presence_choices() def character_hair_color_choices() -> list[str]: return character_policy.character_hair_color_choices() def character_hair_length_choices() -> list[str]: return character_policy.character_hair_length_choices() def character_hair_style_choices() -> list[str]: return character_policy.character_hair_style_choices() def character_eye_color_choices() -> list[str]: return character_policy.character_eye_color_choices() def character_ethnicity_choices() -> list[str]: return ["random"] + list(ETHNICITY_FILTER_CHOICES) def character_figure_choices() -> list[str]: return character_policy.character_figure_choices() def camera_detail_choices() -> list[str]: return camera_policy.camera_detail_choices() def hardcore_detail_density_choices() -> list[str]: return pair_options.hardcore_detail_density_choices() def hardcore_position_family_choices() -> list[str]: return hardcore_position_policy.hardcore_position_family_choices() def hardcore_position_focus_choices() -> list[str]: return hardcore_position_policy.hardcore_position_focus_choices() def hardcore_position_key_choices() -> list[str]: return hardcore_position_policy.hardcore_position_key_choices() def character_softcore_outfit_source_choices() -> list[str]: return [ "no_change", "social_tease", "lingerie_tease", "implied_nude", "explicit_tease", "explicit_nude", "partner_woman", "partner_man", "custom", ] def character_hardcore_clothing_state_choices() -> list[str]: return [ "no_change", "fully_nude", "partly_exposed", "same_outfit", "partially_removed", "custom", ] def camera_orbit_framing_choices() -> list[str]: return camera_policy.camera_orbit_framing_choices() def camera_orbit_focus_choices() -> list[str]: return camera_policy.camera_orbit_focus_choices() def camera_shot_choices() -> list[str]: return camera_policy.camera_shot_choices() def camera_angle_choices() -> list[str]: return camera_policy.camera_angle_choices() def camera_lens_choices() -> list[str]: return camera_policy.camera_lens_choices() def camera_distance_choices() -> list[str]: return camera_policy.camera_distance_choices() def camera_orientation_choices() -> list[str]: return camera_policy.camera_orientation_choices() def camera_phone_choices() -> list[str]: return camera_policy.camera_phone_choices() def camera_priority_choices() -> list[str]: return camera_policy.camera_priority_choices() def build_camera_config_json( camera_mode: str = "standard", shot_size: str = "auto", angle: str = "auto", lens: str = "auto", distance: str = "auto", orientation: str = "auto", phone_visibility: str = "auto", priority: str = "strong", camera_detail: str = "compact", ) -> str: return camera_policy.build_camera_config_json( camera_mode=camera_mode, shot_size=shot_size, angle=angle, lens=lens, distance=distance, orientation=orientation, phone_visibility=phone_visibility, priority=priority, camera_detail=camera_detail, ) def _camera_orbit_direction(horizontal_angle: Any) -> str: return camera_policy._camera_orbit_direction(horizontal_angle) def _camera_orbit_elevation(vertical_angle: Any) -> str: return camera_policy._camera_orbit_elevation(vertical_angle) def _camera_orbit_distance(zoom: Any, framing: str = "from_zoom") -> str: return camera_policy._camera_orbit_distance(zoom, framing) def _camera_orbit_focus(subject_focus: str) -> str: return camera_policy._camera_orbit_focus(subject_focus) def _camera_orbit_prompt( horizontal_angle: Any, vertical_angle: Any, zoom: Any, framing: str = "from_zoom", subject_focus: str = "auto", include_degrees: bool = True, ) -> tuple[str, dict[str, Any]]: return camera_policy.camera_orbit_prompt( horizontal_angle, vertical_angle, zoom, framing=framing, subject_focus=subject_focus, include_degrees=include_degrees, ) def build_camera_orbit_config_json( enabled: bool = True, camera_mode: str = "standard", horizontal_angle: int = 0, vertical_angle: int = 0, zoom: float = 5.0, framing: str = "from_zoom", subject_focus: str = "auto", lens: str = "auto", orientation: str = "auto", phone_visibility: str = "auto", priority: str = "locked", camera_detail: str = "compact", include_degrees: bool = True, ) -> str: return camera_policy.build_camera_orbit_config_json( enabled=enabled, camera_mode=camera_mode, horizontal_angle=horizontal_angle, vertical_angle=vertical_angle, zoom=zoom, framing=framing, subject_focus=subject_focus, lens=lens, orientation=orientation, phone_visibility=phone_visibility, priority=priority, camera_detail=camera_detail, include_degrees=include_degrees, ) QWEN_CAMERA_DIRECTIONS = camera_policy.QWEN_CAMERA_DIRECTIONS QWEN_CAMERA_ELEVATIONS = camera_policy.QWEN_CAMERA_ELEVATIONS QWEN_CAMERA_ZOOMS = camera_policy.QWEN_CAMERA_ZOOMS QWEN_CAMERA_SCENE_CENTER_Y = camera_policy.QWEN_CAMERA_SCENE_CENTER_Y def _qwen_prompt_camera_values(qwen_prompt: Any) -> tuple[int, int, float]: return camera_policy._qwen_prompt_camera_values(qwen_prompt) def _camera_info_dict(camera_info: Any) -> dict[str, Any] | None: return camera_policy._camera_info_dict(camera_info) def _qwen_camera_info_values(camera_info: Any) -> tuple[int, int, float] | None: return camera_policy._qwen_camera_info_values(camera_info) def build_qwen_camera_config_json( qwen_prompt: str = "", camera_info: Any = None, prefer_camera_info: bool = True, camera_mode: str = "standard", subject_focus: str = "auto", lens: str = "auto", orientation: str = "auto", phone_visibility: str = "auto", priority: str = "locked", camera_detail: str = "compact", include_degrees: bool = False, suppress_phone_visibility: bool = True, ) -> str: return camera_policy.build_qwen_camera_config_json( qwen_prompt=qwen_prompt, camera_info=camera_info, prefer_camera_info=prefer_camera_info, camera_mode=camera_mode, subject_focus=subject_focus, lens=lens, orientation=orientation, phone_visibility=phone_visibility, priority=priority, camera_detail=camera_detail, include_degrees=include_degrees, suppress_phone_visibility=suppress_phone_visibility, ) def _choice(value: Any, choices: dict[str, str], default: str) -> str: return camera_policy._choice(value, choices, default) def _parse_camera_config(camera_config: str | dict[str, Any] | None) -> dict[str, Any]: return camera_policy.parse_camera_config(camera_config) def _camera_config_with_mode(camera_config: str | dict[str, Any] | None, camera_mode: str) -> dict[str, Any]: return camera_policy.camera_config_with_mode(camera_config, camera_mode) def _camera_directive(camera_config: str | dict[str, Any] | None) -> tuple[str, dict[str, Any]]: return camera_policy.camera_directive(camera_config) def _insert_positive_directive(prompt: str, directive: str) -> str: return row_camera_policy.insert_positive_directive(prompt, directive) def _camera_caption_text(parsed: dict[str, Any]) -> str: return row_camera_policy.camera_caption_text(parsed) def _coworking_composition_prompt(scene_text: Any, composition: Any, subject_kind: str = "subjects") -> str: return row_camera_policy.coworking_composition_prompt(scene_text, composition, subject_kind) def _apply_coworking_composition(row: dict[str, Any], subject_kind: str) -> dict[str, Any]: return row_camera_policy.apply_contextual_composition(row, subject_kind) def _camera_scene_directive_for_context( scene_text: Any, composition: Any, camera_config: str | dict[str, Any] | None, pov_labels: list[str] | None = None, subject_kind: str = "subjects", ) -> tuple[str, dict[str, Any]]: directive, parsed = row_camera_policy.camera_scene_directive_for_context( scene_text, composition, camera_config, pov_labels, subject_kind, CAMERA_COMPACT_LABELS, ) return directive, parsed def _row_camera_subject_kind(row: dict[str, Any]) -> str: return row_camera_policy.row_camera_subject_kind(row) def _camera_pov_labels_for_row(row: dict[str, Any]) -> list[str]: return _pov_character_labels( _character_slot_label_map(_parse_character_cast(row.get("character_cast_slots"))), int(row.get("men_count") or 0) if str(row.get("men_count") or "").isdigit() else 0, ) def _apply_camera_config(row: dict[str, Any], camera_config: str | dict[str, Any] | None) -> dict[str, Any]: return row_camera_policy.apply_camera_config( row, camera_config, pov_label_resolver=_camera_pov_labels_for_row, compact_labels=CAMERA_COMPACT_LABELS, ) def _row_seed(seed: int, row_number: int, salt: int = 0) -> int: return seed_policy.row_seed(seed, row_number, salt) def _pick_clothing_mode(rng: random.Random, clothing: str, minimal_ratio: float | None) -> str: return row_generation_policy.pick_clothing_mode(rng, clothing, minimal_ratio) def _pick_pose_mode(rng: random.Random, poses: str, standard_ratio: float | None) -> str: return row_generation_policy.pick_pose_mode(rng, poses, standard_ratio) def _pick_figure_bias(rng: random.Random, figure: str) -> str: return row_generation_policy.pick_figure_bias(rng, figure) def _pick_expression_intensity(rng: random.Random, expression_intensity: Any) -> tuple[float, str]: return row_generation_policy.pick_expression_intensity(rng, expression_intensity) def _build_auto_weighted_row( row_number: int, start_index: int, clothing: str, ethnicity: str, poses: str, backside_bias: float, figure: str, no_plus_women: bool, no_black: bool, minimal_clothing_ratio: float | None, standard_pose_ratio: float | None, seed: int, ) -> dict[str, Any]: return row_generation_policy.build_auto_weighted_row( row_number, start_index, clothing, ethnicity, poses, backside_bias, figure, no_plus_women, no_black, minimal_clothing_ratio, standard_pose_ratio, seed, ) def _build_direct_builtin_row( category: str, row_number: int, start_index: int, clothing: str, ethnicity: str, poses: str, backside_bias: float, figure: str, no_plus_women: bool, no_black: bool, minimal_clothing_ratio: float | None, standard_pose_ratio: float | None, seed: int, ) -> dict[str, Any]: return row_generation_policy.build_direct_builtin_row( category, row_number, start_index, clothing, ethnicity, poses, backside_bias, figure, no_plus_women, no_black, minimal_clothing_ratio, standard_pose_ratio, seed, ) def _auto_full_choice(seed_config: dict[str, int], seed: int, row_number: int) -> str: return row_generation_policy.auto_full_choice(seed_config, seed, row_number) def _body_phrase(body: Any, figure_note: Any = "") -> str: return character_profile_policy.body_phrase(body, figure_note) def _safe_profile_name(profile_name: str) -> str: return character_profile_policy.safe_profile_name(profile_name) def _profile_path(profile_name: str) -> Path: return character_profile_policy.profile_path(profile_name) def character_profile_choices() -> list[str]: return character_profile_policy.character_profile_choices() def _load_json_object(value: str | dict[str, Any] | None, label: str) -> dict[str, Any]: return character_profile_policy.load_json_object(value, label) CHARACTER_MANUAL_FIELDS = character_profile_policy.CHARACTER_MANUAL_FIELDS def _parse_character_manual_config(value: str | dict[str, Any] | None) -> dict[str, str]: return character_profile_policy.parse_character_manual_config(value) def _character_manual_summary(config: dict[str, str]) -> str: return character_profile_policy.character_manual_summary(config) def build_character_manual_config_json( manual: str | dict[str, Any] | None = "", combine_mode: str = "merge_nonempty", manual_age: str = "", manual_body: str = "", body_phrase: str = "", skin: str = "", hair: str = "", eyes: str = "", softcore_outfit: str = "", hardcore_clothing: str = "", ) -> str: return character_profile_policy.build_character_manual_config_json( manual=manual, combine_mode=combine_mode, manual_age=manual_age, manual_body=manual_body, body_phrase=body_phrase, skin=skin, hair=hair, eyes=eyes, softcore_outfit=softcore_outfit, hardcore_clothing=hardcore_clothing, ) def _slot_value(value: Any) -> str: return character_policy.slot_value(value) CHARACTER_CHARACTERISTIC_AXES = character_policy.CHARACTER_CHARACTERISTIC_AXES def _empty_characteristics_config() -> dict[str, Any]: return character_policy.empty_characteristics_config() def _normalize_characteristic_choice(value: Any, choices: list[str] | tuple[str, ...]) -> str: return character_policy.normalize_characteristic_choice(value, choices) def _normalize_characteristic_values( values: Any, choices: list[str] | tuple[str, ...] | None = None, *, allow_free_text: bool = False, ) -> list[str]: return character_policy.normalize_characteristic_values(values, choices, allow_free_text=allow_free_text) def _parse_characteristics_config(value: str | dict[str, Any] | None) -> dict[str, Any]: return character_policy.parse_characteristics_config(value) def _characteristics_summary(config: dict[str, Any]) -> str: return character_policy.characteristics_summary(config) def build_characteristics_config_json( characteristics: str | dict[str, Any] | None = "", axis: str = "ages", selected_values: list[str] | tuple[str, ...] | str | None = None, combine_mode: str = "replace_axis", ) -> str: return character_policy.build_characteristics_config_json( characteristics=characteristics, axis=axis, selected_values=selected_values, combine_mode=combine_mode, ) def _characteristic_choice(config: dict[str, Any], key: str, rng: random.Random) -> str: return character_policy.characteristic_choice(config, key, rng) def _eye_phrase_from_key(key: str) -> str: return character_policy.eye_phrase_from_key(key) def _normalize_descriptor_detail(value: Any) -> str: return character_policy.normalize_descriptor_detail(value) def _normalize_presence_mode(value: Any, subject_type: str) -> str: return character_policy.normalize_presence_mode(value, subject_type) def _slot_is_pov(slot: dict[str, Any] | None) -> bool: return pov_policy.slot_is_pov(slot) def _normalize_slot_expression_intensity(value: Any) -> float: return character_slot_policy.normalize_slot_expression_intensity(value) def _slot_expression_enabled(slot: dict[str, Any] | None) -> bool: return character_slot_policy.slot_expression_enabled(slot) def _slot_expression_intensity(slot: dict[str, Any] | None) -> float | None: return character_slot_policy.slot_expression_intensity(slot) def _slot_expression_intensity_for_phase(slot: dict[str, Any] | None, phase: str = "") -> float | None: return character_slot_policy.slot_expression_intensity_for_phase(slot, phase) def _normalize_slot_seed(value: Any) -> int: return character_policy.normalize_slot_seed(value) def _slot_seed(slot: dict[str, Any] | None) -> int: return character_slot_policy.slot_seed(slot) def _slot_seeded_rng(slot: dict[str, Any] | None, salt: int) -> random.Random | None: return character_slot_policy.slot_seeded_rng(slot, salt) def _slot_context_rng(slot: dict[str, Any], fallback_rng: random.Random) -> random.Random: return character_slot_policy.slot_context_rng(slot, fallback_rng) def _slot_effective_figure( slot: dict[str, Any], subject_type: str, fallback_figure: str, ) -> str: return character_slot_policy.slot_effective_figure(slot, subject_type, fallback_figure) def _cast_expression_intensity_override( fallback: float, label_map: dict[str, dict[str, Any]], women_count: int, men_count: int, expression_phase: str = "", ) -> tuple[float | None, str]: return row_expression_policy.cast_expression_intensity_override( fallback, label_map, women_count, men_count, expression_phase, ) def _resolve_expression_route( *, expression_enabled: bool, expression_intensity: float, expression_intensity_source: str, subject_type: str, applied_slot: dict[str, Any] | None = None, character_slots: list[dict[str, Any]] | None = None, character_slot_map: dict[str, dict[str, Any]] | None = None, women_count: int = 1, men_count: int = 1, expression_phase: str = "", ) -> row_expression_policy.ExpressionRoute: return row_expression_policy.resolve_expression_route( expression_enabled=expression_enabled, expression_intensity=expression_intensity, expression_intensity_source=expression_intensity_source, subject_type=subject_type, applied_slot=applied_slot, character_slots=character_slots, character_slot_map=character_slot_map, women_count=women_count, men_count=men_count, expression_phase=expression_phase, ) def _character_expression_entries( rng: random.Random, expression_pool: list[Any], fallback_intensity: float, label_map: dict[str, dict[str, Any]], women_count: int, men_count: int, expression_phase: str = "", ) -> list[str]: return row_expression_policy.character_expression_entries( rng, expression_pool, fallback_intensity, label_map, women_count, men_count, expression_phase, ) def _sanitize_character_expression_text_for_action( expression_text: str, role_graph: Any, item: Any, axis_values: Any = None, ) -> str: return row_expression_policy.sanitize_character_expression_text_for_action( expression_text, role_graph, item, axis_values, ) def _descriptor_detail_for_subject(subject: Any, descriptor_detail: Any) -> str: return character_profile_policy.descriptor_detail_for_subject(subject, descriptor_detail) def _descriptor_from_parts( subject: Any, age: Any, body_phrase: Any, skin: Any, hair: Any, eyes: Any, descriptor_detail: Any = "auto", ) -> str: return character_profile_policy.descriptor_from_parts( subject, age, body_phrase, skin, hair, eyes, descriptor_detail, ) def _slot_manual_or_choice(choice: str, manual_value: str) -> str: return character_slot_policy.slot_manual_or_choice(choice, manual_value) def _normalize_slot_ethnicity(value: Any) -> str: return character_slot_policy.normalize_slot_ethnicity(value) def _normalize_hair_choice(value: Any, choices: list[str]) -> str: return character_policy.normalize_hair_choice(value, choices) def _infer_hair_color_key(text: Any) -> str: return character_policy.infer_hair_color_key(text) def _infer_hair_length_key(text: Any) -> str: return character_policy.infer_hair_length_key(text) def _infer_hair_style_key(text: Any) -> str: return character_policy.infer_hair_style_key(text) def _choose_hair_key(rng: random.Random, choices: list[str]) -> str: return character_policy.choose_hair_key(rng, choices) def _normalize_hair_values(values: Any, choices: list[str]) -> list[str]: return character_policy.normalize_hair_values(values, choices) def _empty_hair_config() -> dict[str, Any]: return character_policy.empty_hair_config() def _parse_hair_config(value: str | dict[str, Any] | None) -> dict[str, Any]: return character_policy.parse_hair_config(value) def _hair_config_summary(config: dict[str, Any]) -> str: return character_policy.hair_config_summary(config) def build_hair_config_json( hair_config: str | dict[str, Any] | None = "", axis: str = "color", selected_values: list[str] | tuple[str, ...] | str | None = None, combine_mode: str = "replace_axis", ) -> str: return character_policy.build_hair_config_json( hair_config=hair_config, axis=axis, selected_values=selected_values, combine_mode=combine_mode, ) def _hair_color_text(key: str) -> str: return character_policy.hair_color_text(key) def _hair_length_text(key: str) -> str: return character_policy.hair_length_text(key) def _hair_phrase_from_parts(color_key: str, length_key: str, style_key: str) -> str: return character_policy.hair_phrase_from_parts(color_key, length_key, style_key) def _hair_descriptor_from_slot(base_hair: Any, slot: dict[str, Any], rng: random.Random) -> str: return character_appearance_policy.hair_descriptor_from_slot(base_hair, slot, rng) def _normalize_character_slot(slot: dict[str, Any]) -> dict[str, Any]: return character_slot_policy.normalize_character_slot(slot) def _parse_character_cast(character_cast: str | dict[str, Any] | list[Any] | None) -> list[dict[str, Any]]: return character_slot_policy.parse_character_cast(character_cast) def _character_slot_summary(slot: dict[str, Any]) -> str: return character_slot_policy.character_slot_summary(slot) def build_character_slot_json( subject_type: str = "woman", label: str = "auto_chain", slot_seed: int = -1, age: str = "random", manual_age: str = "", manual: str | dict[str, Any] | None = "", ethnicity: str = "random", figure: str = "random", body: str = "random", manual_body: str = "", body_phrase: str = "", skin: str = "", hair: str = "", characteristics: str | dict[str, Any] | None = "", hair_config: str | dict[str, Any] | None = "", hair_color: str = "random", hair_length: str = "random", hair_style: str = "random", eyes: str = "", descriptor_detail: str = "auto", expression_enabled: bool = True, expression_intensity: float = -1.0, enabled: bool = True, character_cast: str | dict[str, Any] | list[Any] | None = "", presence_mode: str = "visible", softcore_expression_intensity: float = -1.0, hardcore_expression_intensity: float = -1.0, softcore_outfit: str = "", hardcore_clothing: str = "", ) -> dict[str, str]: return character_slot_policy.build_character_slot_json( subject_type=subject_type, label=label, slot_seed=slot_seed, age=age, manual_age=manual_age, manual=manual, ethnicity=ethnicity, figure=figure, body=body, manual_body=manual_body, body_phrase=body_phrase, skin=skin, hair=hair, characteristics=characteristics, hair_config=hair_config, hair_color=hair_color, hair_length=hair_length, hair_style=hair_style, eyes=eyes, descriptor_detail=descriptor_detail, expression_enabled=expression_enabled, expression_intensity=expression_intensity, enabled=enabled, character_cast=character_cast, presence_mode=presence_mode, softcore_expression_intensity=softcore_expression_intensity, hardcore_expression_intensity=hardcore_expression_intensity, softcore_outfit=softcore_outfit, hardcore_clothing=hardcore_clothing, ) def _slot_explicit_label(slot: dict[str, Any]) -> str: return cast_context_policy.explicit_character_slot_label(slot) def _character_slot_label_map(slots: list[dict[str, Any]]) -> dict[str, dict[str, Any]]: return cast_context_policy.character_slot_label_map(slots) def _pov_character_labels( label_map: dict[str, dict[str, Any]], men_count: int | None = None, ) -> list[str]: return pov_policy.pov_character_labels(label_map, men_count) def _pov_text_with_viewer(text: Any, pov_labels: list[str]) -> str: return pov_policy.pov_text_with_viewer(text, pov_labels) def _pov_role_graph_prompt(role_graph: Any, pov_labels: list[str]) -> str: return pov_policy.pov_role_graph_prompt(role_graph, pov_labels) def _pov_prompt_directive(pov_labels: list[str]) -> str: return pov_policy.pov_prompt_directive(pov_labels) def _pov_composition_prompt(composition: Any, pov_labels: list[str]) -> str: return pov_policy.pov_composition_prompt(composition, pov_labels) def _slot_softcore_outfit(slot: dict[str, Any] | None, rng: random.Random | None = None) -> str: return character_appearance_policy.slot_softcore_outfit(slot, rng) def _slot_hardcore_clothing(slot: dict[str, Any] | None, rng: random.Random | None = None) -> str: return character_appearance_policy.slot_hardcore_clothing(slot, rng) def _context_from_character_slot( rng: random.Random, slot: dict[str, Any], subject_type: str, ethnicity: str, figure: str, no_plus_women: bool, no_black: bool, ) -> dict[str, str]: return character_appearance_policy.context_from_character_slot( rng, slot, subject_type, ethnicity, figure, no_plus_women, no_black, ) def _character_context_for_label( label: str, label_map: dict[str, dict[str, Any]], rng: random.Random, ethnicity: str, figure: str, no_plus_women: bool, no_black: bool, ) -> tuple[dict[str, str], dict[str, Any] | None]: return character_appearance_policy.character_context_for_label( label, label_map, rng, ethnicity, figure, no_plus_women, no_black, ) def _apply_character_context_to_row(row: dict[str, Any], context: dict[str, Any]) -> dict[str, Any]: return character_appearance_policy.apply_character_context_to_row(row, context) def _cast_descriptor_entries( seed_config: dict[str, int], seed: int, row_number: int, ethnicity: str, figure: str, no_plus_women: bool, no_black: bool, women_count: int, men_count: int, character_cast: str | dict[str, Any] | list[Any] | None = "", primary_descriptor: str = "", ) -> tuple[list[str], list[dict[str, Any]]]: return pair_cast.cast_descriptor_entries( seed_config=seed_config, seed=seed, row_number=row_number, ethnicity=ethnicity, figure=figure, no_plus_women=no_plus_women, no_black=no_black, women_count=women_count, men_count=men_count, character_cast=character_cast, primary_descriptor=primary_descriptor, parse_character_cast=_parse_character_cast, character_slot_label_map=_character_slot_label_map, axis_rng=_axis_rng, character_context_for_label=_character_context_for_label, slot_is_pov=_slot_is_pov, ) def _row_from_profile_metadata(metadata_json: str | dict[str, Any] | None) -> dict[str, Any]: return character_profile_policy.row_from_profile_metadata(metadata_json) def _row_from_character_slot(character_slot: str | dict[str, Any] | None) -> dict[str, Any]: return character_appearance_policy.row_from_character_slot(character_slot) def _character_profile_descriptor(profile: dict[str, Any]) -> str: return character_profile_policy.character_profile_descriptor(profile) def _normalize_character_profile(profile: dict[str, Any], profile_name: str = "") -> dict[str, Any]: return character_profile_policy.normalize_character_profile(profile, profile_name) def build_character_profile_json( profile_name: str = "", source: str = "metadata_json", metadata_json: str | dict[str, Any] | None = "", character_slot: str | dict[str, Any] | None = "", subject_type: str = "woman", age: str = "", body: str = "", body_phrase: str = "", skin: str = "", hair: str = "", eyes: str = "", figure: str = "", save_now: bool = False, ) -> dict[str, str]: character_slot_row = _row_from_character_slot(character_slot or metadata_json) if source == "character_slot" else None return character_profile_policy.build_character_profile_json( profile_name=profile_name, source=source, metadata_json=metadata_json, character_slot_row=character_slot_row, subject_type=subject_type, age=age, body=body, body_phrase_value=body_phrase, skin=skin, hair=hair, eyes=eyes, figure=figure, save_now=save_now, ) def save_character_profile_payload(profile_name: str = "", profile_json: str | dict[str, Any] | None = "") -> dict[str, str]: return character_profile_policy.save_character_profile_payload(profile_name, profile_json) def _empty_profile_result(status: str = "empty") -> dict[str, str]: return character_profile_policy.empty_profile_result(status) def _apply_character_profile_overrides( profile: dict[str, Any], override_subject_type: str = "", override_age: str = "", override_body: str = "", override_body_phrase: str = "", override_skin: str = "", override_hair: str = "", override_eyes: str = "", override_figure: str = "", override_descriptor_detail: str = "", ) -> dict[str, Any]: return character_profile_policy.apply_character_profile_overrides( profile, override_subject_type=override_subject_type, override_age=override_age, override_body=override_body, override_body_phrase=override_body_phrase, override_skin=override_skin, override_hair=override_hair, override_eyes=override_eyes, override_figure=override_figure, override_descriptor_detail=override_descriptor_detail, ) def load_character_profile_json( profile_name: str = "", fallback_profile_json: str | dict[str, Any] | None = "", enabled: bool = True, delete_now: bool = False, rename_now: bool = False, rename_to: str = "", override_subject_type: str = "", override_age: str = "", override_body: str = "", override_body_phrase: str = "", override_skin: str = "", override_hair: str = "", override_eyes: str = "", override_figure: str = "", override_descriptor_detail: str = "", ) -> dict[str, str]: return character_profile_policy.load_character_profile_json( profile_name=profile_name, fallback_profile_json=fallback_profile_json, enabled=enabled, delete_now=delete_now, rename_now=rename_now, rename_to=rename_to, override_subject_type=override_subject_type, override_age=override_age, override_body=override_body, override_body_phrase=override_body_phrase, override_skin=override_skin, override_hair=override_hair, override_eyes=override_eyes, override_figure=override_figure, override_descriptor_detail=override_descriptor_detail, ) def _parse_character_profile(character_profile: str | dict[str, Any] | None) -> dict[str, Any]: return character_profile_policy.parse_character_profile(character_profile) def _apply_character_profile_to_context( context: dict[str, Any], character_profile: str | dict[str, Any] | None, ) -> tuple[dict[str, Any], dict[str, Any], str]: return character_profile_policy.apply_character_profile_to_context(context, character_profile) def _composition_prompt(composition: str) -> str: return row_camera_policy.composition_prompt(composition) def _appearance_for_subject( rng: random.Random, subject_type: str, ethnicity: str, figure: str, no_plus_women: bool, no_black: bool, ) -> dict[str, str]: return character_appearance_policy.appearance_for_subject( rng, subject_type, ethnicity, figure, no_plus_women, no_black, ) def _count_phrase(count: int, singular: str, plural: str) -> str: return cast_context_policy.count_phrase(count, singular, plural) def _configured_cast_context(women_count: int, men_count: int) -> dict[str, str]: return cast_context_policy.configured_cast_context(women_count, men_count) def _couple_type_from_counts( rng: random.Random, women_count: int, men_count: int, ) -> tuple[str, str, str, int, int]: return cast_context_policy.couple_type_from_counts( rng, women_count, men_count, choose=g.choose, couple_types=g.COUPLE_TYPES, ) def _subject_context( rng: random.Random, subject_type: str, ethnicity: str, figure: str, no_plus_women: bool, no_black: bool, women_count: int = 1, men_count: int = 1, ) -> dict[str, str]: return subject_context_policy.subject_context( rng, subject_type, ethnicity, figure, no_plus_women, no_black, women_count, men_count, ) def _subject_route( *, subject_type: str, seed_config: dict[str, int], seed: int, row_number: int, ethnicity: str, figure: str, no_plus_women: bool, no_black: bool, women_count: int, men_count: int, character_profile: str | dict[str, Any] | None = None, character_cast: str | dict[str, Any] | list[Any] | None = None, ) -> dict[str, Any]: return row_subject_route_policy.resolve_subject_route( subject_type=subject_type, seed_config=seed_config, seed=seed, row_number=row_number, ethnicity=ethnicity, figure=figure, no_plus_women=no_plus_women, no_black=no_black, women_count=women_count, men_count=men_count, character_profile=character_profile, character_cast=character_cast, ) def _scene_pool( category: dict[str, Any], subcategory: dict[str, Any], item: Any, subject_type: str, location_config: dict[str, Any] | None = None, ) -> list[Any]: return row_pool_policy.scene_pool(category, subcategory, item, subject_type, location_config) def _expression_pool(category: dict[str, Any], subcategory: dict[str, Any], item: Any) -> list[Any]: return row_pool_policy.expression_pool(category, subcategory, item) def _expression_intensity_hint(entry: Any) -> float: return row_expression_policy.expression_intensity_hint(entry) def _expression_entries_for_intensity(entries: list[Any], expression_intensity: float) -> list[Any]: return row_expression_policy.expression_entries_for_intensity(entries, expression_intensity) def _pose_pool(category: dict[str, Any], subcategory: dict[str, Any], item: Any, subject_type: str, poses: str) -> list[Any]: return row_pool_policy.pose_pool(category, subcategory, item, subject_type, poses) def _composition_pool( category: dict[str, Any], subcategory: dict[str, Any], item: Any, subject_type: str, composition_config: dict[str, Any] | None = None, ) -> list[Any]: return row_pool_policy.composition_pool(category, subcategory, item, subject_type, composition_config) def _prompt_axes_route( *, category: dict[str, Any], subcategory: dict[str, Any], item: Any, subject_type: str, context: dict[str, Any], poses: str, women_count: int, men_count: int, scene_rng: random.Random, pose_rng: random.Random, expression_rng: random.Random, composition_rng: random.Random, expression_disabled: bool, expression_intensity: float, character_slots: list[dict[str, Any]] | None = None, character_slot_map: dict[str, dict[str, Any]] | None = None, expression_phase: str = "", source_role_graph: Any = "", item_axis_values: dict[str, Any] | None = None, is_pose_category: bool = False, pov_character_labels: list[str] | None = None, location_config: dict[str, Any] | None = None, composition_config: dict[str, Any] | None = None, ) -> dict[str, Any]: return row_prompt_axes_policy.resolve_prompt_axes( category=category, subcategory=subcategory, item=item, subject_type=subject_type, context=context, poses=poses, women_count=women_count, men_count=men_count, scene_rng=scene_rng, pose_rng=pose_rng, expression_rng=expression_rng, composition_rng=composition_rng, expression_disabled=expression_disabled, expression_intensity=expression_intensity, character_slots=character_slots, character_slot_map=character_slot_map, expression_phase=expression_phase, source_role_graph=source_role_graph, item_axis_values=item_axis_values, is_pose_category=is_pose_category, pov_character_labels=pov_character_labels, location_config=location_config, composition_config=composition_config, ) def _prompt_axes_route_result( *, category: dict[str, Any], subcategory: dict[str, Any], item: Any, subject_type: str, context: dict[str, Any], poses: str, women_count: int, men_count: int, scene_rng: random.Random, pose_rng: random.Random, expression_rng: random.Random, composition_rng: random.Random, expression_disabled: bool, expression_intensity: float, character_slots: list[dict[str, Any]] | None = None, character_slot_map: dict[str, dict[str, Any]] | None = None, expression_phase: str = "", source_role_graph: Any = "", item_axis_values: dict[str, Any] | None = None, is_pose_category: bool = False, pov_character_labels: list[str] | None = None, location_config: dict[str, Any] | None = None, composition_config: dict[str, Any] | None = None, ) -> row_prompt_axes_policy.PromptAxesRoute: return row_prompt_axes_policy.resolve_prompt_axes_result( category=category, subcategory=subcategory, item=item, subject_type=subject_type, context=context, poses=poses, women_count=women_count, men_count=men_count, scene_rng=scene_rng, pose_rng=pose_rng, expression_rng=expression_rng, composition_rng=composition_rng, expression_disabled=expression_disabled, expression_intensity=expression_intensity, character_slots=character_slots, character_slot_map=character_slot_map, expression_phase=expression_phase, source_role_graph=source_role_graph, item_axis_values=item_axis_values, is_pose_category=is_pose_category, pov_character_labels=pov_character_labels, location_config=location_config, composition_config=composition_config, ) def _role_graph_route( *, rng: random.Random, subcategory: dict[str, Any], context: dict[str, Any], item_axis_values: dict[str, Any], pov_character_labels: list[str], is_pose_category: bool, ) -> row_role_graph_policy.RoleGraphRoute: return row_role_graph_policy.resolve_role_graph_route( rng=rng, subcategory=subcategory, context=context, item_axis_values=item_axis_values, pov_character_labels=pov_character_labels, is_pose_category=is_pose_category, ) def _assemble_custom_row(request: row_assembly_policy.CustomRowAssemblyRequest) -> dict[str, Any]: return row_assembly_policy.assemble_custom_row(request) def _build_custom_row( category_choice: str, subcategory_choice: str, row_number: int, start_index: int, ethnicity: str, poses: str, figure: str, no_plus_women: bool, no_black: bool, women_count: int, men_count: int, seed: int, seed_config: dict[str, int], expression_enabled: bool, expression_intensity: float, expression_intensity_source: str = "input", character_profile: str | dict[str, Any] | None = None, character_cast: str | dict[str, Any] | list[Any] | None = None, expression_phase: str = "", hardcore_position_config: str | dict[str, Any] | None = None, location_config: str | dict[str, Any] | None = None, composition_config: str | dict[str, Any] | None = None, style_config: str | dict[str, Any] | None = None, ) -> dict[str, Any]: scene_rng = _axis_rng(seed_config, "scene", seed, row_number) pose_rng = _axis_rng(seed_config, "pose", seed, row_number) role_rng = _axis_rng(seed_config, "role", seed, row_number) expression_rng = _axis_rng(seed_config, "expression", seed, row_number) composition_rng = _axis_rng(seed_config, "composition", seed, row_number) parsed_hardcore_position_config = _parse_hardcore_position_config(hardcore_position_config) parsed_location_config = _parse_location_config(location_config) parsed_composition_config = _parse_composition_config(composition_config) category_route = _select_category_item_route_result( category_choice=category_choice, subcategory_choice=subcategory_choice, seed_config=seed_config, seed=seed, row_number=row_number, women_count=women_count, men_count=men_count, hardcore_position_config=parsed_hardcore_position_config, ) category = category_route.category subcategory = category_route.subcategory women_count = category_route.women_count men_count = category_route.men_count count_adjustment = dict(category_route.count_adjustment) content_axis = category_route.content_axis item = category_route.item item_text = category_route.item_text item_name = category_route.item_name item_axis_values = dict(category_route.item_axis_values) item_template_metadata = dict(category_route.item_template_metadata) item_formatter_hints = dict(category_route.formatter_hints) is_pose_category = category_route.is_pose_category subject_type = str(_merged_field(category, subcategory, item, "subject_type", "single_any")) subject_route = _subject_route( subject_type=subject_type, seed_config=seed_config, seed=seed, row_number=row_number, ethnicity=ethnicity, figure=figure, no_plus_women=no_plus_women, no_black=no_black, women_count=women_count, men_count=men_count, character_profile=character_profile, character_cast=character_cast, ) context = dict(subject_route["context"]) subject_type = str(subject_route.get("subject_type") or context.get("subject_type") or subject_type) character_slots = list(subject_route.get("character_slots") or []) character_slot_map = dict(subject_route.get("character_slot_map") or {}) applied_slot = dict(subject_route.get("applied_slot") or {}) slot_status = str(subject_route.get("character_slot_status") or "none") applied_profile = dict(subject_route.get("applied_profile") or {}) profile_status = str(subject_route.get("character_profile_status") or "none") pov_character_labels = list(subject_route.get("pov_character_labels") or []) cast_descriptors = list(subject_route.get("cast_descriptors") or []) cast_descriptor_text = str(subject_route.get("cast_descriptor_text") or "") role_graph_route = _role_graph_route( rng=role_rng, subcategory=subcategory, context=context, item_axis_values=item_axis_values, pov_character_labels=pov_character_labels, is_pose_category=is_pose_category, ) source_role_graph = role_graph_route.source_role_graph role_graph = role_graph_route.role_graph expression_route = _resolve_expression_route( expression_enabled=expression_enabled, expression_intensity=expression_intensity, expression_intensity_source=expression_intensity_source, subject_type=subject_type, applied_slot=applied_slot, character_slots=character_slots, character_slot_map=character_slot_map, women_count=women_count, men_count=men_count, expression_phase=expression_phase, ) expression_disabled = expression_route.expression_disabled expression_intensity = expression_route.expression_intensity expression_intensity_source = expression_route.expression_intensity_source prompt_axes = _prompt_axes_route_result( category=category, subcategory=subcategory, item=item, subject_type=subject_type, context=context, poses=poses, women_count=women_count, men_count=men_count, scene_rng=scene_rng, pose_rng=pose_rng, expression_rng=expression_rng, composition_rng=composition_rng, expression_disabled=expression_disabled, expression_intensity=expression_intensity, character_slots=character_slots, character_slot_map=character_slot_map, expression_phase=expression_phase, source_role_graph=source_role_graph, item_axis_values=item_axis_values, is_pose_category=is_pose_category, pov_character_labels=pov_character_labels, location_config=parsed_location_config, composition_config=parsed_composition_config, ) scene_slug = prompt_axes.scene_slug scene = prompt_axes.scene scene_entry = dict(prompt_axes.scene_entry) pose = prompt_axes.pose expression = prompt_axes.expression shared_expression = prompt_axes.shared_expression character_expressions = list(prompt_axes.character_expressions) character_expression_text = prompt_axes.character_expression_text source_composition = prompt_axes.source_composition composition = prompt_axes.composition composition_entry = dict(prompt_axes.composition_entry) action_route = _action_position_route( is_pose_category=is_pose_category, subcategory=subcategory, hardcore_position_config=parsed_hardcore_position_config, item_template_metadata=item_template_metadata, item_text=item_text, source_role_graph=source_role_graph, source_composition=source_composition, pose=pose, item_axis_values=item_axis_values, ) position_family = action_route.position_family position_keys = list(action_route.position_keys) position_key = action_route.position_key action_family = action_route.action_family text_fields = _row_text_fields(category, subcategory, item, style_config) formatter_axis_values = _axis_values_with_krea2_variant_keys( item_axis_values, parsed_hardcore_position_config, ) assembly_request = row_assembly_policy.CustomRowAssemblyRequest( row_number=row_number, start_index=start_index, category=category, subcategory=subcategory, item=item, context=context, subject_type=subject_type, item_text=item_text, item_name=item_name, item_axis_values=formatter_axis_values, item_template_metadata=item_template_metadata, formatter_hints=item_formatter_hints, item_label=text_fields.item_label, style=text_fields.style, positive_suffix=text_fields.positive_suffix, negative_prompt=text_fields.negative_prompt, scene_slug=scene_slug, scene=scene, scene_entry=scene_entry, pose=pose, expression=expression, shared_expression=shared_expression, character_expressions=character_expressions, character_expression_text=character_expression_text, expression_disabled=expression_disabled, expression_intensity=expression_intensity, expression_intensity_source=expression_intensity_source, composition=composition, source_composition=source_composition, composition_entry=composition_entry, role_graph=role_graph, source_role_graph=source_role_graph, action_family=action_family, position_family=position_family, position_key=position_key, position_keys=position_keys, pov_character_labels=pov_character_labels, cast_descriptors=cast_descriptors, cast_descriptor_text=cast_descriptor_text, seed_config=seed_config, hardcore_position_config=( parsed_hardcore_position_config if _hardcore_position_config_active(parsed_hardcore_position_config) else {} ), location_config=parsed_location_config if _location_config_active(parsed_location_config) else {}, composition_config=parsed_composition_config if _composition_config_active(parsed_composition_config) else {}, content_seed_axis=content_axis, count_adjustment=count_adjustment, applied_profile=applied_profile, profile_status=profile_status, applied_slot=applied_slot, slot_status=slot_status, character_slots=character_slots, ) return _assemble_custom_row(assembly_request) def _prompt_build_dependencies() -> builder_prompt_route_policy.PromptBuildDependencies: return builder_prompt_route_policy.PromptBuildDependencies( default_trigger=g.TRIGGER, default_negative=g.NEGATIVE_PROMPT, random_subcategory=RANDOM_SUBCATEGORY, apply_pool_extensions=apply_pool_extensions, normalize_ethnicity_filter=normalize_ethnicity_filter, is_false=_is_false, ratio_or_none=_ratio_or_none, parse_seed_config=_parse_seed_config, parse_location_config=_parse_location_config, parse_composition_config=_parse_composition_config, axis_rng=_axis_rng, pick_clothing_mode=_pick_clothing_mode, pick_pose_mode=_pick_pose_mode, pick_figure_bias=_pick_figure_bias, pick_expression_intensity=_pick_expression_intensity, auto_full_choice=_auto_full_choice, build_auto_weighted_row=_build_auto_weighted_row, build_direct_builtin_row=_build_direct_builtin_row, build_custom_row=_build_custom_row, apply_location_config_to_legacy_row=row_location_policy.apply_location_config_to_legacy_row, apply_composition_config_to_legacy_row=row_location_policy.apply_composition_config_to_legacy_row, disable_row_expression=_disable_row_expression, apply_camera_config=_apply_camera_config, normalize_prompt_row=row_policy.normalize_prompt_row, ) def build_prompt( category: str, subcategory: str, row_number: int, start_index: int, seed: int, clothing: str, ethnicity: str, poses: str, backside_bias: float, figure: str, no_plus_women: bool, no_black: bool, minimal_clothing_ratio: float, standard_pose_ratio: float, trigger: str, prepend_trigger_to_prompt: bool, extra_positive: str, extra_negative: str, seed_config: str | dict[str, Any] | None = None, women_count: int = 1, men_count: int = 1, camera_config: str | dict[str, Any] | None = None, expression_intensity: float = 0.5, character_profile: str | dict[str, Any] | None = None, character_cast: str | dict[str, Any] | list[Any] | None = None, expression_enabled: bool = True, expression_phase: str = "", hardcore_position_config: str | dict[str, Any] | None = None, location_config: str | dict[str, Any] | None = None, composition_config: str | dict[str, Any] | None = None, style_config: str | dict[str, Any] | None = None, ) -> dict[str, Any]: return builder_prompt_route_policy.build_prompt( builder_prompt_route_policy.PromptBuildRequest( category=category, subcategory=subcategory, row_number=row_number, start_index=start_index, seed=seed, clothing=clothing, ethnicity=ethnicity, poses=poses, backside_bias=backside_bias, figure=figure, no_plus_women=no_plus_women, no_black=no_black, minimal_clothing_ratio=minimal_clothing_ratio, standard_pose_ratio=standard_pose_ratio, trigger=trigger, prepend_trigger_to_prompt=prepend_trigger_to_prompt, extra_positive=extra_positive, extra_negative=extra_negative, seed_config=seed_config, women_count=women_count, men_count=men_count, camera_config=camera_config, expression_intensity=expression_intensity, character_profile=character_profile, character_cast=character_cast, expression_enabled=expression_enabled, expression_phase=expression_phase, hardcore_position_config=hardcore_position_config, location_config=location_config, composition_config=composition_config, style_config=style_config, ), _prompt_build_dependencies(), ) def _prompt_from_configs_dependencies() -> builder_config_route_policy.PromptFromConfigsDependencies: return builder_config_route_policy.PromptFromConfigsDependencies( parse_category_config=_parse_category_config, parse_cast_config=_parse_cast_config, parse_generation_profile=_parse_generation_profile, parse_filter_config=_parse_filter_config, build_prompt=build_prompt, ) def build_prompt_from_configs( row_number: int, start_index: int, seed: int, category_config: str | dict[str, Any] | None = "", cast_config: str | dict[str, Any] | None = "", generation_profile: str | dict[str, Any] | None = "", filter_config: str | dict[str, Any] | None = "", seed_config: str | dict[str, Any] | None = "", camera_config: str | dict[str, Any] | None = "", character_profile: str | dict[str, Any] | None = "", character_cast: str | dict[str, Any] | list[Any] | None = "", hardcore_position_config: str | dict[str, Any] | None = "", location_config: str | dict[str, Any] | None = "", composition_config: str | dict[str, Any] | None = "", style_config: str | dict[str, Any] | None = "", extra_positive: str = "", extra_negative: str = "", ) -> dict[str, Any]: return builder_config_route_policy.build_prompt_from_configs( builder_config_route_policy.PromptFromConfigsRequest( row_number=row_number, start_index=start_index, seed=seed, category_config=category_config, cast_config=cast_config, generation_profile=generation_profile, filter_config=filter_config, seed_config=seed_config, camera_config=camera_config, character_profile=character_profile, character_cast=character_cast, hardcore_position_config=hardcore_position_config, location_config=location_config, composition_config=composition_config, style_config=style_config, extra_positive=extra_positive, extra_negative=extra_negative, ), _prompt_from_configs_dependencies(), ) INSTA_OF_SOFT_LEVELS = pair_options.INSTA_OF_SOFT_LEVELS INSTA_OF_HARDCORE_LEVELS = pair_options.INSTA_OF_HARDCORE_LEVELS INSTA_OF_PLATFORM_STYLES = pair_options.INSTA_OF_PLATFORM_STYLES INSTA_OF_HARDCORE_CLOTHING_CONTINUITY = pair_options.INSTA_OF_HARDCORE_CLOTHING_CONTINUITY INSTA_OF_NEGATIVE = pair_options.INSTA_OF_NEGATIVE INSTA_OF_SOFT_NEGATIVE = pair_options.INSTA_OF_SOFT_NEGATIVE INSTA_OF_SOFTCORE_SUBCATEGORY_BY_LEVEL = pair_options.INSTA_OF_SOFTCORE_SUBCATEGORY_BY_LEVEL INSTA_OF_SOFTCORE_OUTFITS = pair_options.INSTA_OF_SOFTCORE_OUTFITS INSTA_OF_SOFTCORE_POSES = pair_options.INSTA_OF_SOFTCORE_POSES INSTA_OF_SOFTCORE_PARTNER_WOMEN_OUTFITS = pair_options.INSTA_OF_SOFTCORE_PARTNER_WOMEN_OUTFITS INSTA_OF_SOFTCORE_PARTNER_MEN_OUTFITS = pair_options.INSTA_OF_SOFTCORE_PARTNER_MEN_OUTFITS def character_softcore_outfit_values(source: str, custom_outfits: str = "") -> list[str]: return pair_options.character_softcore_outfit_values(source, custom_outfits) def character_hardcore_clothing_values(state: str, custom_clothing: str = "") -> list[str]: return pair_options.character_hardcore_clothing_values(state, custom_clothing) def build_insta_of_options_json( softcore_cast: str = "solo", hardcore_cast: str = "use_counts", hardcore_women_count: int = 1, hardcore_men_count: int = 1, softcore_level: str = "lingerie_tease", hardcore_level: str = "hardcore", platform_style: str = "hybrid", continuity: str = "same_creator_same_room", hardcore_clothing_continuity: str = "partially_removed", softcore_camera_mode: str = "handheld_selfie", hardcore_camera_mode: str = "from_camera_config", camera_detail: str = "from_camera_config", softcore_expression_intensity: float = 0.45, hardcore_expression_intensity: float = 0.85, softcore_expression_enabled: bool = True, hardcore_expression_enabled: bool = True, hardcore_detail_density: str = "balanced", ) -> str: return pair_options.build_insta_of_options_json( softcore_cast=softcore_cast, hardcore_cast=hardcore_cast, hardcore_women_count=hardcore_women_count, hardcore_men_count=hardcore_men_count, softcore_level=softcore_level, hardcore_level=hardcore_level, platform_style=platform_style, continuity=continuity, hardcore_clothing_continuity=hardcore_clothing_continuity, softcore_camera_mode=softcore_camera_mode, hardcore_camera_mode=hardcore_camera_mode, camera_detail=camera_detail, softcore_expression_intensity=softcore_expression_intensity, hardcore_expression_intensity=hardcore_expression_intensity, softcore_expression_enabled=softcore_expression_enabled, hardcore_expression_enabled=hardcore_expression_enabled, hardcore_detail_density=hardcore_detail_density, hardcore_detail_density_choices=HARDCORE_DETAIL_DENSITY_CHOICES, ) def _parse_insta_of_options(options_json: str | dict[str, Any] | None) -> dict[str, Any]: return pair_options.parse_insta_of_options( options_json, camera_mode_choices=CAMERA_MODE_PROMPTS, camera_detail_choices=CAMERA_DETAIL_CHOICES, hardcore_detail_density_choices=HARDCORE_DETAIL_DENSITY_CHOICES, ) def _insta_of_hardcore_counts(options: dict[str, Any]) -> tuple[int, int]: return pair_options.hardcore_counts(options) def _insta_of_descriptor(row: dict[str, Any]) -> str: return pair_cast.insta_descriptor_from_row(row) def _insta_of_descriptor_from_context(context: dict[str, Any]) -> str: return pair_cast.insta_descriptor_from_context(context) def _insta_of_prompt_cast_descriptors(text: str) -> str: return pair_cast.prompt_cast_descriptors(text) def _insta_of_softcore_category(level: str) -> tuple[str, str]: return pair_options.softcore_category(level) def _insta_of_softcore_outfit(rng: random.Random, level: str) -> str: return g.choose(rng, pair_options.softcore_outfit_pool(level)) def _insta_of_softcore_item_prompt_label(level: str) -> str: return pair_options.softcore_item_prompt_label(level) def _insta_of_softcore_pose(rng: random.Random, level: str) -> str: return g.choose(rng, pair_options.softcore_pose_pool(level)) def _insta_pair_build_dependencies() -> pair_builder.InstaPairBuildDependencies: return pair_builder.InstaPairBuildDependencies( default_trigger=g.TRIGGER, random_subcategory=RANDOM_SUBCATEGORY, soft_negative_base=INSTA_OF_SOFT_NEGATIVE, hard_negative_base=INSTA_OF_NEGATIVE, camera_detail_choices=CAMERA_DETAIL_CHOICES, hardcore_clothing_continuity=INSTA_OF_HARDCORE_CLOTHING_CONTINUITY, platform_styles=INSTA_OF_PLATFORM_STYLES, soft_levels=INSTA_OF_SOFT_LEVELS, hardcore_levels=INSTA_OF_HARDCORE_LEVELS, parse_options=_parse_insta_of_options, parse_filter_config=_parse_filter_config, parse_seed_config=_parse_seed_config, parse_character_cast=_parse_character_cast, character_slot_label_map=_character_slot_label_map, pov_character_labels=_pov_character_labels, softcore_category=_insta_of_softcore_category, build_prompt=build_prompt, axis_rng=_axis_rng, cast_expression_intensity_override=_cast_expression_intensity_override, context_from_character_slot=_context_from_character_slot, apply_character_context_to_row=_apply_character_context_to_row, disable_row_expression=_disable_row_expression, slot_softcore_outfit=_slot_softcore_outfit, softcore_outfit=_insta_of_softcore_outfit, softcore_pose=_insta_of_softcore_pose, softcore_item_prompt_label=_insta_of_softcore_item_prompt_label, pov_prompt_directive=_pov_prompt_directive, pov_composition_prompt=_pov_composition_prompt, hardcore_counts=_insta_of_hardcore_counts, character_context_for_label=_character_context_for_label, slot_is_pov=_slot_is_pov, choose=g.choose, camera_config_with_mode=_camera_config_with_mode, camera_directive=_camera_directive, apply_contextual_composition=_apply_coworking_composition, contextual_composition_prompt=_coworking_composition_prompt, composition_prompt=_composition_prompt, camera_scene_directive_for_context=_camera_scene_directive_for_context, slot_hardcore_clothing=_slot_hardcore_clothing, hardcore_detail_directive=pair_options.hardcore_detail_directive, camera_caption_text=_camera_caption_text, ) def build_insta_of_pair( row_number: int, start_index: int, seed: int, ethnicity: str, figure: str, no_plus_women: bool, no_black: bool, trigger: str, prepend_trigger_to_prompt: bool, seed_config: str | dict[str, Any] | None = None, softcore_seed_config: str | dict[str, Any] | None = None, hardcore_seed_config: str | dict[str, Any] | None = None, options_json: str | dict[str, Any] | None = None, filter_config: str | dict[str, Any] | None = None, camera_config: str | dict[str, Any] | None = None, softcore_camera_config: str | dict[str, Any] | None = None, hardcore_camera_config: str | dict[str, Any] | None = None, character_profile: str | dict[str, Any] | None = "", character_cast: str | dict[str, Any] | list[Any] | None = "", hardcore_position_config: str | dict[str, Any] | None = "", location_config: str | dict[str, Any] | None = "", composition_config: str | dict[str, Any] | None = "", style_config: str | dict[str, Any] | None = "", extra_positive: str = "", extra_negative: str = "", ) -> dict[str, Any]: request = pair_builder.InstaPairBuildRequest( row_number=row_number, start_index=start_index, seed=seed, ethnicity=ethnicity, figure=figure, no_plus_women=no_plus_women, no_black=no_black, trigger=trigger, prepend_trigger_to_prompt=prepend_trigger_to_prompt, seed_config=seed_config, softcore_seed_config=softcore_seed_config, hardcore_seed_config=hardcore_seed_config, options_json=options_json, filter_config=filter_config, camera_config=camera_config, softcore_camera_config=softcore_camera_config, hardcore_camera_config=hardcore_camera_config, character_profile=character_profile, character_cast=character_cast, hardcore_position_config=hardcore_position_config, location_config=location_config, composition_config=composition_config, style_config=style_config, extra_positive=extra_positive, extra_negative=extra_negative, ) return pair_builder.build_insta_of_pair(request, _insta_pair_build_dependencies())