""" 脚本相关 Schema =============== """ from typing import Any from pydantic import BaseModel, Field from app.schemas.segment import Segment ScriptShot = Segment class SubcategoryItem(BaseModel): """小类项""" code: str = Field(..., description="小类代码") name: str = Field(..., description="小类名称") count: int = Field(..., description="提示词文件数量") class CategoryItem(BaseModel): """大类项""" code: str = Field(..., description="大类代码") name: str = Field(..., description="大类名称") subcategories: list[SubcategoryItem] = Field(..., description="小类列表") class GenerateScriptRequest(BaseModel): """生成脚本请求""" category: str = Field(..., description="大类代码,如 bk") subcategory: str = Field(..., description="小类代码,如 ht") duration: int = Field(default=45, ge=30, le=180, description="视频时长(秒)") script_type: str = Field(default="干货型", description="脚本类型") model: str | None = Field(None, description="指定模型(可选)") class PolishRequest(BaseModel): """润色请求""" content: str = Field(..., description="待润色内容", min_length=1) polish_type: str = Field(default="voiceover", description="润色类型:scene / voiceover") shot_type: str | None = Field( default="segment", description="镜头类型:segment(分镜) / empty_shot(空镜),用于画面润色时区分", ) class ScriptGenerationEvent(BaseModel): """ 脚本生成 SSE 事件 与前端 ScriptGenerationEvent 对应 事件类型说明: - start: 开始生成 - generating: AI 生成中 - complete: 完成 - error: 错误 """ type: str = Field( ..., description="事件类型:start / generating / complete / error", ) progress: int = Field(default=0, ge=0, le=100, description="进度百分比") message: str = Field(..., description="状态描述") result: list[Any] | None = Field(None, description="生成的分镜结果(complete 时)") extracted_info: dict[str, Any] | None = Field( None, description="提取的视频信息(complete 时,如果是视频链接)" ) class ModelHealthInfo(BaseModel): """模型健康信息""" id: str = Field(..., description="模型 ID") name: str = Field(..., description="模型名称") is_available: bool = Field(..., description="是否可用") response_time: float = Field(..., description="响应时间(毫秒)") last_error: str | None = Field(None, description="上次错误信息") class ModelHealthResponse(BaseModel): """模型健康检查响应""" status: str = Field(..., description="整体状态:healthy / unhealthy / error") models: list[ModelHealthInfo] = Field(..., description="各模型状态") recommended_model: ModelHealthInfo | None = Field(None, description="推荐的模型") total_models: int = Field(..., description="模型总数") available_models: int = Field(..., description="可用模型数") error: str | None = Field(None, description="错误信息") class TestModelRequest(BaseModel): """测试模型请求""" model_id: str | None = Field(None, description="要测试的模型 ID") class TestModelResponse(BaseModel): """测试模型响应""" success: bool = Field(..., description="是否成功") model: str = Field(..., description="模型名称") response_time: float | None = Field(None, description="响应时间(毫秒)") error: str | None = Field(None, description="错误信息") checked_at: str | None = Field(None, description="检查时间 ISO 格式") class GenerateTitleRequest(BaseModel): """生成标题请求""" script_content: str = Field(..., description="脚本内容(utterances 文本拼接)", min_length=1) title_type: str = Field(..., description="标题类型:main(大标题) / sub(小标题)") max_length: int = Field(default=8, ge=1, le=100, description="最大字数限制") class GenerateTitleResponse(BaseModel): """生成标题响应""" title: str = Field(..., description="生成的标题")