""" API 스키마 정의 iopaint와 호환되는 입출력 형식을 지원합니다. """ from typing import Optional, List, Dict, Any from pydantic import BaseModel, Field from enum import Enum class Device(str, Enum): cpu = "cpu" cuda = "cuda" mps = "mps" class InpaintRequest(BaseModel): """인페인팅 요청 스키마 (iopaint 호환)""" image: str = Field(..., description="base64로 인코딩된 원본 이미지") mask: str = Field(..., description="base64로 인코딩된 마스크 이미지") sd_seed: Optional[int] = Field(-1, description="Stable Diffusion 시드") prompt: Optional[str] = Field("", description="프롬프트") negative_prompt: Optional[str] = Field("", description="네거티브 프롬프트") num_inference_steps: Optional[int] = Field(20, description="추론 스텝 수") guidance_scale: Optional[float] = Field(7.5, description="가이던스 스케일") strength: Optional[float] = Field(1.0, description="인페인팅 강도") model_name: Optional[str] = Field("simple-lama", description="사용할 모델명") class RemoveBGRequest(BaseModel): """배경 제거 요청 스키마""" image: str = Field(..., description="base64로 인코딩된 이미지") model_name: Optional[str] = Field("rembg", description="사용할 모델명") class PluginRequest(BaseModel): """플러그인 요청 기본 스키마""" name: str = Field(..., description="플러그인 이름") image: str = Field(..., description="base64로 인코딩된 이미지") model_name: Optional[str] = Field(None, description="사용할 모델명") class AdjustMaskRequest(BaseModel): """마스크 조정 요청 스키마""" mask: str = Field(..., description="base64로 인코딩된 마스크") kernel_size: int = Field(5, description="커널 크기") operate: str = Field("dilate", description="연산 타입 (dilate/erode)") class InpaintResponse(BaseModel): """인페인팅 응답 스키마""" success: bool = Field(..., description="성공 여부") image: Optional[str] = Field(None, description="base64로 인코딩된 결과 이미지") error: Optional[str] = Field(None, description="에러 메시지") processing_time: Optional[float] = Field(None, description="처리 시간 (초)") seed: Optional[int] = Field(None, description="사용된 시드") class RemoveBGResponse(BaseModel): """배경 제거 응답 스키마""" success: bool = Field(..., description="성공 여부") image: Optional[str] = Field(None, description="base64로 인코딩된 결과 이미지") mask: Optional[str] = Field(None, description="base64로 인코딩된 마스크") error: Optional[str] = Field(None, description="에러 메시지") processing_time: Optional[float] = Field(None, description="처리 시간 (초)") class PluginResponse(BaseModel): """플러그인 응답 스키마""" success: bool = Field(..., description="성공 여부") image: Optional[str] = Field(None, description="base64로 인코딩된 결과 이미지") mask: Optional[str] = Field(None, description="base64로 인코딩된 마스크") error: Optional[str] = Field(None, description="에러 메시지") processing_time: Optional[float] = Field(None, description="처리 시간 (초)") class ModelInfo(BaseModel): """모델 정보 스키마""" name: str = Field(..., description="모델명") type: str = Field(..., description="모델 타입 (inpainting/rembg)") description: Optional[str] = Field(None, description="모델 설명") supported_formats: List[str] = Field(default_factory=list, description="지원하는 이미지 형식") max_image_size: Optional[int] = Field(None, description="최대 이미지 크기") class ServerConfigResponse(BaseModel): """서버 설정 응답 스키마""" models: List[ModelInfo] = Field(..., description="사용 가능한 모델 목록") max_file_size: int = Field(..., description="최대 파일 크기 (MB)") supported_formats: List[str] = Field(..., description="지원하는 이미지 형식") device: Device = Field(..., description="현재 사용 중인 디바이스") is_jetson: bool = Field(..., description="Jetson 시스템 여부") class HealthResponse(BaseModel): """헬스 체크 응답 스키마""" status: str = Field(..., description="서버 상태") timestamp: str = Field(..., description="현재 시간") version: str = Field(..., description="서버 버전") uptime: float = Field(..., description="가동 시간 (초)") class ErrorResponse(BaseModel): """에러 응답 스키마""" error: str = Field(..., description="에러 메시지") detail: Optional[str] = Field(None, description="상세 에러 정보") timestamp: str = Field(..., description="에러 발생 시간")