"""陪练模块Pydantic模式""" from typing import Optional, List, Dict, Any, Generic, TypeVar from datetime import datetime from pydantic import BaseModel, Field, ConfigDict # 定义泛型类型变量 DataT = TypeVar("DataT") from app.models.training import ( TrainingSceneStatus, TrainingSessionStatus, MessageType, MessageRole, ) from app.schemas.base import BaseSchema, TimestampMixin, IDMixin # ========== 陪练场景相关 ========== class TrainingSceneBase(BaseSchema): """陪练场景基础模式""" name: str = Field(..., max_length=100, description="场景名称") description: Optional[str] = Field(None, description="场景描述") category: str = Field(..., max_length=50, description="场景分类") ai_config: Optional[Dict[str, Any]] = Field(None, description="AI配置") prompt_template: Optional[str] = Field(None, description="提示词模板") evaluation_criteria: Optional[Dict[str, Any]] = Field(None, description="评估标准") is_public: bool = Field(True, description="是否公开") required_level: Optional[int] = Field(None, description="所需用户等级") class TrainingSceneCreate(TrainingSceneBase): """创建陪练场景模式""" status: TrainingSceneStatus = Field( default=TrainingSceneStatus.DRAFT, description="场景状态" ) class TrainingSceneUpdate(BaseSchema): """更新陪练场景模式""" name: Optional[str] = Field(None, max_length=100) description: Optional[str] = None category: Optional[str] = Field(None, max_length=50) ai_config: Optional[Dict[str, Any]] = None prompt_template: Optional[str] = None evaluation_criteria: Optional[Dict[str, Any]] = None status: Optional[TrainingSceneStatus] = None is_public: Optional[bool] = None required_level: Optional[int] = None class TrainingSceneInDB(TrainingSceneBase, IDMixin, TimestampMixin): """数据库中的陪练场景模式""" status: TrainingSceneStatus is_deleted: bool = False created_by: Optional[int] = None updated_by: Optional[int] = None class TrainingSceneResponse(TrainingSceneInDB): """陪练场景响应模式""" pass # ========== 陪练会话相关 ========== class TrainingSessionBase(BaseSchema): """陪练会话基础模式""" scene_id: int = Field(..., description="场景ID") session_config: Optional[Dict[str, Any]] = Field(None, description="会话配置") class TrainingSessionCreate(TrainingSessionBase): """创建陪练会话模式""" pass class TrainingSessionUpdate(BaseSchema): """更新陪练会话模式""" status: Optional[TrainingSessionStatus] = None end_time: Optional[datetime] = None duration_seconds: Optional[int] = None total_score: Optional[float] = None evaluation_result: Optional[Dict[str, Any]] = None class TrainingSessionInDB(TrainingSessionBase, IDMixin, TimestampMixin): """数据库中的陪练会话模式""" user_id: int coze_conversation_id: Optional[str] = None start_time: datetime end_time: Optional[datetime] = None duration_seconds: Optional[int] = None status: TrainingSessionStatus total_score: Optional[float] = None evaluation_result: Optional[Dict[str, Any]] = None created_by: Optional[int] = None updated_by: Optional[int] = None class TrainingSessionResponse(TrainingSessionInDB): """陪练会话响应模式""" scene: Optional["TrainingSceneResponse"] = None message_count: Optional[int] = Field(None, description="消息数量") # ========== 消息相关 ========== class TrainingMessageBase(BaseSchema): """陪练消息基础模式""" role: MessageRole = Field(..., description="消息角色") type: MessageType = Field(..., description="消息类型") content: str = Field(..., description="消息内容") voice_url: Optional[str] = Field(None, max_length=500, description="语音文件URL") voice_duration: Optional[float] = Field(None, description="语音时长(秒)") metadata: Optional[Dict[str, Any]] = Field(None, description="消息元数据") class TrainingMessageCreate(TrainingMessageBase): """创建陪练消息模式""" session_id: int = Field(..., description="会话ID") coze_message_id: Optional[str] = Field(None, max_length=100, description="Coze消息ID") class TrainingMessageInDB(TrainingMessageBase, IDMixin, TimestampMixin): """数据库中的陪练消息模式""" session_id: int coze_message_id: Optional[str] = None class TrainingMessageResponse(TrainingMessageInDB): """陪练消息响应模式""" pass # ========== 报告相关 ========== class TrainingReportBase(BaseSchema): """陪练报告基础模式""" overall_score: float = Field(..., ge=0, le=100, description="总体得分") dimension_scores: Dict[str, float] = Field(..., description="各维度得分") strengths: List[str] = Field(..., description="优势点") weaknesses: List[str] = Field(..., description="待改进点") suggestions: List[str] = Field(..., description="改进建议") detailed_analysis: Optional[str] = Field(None, description="详细分析") transcript: Optional[str] = Field(None, description="对话文本记录") statistics: Optional[Dict[str, Any]] = Field(None, description="统计数据") class TrainingReportCreate(TrainingReportBase): """创建陪练报告模式""" session_id: int = Field(..., description="会话ID") user_id: int = Field(..., description="用户ID") class TrainingReportInDB(TrainingReportBase, IDMixin, TimestampMixin): """数据库中的陪练报告模式""" session_id: int user_id: int created_by: Optional[int] = None updated_by: Optional[int] = None class TrainingReportResponse(TrainingReportInDB): """陪练报告响应模式""" session: Optional[TrainingSessionResponse] = None # ========== 会话操作相关 ========== class StartTrainingRequest(BaseSchema): """开始陪练请求""" scene_id: int = Field(..., description="场景ID") config: Optional[Dict[str, Any]] = Field(None, description="会话配置") class StartTrainingResponse(BaseSchema): """开始陪练响应""" session_id: int = Field(..., description="会话ID") coze_conversation_id: Optional[str] = Field(None, description="Coze会话ID") scene: TrainingSceneResponse = Field(..., description="场景信息") websocket_url: Optional[str] = Field(None, description="WebSocket连接URL") class EndTrainingRequest(BaseSchema): """结束陪练请求""" generate_report: bool = Field(True, description="是否生成报告") class EndTrainingResponse(BaseSchema): """结束陪练响应""" session: TrainingSessionResponse = Field(..., description="会话信息") report: Optional[TrainingReportResponse] = Field(None, description="陪练报告") # ========== 列表查询相关 ========== class TrainingSceneListQuery(BaseSchema): """陪练场景列表查询参数""" category: Optional[str] = Field(None, description="场景分类") status: Optional[TrainingSceneStatus] = Field(None, description="场景状态") is_public: Optional[bool] = Field(None, description="是否公开") search: Optional[str] = Field(None, description="搜索关键词") page: int = Field(1, ge=1, description="页码") page_size: int = Field(20, ge=1, le=100, description="每页数量") class TrainingSessionListQuery(BaseSchema): """陪练会话列表查询参数""" scene_id: Optional[int] = Field(None, description="场景ID") status: Optional[TrainingSessionStatus] = Field(None, description="会话状态") start_date: Optional[datetime] = Field(None, description="开始日期") end_date: Optional[datetime] = Field(None, description="结束日期") page: int = Field(1, ge=1, description="页码") page_size: int = Field(20, ge=1, le=100, description="每页数量") class PaginatedResponse(BaseModel, Generic[DataT]): """分页响应模式""" items: List[DataT] = Field(..., description="数据列表") total: int = Field(..., description="总数量") page: int = Field(..., description="当前页码") page_size: int = Field(..., description="每页数量") pages: int = Field(..., description="总页数") # 更新前向引用 TrainingSessionResponse.model_rebuild() TrainingReportResponse.model_rebuild()