| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- """
- Pydantic schemas for External API.
- Defines request and response models for external system integration.
- """
- from datetime import datetime
- from typing import Optional, List, Any
- from enum import Enum
- from pydantic import BaseModel, Field
- # ============== 枚举定义 ==============
- class TaskType(str, Enum):
- """支持的任务类型"""
- TEXT_CLASSIFICATION = "text_classification"
- IMAGE_CLASSIFICATION = "image_classification"
- OBJECT_DETECTION = "object_detection"
- NER = "ner"
- class ExternalExportFormat(str, Enum):
- """支持的导出格式"""
- JSON = "json"
- CSV = "csv"
- SHAREGPT = "sharegpt"
- YOLO = "yolo"
- COCO = "coco"
- ALPACA = "alpaca"
- # ============== 项目初始化相关 ==============
- class TaskDataItem(BaseModel):
- """单个任务数据项"""
- id: Optional[str] = Field(None, description="外部系统的数据ID,用于关联")
- content: str = Field(..., description="数据内容(文本或图像URL)")
- metadata: Optional[dict] = Field(None, description="额外元数据")
-
- class Config:
- json_schema_extra = {
- "example": {
- "id": "ext_001",
- "content": "https://example.com/image.jpg",
- "metadata": {"batch": "001", "source": "商品库"}
- }
- }
- class ProjectInitRequest(BaseModel):
- """项目初始化请求"""
- name: str = Field(..., min_length=1, description="项目名称")
- description: Optional[str] = Field("", description="项目描述")
- task_type: TaskType = Field(..., description="任务类型")
- data: List[TaskDataItem] = Field(..., min_length=1, description="任务数据列表")
- external_id: Optional[str] = Field(None, description="外部系统的项目ID,用于关联查询")
-
- class Config:
- json_schema_extra = {
- "example": {
- "name": "图像分类项目-批次001",
- "description": "对商品图片进行分类标注",
- "task_type": "image_classification",
- "data": [
- {
- "id": "ext_001",
- "content": "https://example.com/images/product1.jpg",
- "metadata": {"batch": "001"}
- }
- ],
- "external_id": "sample_center_proj_001"
- }
- }
- class ProjectInitResponse(BaseModel):
- """项目初始化响应"""
- project_id: str = Field(..., description="标注平台项目ID,样本中心需保存用于后续回调")
- project_name: str = Field(..., description="项目名称")
- task_count: int = Field(..., description="创建的任务数量")
- status: str = Field(..., description="项目状态")
- created_at: datetime = Field(..., description="创建时间")
- config: str = Field(..., description="实际使用的XML配置模板")
- external_id: Optional[str] = Field(None, description="外部系统的项目ID")
-
- class Config:
- json_schema_extra = {
- "example": {
- "project_id": "proj_abc123def456",
- "project_name": "图像分类项目-批次001",
- "task_count": 100,
- "status": "draft",
- "created_at": "2026-02-03T10:30:00Z",
- "config": "<View>...</View>",
- "external_id": "sample_center_proj_001"
- }
- }
- # ============== 进度查询相关 ==============
- class AnnotatorProgress(BaseModel):
- """标注人员进度"""
- user_id: str = Field(..., description="用户ID")
- username: str = Field(..., description="用户名")
- assigned_count: int = Field(..., description="分配的任务数")
- completed_count: int = Field(..., description="已完成数")
- in_progress_count: int = Field(..., description="进行中数")
- completion_rate: float = Field(..., description="个人完成率(0-100)")
- class ProgressResponse(BaseModel):
- """项目进度响应"""
- project_id: str = Field(..., description="项目ID")
- project_name: str = Field(..., description="项目名称")
- status: str = Field(..., description="项目状态")
- total_tasks: int = Field(..., description="总任务数")
- completed_tasks: int = Field(..., description="已完成任务数")
- in_progress_tasks: int = Field(..., description="进行中任务数")
- pending_tasks: int = Field(..., description="待处理任务数")
- completion_percentage: float = Field(..., description="完成百分比(0-100)")
- annotators: List[AnnotatorProgress] = Field(default_factory=list, description="标注人员列表")
- last_updated: Optional[datetime] = Field(None, description="最后更新时间")
-
- class Config:
- json_schema_extra = {
- "example": {
- "project_id": "proj_abc123def456",
- "project_name": "图像分类项目-批次001",
- "status": "in_progress",
- "total_tasks": 100,
- "completed_tasks": 45,
- "in_progress_tasks": 30,
- "pending_tasks": 25,
- "completion_percentage": 45.0,
- "annotators": [
- {
- "user_id": "user_001",
- "username": "annotator1",
- "assigned_count": 50,
- "completed_count": 25,
- "in_progress_count": 15,
- "completion_rate": 50.0
- }
- ],
- "last_updated": "2026-02-03T15:30:00Z"
- }
- }
- # ============== 数据导出相关 ==============
- class ExternalExportRequest(BaseModel):
- """导出请求"""
- format: ExternalExportFormat = Field(
- default=ExternalExportFormat.JSON,
- description="导出格式"
- )
- completed_only: bool = Field(
- default=True,
- description="是否只导出已完成的任务"
- )
- callback_url: Optional[str] = Field(
- None,
- description="回调URL,导出完成后通知样本中心"
- )
-
- class Config:
- json_schema_extra = {
- "example": {
- "format": "sharegpt",
- "completed_only": True,
- "callback_url": "https://sample-center.example.com/api/callback/export"
- }
- }
- class ExportedTaskData(BaseModel):
- """导出的任务数据"""
- task_id: str = Field(..., description="任务ID")
- external_id: Optional[str] = Field(None, description="外部系统的数据ID")
- original_data: dict = Field(..., description="原始数据")
- annotations: List[dict] = Field(default_factory=list, description="标注结果列表")
- status: str = Field(..., description="任务状态")
- annotator: Optional[str] = Field(None, description="标注人员")
- completed_at: Optional[datetime] = Field(None, description="完成时间")
- class ExternalExportResponse(BaseModel):
- """导出响应"""
- project_id: str = Field(..., description="项目ID")
- format: str = Field(..., description="导出格式")
- total_exported: int = Field(..., description="导出的任务数量")
- file_url: str = Field(..., description="文件下载URL")
- file_name: str = Field(..., description="文件名")
- file_size: Optional[int] = Field(None, description="文件大小(字节)")
- expires_at: Optional[datetime] = Field(None, description="下载链接过期时间")
-
- class Config:
- json_schema_extra = {
- "example": {
- "project_id": "proj_abc123def456",
- "format": "sharegpt",
- "total_exported": 45,
- "file_url": "/api/exports/export_789/download",
- "file_name": "export_proj_abc123_sharegpt_20260203.json",
- "file_size": 1024000,
- "expires_at": "2026-02-10T10:30:00Z"
- }
- }
- class ExportCallbackPayload(BaseModel):
- """导出完成回调载荷"""
- project_id: str = Field(..., description="项目ID")
- export_id: str = Field(..., description="导出任务ID")
- status: str = Field(..., description="状态:completed 或 failed")
- format: str = Field(..., description="导出格式")
- total_exported: int = Field(..., description="导出的任务数量")
- file_url: str = Field(..., description="文件下载URL(完整URL)")
- file_name: str = Field(..., description="文件名")
- file_size: int = Field(..., description="文件大小(字节)")
- error_message: Optional[str] = Field(None, description="错误信息(失败时)")
- # ============== 错误响应 ==============
- class ErrorResponse(BaseModel):
- """统一错误响应格式"""
- error_code: str = Field(..., description="错误码")
- message: str = Field(..., description="错误信息")
- details: Optional[dict] = Field(None, description="详细信息")
-
- class Config:
- json_schema_extra = {
- "example": {
- "error_code": "PROJECT_NOT_FOUND",
- "message": "项目不存在",
- "details": {"project_id": "proj_invalid"}
- }
- }
|