Files
dreamtail/api/models.py
Vixy e4294b57e6 DreamTail v1.0.0 with IP-Adapter FaceID support
- SDXL image generation using RealVisXL_V4.0
- IP-Adapter FaceID integration for consistent face generation
- Simplified API (removed client_id requirement)
- New params: face_image, face_strength
- 'vixy' shortcut for face-locked generation
- Queue-based async job processing
- FastAPI with proper error handling

Co-authored-by: Alex <alex@k4zka.online>
2026-01-01 19:54:59 -06:00

74 lines
2.9 KiB
Python
Executable File

"""
Pydantic models for API requests and responses.
"""
from typing import Optional, Dict, Any, Literal
from pydantic import BaseModel, Field, validator
from datetime import datetime
import config
class GenerationParams(BaseModel):
"""Optional generation parameters."""
width: int = Field(default=config.DEFAULT_WIDTH, ge=512, le=2048)
height: int = Field(default=config.DEFAULT_HEIGHT, ge=512, le=2048)
num_inference_steps: int = Field(default=config.DEFAULT_STEPS, ge=config.MIN_STEPS, le=config.MAX_STEPS)
guidance_scale: float = Field(default=config.DEFAULT_GUIDANCE_SCALE, ge=config.MIN_GUIDANCE, le=config.MAX_GUIDANCE)
seed: Optional[int] = Field(default=None, description="Random seed for reproducibility")
face_image: Optional[str] = Field(default=None, description="Face reference image name (from faces directory) or 'vixy' for default")
face_strength: float = Field(default=config.DEFAULT_FACE_STRENGTH, ge=0.0, le=1.0, description="Face conditioning strength (0.0-1.0)")
@validator('width', 'height')
def must_be_multiple_of_8(cls, v):
if v % 8 != 0:
raise ValueError('Width and height must be multiples of 8')
return v
class GenerateRequest(BaseModel):
"""Request to generate an image."""
prompt: str = Field(..., min_length=1, max_length=2000, description="Text prompt for image generation")
negative_prompt: Optional[str] = Field(default=None, max_length=2000, description="Negative prompt to avoid certain features")
params: Optional[GenerationParams] = Field(default_factory=GenerationParams)
class JobResponse(BaseModel):
"""Response when submitting a generation job."""
job_id: str = Field(..., description="Unique job identifier")
status: Literal["queued", "processing", "completed", "failed"] = Field(..., description="Current job status")
created_at: datetime = Field(..., description="Job creation timestamp")
message: Optional[str] = Field(default=None, description="Optional message")
class JobStatus(BaseModel):
"""Detailed job status information."""
job_id: str
status: Literal["queued", "processing", "completed", "failed"]
progress: int = Field(..., ge=0, le=100, description="Progress percentage (0-100)")
created_at: datetime
started_at: Optional[datetime] = None
completed_at: Optional[datetime] = None
error: Optional[str] = None
prompt: str
class HealthResponse(BaseModel):
"""Health check response."""
model_config = {"protected_namespaces": ()} # Allow "model_" prefix
status: Literal["healthy", "unhealthy"]
version: str
model_loaded: bool
queue_size: int
active_jobs: int
uptime_seconds: float
class ModelsResponse(BaseModel):
"""Available models information."""
base_model: str
refiner_model: Optional[str] = None
refiner_enabled: bool
device: str
fp16_enabled: bool