from pydantic import BaseModel, Field, field_serializer, field_validator, ConfigDict from typing import Optional, List, Dict, Any import datetime import uuid from app.models.models_model import ModelProvider, ModelType # ModelConfig Schemas class ModelConfigBase(BaseModel): """模型配置基础Schema""" name: str = Field(..., description="模型显示名称", max_length=255) type: ModelType = Field(..., description="模型类型") description: Optional[str] = Field(None, description="模型描述") config: Optional[Dict[str, Any]] = Field({}, description="模型配置参数") is_active: bool = Field(True, description="是否激活") is_public: bool = Field(False, description="是否公开") class ApiKeyCreateNested(BaseModel): """用于在创建模型时内嵌创建API Key的Schema""" model_name: str = Field(..., description="模型实际名称", max_length=255) provider: ModelProvider = Field(..., description="API Key提供商") api_key: str = Field(..., description="API密钥", max_length=500) api_base: Optional[str] = Field(None, description="API基础URL", max_length=500) config: Optional[Dict[str, Any]] = Field({}, description="API Key特定配置") priority: str = Field("1", description="优先级", max_length=10) class ModelConfigCreate(ModelConfigBase): """创建模型配置Schema""" api_keys: Optional[ApiKeyCreateNested] = Field(None, description="同时创建的API Key配置") skip_validation: Optional[bool] = Field(False, description="是否跳过配置验证") class ModelConfigUpdate(BaseModel): """更新模型配置Schema""" name: Optional[str] = Field(None, description="模型显示名称", max_length=255) type: Optional[ModelType] = Field(None, description="模型类型") description: Optional[str] = Field(None, description="模型描述") config: Optional[Dict[str, Any]] = Field(None, description="模型配置参数") is_active: Optional[bool] = Field(None, description="是否激活") is_public: Optional[bool] = Field(None, description="是否公开") class ModelConfig(ModelConfigBase): """模型配置Schema""" model_config = ConfigDict(from_attributes=True) id: uuid.UUID created_at: datetime.datetime updated_at: datetime.datetime api_keys: List["ModelApiKey"] = [] # ModelApiKey Schemas class ModelApiKeyBase(BaseModel): """API Key基础Schema""" model_name: str = Field(..., description="模型实际名称", max_length=255) provider: ModelProvider = Field(..., description="API Key提供商") api_key: str = Field(..., description="API密钥", max_length=500) api_base: Optional[str] = Field(None, description="API基础URL", max_length=500) config: Optional[Dict[str, Any]] = Field(None, description="API Key特定配置") is_active: bool = Field(True, description="是否激活") priority: str = Field("1", description="优先级", max_length=10) class ModelApiKeyCreate(ModelApiKeyBase): """创建API Key Schema""" model_config_id: uuid.UUID = Field(..., description="模型配置ID") class ModelApiKeyUpdate(BaseModel): """更新API Key Schema""" model_name: Optional[str] = Field(None, description="模型实际名称", max_length=255) provider: Optional[ModelProvider] = Field(None, description="API Key提供商") api_key: Optional[str] = Field(None, description="API密钥", max_length=500) api_base: Optional[str] = Field(None, description="API基础URL", max_length=500) config: Optional[Dict[str, Any]] = Field(None, description="API Key特定配置") is_active: Optional[bool] = Field(None, description="是否激活") priority: Optional[str] = Field(None, description="优先级", max_length=10) class ModelApiKey(ModelApiKeyBase): """API Key Schema""" id: uuid.UUID model_config_id: uuid.UUID usage_count: str last_used_at: Optional[datetime.datetime] created_at: datetime.datetime updated_at: datetime.datetime @field_validator("config", mode="before") @classmethod def parse_config(cls, v): """处理 config 字段,如果是字符串则解析为字典""" if isinstance(v, str): import json try: return json.loads(v) except json.JSONDecodeError: return {} return v @field_serializer("created_at", when_used="json") def _serialize_created_at(self, dt: datetime.datetime): return int(dt.timestamp() * 1000) if dt else None @field_serializer("updated_at", when_used="json") def _serialize_updated_at(self, dt: datetime.datetime): return int(dt.timestamp() * 1000) if dt else None model_config = ConfigDict(from_attributes=True) @field_serializer("last_used_at", when_used="json") def _serialize_last_used_at(self, dt: datetime.datetime): return int(dt.timestamp() * 1000) if dt else None # 查询和响应Schemas class ModelConfigQuery(BaseModel): """模型配置查询Schema""" type: Optional[List[ModelType]] = Field(None, description="模型类型筛选(支持多个)") provider: Optional[ModelProvider] = Field(None, description="提供商筛选(通过API Key)") is_active: Optional[bool] = Field(None, description="激活状态筛选") is_public: Optional[bool] = Field(None, description="公开状态筛选") search: Optional[str] = Field(None, description="搜索关键词", max_length=255) page: int = Field(1, description="页码", ge=1) pagesize: int = Field(10, description="每页数量", ge=1, le=100) class ModelMarketplace(BaseModel): """模型广场响应Schema""" llm_models: List[ModelConfig] = [] embedding_models: List[ModelConfig] = [] rerank_models: List[ModelConfig] = [] total_count: int active_count: int # 统计信息Schema class ModelStats(BaseModel): """模型统计信息Schema""" total_models: int active_models: int llm_count: int embedding_count: int rerank_count: int provider_stats: Dict[str, int] # 验证模型配置Schema class ModelValidateRequest(BaseModel): """验证模型配置请求""" model_name: str = Field(..., description="模型实际名称") provider: ModelProvider = Field(..., description="API Key提供商") api_key: str = Field(..., description="API密钥") api_base: Optional[str] = Field(None, description="API基础URL") model_type: Optional[ModelType] = Field(ModelType.LLM, description="模型类型") test_message: Optional[str] = Field("Hello", description="测试消息") class ModelValidateResponse(BaseModel): """验证模型配置响应""" valid: bool = Field(..., description="是否有效") message: str = Field(..., description="验证消息") response: Optional[str] = Field(None, description="模型响应内容") elapsed_time: Optional[float] = Field(None, description="响应时间(秒)") error: Optional[str] = Field(None, description="错误信息") usage: Optional[Dict[str, Any]] = Field(None, description="Token使用情况") # 更新前向引用 ModelConfig.model_rebuild()