Files
MuMuAINovel/backend/app/schemas/chapter.py
T
2025-11-30 13:00:26 +08:00

166 lines
6.5 KiB
Python

"""章节相关的Pydantic模型"""
from pydantic import BaseModel, Field
from typing import Optional, List, Dict, Any
from datetime import datetime
class ChapterBase(BaseModel):
"""章节基础模型"""
title: str = Field(..., description="章节标题")
chapter_number: int = Field(..., description="章节序号")
content: Optional[str] = Field(None, description="章节内容")
summary: Optional[str] = Field(None, description="章节摘要")
word_count: Optional[int] = Field(0, description="字数")
status: Optional[str] = Field("draft", description="章节状态")
outline_id: Optional[str] = Field(None, description="关联的大纲ID")
sub_index: Optional[int] = Field(1, description="大纲下的子章节序号")
expansion_plan: Optional[str] = Field(None, description="展开规划详情(JSON)")
class ChapterCreate(BaseModel):
"""创建章节的请求模型"""
project_id: str = Field(..., description="所属项目ID")
title: str = Field(..., description="章节标题")
chapter_number: int = Field(..., description="章节序号")
content: Optional[str] = Field(None, description="章节内容")
summary: Optional[str] = Field(None, description="章节摘要")
status: Optional[str] = Field("draft", description="章节状态")
outline_id: Optional[str] = Field(None, description="关联的大纲ID")
sub_index: Optional[int] = Field(1, description="大纲下的子章节序号")
expansion_plan: Optional[str] = Field(None, description="展开规划详情(JSON)")
class ChapterUpdate(BaseModel):
"""更新章节的请求模型"""
title: Optional[str] = None
content: Optional[str] = None
# chapter_number 不允许修改,只能通过大纲的重排序来调整
summary: Optional[str] = None
# word_count 自动计算,不允许手动修改
status: Optional[str] = None
class ChapterResponse(BaseModel):
"""章节响应模型"""
id: str
project_id: str
title: str
chapter_number: int
content: Optional[str] = None
summary: Optional[str] = None
word_count: int = 0
status: str
outline_id: Optional[str] = None
sub_index: Optional[int] = 1
expansion_plan: Optional[str] = None
outline_title: Optional[str] = None # 大纲标题(从Outline表联查)
outline_order: Optional[int] = None # 大纲排序序号(从Outline表联查)
created_at: datetime
updated_at: datetime
class Config:
from_attributes = True
class ChapterListResponse(BaseModel):
"""章节列表响应模型"""
total: int
items: list[ChapterResponse]
class ChapterGenerateRequest(BaseModel):
"""AI生成章节内容的请求模型"""
style_id: Optional[int] = Field(None, description="写作风格ID,不提供则不使用任何风格")
target_word_count: Optional[int] = Field(
3000,
description="目标字数,默认3000字",
ge=500, # 最小500字
le=10000 # 最大10000字
)
enable_mcp: bool = Field(True, description="是否启用MCP工具增强(搜索参考资料)")
class BatchGenerateRequest(BaseModel):
"""批量生成章节的请求模型"""
start_chapter_number: int = Field(..., description="起始章节序号")
count: int = Field(..., description="生成章节数量", ge=1, le=20)
style_id: Optional[int] = Field(None, description="写作风格ID")
target_word_count: Optional[int] = Field(
3000,
description="目标字数,默认3000字",
ge=500,
le=10000
)
enable_analysis: bool = Field(False, description="是否启用同步分析")
enable_mcp: bool = Field(True, description="是否启用MCP工具增强(搜索参考资料)")
max_retries: int = Field(3, description="每个章节的最大重试次数", ge=0, le=5)
class BatchGenerateResponse(BaseModel):
"""批量生成响应模型"""
batch_id: str = Field(..., description="批次ID")
message: str = Field(..., description="响应消息")
chapters_to_generate: list[dict] = Field(..., description="待生成章节列表")
estimated_time_minutes: int = Field(..., description="预估耗时(分钟)")
class BatchGenerateStatusResponse(BaseModel):
"""批量生成状态响应模型"""
batch_id: str
status: str
total: int
completed: int
current_chapter_id: Optional[str] = None
current_chapter_number: Optional[int] = None
current_retry_count: Optional[int] = None
max_retries: Optional[int] = None
failed_chapters: list[dict] = []
created_at: Optional[str] = None
started_at: Optional[str] = None
completed_at: Optional[str] = None
error_message: Optional[str] = None
class SceneData(BaseModel):
"""场景数据模型"""
location: str = Field(..., description="场景地点")
characters: List[str] = Field(..., description="参与角色列表")
purpose: str = Field(..., description="场景目的")
class ExpansionPlanUpdate(BaseModel):
"""章节规划更新模型"""
summary: Optional[str] = Field(None, description="章节情节概要")
key_events: Optional[List[str]] = Field(None, description="关键事件列表")
character_focus: Optional[List[str]] = Field(None, description="涉及角色列表")
emotional_tone: Optional[str] = Field(None, description="情感基调")
narrative_goal: Optional[str] = Field(None, description="叙事目标")
conflict_type: Optional[str] = Field(None, description="冲突类型")
estimated_words: Optional[int] = Field(None, description="预估字数", ge=500, le=10000)
scenes: Optional[List[SceneData]] = Field(None, description="场景列表")
class Config:
json_schema_extra = {
"example": {
"key_events": ["主角遇到挑战", "关键决策时刻"],
"character_focus": ["张三", "李四"],
"emotional_tone": "紧张激烈",
"narrative_goal": "推进主线剧情",
"conflict_type": "内心冲突",
"estimated_words": 3000,
"scenes": [
{
"location": "城市广场",
"characters": ["张三", "李四"],
"purpose": "初次相遇"
}
]
}
}
class ExpansionPlanResponse(BaseModel):
"""章节规划响应模型"""
id: str = Field(..., description="章节ID")
expansion_plan: Optional[Dict[str, Any]] = Field(None, description="规划数据")
message: str = Field(..., description="响应消息")