Ctrl K
ComunidadGuías…

src/imagegen/contracts.py

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
"""Stable contracts for DiceFrame image generation."""

from __future__ import annotations

from dataclasses import dataclass, field
import re
from typing import Any


IMAGE_PURPOSES = frozenset({"scene", "avatar", "item", "map", "freeform"})
IMAGE_PROVIDER_IDS = frozenset({"openai-compatible", "minimax"})
# 提示词模板变量是一份契约:配置校验、AI 优化和最终组合必须认同一套变量名,
# 否则会出现「设置页存得下、生图时替换不掉」这类只在运行时才暴露的偏差。
PROMPT_TEMPLATE_VARIABLES = frozenset({"scene", "narration", "actions", "panels"})
PROMPT_TEMPLATE_VARIABLE_RE = re.compile(r"\{([A-Za-z_][A-Za-z0-9_]*)\}")


def game_image_owner_id(game_key: Any) -> str:
    if isinstance(game_key, (list, tuple)):
        return ":".join(str(part) for part in game_key)
    return str(game_key or "")


@dataclass(frozen=True)
class ImageReference:
    """Ephemeral image input; bytes never enter persisted generation records."""

    character_id: str
    content: bytes
    content_type: str = "image/webp"
    file_name: str = "reference.webp"


@dataclass(frozen=True)
class ImageGenerationRequest:
    prompt: str
    purpose: str = "freeform"
    owner_type: str = "system"
    owner_id: str = ""
    aspect_ratio: str = ""
    style: str = ""
    context: dict[str, Any] = field(default_factory=dict)
    reference_images: tuple[ImageReference, ...] = ()


@dataclass(frozen=True)
class ImageGenerationResult:
    generation_id: str
    asset_id: str
    purpose: str
    prompt: str
    revised_prompt: str
    provider: str
    model: str
    created_at: str

    def public_dict(self) -> dict[str, Any]:
        return {
            "generation_id": self.generation_id,
            "asset_id": self.asset_id,
            "purpose": self.purpose,
            "prompt": self.prompt,
            "revised_prompt": self.revised_prompt,
            "provider": self.provider,
            "model": self.model,
            "created_at": self.created_at,
        }