TravelContentCreator/api/models/vibrant_poster.py

331 lines
14 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
海报API通用模型定义
支持多种模板类型的海报生成
"""
from typing import List, Dict, Any, Optional, Union
from pydantic import BaseModel, Field
# 基础模板信息
class TemplateInfo(BaseModel):
"""模板信息模型"""
id: str = Field(..., description="模板ID")
name: str = Field(..., description="模板名称")
description: str = Field(..., description="模板描述")
size: List[int] = Field(..., description="模板尺寸 [宽, 高]")
required_fields: List[str] = Field(..., description="必填字段列表")
optional_fields: List[str] = Field(default=[], description="可选字段列表")
class Config:
schema_extra = {
"example": {
"id": "vibrant",
"name": "Vibrant活力模板",
"description": "适合旅游景点、娱乐活动的活力海报模板",
"size": [900, 1200],
"required_fields": ["title", "slogan", "price", "ticket_type", "content_items"],
"optional_fields": ["remarks", "tag", "pagination"]
}
}
# 通用内容模型(支持任意字段)
class PosterContent(BaseModel):
"""通用海报内容模型,支持动态字段"""
class Config:
extra = "allow" # 允许额外字段
schema_extra = {
"example": {
"title": "海洋奇幻世界",
"slogan": "探索深海秘境,感受蓝色奇迹的无限魅力",
"price": "299",
"ticket_type": "成人票",
"content_items": [
"海洋馆门票1张含所有展区",
"海豚表演VIP座位"
]
}
}
# 保持向后兼容的Vibrant内容模型
class VibrantPosterContent(PosterContent):
"""Vibrant海报内容模型向后兼容"""
title: Optional[str] = Field(None, description="主标题8-12字符")
slogan: Optional[str] = Field(None, description="副标题/宣传语10-20字符")
price: Optional[str] = Field(None, description="价格,如果没有价格则用'欢迎咨询'")
ticket_type: Optional[str] = Field(None, description="票种类型(如成人票、套餐票等)")
content_button: Optional[str] = Field(None, description="内容按钮文字")
content_items: Optional[List[str]] = Field(None, description="套餐内容列表3-5个项目")
remarks: Optional[List[str]] = Field(None, description="备注信息1-3条")
tag: Optional[str] = Field(None, description="标签")
pagination: Optional[str] = Field(None, description="分页信息")
# 通用海报生成请求
class PosterGenerationRequest(BaseModel):
"""通用海报生成请求模型"""
# 模板相关
template_id: str = Field(..., description="模板ID")
# 内容相关(二选一)
content: Optional[Dict[str, Any]] = Field(None, description="直接提供的海报内容")
source_data: Optional[Dict[str, Any]] = Field(None, description="源数据用于AI生成内容")
# 生成参数
topic_name: Optional[str] = Field(None, description="主题名称,用于文件命名")
image_path: Optional[str] = Field(None, description="指定图片路径,如果不提供则随机选择")
image_dir: Optional[str] = Field(None, description="图片目录,如果不提供使用默认目录")
output_dir: Optional[str] = Field(None, description="输出目录,如果不提供使用默认目录")
# AI参数
temperature: Optional[float] = Field(default=0.7, description="AI生成温度参数")
class Config:
schema_extra = {
"example": {
"template_id": "vibrant",
"source_data": {
"scenic_info": {
"name": "天津冒险湾",
"location": "天津市",
"type": "水上乐园"
},
"product_info": {
"name": "冒险湾门票",
"price": 299,
"type": "成人票"
},
"tweet_info": {
"title": "夏日清凉首选",
"content": "天津冒险湾水上乐园,多种刺激项目等你来挑战..."
}
},
"topic_name": "天津冒险湾",
"temperature": 0.7
}
}
# 内容生成请求
class ContentGenerationRequest(BaseModel):
"""内容生成请求模型"""
template_id: str = Field(..., description="模板ID")
source_data: Dict[str, Any] = Field(..., description="源数据用于AI生成内容")
temperature: Optional[float] = Field(default=0.7, description="AI生成温度参数")
class Config:
schema_extra = {
"example": {
"template_id": "vibrant",
"source_data": {
"scenic_info": {"name": "天津冒险湾", "type": "水上乐园"},
"product_info": {"name": "门票", "price": 299},
"tweet_info": {"title": "夏日清凉", "content": "水上乐园体验"}
},
"temperature": 0.7
}
}
# 保持向后兼容
class VibrantPosterRequest(PosterGenerationRequest):
"""Vibrant海报生成请求模型向后兼容"""
template_id: str = Field(default="vibrant", description="模板ID默认为vibrant")
# 兼容旧的字段结构
scenic_info: Optional[Dict[str, Any]] = Field(None, description="景区信息")
product_info: Optional[Dict[str, Any]] = Field(None, description="产品信息")
tweet_info: Optional[Dict[str, Any]] = Field(None, description="推文信息")
def __init__(self, **data):
# 转换旧格式到新格式
if 'scenic_info' in data or 'product_info' in data or 'tweet_info' in data:
source_data = {}
for key in ['scenic_info', 'product_info', 'tweet_info']:
if key in data and data[key] is not None:
source_data[key] = data.pop(key)
if source_data and 'source_data' not in data:
data['source_data'] = source_data
super().__init__(**data)
# 标准API响应基础类
class BaseAPIResponse(BaseModel):
"""API响应基础模型"""
success: bool = Field(..., description="操作是否成功")
message: str = Field(default="", description="响应消息")
request_id: str = Field(..., description="请求ID")
timestamp: str = Field(..., description="响应时间戳")
# 通用海报生成响应
class PosterGenerationResponse(BaseAPIResponse):
"""通用海报生成响应模型"""
data: Optional[Dict[str, Any]] = Field(None, description="响应数据")
class Config:
schema_extra = {
"example": {
"success": True,
"message": "海报生成成功",
"request_id": "poster-20240715-123456-a1b2c3d4",
"timestamp": "2024-07-15T12:34:56Z",
"data": {
"template_id": "vibrant",
"topic_name": "天津冒险湾",
"poster_path": "/result/posters/vibrant_海洋奇幻世界_20240715_123456.png",
"content": {
"title": "海洋奇幻世界",
"slogan": "探索深海秘境,感受蓝色奇迹的无限魅力",
"price": "299"
},
"metadata": {
"image_used": "/data/images/ocean_park.jpg",
"generation_method": "ai_generated",
"template_size": [900, 1200],
"processing_time": 3.2
}
}
}
}
# 内容生成响应
class ContentGenerationResponse(BaseAPIResponse):
"""内容生成响应模型"""
data: Optional[Dict[str, Any]] = Field(None, description="生成的内容")
class Config:
schema_extra = {
"example": {
"success": True,
"message": "内容生成成功",
"request_id": "content-20240715-123456-a1b2c3d4",
"timestamp": "2024-07-15T12:34:56Z",
"data": {
"template_id": "vibrant",
"content": {
"title": "冒险湾水世界",
"slogan": "夏日激情体验,清凉无限乐趣",
"price": "299",
"ticket_type": "成人票"
},
"metadata": {
"generation_method": "ai_generated",
"temperature": 0.7
}
}
}
}
# 模板列表响应
class TemplateListResponse(BaseAPIResponse):
"""模板列表响应模型"""
data: Optional[List[TemplateInfo]] = Field(None, description="模板列表")
class Config:
schema_extra = {
"example": {
"success": True,
"message": "获取模板列表成功",
"request_id": "templates-20240715-123456",
"timestamp": "2024-07-15T12:34:56Z",
"data": [
{
"id": "vibrant",
"name": "Vibrant活力模板",
"description": "适合旅游景点、娱乐活动的活力海报模板",
"size": [900, 1200],
"required_fields": ["title", "slogan", "price"],
"optional_fields": ["remarks", "tag"]
}
]
}
}
# 保持向后兼容的响应模型
class VibrantPosterResponse(BaseModel):
"""Vibrant海报生成响应模型向后兼容"""
request_id: str = Field(..., description="请求ID")
topic_name: str = Field(..., description="主题名称")
poster_path: str = Field(..., description="生成的海报文件路径")
generated_content: Dict[str, Any] = Field(..., description="生成或使用的海报内容")
image_used: str = Field(..., description="使用的图片路径")
generation_method: str = Field(..., description="生成方式direct直接使用提供内容或ai_generatedAI生成")
class Config:
schema_extra = {
"example": {
"request_id": "vibrant-20240715-123456-a1b2c3d4",
"topic_name": "天津冒险湾",
"poster_path": "/result/posters/vibrant_海洋奇幻世界_20240715_123456.png",
"generated_content": {
"title": "海洋奇幻世界",
"slogan": "探索深海秘境,感受蓝色奇迹的无限魅力",
"price": "299",
"ticket_type": "成人票",
"content_items": ["海洋馆门票1张", "海豚表演VIP座位"]
},
"image_used": "/data/images/ocean_park.jpg",
"generation_method": "ai_generated"
}
}
class BatchVibrantPosterRequest(BaseModel):
"""批量Vibrant海报生成请求模型"""
base_path: str = Field(..., description="包含多个topic目录的基础路径")
image_dir: Optional[str] = Field(None, description="图片目录")
scenic_info_file: Optional[str] = Field(None, description="景区信息文件路径")
product_info_file: Optional[str] = Field(None, description="产品信息文件路径")
output_base: Optional[str] = Field(default="result/posters", description="输出基础目录")
parallel_count: Optional[int] = Field(default=3, description="并发处理数量")
temperature: Optional[float] = Field(default=0.7, description="AI生成温度参数")
class Config:
schema_extra = {
"example": {
"base_path": "/root/TravelContentCreator/result/run_20250710_165327",
"image_dir": "/root/TravelContentCreator/data/images",
"scenic_info_file": "/root/TravelContentCreator/resource/data/Object/天津冒险湾.txt",
"product_info_file": "/root/TravelContentCreator/resource/data/Product/product.bak",
"output_base": "result/posters",
"parallel_count": 3,
"temperature": 0.7
}
}
class BatchVibrantPosterResponse(BaseModel):
"""批量Vibrant海报生成响应模型"""
request_id: str = Field(..., description="批量处理请求ID")
total_topics: int = Field(..., description="总共处理的topic数量")
successful_count: int = Field(..., description="成功生成的海报数量")
failed_count: int = Field(..., description="失败的海报数量")
output_base_dir: str = Field(..., description="输出基础目录")
successful_topics: List[str] = Field(..., description="成功处理的topic列表")
failed_topics: List[Dict[str, str]] = Field(..., description="失败的topic及错误信息")
class Config:
schema_extra = {
"example": {
"request_id": "batch-vibrant-20240715-123456",
"total_topics": 5,
"successful_count": 4,
"failed_count": 1,
"output_base_dir": "/result/posters/run_20250710_165327",
"successful_topics": ["topic_1", "topic_2", "topic_3", "topic_4"],
"failed_topics": [
{"topic": "topic_5", "error": "图片文件不存在"}
]
}
}