from pydantic import BaseModel, Field from typing import List, Optional from enum import StrEnum, auto class SpaceType(StrEnum): exterior_front = auto() exterior_night = auto() exterior_aerial = auto() exterior_sign = auto() garden = auto() entrance = auto() lobby = auto() reception = auto() hallway = auto() bedroom = auto() livingroom = auto() kitchen = auto() dining = auto() room = auto() bathroom = auto() amenity = auto() view_window = auto() view_ocean = auto() view_city = auto() view_mountain = auto() balcony = auto() cafe = auto() lounge = auto() rooftop = auto() pool = auto() breakfast_hall = auto() spa = auto() fitness = auto() bbq = auto() terrace = auto() glamping = auto() neighborhood = auto() landmark = auto() detail_welcome = auto() detail_beverage = auto() detail_lighting = auto() detail_decor = auto() detail_tableware = auto() class Subject(StrEnum): empty_space = auto() exterior_building = auto() architecture_detail = auto() decoration = auto() furniture = auto() food_dish = auto() nature = auto() signage = auto() amenity_item = auto() person = auto() class Camera(StrEnum): wide_angle = auto() tight_crop = auto() panoramic = auto() symmetrical = auto() leading_line = auto() golden_hour = auto() night_shot = auto() high_contrast = auto() low_light = auto() drone_shot = auto() has_face = auto() class MotionRecommended(StrEnum): static = auto() slow_pan = auto() slow_zoom_in = auto() slow_zoom_out = auto() walkthrough = auto() dolly = auto() class NarrativePhase(StrEnum): intro = auto() welcome = auto() core = auto() highlight = auto() support = auto() accent = auto() class NarrativePreference(BaseModel): intro: float = Field(..., description="첫인상 — 여기가 어디인가 | 장소의 정체성과 위치를 전달하는 이미지. 영상 첫 1~2초에 어떤 곳인지 즉시 인지시키는 역할. 건물 외관, 간판, 정원 등 **장소 자체를 보여주는** 컷") welcome: float = Field(..., description="진입/환영 — 어떻게 들어가나 | 도착 후 내부로 들어가는 경험을 전달하는 이미지. 공간의 첫 분위기와 동선을 보여줘 들어가고 싶다는 기대감을 만드는 역할. **문을 열고 들어갔을 때 보이는** 컷.") core: float = Field(..., description="핵심 가치 — 무엇을 경험하나 | **고객이 이 장소를 찾는 본질적 이유.** 이 이미지가 없으면 영상 자체가 성립하지 않음. 질문: 이 비즈니스에서 돈을 지불하는 대상이 뭔가? → 그 답이 core.") highlight: float = Field(..., description="차별화 — 뭐가 특별한가 | **같은 카테고리의 경쟁사 대비 이곳을 선택하게 만드는 이유.** core가 왜 왔는가라면, highlight는 왜 **여기**인가에 대한 답.") support: float = Field(..., description="보조/부대 — 그 외에 뭐가 있나 | 핵심은 아니지만 전체 경험을 풍성하게 하는 부가 요소. 없어도 영상은 성립하지만, 있으면 설득력이 올라감. **이것도 있어요** 라고 말하는 컷.") accent: float = Field(..., description="감성/마무리 — 어떤 느낌인가 | 공간의 분위기와 톤을 전달하는 감성 디테일 컷. 직접적 정보 전달보다 **느낌과 무드**를 제공. 영상 사이사이에 삽입되어 완성도를 높이는 역할.") # Input 정의 class ImageTagPromptInput(BaseModel): img_url : str = Field(..., description="이미지 URL") space_type: list[str] = Field(list(SpaceType), description="공간적 정보를 가지는 태그 리스트") subject: list[str] = Field(list(Subject), description="피사체 정보를 가지는 태그 리스트") camera: list[str] = Field(list(Camera), description="카메라 정보를 가지는 태그 리스트") motion_recommended: list[str] = Field(list(MotionRecommended), description="가능한 카메라 모션 리스트") # Output 정의 class ImageTagPromptOutput(BaseModel): #ad_avaliable : bool = Field(..., description="광고 영상 사용 가능 이미지 여부") space_type: list[SpaceType] = Field(..., description="공간적 정보를 가지는 태그 리스트") subject: list[Subject] = Field(..., description="피사체 정보를 가지는 태그 리스트") camera: list[Camera] = Field(..., description="카메라 정보를 가지는 태그 리스트") motion_recommended: list[MotionRecommended] = Field(..., description="가능한 카메라 모션 리스트") narrative_preference: NarrativePreference = Field(..., description="이미지의 내러티브 상 점수")