From 90fe8dbd11399be476dda44c90a862342aaff942 Mon Sep 17 00:00:00 2001 From: Wang Xiuqiang Date: Mon, 9 Jun 2025 16:08:14 +0800 Subject: [PATCH] =?UTF-8?q?=E6=90=AD=E5=BB=BA=20pipeline=20framework?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- outputs/poster_content.json | 8 +- outputs/prompts.yaml | 5 + requirements.txt | 20 +- .../generate_layout.cpython-311.pyc | Bin 0 -> 6569 bytes .../__pycache__/generate_text.cpython-311.pyc | Bin 0 -> 17181 bytes scripts/generate_layout.py | 5 +- scripts/generate_text.py | 4 +- scripts/run_pipeline.py | 175 +++++++++++++++ scripts/run_pipline.md | 208 ++++++++++++++++++ 9 files changed, 406 insertions(+), 19 deletions(-) create mode 100644 outputs/prompts.yaml create mode 100644 scripts/__pycache__/generate_layout.cpython-311.pyc create mode 100644 scripts/__pycache__/generate_text.cpython-311.pyc create mode 100644 scripts/run_pipeline.py create mode 100644 scripts/run_pipline.md diff --git a/outputs/poster_content.json b/outputs/poster_content.json index 505d224..f05de6b 100644 --- a/outputs/poster_content.json +++ b/outputs/poster_content.json @@ -4,13 +4,13 @@ "color": "#000000" }, "layer6_title_content": { - "content": "世界读书日", + "content": "国庆盛典", "font_name": "FZLanTingHei-ExtraBold-GB", "color": "#000000" }, "layer7_subtitle_content": { - "content": "阅古今中外,启智慧之门", - "font_name": "Adobe Song Std L", - "color": "#4F4F4F" + "content": "共庆华诞,同绘未来", + "font_name": "SimHei", + "color": "#555555" } } \ No newline at end of file diff --git a/outputs/prompts.yaml b/outputs/prompts.yaml new file mode 100644 index 0000000..57fed3f --- /dev/null +++ b/outputs/prompts.yaml @@ -0,0 +1,5 @@ +description: "Generated prompt based on user input: \u7AEF\u5348\u8282\u6D77\u62A5\ + \uFF0C\u5305\u542B\u80CC\u666F\u3001\u6D3B\u52A8\u4EAE\u70B9\u548C\u56FE\u6807" +generated_at: 03:05 PM HKT on Monday, June 09, 2025 +user_prompt: "\u7AEF\u5348\u8282\u6D77\u62A5\uFF0C\u5305\u542B\u80CC\u666F\u3001\u6D3B\ + \u52A8\u4EAE\u70B9\u548C\u56FE\u6807" diff --git a/requirements.txt b/requirements.txt index 2cc43e7..af1d048 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,11 +1,9 @@ -# 基础依赖 -python-dotenv # 用于加载.env文件中的环境变量 -pyyaml # 用于解析YAML配置文件 - -# API客户端 -openai == 1.82.1 # 用于调用OpenAI/Moonshot/DeepSeek API - -# 图像处理 -Pillow # PIL库,用于基础图像处理 -psd-tools # 用于PSD文件的创建和操作 - +fastapi>=0.68.0 +uvicorn>=0.18.0 +python-dotenv>=0.21.0 +pyyaml>=6.0 +websocket-client>=1.5.0 +requests>=2.28.0 +pillow>=9.0.0 +psd-tools>=1.9.0 +openai>=1.0.0 diff --git a/scripts/__pycache__/generate_layout.cpython-311.pyc b/scripts/__pycache__/generate_layout.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..28ceef0ab8047395d67d7ba16ecda47b38827ec4 GIT binary patch literal 6569 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 S*A?l$S&~_or~7>#mH!`4Eseea literal 0 HcmV?d00001 diff --git a/scripts/generate_layout.py b/scripts/generate_layout.py index 8bea5d3..2c1fa2c 100644 --- a/scripts/generate_layout.py +++ b/scripts/generate_layout.py @@ -98,6 +98,8 @@ def call_deepseek( raise raise Exception("达到最大重试次数,API 调用失败") + + def generate_vue_code(prompt=None): prompt = ( "生成一个Vue组件代码,用于端午节活动海报,包含以下部分并指定排版位置:" @@ -123,6 +125,5 @@ def save_code(code, file_path="../outputs/generated_code.vue"): f.write(code) if __name__ == "__main__": - vue_code = generate_vue_code() - save_code(vue_code) + save_code(generate_vue_code()) print("Vue组件代码已生成并保存到outputs/generated_code.vue") \ No newline at end of file diff --git a/scripts/generate_text.py b/scripts/generate_text.py index 2f6be0b..e9b344f 100644 --- a/scripts/generate_text.py +++ b/scripts/generate_text.py @@ -249,7 +249,7 @@ if __name__ == "__main__": # user_input_example2 = "我要一个端午节的海报,中国风,深色背景。" # user_input_example3 = "世界读书日海报,简约风格,元素包含打开的书和思考的人。" - load_config_from_file("./configs/font.yaml") + load_config_from_file("../configs/font.yaml") user_input = input("请输入您的海报需求:") @@ -260,7 +260,7 @@ if __name__ == "__main__": if suggestions: # print("\n--- 最终输出给调用者的内容 ---") # print(json.dumps(suggestions, indent=2, ensure_ascii=False)) - output_folder = "outputs" + output_folder = "../outputs" output_file = os.path.join(output_folder, "poster_content.json") try: with open(output_file, "w", encoding="utf-8") as file: diff --git a/scripts/run_pipeline.py b/scripts/run_pipeline.py new file mode 100644 index 0000000..bd64b77 --- /dev/null +++ b/scripts/run_pipeline.py @@ -0,0 +1,175 @@ +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) \ No newline at end of file diff --git a/scripts/run_pipline.md b/scripts/run_pipline.md new file mode 100644 index 0000000..4bb854b --- /dev/null +++ b/scripts/run_pipline.md @@ -0,0 +1,208 @@ +# 自动执行流程说明文档 + +本流程通过多个脚本与配置文件协作,自动生成海报的排版、文案、图像并输出 PSD 文件,最终通过 API 提供服务。 + +--- + +## 一、自动执行流程的步骤 + +### 步骤 1: 配置加载 + +**目标**:加载必要的配置信息(如 API 密钥、字体规则、Prompt 模板)。 + +**涉及文件**: +- `.env`:加载 DeepSeek API 密钥等环境变量。 +- `configs/fonts.yaml`:加载字体与配色规则。 +- `configs/prompts.json`:加载图像生成 Prompt 模板。 + +**过程**: +- 使用 `dotenv` 加载 `.env` 中的 `DEEPSEEK_API_KEY`。 +- 使用 `yaml` 或 `json` 库加载 `fonts.yaml` 和 `prompts.json`。 + +**输出**:配置对象(字典或类),供后续步骤使用。 + +--- + +### 步骤 2: 排版生成 + +**目标**:使用 LLM 生成海报的排版结构(Vue 组件)。 + +**涉及文件**: +- `scripts/generate_layout.py`:调用 DeepSeek API 生成 Vue 组件代码。 + +**过程**: +- 调用 `generate_layout.py` 中的 `generate_vue_code` 函数。 +- 传入从 `prompts.json` 动态读取的 Prompt,结合字体规则生成 Vue 代码。 + +**输出**:Vue 组件代码,保存为 `outputs/generated_code.vue`。 + +--- + +### 步骤 3: 文案生成 + +**目标**:生成海报文案内容(标题、副标题、活动描述等)。 + +**涉及文件**: +- `scripts/generate_text.py`:调用 LLM 生成文案。 + +**过程**: +- 调用脚本生成端午节相关文案(如“端午安康”、“包粽子比赛”)。 +- 文案可按 `prompts.json` 中模板动态调整。 + +**输出**:文案内容(字符串或字典),供后续步骤使用。 + +--- + +### 步骤 4: 图像生成 + +**目标**:使用 ComfyUI 生成海报图层。 + +**涉及文件**: +- `comfyui_flows/layer_generation.json`:定义图层生成流程。 +- `scripts/generate_images.py`:调用 ComfyUI API 生成图层。 +- `images/`:存储背景、前景、文字图层。 + +**过程**: +- 运行 `generate_images.py`,加载 `layer_generation.json`。 +- 根据排版与文案生成: + - `background.png` + - `foreground.png` + - `text_overlay.png` + +**输出**:图像文件保存到 `images/` 目录。 + +--- + +### 步骤 5: 合成海报 + +**目标**:将图层合成为最终海报。 + +**涉及文件**: +- `scripts/compose_poster.py`:合成图层脚本。 +- `outputs/final_poster.png`:合成结果。 + +**过程**: +- 读取 `generated_code.vue` 中的排版位置信息。 +- 使用 `image_utils.py` 对图层进行合成。 + +**输出**:`final_poster.png` + +--- + +### 步骤 6: 导出 PSD 文件 + +**目标**:导出 PSD 文件以便后期修改。 + +**涉及文件**: +- `scripts/export_psd.py`:PSD 导出脚本。 +- `outputs/final_poster.psd`:导出的 PSD 文件。 + +**过程**: +- 将 `final_poster.png` 转换为 PSD。 +- 保留图层信息。 + +**输出**:`final_poster.psd` + +--- + +### 步骤 7: 提供前端接口 + +**目标**:将结果通过 API 提供给前端调用。 + +**涉及文件**: +- `run_pipeline.py`:协调整体流程并定义 API 接口。 + +**过程**: +- 使用 `FastAPI` 或 `Flask` 创建端点(如 `/generate_poster`)。 +- 接收前端请求,依次调用上述所有步骤。 +- 返回最终文件的 URL 或文件流。 + +**输出**:HTTP 响应,包含 `final_poster.png` 链接或文件流。 + +--- + +## 二、如何实现自动执行流程 + +### 环境准备 + +- **依赖安装**:确保 `requirements.txt` 包含以下依赖: + - `openai` + - `python-dotenv` + - `PyYAML` + - `requests`(用于 ComfyUI API 调用) + - `Pillow`(图像处理) + - `psd-tools`(PSD 导出) + +- **API 密钥配置**:在 `.env` 文件中添加以下字段: + ```env + DEEPSEEK_API_KEY=your_api_key + COMFYUI_API_KEY=your_comfyui_key + +```python +import os +from dotenv import load_dotenv +from scripts.generate_layout import generate_vue_code +from scripts.generate_text import generate_text # 假设存在 +from scripts.generate_images import generate_images # 假设存在 +from scripts.compose_poster import compose_poster # 假设存在 +from scripts.export_psd import export_psd # 假设存在 +import yaml +import json +from fastapi import FastAPI, HTTPException +from fastapi.responses import FileResponse + +# 加载环境变量和配置 +load_dotenv() +app = FastAPI() + +with open("configs/fonts.yaml", "r", encoding="utf-8") as f: + fonts_config = yaml.safe_load(f) +with open("configs/prompts.json", "r", encoding="utf-8") as f: + prompts_config = json.load(f) + +# 一键执行流程 +def run_pipeline(): + try: + # 步骤 1: 排版生成 + layout_code = generate_vue_code() + with open("../outputs/generated_code.vue", "w", encoding="utf-8") as f: + f.write(layout_code) + + # 步骤 2: 文案生成 + text_content = generate_text(prompts_config.get("text_prompt", "")) + + # 步骤 3: 图像生成 + generate_images( + workflow_path="comfyui_flows/layer_generation.json", + text_content=text_content, + output_dir="images/" + ) + + # 步骤 4: 合成海报 + compose_poster( + layout_path="../outputs/generated_code.vue", + image_dir="images/", + output_path="../outputs/final_poster.png" + ) + + # 步骤 5: 导出 PSD + export_psd( + input_path="../outputs/final_poster.png", + output_path="../outputs/final_poster.psd" + ) + + return "../outputs/final_poster.png" + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + +# API 端点 +@app.get("/generate_poster") +async def generate_poster(): + output_path = run_pipeline() + return FileResponse(output_path, media_type="image/png") + +if __name__ == "__main__": + import uvicorn + uvicorn.run(app, host="0.0.0.0", port=8000) + +``` \ No newline at end of file