175 lines
7.1 KiB
Python
175 lines
7.1 KiB
Python
import os
|
||
from dotenv import load_dotenv
|
||
import yaml
|
||
from generate_layout import call_deepseek, generate_vue_code, save_code
|
||
from generate_text import load_config_from_file, get_poster_content_suggestions
|
||
from fastapi import FastAPI, HTTPException
|
||
from fastapi.responses import FileResponse
|
||
from ComfyUI.flux_con import comfyui_img_info # 导入已实现的图像生成函数
|
||
|
||
# 配置路径
|
||
config_paths = {
|
||
"font": "../configs/font.yaml",
|
||
"output_folder": "../outputs/",
|
||
}
|
||
|
||
# 加载环境变量和配置
|
||
load_dotenv()
|
||
app = FastAPI()
|
||
|
||
with open(config_paths["font"], "r", encoding="utf-8") as f:
|
||
fonts_config = yaml.safe_load(f)
|
||
|
||
|
||
# 假设的 DeepSeek 提示词分析接口
|
||
def llm_user_analysis(user_input):
|
||
# 占位符实现,模拟 DeepSeek 分析
|
||
if not user_input:
|
||
user_input = "端午节海报,包含背景和活动亮点"
|
||
return {
|
||
"analyzed_prompt": user_input,
|
||
"keywords": ["端午节", "背景", "活动亮点"],
|
||
"width": 1080,
|
||
"height": 1920,
|
||
"batch_size": 2
|
||
}
|
||
|
||
|
||
# 假设的 PSD 合成接口(占位符)
|
||
def create_psd_from_images(img_list, vue_layout_path, output_path):
|
||
print(f"Generating PSD from {img_list} using layout {vue_layout_path} to {output_path}")
|
||
return None
|
||
|
||
|
||
# 动态生成 prompts.yaml 基于用户输入
|
||
def generate_prompts_yaml(user_input):
|
||
prompts_data = {
|
||
"user_prompt": user_input,
|
||
"generated_at": "02:50 PM HKT on Monday, June 09, 2025",
|
||
"description": f"Generated prompt based on user input: {user_input}"
|
||
}
|
||
prompts_yaml_path = os.path.join(config_paths["output_folder"], "prompts.yaml")
|
||
with open(prompts_yaml_path, "w", encoding="utf-8") as f:
|
||
yaml.dump(prompts_data, f)
|
||
return prompts_yaml_path
|
||
|
||
|
||
# 生成动态Vue排版Prompt,支持多张图片
|
||
def generate_layout_prompt(user_input_analysis_result, parse_imglist):
|
||
width = user_input_analysis_result["width"]
|
||
height = user_input_analysis_result["height"]
|
||
|
||
# 构造图片信息字符串
|
||
images_info = "\n".join(
|
||
[f"- {img['picture_name']} ({img['picture_description']})" for img in parse_imglist]
|
||
)
|
||
|
||
# 调用DeepSeek生成动态排版Prompt
|
||
system_prompt = "你是一个擅长前端开发的AI,专注于生成Vue.js代码。给定组件尺寸和多张图片信息,自动分析并建议合理的排版位置,使用absolute定位,仅关注位置,不包含样式描述。"
|
||
prompt = (
|
||
f"根据组件尺寸 {width}x{height}px 和以下图片信息,生成一个Vue组件代码的Prompt,包含以下部分并指定动态排版位置:\n"
|
||
f"图片信息:\n{images_info}\n"
|
||
f"要求:\n"
|
||
f"1. 背景图层:使用第一张图片,占据整个组件区域。"
|
||
f"2. 主体图层:包含标题和副标题,位于合适位置,居中。"
|
||
f"3. 活动亮点:使用剩余图片,位于合适位置,居中,使用网格或分层布局展示所有图片。"
|
||
f"4. 页脚:包含主办单位信息和logo图片,位于合适位置,居中。"
|
||
f"组件尺寸为{width}x{height}px,布局使用absolute定位,仅关注排版位置。"
|
||
f"返回一个格式化的Prompt字符串,供生成Vue代码使用。"
|
||
)
|
||
|
||
result, _ = call_deepseek(prompt=prompt, system_prompt=system_prompt, temperature=0.4)
|
||
return result
|
||
|
||
|
||
# 一键执行流程
|
||
def run_pipeline(user_input=None):
|
||
"""
|
||
自动执行海报生成流程:
|
||
1. 使用 llm_user_analysis 分析用户提示词得到 user_input_analysis_result。
|
||
2. 使用 comfyui_img_info 生成 parse_imglist 列表。
|
||
3. 根据 user_input_analysis_result 生成文案 suggestions。
|
||
4. 结合 parse_imglist 和动态生成的 prompts.yaml 生成 Vue 排版文件。
|
||
5. 将 parse_imglist 组装成 img_list,调用 create_psd_from_images 合成 PSD。
|
||
:param user_input: 用户提供的提示词(可选,默认使用占位符)
|
||
:return: 合成海报的路径
|
||
"""
|
||
# 步骤 1: 加载配置
|
||
load_config_from_file(generate_prompts_yaml(user_input)) # 动态生成 prompts.yaml
|
||
|
||
# 步骤 2: 分析用户提示词
|
||
user_input_analysis_result = llm_user_analysis(user_input)
|
||
print(f"Analyzed result: {user_input_analysis_result}")
|
||
|
||
# 步骤 3: 生成图片信息
|
||
system_prompt = user_input_analysis_result["analyzed_prompt"]
|
||
parse_imglist = comfyui_img_info(user_input_analysis_result, system_prompt)
|
||
print(f"Generated image list: {parse_imglist}")
|
||
|
||
# 步骤 4: 生成文案
|
||
suggestions = get_poster_content_suggestions(user_input_analysis_result)
|
||
print(f"Generated suggestions: {suggestions}")
|
||
|
||
# 步骤 5: 生成 Vue 排版(动态Prompt,支持多张图片)
|
||
dynamic_prompt = generate_layout_prompt(user_input_analysis_result, parse_imglist)
|
||
print(f"Generated dynamic layout prompt: {dynamic_prompt}")
|
||
vue_code = generate_vue_code(dynamic_prompt)
|
||
save_code(vue_code, file_path=os.path.join(config_paths["output_folder"], "generated_code.vue"))
|
||
print("Generated Vue layout")
|
||
|
||
# 步骤 6: 合成 PSD
|
||
img_list = [(pic["picture_name"], pic["picture_type"]) for pic in parse_imglist]
|
||
create_psd_from_images(
|
||
img_list=img_list,
|
||
vue_layout_path=os.path.join(config_paths["output_folder"], "generated_code.vue"),
|
||
output_path=os.path.join(config_paths["output_folder"], "final_poster.psd")
|
||
)
|
||
print("Generated PSD file")
|
||
|
||
return os.path.join(config_paths["output_folder"], "final_poster.png") # 假设 PNG 作为最终输出
|
||
|
||
|
||
# 本地运行函数
|
||
def run_local_pipeline(user_input=None):
|
||
"""
|
||
本地运行整个管道流程,输出结果到控制台和文件系统。
|
||
:param user_input: 用户提供的提示词(可选,默认使用占位符)
|
||
:return: None,打印运行结果
|
||
"""
|
||
print(f"Starting local pipeline with input: {user_input}")
|
||
output_path = run_pipeline(user_input)
|
||
print(f"Pipeline completed. Results saved to:")
|
||
print(f"- Vue layout: {os.path.join(config_paths['output_folder'], 'generated_code.vue')}")
|
||
print(f"- PSD file: {os.path.join(config_paths['output_folder'], 'final_poster.psd')}")
|
||
print(f"- Final poster (placeholder): {output_path}")
|
||
print("Check the outputs/ directory for generated files.")
|
||
|
||
|
||
# API 端点
|
||
@app.get("/generate_poster")
|
||
async def generate_poster(user_input: str = None):
|
||
output_path = run_pipeline(user_input)
|
||
return FileResponse(output_path, media_type="image/png")
|
||
|
||
|
||
# 可选 API 端点
|
||
@app.get("/generate_poster_psd")
|
||
async def generate_poster_psd(user_input: str = None):
|
||
try:
|
||
output_path = run_pipeline(user_input)
|
||
return {
|
||
"image_url": output_path,
|
||
"font_info": fonts_config,
|
||
"psd_path": os.path.join(config_paths["output_folder"], "final_poster.psd")
|
||
}
|
||
except Exception as e:
|
||
raise HTTPException(status_code=500, detail=f"PSD generation failed: {str(e)}")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
import uvicorn
|
||
|
||
# 启动本地运行(可选)
|
||
run_local_pipeline("端午节海报,包含背景、活动亮点和图标")
|
||
# 或者启动API服务器
|
||
# uvicorn.run(app, host="0.0.0.0", port=8000) |