Files
MuMuAINovel/backend/app/schemas/foreshadow.py
T

197 lines
6.9 KiB
Python
Raw Normal View History

"""伏笔管理 Pydantic Schema"""
from pydantic import BaseModel, Field
from typing import Optional, List
from datetime import datetime
from enum import Enum
class ForeshadowStatus(str, Enum):
"""伏笔状态枚举"""
PENDING = "pending" # 待埋入
PLANTED = "planted" # 已埋入
RESOLVED = "resolved" # 已回收
PARTIALLY_RESOLVED = "partially_resolved" # 部分回收
ABANDONED = "abandoned" # 已废弃
class ForeshadowSourceType(str, Enum):
"""伏笔来源类型"""
ANALYSIS = "analysis" # 分析提取
MANUAL = "manual" # 手动添加
class ForeshadowCategory(str, Enum):
"""伏笔分类"""
IDENTITY = "identity" # 身世
MYSTERY = "mystery" # 悬念
ITEM = "item" # 物品
RELATIONSHIP = "relationship" # 关系
EVENT = "event" # 事件
ABILITY = "ability" # 能力
PROPHECY = "prophecy" # 预言
class ForeshadowBase(BaseModel):
"""伏笔基础信息"""
title: str = Field(..., min_length=1, max_length=200, description="伏笔标题")
content: str = Field(..., min_length=1, description="伏笔详细内容/描述")
hint_text: Optional[str] = Field(None, description="埋伏笔时的暗示文本")
resolution_text: Optional[str] = Field(None, description="回收伏笔时的揭示文本")
# 章节关联
plant_chapter_number: Optional[int] = Field(None, ge=1, description="计划埋入章节号")
target_resolve_chapter_number: Optional[int] = Field(None, ge=1, description="计划回收章节号")
# 状态
is_long_term: bool = Field(False, description="是否长线伏笔")
# 重要性
importance: float = Field(0.5, ge=0.0, le=1.0, description="重要性评分 0.0-1.0")
strength: int = Field(5, ge=1, le=10, description="伏笔强度 1-10")
subtlety: int = Field(5, ge=1, le=10, description="隐藏度 1-10")
# 关联信息
related_characters: Optional[List[str]] = Field(None, description="关联角色名列表")
tags: Optional[List[str]] = Field(None, description="标签列表")
category: Optional[str] = Field(None, description="分类")
# 备注
notes: Optional[str] = Field(None, description="创作备注")
resolution_notes: Optional[str] = Field(None, description="回收方式说明")
# AI辅助设置
auto_remind: bool = Field(True, description="是否自动提醒")
remind_before_chapters: int = Field(5, ge=1, le=20, description="提前几章提醒")
include_in_context: bool = Field(True, description="是否包含在生成上下文中")
class ForeshadowCreate(ForeshadowBase):
"""创建伏笔请求"""
project_id: str = Field(..., description="项目ID")
class ForeshadowUpdate(BaseModel):
"""更新伏笔请求"""
title: Optional[str] = Field(None, min_length=1, max_length=200)
content: Optional[str] = Field(None, min_length=1)
hint_text: Optional[str] = None
resolution_text: Optional[str] = None
plant_chapter_number: Optional[int] = Field(None, ge=1)
target_resolve_chapter_number: Optional[int] = Field(None, ge=1)
status: Optional[ForeshadowStatus] = None
is_long_term: Optional[bool] = None
importance: Optional[float] = Field(None, ge=0.0, le=1.0)
strength: Optional[int] = Field(None, ge=1, le=10)
subtlety: Optional[int] = Field(None, ge=1, le=10)
urgency: Optional[int] = Field(None, ge=0, le=3)
related_characters: Optional[List[str]] = None
related_foreshadow_ids: Optional[List[str]] = None
tags: Optional[List[str]] = None
category: Optional[str] = None
notes: Optional[str] = None
resolution_notes: Optional[str] = None
auto_remind: Optional[bool] = None
remind_before_chapters: Optional[int] = Field(None, ge=1, le=20)
include_in_context: Optional[bool] = None
class ForeshadowResponse(ForeshadowBase):
"""伏笔响应"""
id: str
project_id: str
source_type: Optional[str] = None
source_memory_id: Optional[str] = None
source_analysis_id: Optional[str] = None
plant_chapter_id: Optional[str] = None
target_resolve_chapter_id: Optional[str] = None
actual_resolve_chapter_id: Optional[str] = None
actual_resolve_chapter_number: Optional[int] = None
status: str = "pending"
urgency: int = 0
related_foreshadow_ids: Optional[List[str]] = None
created_at: Optional[datetime] = None
updated_at: Optional[datetime] = None
planted_at: Optional[datetime] = None
resolved_at: Optional[datetime] = None
class Config:
from_attributes = True
class ForeshadowListResponse(BaseModel):
"""伏笔列表响应"""
total: int
items: List[ForeshadowResponse]
stats: Optional[dict] = None
class ForeshadowStatsResponse(BaseModel):
"""伏笔统计响应"""
total: int
pending: int
planted: int
resolved: int
partially_resolved: int
abandoned: int
long_term_count: int
overdue_count: int # 超期未回收数量
class PlantForeshadowRequest(BaseModel):
"""标记伏笔埋入请求"""
chapter_id: str = Field(..., description="埋入章节ID")
chapter_number: int = Field(..., ge=1, description="埋入章节号")
hint_text: Optional[str] = Field(None, description="暗示文本")
class ResolveForeshadowRequest(BaseModel):
"""标记伏笔回收请求"""
chapter_id: str = Field(..., description="回收章节ID")
chapter_number: int = Field(..., ge=1, description="回收章节号")
resolution_text: Optional[str] = Field(None, description="揭示文本")
is_partial: bool = Field(False, description="是否部分回收")
class SyncFromAnalysisRequest(BaseModel):
"""从分析同步伏笔请求"""
chapter_ids: Optional[List[str]] = Field(None, description="指定章节ID列表,为空则同步全部")
overwrite_existing: bool = Field(False, description="是否覆盖已存在的伏笔")
auto_set_planted: bool = Field(True, description="自动设置为已埋入状态")
class SyncFromAnalysisResponse(BaseModel):
"""从分析同步伏笔响应"""
synced_count: int
skipped_count: int
resolved_count: int = 0
new_foreshadows: List[ForeshadowResponse] = []
skipped_reasons: List[dict] = []
class ForeshadowContextRequest(BaseModel):
"""获取章节伏笔上下文请求"""
chapter_number: int = Field(..., ge=1, description="章节号")
include_pending: bool = Field(True, description="包含待埋入伏笔")
include_overdue: bool = Field(True, description="包含超期伏笔")
lookahead: int = Field(5, ge=1, le=20, description="向前看几章")
class ForeshadowContextResponse(BaseModel):
"""伏笔上下文响应"""
chapter_number: int
context_text: str
pending_plant: List[ForeshadowResponse] # 本章待埋入
pending_resolve: List[ForeshadowResponse] # 即将需要回收
overdue: List[ForeshadowResponse] # 超期未回收
recently_planted: List[ForeshadowResponse] # 最近埋入(可铺垫)