Extract shared POV policy

This commit is contained in:
2026-06-27 03:22:25 +02:00
parent 9ca2320df2
commit 61535cc60d
6 changed files with 197 additions and 96 deletions
+8 -41
View File
@@ -39,6 +39,7 @@ try:
from . import pair_output
from . import pair_rows
from . import pair_options
from . import pov_policy
from . import row_normalization as row_policy
from . import row_camera as row_camera_policy
from . import row_location as row_location_policy
@@ -81,6 +82,7 @@ except ImportError: # Allows local smoke tests with `python -c`.
import pair_output
import pair_rows
import pair_options
import pov_policy
import row_normalization as row_policy
import row_camera as row_camera_policy
import row_location as row_location_policy
@@ -1790,9 +1792,7 @@ def _normalize_presence_mode(value: Any, subject_type: str) -> str:
def _slot_is_pov(slot: dict[str, Any] | None) -> bool:
if not slot:
return False
return slot.get("subject_type") == "man" and slot.get("presence_mode") == "pov"
return pov_policy.slot_is_pov(slot)
def _normalize_slot_expression_intensity(value: Any) -> float:
@@ -2457,56 +2457,23 @@ def _pov_character_labels(
label_map: dict[str, dict[str, Any]],
men_count: int | None = None,
) -> list[str]:
if men_count is None:
labels = sorted(label for label in label_map if label.startswith("Man "))
else:
labels = [f"Man {chr(ord('A') + index)}" for index in range(max(0, men_count))]
return [label for label in labels if _slot_is_pov(label_map.get(label))]
return pov_policy.pov_character_labels(label_map, men_count)
def _pov_text_with_viewer(text: Any, pov_labels: list[str]) -> str:
rendered = str(text or "").strip()
if not rendered or not pov_labels:
return rendered
for label in sorted(pov_labels, key=len, reverse=True):
escaped = re.escape(label)
rendered = re.sub(rf"\b{escaped}'s\b", "the POV viewer's", rendered)
rendered = re.sub(rf"\b{escaped}\b", "the POV viewer", rendered)
rendered = re.sub(r"\bthe POV viewer is positioned\b", "the POV camera is positioned", rendered, flags=re.IGNORECASE)
return _clean_prompt_punctuation(rendered)
return pov_policy.pov_text_with_viewer(text, pov_labels)
def _pov_role_graph_prompt(role_graph: Any, pov_labels: list[str]) -> str:
role_graph_text = str(role_graph or "").strip()
if not role_graph_text or not pov_labels:
return role_graph_text
viewer_text = _pov_text_with_viewer(role_graph_text, pov_labels)
label_text = ", ".join(pov_labels)
return f"First-person POV from {label_text}; {viewer_text}"
return pov_policy.pov_role_graph_prompt(role_graph, pov_labels)
def _pov_prompt_directive(pov_labels: list[str]) -> str:
if not pov_labels:
return ""
label_text = ", ".join(pov_labels)
return (
f"POV participant: {label_text} is the first-person camera viewpoint; "
"he remains the off-camera viewpoint, represented by foreground hands, body position, or camera perspective cues when needed."
)
return pov_policy.pov_prompt_directive(pov_labels)
def _pov_composition_prompt(composition: Any, pov_labels: list[str]) -> str:
text = str(composition or "").strip()
if not text or not pov_labels:
return text
text = re.sub(r"\ball participants visible\b", "visible partners readable", text, flags=re.IGNORECASE)
text = re.sub(r"\ball adult bodies visible\b", "visible partners readable", text, flags=re.IGNORECASE)
text = re.sub(r"\ball bodies visible\b", "visible partners readable", text, flags=re.IGNORECASE)
text = re.sub(r"\ball three bodies readable\b", "visible partner bodies readable", text, flags=re.IGNORECASE)
text = re.sub(r"\bwide group-sex composition\b", "first-person group-sex POV composition", text, flags=re.IGNORECASE)
if "pov" not in text.lower() and "first-person" not in text.lower():
text = f"{text}, adapted for first-person POV with the POV participant kept off-camera"
return _clean_prompt_punctuation(text)
return pov_policy.pov_composition_prompt(composition, pov_labels)
def _body_exposure_scene_text(scene: Any) -> str: