添加Docker自包含部署分支
- 新增 Seg_Server_Docker 自包含部署内容,包含前后端、FastAPI、Celery、PostgreSQL、Redis、MinIO、演示视频和 DICOM 数据。 - 保留 demo 数据以支持恢复演示出厂设置,排除 SAM 2.1 .pt 权重并在 README 中补充下载命令。 - 补充 GPU 部署、backend/worker 镜像复用、frpc/frps + NPM 公网域名反代部署说明。 - 在 .env/.env.example 中用 # XXXX 标注局域网和公网域名部署需要修改的配置项。 - 添加部署分支 .gitignore,忽略本地模型权重、构建产物、缓存和日志。
This commit is contained in:
385
backend/schemas.py
Normal file
385
backend/schemas.py
Normal file
@@ -0,0 +1,385 @@
|
||||
"""Pydantic schemas for request/response validation."""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Literal, Optional, Any
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Auth / user schemas
|
||||
# ---------------------------------------------------------------------------
|
||||
class UserOut(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
username: str
|
||||
role: str
|
||||
is_active: int
|
||||
|
||||
|
||||
class LoginResponse(BaseModel):
|
||||
token: str
|
||||
token_type: str = "bearer"
|
||||
username: str
|
||||
user: UserOut
|
||||
|
||||
|
||||
class AdminUserCreate(BaseModel):
|
||||
username: str
|
||||
password: str
|
||||
role: str = "annotator"
|
||||
is_active: bool = True
|
||||
|
||||
|
||||
class AdminUserUpdate(BaseModel):
|
||||
username: Optional[str] = None
|
||||
password: Optional[str] = None
|
||||
role: Optional[str] = None
|
||||
is_active: Optional[bool] = None
|
||||
|
||||
|
||||
class AuditLogOut(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
actor_user_id: Optional[int] = None
|
||||
action: str
|
||||
target_type: Optional[str] = None
|
||||
target_id: Optional[str] = None
|
||||
detail: Optional[dict[str, Any]] = None
|
||||
created_at: datetime
|
||||
|
||||
|
||||
class DemoFactoryResetRequest(BaseModel):
|
||||
confirmation: str
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Project schemas
|
||||
# ---------------------------------------------------------------------------
|
||||
class ProjectBase(BaseModel):
|
||||
name: str
|
||||
description: Optional[str] = None
|
||||
video_path: Optional[str] = None
|
||||
thumbnail_url: Optional[str] = None
|
||||
status: Optional[str] = "pending"
|
||||
source_type: Optional[str] = "video"
|
||||
original_fps: Optional[float] = None
|
||||
parse_fps: Optional[float] = 30.0
|
||||
|
||||
|
||||
class ProjectCreate(ProjectBase):
|
||||
pass
|
||||
|
||||
|
||||
class ProjectUpdate(BaseModel):
|
||||
name: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
video_path: Optional[str] = None
|
||||
thumbnail_url: Optional[str] = None
|
||||
status: Optional[str] = None
|
||||
source_type: Optional[str] = None
|
||||
original_fps: Optional[float] = None
|
||||
parse_fps: Optional[float] = None
|
||||
|
||||
|
||||
class ProjectCopyRequest(BaseModel):
|
||||
mode: Literal["reset", "full"] = "reset"
|
||||
name: Optional[str] = None
|
||||
|
||||
|
||||
class ProjectOut(ProjectBase):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
owner_user_id: Optional[int] = None
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
frame_count: int = 0
|
||||
|
||||
|
||||
class DemoFactoryResetOut(BaseModel):
|
||||
admin_user: UserOut
|
||||
project: ProjectOut
|
||||
projects: list[ProjectOut]
|
||||
deleted_counts: dict[str, int]
|
||||
message: str
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Frame schemas
|
||||
# ---------------------------------------------------------------------------
|
||||
class FrameBase(BaseModel):
|
||||
frame_index: int
|
||||
image_url: str
|
||||
width: Optional[int] = None
|
||||
height: Optional[int] = None
|
||||
timestamp_ms: Optional[float] = None
|
||||
source_frame_number: Optional[int] = None
|
||||
|
||||
|
||||
class FrameCreate(FrameBase):
|
||||
project_id: int
|
||||
|
||||
|
||||
class FrameOut(FrameBase):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
project_id: int
|
||||
created_at: datetime
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Template schemas
|
||||
# ---------------------------------------------------------------------------
|
||||
class TemplateBase(BaseModel):
|
||||
name: str
|
||||
description: Optional[str] = None
|
||||
color: str
|
||||
z_index: int = 0
|
||||
mapping_rules: Optional[dict[str, Any]] = None
|
||||
classes: Optional[list[dict[str, Any]]] = None
|
||||
rules: Optional[list[dict[str, Any]]] = None
|
||||
|
||||
|
||||
class TemplateCreate(TemplateBase):
|
||||
pass
|
||||
|
||||
|
||||
class TemplateUpdate(BaseModel):
|
||||
name: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
color: Optional[str] = None
|
||||
z_index: Optional[int] = None
|
||||
mapping_rules: Optional[dict[str, Any]] = None
|
||||
classes: Optional[list[dict[str, Any]]] = None
|
||||
rules: Optional[list[dict[str, Any]]] = None
|
||||
|
||||
|
||||
class TemplateOut(TemplateBase):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
owner_user_id: Optional[int] = None
|
||||
created_at: datetime
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Annotation schemas
|
||||
# ---------------------------------------------------------------------------
|
||||
class AnnotationBase(BaseModel):
|
||||
project_id: int
|
||||
frame_id: Optional[int] = None
|
||||
template_id: Optional[int] = None
|
||||
mask_data: Optional[dict[str, Any]] = None
|
||||
points: Optional[list[list[float]]] = None
|
||||
bbox: Optional[list[float]] = None
|
||||
|
||||
|
||||
class AnnotationCreate(AnnotationBase):
|
||||
pass
|
||||
|
||||
|
||||
class AnnotationUpdate(BaseModel):
|
||||
mask_data: Optional[dict[str, Any]] = None
|
||||
points: Optional[list[list[float]]] = None
|
||||
bbox: Optional[list[float]] = None
|
||||
template_id: Optional[int] = None
|
||||
|
||||
|
||||
class AnnotationOut(AnnotationBase):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Mask schemas
|
||||
# ---------------------------------------------------------------------------
|
||||
class MaskBase(BaseModel):
|
||||
annotation_id: int
|
||||
mask_url: str
|
||||
format: str = "png"
|
||||
|
||||
|
||||
class MaskCreate(MaskBase):
|
||||
pass
|
||||
|
||||
|
||||
class MaskOut(MaskBase):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
created_at: datetime
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Processing task schemas
|
||||
# ---------------------------------------------------------------------------
|
||||
class ProcessingTaskOut(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
task_type: str
|
||||
status: str
|
||||
progress: int
|
||||
message: Optional[str] = None
|
||||
project_id: Optional[int] = None
|
||||
celery_task_id: Optional[str] = None
|
||||
payload: Optional[dict[str, Any]] = None
|
||||
result: Optional[dict[str, Any]] = None
|
||||
error: Optional[str] = None
|
||||
created_at: datetime
|
||||
started_at: Optional[datetime] = None
|
||||
finished_at: Optional[datetime] = None
|
||||
updated_at: datetime
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# AI schemas
|
||||
# ---------------------------------------------------------------------------
|
||||
class PredictRequest(BaseModel):
|
||||
image_id: int
|
||||
prompt_type: str # point / box / semantic
|
||||
prompt_data: Any
|
||||
model: Optional[str] = None
|
||||
options: Optional[dict[str, Any]] = None
|
||||
|
||||
|
||||
class PredictResponse(BaseModel):
|
||||
polygons: list[list[list[float]]]
|
||||
scores: Optional[list[float]] = None
|
||||
|
||||
|
||||
class MaskAnalysisRequest(BaseModel):
|
||||
frame_id: Optional[int] = None
|
||||
mask_data: dict[str, Any]
|
||||
points: Optional[list[list[float]]] = None
|
||||
bbox: Optional[list[float]] = None
|
||||
extract_skeleton: bool = False
|
||||
|
||||
|
||||
class MaskAnalysisResponse(BaseModel):
|
||||
confidence: Optional[float] = None
|
||||
confidence_source: str
|
||||
topology_anchor_count: int
|
||||
topology_anchors: list[list[float]]
|
||||
area: float
|
||||
bbox: Optional[list[float]] = None
|
||||
source: Optional[str] = None
|
||||
message: str
|
||||
|
||||
|
||||
class SmoothMaskRequest(BaseModel):
|
||||
frame_id: Optional[int] = None
|
||||
mask_data: dict[str, Any]
|
||||
points: Optional[list[list[float]]] = None
|
||||
bbox: Optional[list[float]] = None
|
||||
strength: float = 0.0
|
||||
method: str = "chaikin"
|
||||
|
||||
|
||||
class SmoothMaskResponse(BaseModel):
|
||||
polygons: list[list[list[float]]]
|
||||
topology_anchor_count: int
|
||||
topology_anchors: list[list[float]]
|
||||
area: float
|
||||
bbox: Optional[list[float]] = None
|
||||
smoothing: dict[str, Any]
|
||||
message: str
|
||||
|
||||
|
||||
class PropagationSeed(BaseModel):
|
||||
polygons: Optional[list[list[list[float]]]] = None
|
||||
holes: Optional[list[list[list[list[float]]]]] = None
|
||||
bbox: Optional[list[float]] = None
|
||||
points: Optional[list[list[float]]] = None
|
||||
labels: Optional[list[int]] = None
|
||||
label: Optional[str] = None
|
||||
color: Optional[str] = None
|
||||
class_metadata: Optional[dict[str, Any]] = None
|
||||
template_id: Optional[int] = None
|
||||
source_mask_id: Optional[str] = None
|
||||
source_annotation_id: Optional[int] = None
|
||||
source_instance_id: Optional[str] = None
|
||||
propagation_seed_signature: Optional[str] = None
|
||||
smoothing: Optional[dict[str, Any]] = None
|
||||
|
||||
|
||||
class PropagateRequest(BaseModel):
|
||||
project_id: int
|
||||
frame_id: int
|
||||
model: Optional[str] = "sam2.1_hiera_tiny"
|
||||
seed: PropagationSeed
|
||||
direction: str = "forward"
|
||||
max_frames: int = 30
|
||||
include_source: bool = False
|
||||
save_annotations: bool = True
|
||||
|
||||
|
||||
class PropagateResponse(BaseModel):
|
||||
model: str
|
||||
direction: str
|
||||
source_frame_id: int
|
||||
processed_frame_count: int
|
||||
created_annotation_count: int
|
||||
annotations: list[AnnotationOut]
|
||||
|
||||
|
||||
class PropagateTaskStep(BaseModel):
|
||||
seed: PropagationSeed
|
||||
direction: str = "forward"
|
||||
max_frames: int = 30
|
||||
|
||||
|
||||
class PropagateTaskRequest(BaseModel):
|
||||
project_id: int
|
||||
frame_id: int
|
||||
model: Optional[str] = "sam2.1_hiera_tiny"
|
||||
steps: list[PropagateTaskStep]
|
||||
include_source: bool = False
|
||||
save_annotations: bool = True
|
||||
|
||||
|
||||
class AiModelStatus(BaseModel):
|
||||
id: str
|
||||
label: str
|
||||
available: bool
|
||||
loaded: bool = False
|
||||
device: str
|
||||
supports: list[str]
|
||||
message: str
|
||||
package_available: bool = False
|
||||
checkpoint_exists: bool = False
|
||||
checkpoint_path: Optional[str] = None
|
||||
python_ok: bool = True
|
||||
torch_ok: bool = True
|
||||
cuda_required: bool = False
|
||||
external_available: bool = False
|
||||
external_python: Optional[str] = None
|
||||
|
||||
|
||||
class GpuStatus(BaseModel):
|
||||
available: bool
|
||||
device: str
|
||||
name: Optional[str] = None
|
||||
torch_available: bool
|
||||
torch_version: Optional[str] = None
|
||||
cuda_version: Optional[str] = None
|
||||
|
||||
|
||||
class AiRuntimeStatus(BaseModel):
|
||||
selected_model: str
|
||||
gpu: GpuStatus
|
||||
models: list[AiModelStatus]
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Export schemas
|
||||
# ---------------------------------------------------------------------------
|
||||
class ExportStatus(BaseModel):
|
||||
url: str
|
||||
format: str
|
||||
Reference in New Issue
Block a user