from __future__ import annotations from typing import Optional from pydantic import BaseModel, Field class ImageInput(BaseModel): image_b64: str = Field(..., description="PNG/JPG 编码后的 base64(不含 data: 前缀)") model_name: Optional[str] = Field(None, description="模型 key(来自 /models)") class DepthRequest(ImageInput): pass class SegmentRequest(ImageInput): pass class SamPromptSegmentRequest(BaseModel): image_b64: str = Field(..., description="裁剪后的 RGB 图 base64(PNG/JPG)") overlay_b64: Optional[str] = Field( None, description="与裁剪同尺寸的标记叠加 PNG base64(可选;当前用于校验尺寸一致)", ) point_coords: list[list[float]] = Field( ..., description="裁剪坐标系下的提示点 [[x,y], ...]", ) point_labels: list[int] = Field( ..., description="与 point_coords 等长:1=前景,0=背景", ) box_xyxy: list[float] = Field( ..., description="裁剪内笔画紧包围盒 [x1,y1,x2,y2](像素)", min_length=4, max_length=4, ) expand_px: int = Field( 2, ge=0, le=20, description="对输出 mask 做轻微膨胀的像素半径(0 表示不扩大;建议 1~3)", ) class InpaintRequest(ImageInput): prompt: Optional[str] = Field("", description="补全 prompt") strength: float = Field(0.8, ge=0.0, le=1.0) negative_prompt: Optional[str] = Field("", description="负向 prompt") mask_b64: Optional[str] = Field(None, description="mask PNG base64(可选)") max_side: int = Field(1024, ge=128, le=2048) class AnimateRequest(BaseModel): model_name: Optional[str] = Field(None, description="模型 key(来自 /models)") prompt: str = Field(..., description="文本提示词") negative_prompt: Optional[str] = Field("", description="负向提示词") num_inference_steps: int = Field(25, ge=1, le=200) guidance_scale: float = Field(8.0, ge=0.0, le=30.0) width: int = Field(512, ge=128, le=2048) height: int = Field(512, ge=128, le=2048) video_length: int = Field(16, ge=1, le=128) seed: int = Field(-1, description="-1 表示随机种子") class CharacterAnimateRequest(BaseModel): image_b64: str = Field(..., description="透明背景角色 PNG 的 base64(不含 data: 前缀)") model_name: Optional[str] = Field(None, description="模型 key(来自 /models)") prompt: str = Field(..., description="角色动画提示词") negative_prompt: Optional[str] = Field("", description="负向提示词") background_color: str = Field( "#00FF00", description="生成时使用的纯色背景,支持 #RRGGBB 或 R,G,B", ) background_tolerance: int = Field( 40, ge=0, le=255, description="自动剔除背景的 RGB 色差阈值,越大剔除越激进", ) num_inference_steps: int = Field(25, ge=1, le=200) guidance_scale: float = Field(8.0, ge=0.0, le=30.0) video_length: int = Field(16, ge=1, le=128, description="前端请求生成的帧数") seed: int = Field(-1, description="-1 表示随机种子") max_side: int = Field( 768, ge=128, le=2048, description="推理分辨率长边上限;会保持输入比例并对齐到 8 的倍数", )