Extract Krea pair formatter route
This commit is contained in:
@@ -329,12 +329,16 @@ Owner: `krea_formatter.py`.
|
|||||||
Keep here:
|
Keep here:
|
||||||
|
|
||||||
- Krea prose style;
|
- Krea prose style;
|
||||||
- Krea route orchestration;
|
- Krea top-level route orchestration;
|
||||||
- camera-scene preservation;
|
- camera-scene preservation;
|
||||||
- fallback text parsing.
|
- fallback text parsing.
|
||||||
|
|
||||||
Already isolated:
|
Already isolated:
|
||||||
|
|
||||||
|
- `krea_pair_formatter.py` owns Insta/OF pair soft/hard Krea prose assembly
|
||||||
|
behind `KreaPairFormatRequest`, `KreaPairFormatDependencies`, and
|
||||||
|
`KreaPairPrompts`; `krea_formatter.py` keeps the `_insta_pair_to_krea`
|
||||||
|
compatibility wrapper.
|
||||||
- `krea_cast.py` owns cast descriptor parsing, cast labels, cast prose, label
|
- `krea_cast.py` owns cast descriptor parsing, cast labels, cast prose, label
|
||||||
joining, natural cast descriptor text, and label replacement for formatter
|
joining, natural cast descriptor text, and label replacement for formatter
|
||||||
routes, including the caption naturalizer's cast metadata path.
|
routes, including the caption naturalizer's cast metadata path.
|
||||||
|
|||||||
@@ -648,7 +648,8 @@ Important POV rule:
|
|||||||
|
|
||||||
`format_krea2_prompt` chooses between three roads:
|
`format_krea2_prompt` chooses between three roads:
|
||||||
|
|
||||||
- Pair metadata: `_insta_pair_to_krea`.
|
- Pair metadata: `krea_pair_formatter.format_insta_pair_result` through the
|
||||||
|
`_insta_pair_to_krea` compatibility wrapper.
|
||||||
- Normal metadata row: `_normal_row_to_krea`.
|
- Normal metadata row: `_normal_row_to_krea`.
|
||||||
- Plain text fallback: `_fallback_text_to_krea`.
|
- Plain text fallback: `_fallback_text_to_krea`.
|
||||||
|
|
||||||
@@ -663,6 +664,8 @@ Key Krea2 ownership:
|
|||||||
- Climax role/detail cleanup: `krea_action_climax.py`.
|
- Climax role/detail cleanup: `krea_action_climax.py`.
|
||||||
- Non-POV action-family routing: `krea_action_dispatch.py`.
|
- Non-POV action-family routing: `krea_action_dispatch.py`.
|
||||||
- Non-POV hardcore action sentence: `krea_actions.hardcore_action_sentence`.
|
- Non-POV hardcore action sentence: `krea_actions.hardcore_action_sentence`.
|
||||||
|
- Insta/OF pair soft/hard Krea prose assembly:
|
||||||
|
`krea_pair_formatter.format_insta_pair_result`.
|
||||||
- Shared POV labels/filtering/composition cleanup: `pov_policy.py`.
|
- Shared POV labels/filtering/composition cleanup: `pov_policy.py`.
|
||||||
- Krea POV camera support: `krea_pov.py`.
|
- Krea POV camera support: `krea_pov.py`.
|
||||||
- Detail clause splitting and density limiting: `krea_detail.py`.
|
- Detail clause splitting and density limiting: `krea_detail.py`.
|
||||||
@@ -676,8 +679,8 @@ Krea2 field consumption:
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| Normal single row | `subject_type`, `item`, `pose`, `scene_text`, `expression`, `composition`, `camera_*`, style fields | `_normal_row_to_krea` |
|
| Normal single row | `subject_type`, `item`, `pose`, `scene_text`, `expression`, `composition`, `camera_*`, style fields | `_normal_row_to_krea` |
|
||||||
| Normal configured cast/hardcore row | `cast_descriptor_text`, `women_count`, `men_count`, `source_role_graph`, `role_graph`, `item`, `item_axis_values`, `source_composition`, `pov_character_labels` | `_normal_row_to_krea`, `krea_actions.hardcore_action_sentence`, `krea_pov_actions.pov_action_phrase` |
|
| Normal configured cast/hardcore row | `cast_descriptor_text`, `women_count`, `men_count`, `source_role_graph`, `role_graph`, `item`, `item_axis_values`, `source_composition`, `pov_character_labels` | `_normal_row_to_krea`, `krea_actions.hardcore_action_sentence`, `krea_pov_actions.pov_action_phrase` |
|
||||||
| Insta/OF pair softcore | `shared_descriptor`, `softcore_row`, `softcore_partner_styling`, options, soft camera fields | `_insta_pair_to_krea` |
|
| Insta/OF pair softcore | `shared_descriptor`, `softcore_row`, `softcore_partner_styling`, options, soft camera fields | `krea_pair_formatter.format_insta_pair_result` |
|
||||||
| Insta/OF pair hardcore | `hardcore_row`, `shared_cast_descriptors`, `hardcore_clothing_state`, `hardcore_detail_density`, hard camera fields, POV labels | `_insta_pair_to_krea`, `krea_actions.hardcore_action_sentence`, `krea_pov_actions.pov_action_phrase`, `krea_clothing.natural_clothing_state` |
|
| Insta/OF pair hardcore | `hardcore_row`, `shared_cast_descriptors`, `hardcore_clothing_state`, `hardcore_detail_density`, hard camera fields, POV labels | `krea_pair_formatter.format_insta_pair_result`, `krea_actions.hardcore_action_sentence`, `krea_pov_actions.pov_action_phrase`, `krea_clothing.natural_clothing_state` |
|
||||||
| Plain text fallback | `source_text` only | `_fallback_text_to_krea` |
|
| Plain text fallback | `source_text` only | `_fallback_text_to_krea` |
|
||||||
|
|
||||||
If metadata is connected and `method` says `text(fallback)`, the formatter did
|
If metadata is connected and `method` says `text(fallback)`, the formatter did
|
||||||
|
|||||||
+40
-158
@@ -11,6 +11,7 @@ try:
|
|||||||
is_outercourse_text as _is_outercourse_text,
|
is_outercourse_text as _is_outercourse_text,
|
||||||
normalize_hardcore_detail_density as _normalize_hardcore_detail_density,
|
normalize_hardcore_detail_density as _normalize_hardcore_detail_density,
|
||||||
)
|
)
|
||||||
|
from . import krea_pair_formatter
|
||||||
from .hardcore_text_cleanup import (
|
from .hardcore_text_cleanup import (
|
||||||
sanitize_hardcore_axis_values as _sanitize_hardcore_axis_values,
|
sanitize_hardcore_axis_values as _sanitize_hardcore_axis_values,
|
||||||
sanitize_hardcore_environment_anchors as _sanitize_hardcore_environment_anchors,
|
sanitize_hardcore_environment_anchors as _sanitize_hardcore_environment_anchors,
|
||||||
@@ -42,6 +43,7 @@ except ImportError: # Allows local smoke tests with `python -c`.
|
|||||||
is_outercourse_text as _is_outercourse_text,
|
is_outercourse_text as _is_outercourse_text,
|
||||||
normalize_hardcore_detail_density as _normalize_hardcore_detail_density,
|
normalize_hardcore_detail_density as _normalize_hardcore_detail_density,
|
||||||
)
|
)
|
||||||
|
import krea_pair_formatter
|
||||||
from hardcore_text_cleanup import (
|
from hardcore_text_cleanup import (
|
||||||
sanitize_hardcore_axis_values as _sanitize_hardcore_axis_values,
|
sanitize_hardcore_axis_values as _sanitize_hardcore_axis_values,
|
||||||
sanitize_hardcore_environment_anchors as _sanitize_hardcore_environment_anchors,
|
sanitize_hardcore_environment_anchors as _sanitize_hardcore_environment_anchors,
|
||||||
@@ -536,166 +538,46 @@ def _normal_row_to_krea(row: dict[str, Any], detail_level: str, style_mode: str)
|
|||||||
return _paragraph(parts), "metadata(generic)"
|
return _paragraph(parts), "metadata(generic)"
|
||||||
|
|
||||||
|
|
||||||
|
def _krea_pair_format_dependencies() -> krea_pair_formatter.KreaPairFormatDependencies:
|
||||||
|
return krea_pair_formatter.KreaPairFormatDependencies(
|
||||||
|
clean=_clean,
|
||||||
|
prompt_cast_descriptors=_prompt_cast_descriptors,
|
||||||
|
pair_camera_phrase=_pair_camera_phrase,
|
||||||
|
camera_scene_phrase=_camera_scene_phrase,
|
||||||
|
style_phrase=_style_phrase,
|
||||||
|
sanitize_hardcore_environment_anchors=_sanitize_hardcore_environment_anchors,
|
||||||
|
sanitize_hardcore_axis_values=_sanitize_hardcore_axis_values,
|
||||||
|
sanitize_scene_text_for_cast=_sanitize_scene_text_for_cast,
|
||||||
|
normalize_hardcore_detail_density=_normalize_hardcore_detail_density,
|
||||||
|
row_action_family=route_metadata_policy.row_action_family,
|
||||||
|
hardcore_action_sentence=_hardcore_action_sentence,
|
||||||
|
pov_action_phrase=_pov_action_phrase,
|
||||||
|
pov_labels_from_value=_pov_labels_from_value,
|
||||||
|
merge_labels=_merge_labels,
|
||||||
|
cast_prose_omit=lambda text, omit_labels: _cast_prose(text, omit_labels=omit_labels),
|
||||||
|
label_join=_label_join,
|
||||||
|
filter_pov_labeled_clauses=_filter_pov_labeled_clauses,
|
||||||
|
natural_label_text=_natural_label_text,
|
||||||
|
expression_disabled=_expression_disabled,
|
||||||
|
expression_phrase=_expression_phrase,
|
||||||
|
pov_camera_phrase=lambda labels: _pov_camera_phrase(labels),
|
||||||
|
pov_soft_camera_phrase=lambda labels: _pov_camera_phrase(labels, softcore=True),
|
||||||
|
pov_composition_text=_pov_composition_text,
|
||||||
|
natural_clothing_state=_natural_clothing_state,
|
||||||
|
composition_phrase=_composition_phrase,
|
||||||
|
paragraph=_paragraph,
|
||||||
|
combine_negative=_combine_negative,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _insta_pair_to_krea(row: dict[str, Any], detail_level: str, style_mode: str) -> tuple[str, str, str, str]:
|
def _insta_pair_to_krea(row: dict[str, Any], detail_level: str, style_mode: str) -> tuple[str, str, str, str]:
|
||||||
descriptor = _clean(row.get("shared_descriptor"))
|
return krea_pair_formatter.format_insta_pair(
|
||||||
cast_descriptors = row.get("shared_cast_descriptors")
|
krea_pair_formatter.KreaPairFormatRequest(
|
||||||
if isinstance(cast_descriptors, list):
|
row=row,
|
||||||
cast_descriptor_text = "; ".join(_clean(item) for item in cast_descriptors if _clean(item))
|
detail_level=detail_level,
|
||||||
else:
|
style_mode=style_mode,
|
||||||
cast_descriptor_text = _clean(cast_descriptors)
|
|
||||||
cast_descriptor_text = _prompt_cast_descriptors(cast_descriptor_text)
|
|
||||||
soft = row.get("softcore_row") if isinstance(row.get("softcore_row"), dict) else {}
|
|
||||||
hard = row.get("hardcore_row") if isinstance(row.get("hardcore_row"), dict) else {}
|
|
||||||
soft_camera = _pair_camera_phrase(row.get("softcore_camera_directive"), row.get("softcore_camera_config"), soft)
|
|
||||||
hard_camera = _pair_camera_phrase(row.get("hardcore_camera_directive"), row.get("hardcore_camera_config"), hard)
|
|
||||||
soft_camera_scene = _camera_scene_phrase(soft) or _clean(row.get("softcore_camera_scene_directive"))
|
|
||||||
hard_camera_scene = _camera_scene_phrase(hard) or _clean(row.get("hardcore_camera_scene_directive"))
|
|
||||||
soft_style = _style_phrase(soft, style_mode)
|
|
||||||
hard_style = _style_phrase(hard, style_mode)
|
|
||||||
options = row.get("options") if isinstance(row.get("options"), dict) else {}
|
|
||||||
soft_level = _clean(options.get("softcore_level")).replace("_", " ")
|
|
||||||
hard_level = _clean(options.get("hardcore_level")).replace("_", " ")
|
|
||||||
same_room = options.get("continuity") == "same_creator_same_room"
|
|
||||||
hard_scene = soft.get("scene_text") if same_room and soft.get("scene_text") else hard.get("scene_text")
|
|
||||||
hard_composition = _sanitize_hardcore_environment_anchors(hard.get("composition"))
|
|
||||||
hard_source_composition = _sanitize_hardcore_environment_anchors(hard.get("source_composition") or hard_composition)
|
|
||||||
pov_labels = _merge_labels(
|
|
||||||
_pov_labels_from_value(row.get("pov_character_labels")),
|
|
||||||
_pov_labels_from_value(soft.get("pov_character_labels")),
|
|
||||||
_pov_labels_from_value(hard.get("pov_character_labels")),
|
|
||||||
)
|
|
||||||
if pov_labels:
|
|
||||||
hard_camera = ""
|
|
||||||
if options.get("softcore_cast") == "same_as_hardcore":
|
|
||||||
soft_camera = ""
|
|
||||||
soft_cast_descriptor_text = (
|
|
||||||
cast_descriptor_text
|
|
||||||
if options.get("softcore_cast") == "same_as_hardcore"
|
|
||||||
else f"Woman A: {descriptor}"
|
|
||||||
)
|
|
||||||
soft_cast_prose, soft_labels = _cast_prose(
|
|
||||||
soft_cast_descriptor_text,
|
|
||||||
omit_labels=pov_labels if options.get("softcore_cast") == "same_as_hardcore" else [],
|
|
||||||
)
|
|
||||||
hard_cast_prose, hard_labels = _cast_prose(cast_descriptor_text, omit_labels=pov_labels)
|
|
||||||
soft_labels = _merge_labels(soft_labels, pov_labels if options.get("softcore_cast") == "same_as_hardcore" else [])
|
|
||||||
hard_labels = _merge_labels(hard_labels, pov_labels)
|
|
||||||
hard_item = _sanitize_scene_text_for_cast(_sanitize_hardcore_environment_anchors(hard.get("item")), hard_labels)
|
|
||||||
hard_role_graph = _sanitize_scene_text_for_cast(
|
|
||||||
_sanitize_hardcore_environment_anchors(hard.get("source_role_graph") or hard.get("role_graph")),
|
|
||||||
hard_labels,
|
|
||||||
)
|
|
||||||
hard_item = _natural_label_text(hard_item, hard_labels)
|
|
||||||
hard_role_graph = _natural_label_text(hard_role_graph, hard_labels)
|
|
||||||
hard_axis_values = _sanitize_hardcore_axis_values(hard.get("item_axis_values"))
|
|
||||||
hard_detail_density = _normalize_hardcore_detail_density(
|
|
||||||
hard.get("hardcore_detail_density") or row.get("hardcore_detail_density") or options.get("hardcore_detail_density")
|
|
||||||
)
|
|
||||||
hard_action = _hardcore_action_sentence(
|
|
||||||
hard_role_graph,
|
|
||||||
hard_item,
|
|
||||||
hard_source_composition,
|
|
||||||
hard_axis_values,
|
|
||||||
hard_detail_density,
|
|
||||||
route_metadata_policy.row_action_family(hard) or route_metadata_policy.row_action_family(row),
|
|
||||||
)
|
|
||||||
hard_action = _pov_action_phrase(
|
|
||||||
hard_action,
|
|
||||||
pov_labels,
|
|
||||||
hard_role_graph,
|
|
||||||
hard_item,
|
|
||||||
hard_source_composition,
|
|
||||||
hard_axis_values,
|
|
||||||
hard_detail_density,
|
|
||||||
)
|
|
||||||
hard_output_composition = _pov_composition_text(hard_composition, pov_labels)
|
|
||||||
same_soft_cast = options.get("softcore_cast") == "same_as_hardcore"
|
|
||||||
soft_output_composition = _pov_composition_text(soft.get("composition"), pov_labels if same_soft_cast else [])
|
|
||||||
if same_soft_cast and pov_labels:
|
|
||||||
soft_cast_presence = (
|
|
||||||
"the woman is framed from the POV participant's first-person camera in a soft creator-teaser pose, "
|
|
||||||
"with the POV participant kept off-camera as the viewpoint and implied by camera position or foreground cues"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
soft_cast_presence = (
|
|
||||||
f"{_label_join(soft_labels)} share the frame in a soft creator-teaser pose"
|
|
||||||
if same_soft_cast
|
|
||||||
else "The image focuses on the woman alone"
|
|
||||||
)
|
|
||||||
partner_styling = row.get("softcore_partner_styling")
|
|
||||||
if isinstance(partner_styling, dict):
|
|
||||||
outfits = partner_styling.get("outfits")
|
|
||||||
partner_outfit_text = "; ".join(_clean(item) for item in outfits if _clean(item)) if isinstance(outfits, list) else ""
|
|
||||||
partner_pose = _clean(partner_styling.get("pose"))
|
|
||||||
else:
|
|
||||||
partner_outfit_text = ""
|
|
||||||
partner_pose = ""
|
|
||||||
partner_outfit_text = _filter_pov_labeled_clauses(partner_outfit_text, pov_labels)
|
|
||||||
if pov_labels:
|
|
||||||
partner_pose = ""
|
|
||||||
partner_outfit_text = _natural_label_text(partner_outfit_text, soft_labels)
|
|
||||||
|
|
||||||
soft_expression = ""
|
|
||||||
if not _expression_disabled(soft):
|
|
||||||
soft_expression_source = _filter_pov_labeled_clauses(
|
|
||||||
_clean(soft.get("character_expression_text")) or _clean(soft.get("expression")),
|
|
||||||
pov_labels,
|
|
||||||
)
|
|
||||||
soft_expression = _natural_label_text(
|
|
||||||
soft_expression_source,
|
|
||||||
soft_labels,
|
|
||||||
)
|
|
||||||
hard_expression = ""
|
|
||||||
if not _expression_disabled(hard):
|
|
||||||
hard_expression_source = _filter_pov_labeled_clauses(
|
|
||||||
_clean(hard.get("character_expression_text")) or _clean(hard.get("expression")),
|
|
||||||
pov_labels,
|
|
||||||
)
|
|
||||||
hard_expression = _natural_label_text(
|
|
||||||
hard_expression_source,
|
|
||||||
hard_labels,
|
|
||||||
)
|
|
||||||
soft_item = _clean(soft.get("item"))
|
|
||||||
soft_item_label = _clean(soft.get("softcore_item_prompt_label"))
|
|
||||||
soft_item_phrase = ""
|
|
||||||
if soft_item:
|
|
||||||
soft_item_phrase = f"body exposure: {soft_item}" if soft_item_label == "Body exposure" else f"wearing {soft_item}"
|
|
||||||
|
|
||||||
soft_parts = [
|
|
||||||
soft_cast_prose,
|
|
||||||
soft_cast_presence,
|
|
||||||
partner_outfit_text,
|
|
||||||
partner_pose,
|
|
||||||
_pov_camera_phrase(pov_labels, softcore=True) if same_soft_cast else "",
|
|
||||||
soft_item_phrase,
|
|
||||||
f"{soft.get('pose')}" if soft.get("pose") else "",
|
|
||||||
_expression_phrase(soft_expression),
|
|
||||||
f"in {soft.get('scene_text')}" if soft.get("scene_text") else "",
|
|
||||||
soft_camera_scene,
|
|
||||||
f"framed as {soft_output_composition}" if soft_output_composition else "",
|
|
||||||
soft_camera,
|
|
||||||
soft_style if detail_level != "concise" else "",
|
|
||||||
]
|
|
||||||
hard_parts = [
|
|
||||||
hard_action,
|
|
||||||
_pov_camera_phrase(pov_labels),
|
|
||||||
_natural_label_text(
|
|
||||||
_filter_pov_labeled_clauses(_natural_clothing_state(row.get("hardcore_clothing_state"), hard_action), pov_labels),
|
|
||||||
hard_labels,
|
|
||||||
),
|
),
|
||||||
hard_cast_prose,
|
_krea_pair_format_dependencies(),
|
||||||
f"set in {hard_scene}" if hard_scene else "",
|
|
||||||
hard_camera_scene,
|
|
||||||
_expression_phrase(hard_expression),
|
|
||||||
_composition_phrase(hard_output_composition, hard_action, detail_density=hard_detail_density),
|
|
||||||
hard_camera,
|
|
||||||
hard_style if detail_level != "concise" else "",
|
|
||||||
]
|
|
||||||
return (
|
|
||||||
_paragraph(soft_parts),
|
|
||||||
_combine_negative(row.get("softcore_negative_prompt")),
|
|
||||||
_paragraph(hard_parts),
|
|
||||||
_combine_negative(row.get("hardcore_negative_prompt")),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,226 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Any, Callable
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class KreaPairFormatRequest:
|
||||||
|
row: dict[str, Any]
|
||||||
|
detail_level: str
|
||||||
|
style_mode: str
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class KreaPairPrompts:
|
||||||
|
soft_prompt: str
|
||||||
|
soft_negative: str
|
||||||
|
hard_prompt: str
|
||||||
|
hard_negative: str
|
||||||
|
|
||||||
|
def as_tuple(self) -> tuple[str, str, str, str]:
|
||||||
|
return self.soft_prompt, self.soft_negative, self.hard_prompt, self.hard_negative
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class KreaPairFormatDependencies:
|
||||||
|
clean: Callable[[Any], str]
|
||||||
|
prompt_cast_descriptors: Callable[[str], str]
|
||||||
|
pair_camera_phrase: Callable[[Any, Any, dict[str, Any]], str]
|
||||||
|
camera_scene_phrase: Callable[[dict[str, Any]], str]
|
||||||
|
style_phrase: Callable[[dict[str, Any], str], str]
|
||||||
|
sanitize_hardcore_environment_anchors: Callable[[Any], str]
|
||||||
|
sanitize_hardcore_axis_values: Callable[[Any], Any]
|
||||||
|
sanitize_scene_text_for_cast: Callable[[Any, list[str]], str]
|
||||||
|
normalize_hardcore_detail_density: Callable[[Any], str]
|
||||||
|
row_action_family: Callable[[Any], str]
|
||||||
|
hardcore_action_sentence: Callable[[str, str, str, Any, str, str], str]
|
||||||
|
pov_action_phrase: Callable[[str, list[str], str, str, str, Any, str], str]
|
||||||
|
pov_labels_from_value: Callable[[Any], list[str]]
|
||||||
|
merge_labels: Callable[..., list[str]]
|
||||||
|
cast_prose_omit: Callable[[str, list[str]], tuple[str, list[str]]]
|
||||||
|
label_join: Callable[[list[str]], str]
|
||||||
|
filter_pov_labeled_clauses: Callable[[Any, list[str]], str]
|
||||||
|
natural_label_text: Callable[[Any, list[str]], str]
|
||||||
|
expression_disabled: Callable[[dict[str, Any]], bool]
|
||||||
|
expression_phrase: Callable[[Any], str]
|
||||||
|
pov_camera_phrase: Callable[[list[str]], str]
|
||||||
|
pov_soft_camera_phrase: Callable[[list[str]], str]
|
||||||
|
pov_composition_text: Callable[[Any, list[str]], str]
|
||||||
|
natural_clothing_state: Callable[[Any, str], str]
|
||||||
|
composition_phrase: Callable[..., str]
|
||||||
|
paragraph: Callable[[list[str]], str]
|
||||||
|
combine_negative: Callable[..., str]
|
||||||
|
|
||||||
|
|
||||||
|
def format_insta_pair_result(request: KreaPairFormatRequest, deps: KreaPairFormatDependencies) -> KreaPairPrompts:
|
||||||
|
row = request.row
|
||||||
|
detail_level = request.detail_level
|
||||||
|
style_mode = request.style_mode
|
||||||
|
descriptor = deps.clean(row.get("shared_descriptor"))
|
||||||
|
cast_descriptors = row.get("shared_cast_descriptors")
|
||||||
|
if isinstance(cast_descriptors, list):
|
||||||
|
cast_descriptor_text = "; ".join(deps.clean(item) for item in cast_descriptors if deps.clean(item))
|
||||||
|
else:
|
||||||
|
cast_descriptor_text = deps.clean(cast_descriptors)
|
||||||
|
cast_descriptor_text = deps.prompt_cast_descriptors(cast_descriptor_text)
|
||||||
|
soft = row.get("softcore_row") if isinstance(row.get("softcore_row"), dict) else {}
|
||||||
|
hard = row.get("hardcore_row") if isinstance(row.get("hardcore_row"), dict) else {}
|
||||||
|
soft_camera = deps.pair_camera_phrase(row.get("softcore_camera_directive"), row.get("softcore_camera_config"), soft)
|
||||||
|
hard_camera = deps.pair_camera_phrase(row.get("hardcore_camera_directive"), row.get("hardcore_camera_config"), hard)
|
||||||
|
soft_camera_scene = deps.camera_scene_phrase(soft) or deps.clean(row.get("softcore_camera_scene_directive"))
|
||||||
|
hard_camera_scene = deps.camera_scene_phrase(hard) or deps.clean(row.get("hardcore_camera_scene_directive"))
|
||||||
|
soft_style = deps.style_phrase(soft, style_mode)
|
||||||
|
hard_style = deps.style_phrase(hard, style_mode)
|
||||||
|
options = row.get("options") if isinstance(row.get("options"), dict) else {}
|
||||||
|
soft_level = deps.clean(options.get("softcore_level")).replace("_", " ")
|
||||||
|
hard_level = deps.clean(options.get("hardcore_level")).replace("_", " ")
|
||||||
|
same_room = options.get("continuity") == "same_creator_same_room"
|
||||||
|
hard_scene = soft.get("scene_text") if same_room and soft.get("scene_text") else hard.get("scene_text")
|
||||||
|
hard_composition = deps.sanitize_hardcore_environment_anchors(hard.get("composition"))
|
||||||
|
hard_source_composition = deps.sanitize_hardcore_environment_anchors(hard.get("source_composition") or hard_composition)
|
||||||
|
pov_labels = deps.merge_labels(
|
||||||
|
deps.pov_labels_from_value(row.get("pov_character_labels")),
|
||||||
|
deps.pov_labels_from_value(soft.get("pov_character_labels")),
|
||||||
|
deps.pov_labels_from_value(hard.get("pov_character_labels")),
|
||||||
|
)
|
||||||
|
if pov_labels:
|
||||||
|
hard_camera = ""
|
||||||
|
if options.get("softcore_cast") == "same_as_hardcore":
|
||||||
|
soft_camera = ""
|
||||||
|
soft_cast_descriptor_text = (
|
||||||
|
cast_descriptor_text
|
||||||
|
if options.get("softcore_cast") == "same_as_hardcore"
|
||||||
|
else f"Woman A: {descriptor}"
|
||||||
|
)
|
||||||
|
soft_cast_prose, soft_labels = deps.cast_prose_omit(
|
||||||
|
soft_cast_descriptor_text,
|
||||||
|
pov_labels if options.get("softcore_cast") == "same_as_hardcore" else [],
|
||||||
|
)
|
||||||
|
hard_cast_prose, hard_labels = deps.cast_prose_omit(cast_descriptor_text, pov_labels)
|
||||||
|
soft_labels = deps.merge_labels(soft_labels, pov_labels if options.get("softcore_cast") == "same_as_hardcore" else [])
|
||||||
|
hard_labels = deps.merge_labels(hard_labels, pov_labels)
|
||||||
|
hard_item = deps.sanitize_scene_text_for_cast(
|
||||||
|
deps.sanitize_hardcore_environment_anchors(hard.get("item")),
|
||||||
|
hard_labels,
|
||||||
|
)
|
||||||
|
hard_role_graph = deps.sanitize_scene_text_for_cast(
|
||||||
|
deps.sanitize_hardcore_environment_anchors(hard.get("source_role_graph") or hard.get("role_graph")),
|
||||||
|
hard_labels,
|
||||||
|
)
|
||||||
|
hard_item = deps.natural_label_text(hard_item, hard_labels)
|
||||||
|
hard_role_graph = deps.natural_label_text(hard_role_graph, hard_labels)
|
||||||
|
hard_axis_values = deps.sanitize_hardcore_axis_values(hard.get("item_axis_values"))
|
||||||
|
hard_detail_density = deps.normalize_hardcore_detail_density(
|
||||||
|
hard.get("hardcore_detail_density") or row.get("hardcore_detail_density") or options.get("hardcore_detail_density")
|
||||||
|
)
|
||||||
|
hard_action = deps.hardcore_action_sentence(
|
||||||
|
hard_role_graph,
|
||||||
|
hard_item,
|
||||||
|
hard_source_composition,
|
||||||
|
hard_axis_values,
|
||||||
|
hard_detail_density,
|
||||||
|
deps.row_action_family(hard) or deps.row_action_family(row),
|
||||||
|
)
|
||||||
|
hard_action = deps.pov_action_phrase(
|
||||||
|
hard_action,
|
||||||
|
pov_labels,
|
||||||
|
hard_role_graph,
|
||||||
|
hard_item,
|
||||||
|
hard_source_composition,
|
||||||
|
hard_axis_values,
|
||||||
|
hard_detail_density,
|
||||||
|
)
|
||||||
|
hard_output_composition = deps.pov_composition_text(hard_composition, pov_labels)
|
||||||
|
same_soft_cast = options.get("softcore_cast") == "same_as_hardcore"
|
||||||
|
soft_output_composition = deps.pov_composition_text(soft.get("composition"), pov_labels if same_soft_cast else [])
|
||||||
|
if same_soft_cast and pov_labels:
|
||||||
|
soft_cast_presence = (
|
||||||
|
"the woman is framed from the POV participant's first-person camera in a soft creator-teaser pose, "
|
||||||
|
"with the POV participant kept off-camera as the viewpoint and implied by camera position or foreground cues"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
soft_cast_presence = (
|
||||||
|
f"{deps.label_join(soft_labels)} share the frame in a soft creator-teaser pose"
|
||||||
|
if same_soft_cast
|
||||||
|
else "The image focuses on the woman alone"
|
||||||
|
)
|
||||||
|
partner_styling = row.get("softcore_partner_styling")
|
||||||
|
if isinstance(partner_styling, dict):
|
||||||
|
outfits = partner_styling.get("outfits")
|
||||||
|
partner_outfit_text = "; ".join(deps.clean(item) for item in outfits if deps.clean(item)) if isinstance(outfits, list) else ""
|
||||||
|
partner_pose = deps.clean(partner_styling.get("pose"))
|
||||||
|
else:
|
||||||
|
partner_outfit_text = ""
|
||||||
|
partner_pose = ""
|
||||||
|
partner_outfit_text = deps.filter_pov_labeled_clauses(partner_outfit_text, pov_labels)
|
||||||
|
if pov_labels:
|
||||||
|
partner_pose = ""
|
||||||
|
partner_outfit_text = deps.natural_label_text(partner_outfit_text, soft_labels)
|
||||||
|
|
||||||
|
soft_expression = ""
|
||||||
|
if not deps.expression_disabled(soft):
|
||||||
|
soft_expression_source = deps.filter_pov_labeled_clauses(
|
||||||
|
deps.clean(soft.get("character_expression_text")) or deps.clean(soft.get("expression")),
|
||||||
|
pov_labels,
|
||||||
|
)
|
||||||
|
soft_expression = deps.natural_label_text(
|
||||||
|
soft_expression_source,
|
||||||
|
soft_labels,
|
||||||
|
)
|
||||||
|
hard_expression = ""
|
||||||
|
if not deps.expression_disabled(hard):
|
||||||
|
hard_expression_source = deps.filter_pov_labeled_clauses(
|
||||||
|
deps.clean(hard.get("character_expression_text")) or deps.clean(hard.get("expression")),
|
||||||
|
pov_labels,
|
||||||
|
)
|
||||||
|
hard_expression = deps.natural_label_text(
|
||||||
|
hard_expression_source,
|
||||||
|
hard_labels,
|
||||||
|
)
|
||||||
|
soft_item = deps.clean(soft.get("item"))
|
||||||
|
soft_item_label = deps.clean(soft.get("softcore_item_prompt_label"))
|
||||||
|
soft_item_phrase = ""
|
||||||
|
if soft_item:
|
||||||
|
soft_item_phrase = f"body exposure: {soft_item}" if soft_item_label == "Body exposure" else f"wearing {soft_item}"
|
||||||
|
|
||||||
|
soft_parts = [
|
||||||
|
soft_cast_prose,
|
||||||
|
soft_cast_presence,
|
||||||
|
partner_outfit_text,
|
||||||
|
partner_pose,
|
||||||
|
deps.pov_soft_camera_phrase(pov_labels) if same_soft_cast else "",
|
||||||
|
soft_item_phrase,
|
||||||
|
f"{soft.get('pose')}" if soft.get("pose") else "",
|
||||||
|
deps.expression_phrase(soft_expression),
|
||||||
|
f"in {soft.get('scene_text')}" if soft.get("scene_text") else "",
|
||||||
|
soft_camera_scene,
|
||||||
|
f"framed as {soft_output_composition}" if soft_output_composition else "",
|
||||||
|
soft_camera,
|
||||||
|
soft_style if detail_level != "concise" else "",
|
||||||
|
]
|
||||||
|
hard_parts = [
|
||||||
|
hard_action,
|
||||||
|
deps.pov_camera_phrase(pov_labels),
|
||||||
|
deps.natural_label_text(
|
||||||
|
deps.filter_pov_labeled_clauses(deps.natural_clothing_state(row.get("hardcore_clothing_state"), hard_action), pov_labels),
|
||||||
|
hard_labels,
|
||||||
|
),
|
||||||
|
hard_cast_prose,
|
||||||
|
f"set in {hard_scene}" if hard_scene else "",
|
||||||
|
hard_camera_scene,
|
||||||
|
deps.expression_phrase(hard_expression),
|
||||||
|
deps.composition_phrase(hard_output_composition, hard_action, detail_density=hard_detail_density),
|
||||||
|
hard_camera,
|
||||||
|
hard_style if detail_level != "concise" else "",
|
||||||
|
]
|
||||||
|
return KreaPairPrompts(
|
||||||
|
soft_prompt=deps.paragraph(soft_parts),
|
||||||
|
soft_negative=deps.combine_negative(row.get("softcore_negative_prompt")),
|
||||||
|
hard_prompt=deps.paragraph(hard_parts),
|
||||||
|
hard_negative=deps.combine_negative(row.get("hardcore_negative_prompt")),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def format_insta_pair(request: KreaPairFormatRequest, deps: KreaPairFormatDependencies) -> tuple[str, str, str, str]:
|
||||||
|
return format_insta_pair_result(request, deps).as_tuple()
|
||||||
@@ -43,6 +43,7 @@ import generation_profile_config # noqa: E402
|
|||||||
import index_switch_policy # noqa: E402
|
import index_switch_policy # noqa: E402
|
||||||
import krea_cast # noqa: E402
|
import krea_cast # noqa: E402
|
||||||
import krea_formatter # noqa: E402
|
import krea_formatter # noqa: E402
|
||||||
|
import krea_pair_formatter # noqa: E402
|
||||||
import location_config # noqa: E402
|
import location_config # noqa: E402
|
||||||
import loop_nodes # noqa: E402
|
import loop_nodes # noqa: E402
|
||||||
import pair_builder # noqa: E402
|
import pair_builder # noqa: E402
|
||||||
@@ -3196,6 +3197,15 @@ def smoke_krea_pair_clothing_state() -> None:
|
|||||||
hardcore_position_config=_action_filter("penetration_only"),
|
hardcore_position_config=_action_filter("penetration_only"),
|
||||||
)
|
)
|
||||||
_expect_pair(pair, "krea_pair_clothing_state")
|
_expect_pair(pair, "krea_pair_clothing_state")
|
||||||
|
typed_route = krea_pair_formatter.format_insta_pair_result(
|
||||||
|
krea_pair_formatter.KreaPairFormatRequest(pair, "balanced", "preserve"),
|
||||||
|
krea_formatter._krea_pair_format_dependencies(),
|
||||||
|
)
|
||||||
|
legacy_route = krea_formatter._insta_pair_to_krea(pair, "balanced", "preserve")
|
||||||
|
_expect(
|
||||||
|
typed_route.as_tuple() == legacy_route,
|
||||||
|
"Typed Krea pair formatter route should match legacy wrapper output",
|
||||||
|
)
|
||||||
krea = krea_formatter.format_krea2_prompt("", metadata_json=_json(pair), target="hardcore")
|
krea = krea_formatter.format_krea2_prompt("", metadata_json=_json(pair), target="hardcore")
|
||||||
prompt = _expect_text("krea_pair_clothing_state.krea_prompt", krea.get("krea_prompt"), 60)
|
prompt = _expect_text("krea_pair_clothing_state.krea_prompt", krea.get("krea_prompt"), 60)
|
||||||
lower = prompt.lower()
|
lower = prompt.lower()
|
||||||
|
|||||||
Reference in New Issue
Block a user