ppt-web / src /summeryanyfile /core /models.py
26fwyzpz6f-max
Clean deploy without binary files
6aecb2e
Raw
History Blame Contribute Delete
7.42 kB
"""
数据模型定义
"""
import os
from dataclasses import dataclass
from typing import List, Dict, Any, Literal, TypedDict, Optional
from enum import Enum
def _get_default_max_tokens() -> int:
"""
从环境变量获取默认的 max_tokens 值
Returns:
默认的 max_tokens 值
"""
try:
# 尝试从环境变量读取
env_value = os.getenv("MAX_TOKENS")
if env_value:
return int(env_value)
except (ValueError, TypeError):
pass
# 如果环境变量不存在或无效,返回默认值
return 4000
def _get_default_temperature() -> float:
"""
从环境变量获取默认的 temperature 值
Returns:
默认的 temperature 值
"""
try:
# 尝试从环境变量读取
env_value = os.getenv("TEMPERATURE")
if env_value:
return float(env_value)
except (ValueError, TypeError):
pass
# 如果环境变量不存在或无效,返回默认值
return 0.7
class ChunkStrategy(Enum):
"""文档分块策略"""
PARAGRAPH = "paragraph" # 基于段落分块
SEMANTIC = "semantic" # 语义分块
RECURSIVE = "recursive" # 递归分块
HYBRID = "hybrid" # 混合策略
FAST = "fast" # 快速分块策略
@dataclass
class SlideInfo:
"""幻灯片信息数据类"""
page_number: int
title: str
content_points: List[str]
slide_type: Literal["title", "content", "conclusion"]
description: str
chart_config: Optional[Dict[str, Any]] = None # 新增:图表配置
def to_dict(self) -> Dict[str, Any]:
"""转换为字典格式"""
result = {
"page_number": self.page_number,
"title": self.title,
"content_points": self.content_points,
"slide_type": self.slide_type,
"description": self.description,
}
# 只有当chart_config存在时才添加到字典中
if self.chart_config is not None:
result["chart_config"] = self.chart_config
return result
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "SlideInfo":
"""从字典创建实例"""
return cls(
page_number=data.get("page_number", 1),
title=data.get("title", ""),
content_points=data.get("content_points", []),
slide_type=data.get("slide_type", "content"),
description=data.get("description", ""),
chart_config=data.get("chart_config"), # 新增:图表配置
)
class PPTState(TypedDict):
"""PPT生成状态"""
document_chunks: List[str]
current_index: int
ppt_title: str
slides: List[Dict[str, Any]]
total_pages: int
page_count_mode: str
document_structure: Dict[str, Any]
accumulated_context: str
# 项目信息参数
project_topic: str
project_scenario: str
project_requirements: str
target_audience: str
custom_audience: str
ppt_style: str
custom_style_prompt: str
# 页数设置参数
min_pages: Optional[int]
max_pages: Optional[int]
fixed_pages: Optional[int]
@dataclass
class DocumentInfo:
"""文档信息"""
title: str
content: str
file_path: str
file_type: str
encoding: str
size: int
def to_dict(self) -> Dict[str, Any]:
"""转换为字典格式"""
return {
"title": self.title,
"content": self.content,
"file_path": self.file_path,
"file_type": self.file_type,
"encoding": self.encoding,
"size": self.size,
}
@dataclass
class ProcessingConfig:
"""处理配置"""
max_slides: int = 25
min_slides: int = 5 # 新增:最小页数
chunk_size: int = 3000
chunk_overlap: int = 200
chunk_strategy: ChunkStrategy = ChunkStrategy.PARAGRAPH
llm_model: str = "gpt-4o-mini"
llm_provider: str = "openai"
temperature: float = None # 将在 __post_init__ 中设置默认值
max_tokens: int = None # 将在 __post_init__ 中设置默认值
recursion_limit: Optional[int] = None # 工作流递归限制,None表示自动计算
target_language: str = "zh" # 新增:目标语言,由用户在表单中选择
# API配置(从数据库读取,不使用环境变量)
api_key: Optional[str] = None
base_url: Optional[str] = None
use_responses_api: bool = False
enable_reasoning: bool = False
reasoning_effort: str = "medium"
def __post_init__(self):
"""后处理验证和默认值设置"""
# 如果 max_tokens 为 None,从环境变量获取默认值
if self.max_tokens is None:
self.max_tokens = _get_default_max_tokens()
# 如果 temperature 为 None,从环境变量获取默认值
if self.temperature is None:
self.temperature = _get_default_temperature()
# 验证逻辑
if self.min_slides > self.max_slides:
raise ValueError(f"最小页数({self.min_slides})不能大于最大页数({self.max_slides})")
if self.min_slides < 1:
raise ValueError("最小页数不能小于1")
if self.max_slides > 1000:
raise ValueError("最大页数不能超过1000")
if self.recursion_limit is not None and self.recursion_limit < 10:
raise ValueError("递归限制不能小于10")
@property
def slides_range(self) -> str:
"""获取页数范围的字符串表示"""
if self.min_slides == self.max_slides:
return f"{self.min_slides}页"
return f"{self.min_slides}-{self.max_slides}页"
def to_dict(self) -> Dict[str, Any]:
"""转换为字典格式"""
return {
"max_slides": self.max_slides,
"min_slides": self.min_slides,
"slides_range": self.slides_range,
"chunk_size": self.chunk_size,
"chunk_overlap": self.chunk_overlap,
"chunk_strategy": self.chunk_strategy.value,
"llm_model": self.llm_model,
"llm_provider": self.llm_provider,
"temperature": self.temperature,
"max_tokens": self.max_tokens,
"recursion_limit": self.recursion_limit,
"target_language": self.target_language,
"use_responses_api": self.use_responses_api,
"enable_reasoning": self.enable_reasoning,
"reasoning_effort": self.reasoning_effort,
}
@dataclass
class PPTOutline:
"""PPT大纲结果"""
title: str
total_pages: int
page_count_mode: str
slides: List[SlideInfo]
def to_dict(self) -> Dict[str, Any]:
"""转换为字典格式"""
return {
"title": self.title,
"total_pages": self.total_pages,
"page_count_mode": self.page_count_mode,
"slides": [slide.to_dict() for slide in self.slides],
}
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "PPTOutline":
"""从字典创建实例"""
slides = [SlideInfo.from_dict(slide_data) for slide_data in data.get("slides", [])]
return cls(
title=data.get("title", ""),
total_pages=data.get("total_pages", 0),
page_count_mode=data.get("page_count_mode", "final"),
slides=slides,
)