from __future__ import annotations from dataclasses import dataclass from typing import Any try: from . import generate_prompt_batches as g from . import pov_policy from . import row_camera as row_camera_policy from . import row_expression as row_expression_policy from . import row_rendering as row_rendering_policy except ImportError: # Allows local smoke tests from the repository root. import generate_prompt_batches as g import pov_policy import row_camera as row_camera_policy import row_expression as row_expression_policy import row_rendering as row_rendering_policy @dataclass(frozen=True) class CustomRowAssemblyRequest: row_number: int start_index: int category: dict[str, Any] subcategory: dict[str, Any] item: Any context: dict[str, Any] subject_type: str item_text: str item_name: str item_axis_values: dict[str, Any] item_template_metadata: dict[str, Any] formatter_hints: dict[str, Any] item_label: str style: str positive_suffix: str negative_prompt: str scene_slug: str scene: str pose: str expression: str shared_expression: str character_expressions: list[str] character_expression_text: str expression_disabled: bool expression_intensity: float | None expression_intensity_source: str composition: str source_composition: str role_graph: str source_role_graph: str action_family: str position_family: str position_key: str position_keys: list[str] pov_character_labels: list[str] cast_descriptors: list[str] cast_descriptor_text: str seed_config: dict[str, Any] hardcore_position_config: dict[str, Any] | None = None location_config: dict[str, Any] | None = None composition_config: dict[str, Any] | None = None content_seed_axis: str = "content" count_adjustment: dict[str, Any] | None = None applied_profile: dict[str, Any] | None = None profile_status: str = "none" applied_slot: dict[str, Any] | None = None slot_status: str = "none" character_slots: list[dict[str, Any]] | None = None def assemble_custom_row(request: CustomRowAssemblyRequest) -> dict[str, Any]: r = request render_context = dict(r.context) pov_prompt_directive = pov_policy.pov_prompt_directive(r.pov_character_labels) render_context.update( { "trigger": g.TRIGGER, "main_category": r.category["name"], "subcategory": r.subcategory["name"], "category": r.category["name"], "item": r.item_text, "item_name": r.item_name, "item_label": r.item_label, "style": r.style, "scene": r.scene, "scene_slug": r.scene_slug, "pose": r.pose, "expression": r.expression, "shared_expression": r.shared_expression, "character_expressions": r.character_expressions, "character_expression_text": r.character_expression_text, "expression_enabled": not r.expression_disabled, "expression_disabled": r.expression_disabled, "expression_intensity": r.expression_intensity, "expression_intensity_source": r.expression_intensity_source, "composition": r.composition, "source_composition": r.source_composition, "composition_prompt": row_camera_policy.composition_prompt(r.composition), "composition_config": r.composition_config or {}, "role_graph": r.role_graph, "source_role_graph": r.source_role_graph, "action_family": r.action_family, "position_family": r.position_family, "position_key": r.position_key, "position_keys": r.position_keys, "pov_character_labels": r.pov_character_labels, "pov_prompt_directive": pov_prompt_directive, "cast_descriptors": r.cast_descriptor_text, "positive_suffix": r.positive_suffix, "negative_prompt": r.negative_prompt, } ) rendered = row_rendering_policy.render_prompt_caption( item=r.item, subcategory=r.subcategory, category=r.category, subject_type=r.subject_type, context=render_context, cast_descriptor_text=r.cast_descriptor_text, pov_prompt_directive=pov_prompt_directive if r.pov_character_labels else "", ) batch = max(1, ((r.row_number - 1) // g.BATCH_SIZE) + 1) index = r.start_index + r.row_number - 1 row = g.row_base( index, batch, render_context["subject"], render_context["age"], render_context["body"], r.scene_slug, r.composition, ) row.update( { "prompt": rendered["prompt"], "caption": rendered["caption"], "negative_prompt": r.negative_prompt, "expression": r.expression, "main_category": r.category["name"], "subcategory": r.subcategory["name"], "category_slug": r.category["slug"], "subcategory_slug": r.subcategory["slug"], "subject_type": r.subject_type, "subject_phrase": render_context.get("subject_phrase", ""), "body_phrase": render_context.get("body_phrase", ""), "skin": render_context.get("skin", ""), "hair": render_context.get("hair", ""), "eyes": render_context.get("eyes", ""), "style": r.style, "item": r.item_text, "item_label": r.item_label, "positive_suffix": r.positive_suffix, "custom_item": r.item_name, "item_axis_values": r.item_axis_values, "item_template_metadata": r.item_template_metadata, "formatter_hints": r.formatter_hints, "scene_text": r.scene, "location_config": r.location_config or {}, "pose": r.pose, "seed_config": r.seed_config, "hardcore_position_config": r.hardcore_position_config or {}, "content_seed_axis": r.content_seed_axis, "role_graph": r.role_graph, "source_role_graph": r.source_role_graph, "action_family": r.action_family, "position_family": r.position_family, "position_key": r.position_key, "position_keys": r.position_keys, "source_composition": r.source_composition, "pov_character_labels": r.pov_character_labels, "pov_prompt_directive": pov_prompt_directive, "shared_expression": r.shared_expression, "character_expressions": r.character_expressions, "character_expression_text": r.character_expression_text, "expression_enabled": not r.expression_disabled, "expression_disabled": r.expression_disabled, "cast_summary": render_context.get("cast_summary", ""), "cast_descriptors": r.cast_descriptors, "cast_descriptor_text": r.cast_descriptor_text, "scene_kind": render_context.get("scene_kind", ""), "women_count": render_context.get("women_count", ""), "men_count": render_context.get("men_count", ""), "person_count": render_context.get("person_count", ""), "cast_count_adjustment": r.count_adjustment if r.subject_type == "configured_cast" else {}, "character_profile": r.applied_profile or {}, "character_profile_status": r.profile_status, "character_slot": r.applied_slot or {}, "character_slot_status": r.slot_status, "character_cast_slots": r.character_slots or [], "expression_intensity": r.expression_intensity, "expression_intensity_source": r.expression_intensity_source, "source": "json_category", } ) if render_context.get("figure"): row["figure"] = render_context["figure"] if r.expression_disabled: row = row_expression_policy.disable_row_expression(row, r.expression_intensity_source) return row