vesion 0.5.0 基座版本
@ -122,30 +122,5 @@ if result["status"] == "success":
|
||||
f.write(psd_response.content)
|
||||
```
|
||||
|
||||
## 错误处理
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "error",
|
||||
"message": "错误描述",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
|
||||
常见错误码:
|
||||
- `400`: 请求参数错误
|
||||
- `404`: 资源不存在
|
||||
- `500`: 服务器内部错误
|
||||
|
||||
## 部署
|
||||
|
||||
### 开发环境
|
||||
```bash
|
||||
cd scripts
|
||||
python run_pipeline.py # 选择2
|
||||
```
|
||||
|
||||
### 生产环境
|
||||
```bash
|
||||
uvicorn scripts.run_pipeline:app --host 0.0.0.0 --port 8000
|
||||
```
|
BIN
outputs/1317439_20250705022329_0.png
Normal file
After Width: | Height: | Size: 2.6 MiB |
Before Width: | Height: | Size: 2.0 MiB |
Before Width: | Height: | Size: 1.9 MiB |
Before Width: | Height: | Size: 2.5 MiB |
Before Width: | Height: | Size: 2.3 MiB |
Before Width: | Height: | Size: 2.0 MiB |
Before Width: | Height: | Size: 1.9 MiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 1.1 MiB |
8
outputs/deepseek_output/南开大学海报_20250705010133313.txt
Normal file
@ -0,0 +1,8 @@
|
||||
no text, no AI style
|
||||
Cartoon-Style Nankai University Poster,
|
||||
featuring the iconic main building with exaggerated playful proportions, its red-brick façade adorned with oversized arched windows glowing like amber honey. Towering pine trees with spiral-shaped needles frame the scene, while cheerful squirrels in tiny scarves scamper across cobblestone paths.
|
||||
|
||||
The clock tower stands tall, its face smiling like a friendly sun, with floating musical notes escaping the bells. Students with simplified, round faces carry stacks of books that emit tiny sparkles, their backpacks shaped like clouds. Cherry blossom petals drift in the air, each one a soft pink watercolor stroke.
|
||||
|
||||
Environment:
|
||||
A gradient sky shifts from peach dawn to lavender twilight, dotted with cartoon stars. The lawn is a patchwork of emerald and lime, textured like plush felt. A mirrored lake reflects the building upside-down, rippling with tiny fish that leap as heart-shaped splashes. Fireflies hover near lanterns shaped like glowing pearls.
|
@ -1,120 +0,0 @@
|
||||
<template>
|
||||
<div class="poster-container lotus-theme">
|
||||
<div class="background-layer">
|
||||
<img src="../outputs/lotus.jpg" alt="荷花背景" class="background-image" />
|
||||
</div>
|
||||
<div class="content-layer">
|
||||
<div class="title-section">
|
||||
<h1 class="main-title lotus-title">{{ title }}</h1>
|
||||
<h2 class="subtitle lotus-subtitle">{{ subtitle }}</h2>
|
||||
</div>
|
||||
<div class="main-content lotus-content">
|
||||
<div class="decoration-elements">
|
||||
<div class="lotus-decoration"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-section">
|
||||
<div class="logo-area">
|
||||
<span class="logo-text">{{ logoText }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const title = ref('端午节')
|
||||
const subtitle = ref('粽叶飘香,龙舟竞渡')
|
||||
const logoText = ref('')
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.poster-container {
|
||||
width: 1080px;
|
||||
height: 1920px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(135deg, #f8f4e6, #e8dcc0);
|
||||
}
|
||||
|
||||
.background-layer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.background-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.content-layer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.title-section {
|
||||
position: absolute;
|
||||
top: 20%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
text-align: center;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.lotus-title {
|
||||
font-size: 64px;
|
||||
font-weight: bold;
|
||||
color: #2d5016;
|
||||
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
|
||||
margin-bottom: 20px;
|
||||
font-family: 'SimSun', serif;
|
||||
}
|
||||
|
||||
.lotus-subtitle {
|
||||
font-size: 32px;
|
||||
color: #4a6741;
|
||||
margin-bottom: 40px;
|
||||
font-family: 'KaiTi', cursive;
|
||||
}
|
||||
|
||||
.lotus-content {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.lotus-decoration {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background: radial-gradient(circle, rgba(255,192,203,0.6), rgba(255,182,193,0.3));
|
||||
border-radius: 50%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.footer-section {
|
||||
position: absolute;
|
||||
bottom: 10%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
font-size: 24px;
|
||||
color: #2d5016;
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
48
outputs/layout.json
Normal file
@ -0,0 +1,48 @@
|
||||
{
|
||||
"canvas": {
|
||||
"width": 1080,
|
||||
"height": 1920
|
||||
},
|
||||
"images": {
|
||||
"background.png": {
|
||||
"position": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"size": {
|
||||
"width": 1080,
|
||||
"height": 1920
|
||||
}
|
||||
},
|
||||
"nankai.png": {
|
||||
"position": {
|
||||
"x": 390,
|
||||
"y": 200
|
||||
},
|
||||
"size": {
|
||||
"width": 300,
|
||||
"height": 300
|
||||
}
|
||||
},
|
||||
"lotus.jpg": {
|
||||
"position": {
|
||||
"x": 270,
|
||||
"y": 960
|
||||
},
|
||||
"size": {
|
||||
"width": 540,
|
||||
"height": 500
|
||||
}
|
||||
},
|
||||
"stamp.jpg": {
|
||||
"position": {
|
||||
"x": 800,
|
||||
"y": 1600
|
||||
},
|
||||
"size": {
|
||||
"width": 200,
|
||||
"height": 200
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,16 +1,16 @@
|
||||
{
|
||||
"layer5_logo_content": {
|
||||
"text": "",
|
||||
"color": "#000000"
|
||||
"color": "#7E0C6E"
|
||||
},
|
||||
"layer6_title_content": {
|
||||
"content": "端午节",
|
||||
"font_name": "SimHei",
|
||||
"content": "南开风采",
|
||||
"font_name": "FZLanTingHei-ExtraBold-GB",
|
||||
"color": "#000000"
|
||||
},
|
||||
"layer7_subtitle_content": {
|
||||
"content": "粽叶飘香,龙舟竞渡",
|
||||
"font_name": "SimHei",
|
||||
"color": "#7E0C6E"
|
||||
"content": "百年学府,智慧之光",
|
||||
"font_name": "Microsoft YaHei",
|
||||
"color": "#333333"
|
||||
}
|
||||
}
|
225
outputs/poster_layout.vue
Normal file
@ -0,0 +1,225 @@
|
||||
<template>
|
||||
<div class="poster-container" :style="containerStyle">
|
||||
<!-- 图片层 - 根据layout.json定义 -->
|
||||
<div
|
||||
v-for="(imageInfo, imageName) in layout.images"
|
||||
:key="imageName"
|
||||
class="image-layer"
|
||||
:style="getImageStyle(imageInfo, imageName)"
|
||||
></div>
|
||||
|
||||
<!-- 文本层 -->
|
||||
<div class="text-layer title" :style="getTitleStyle()">
|
||||
{{ content.layer6_title_content.content }}
|
||||
</div>
|
||||
|
||||
<div class="text-layer subtitle" :style="getSubtitleStyle()">
|
||||
{{ content.layer7_subtitle_content.content }}
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="content.layer5_logo_content.text"
|
||||
class="text-layer logo"
|
||||
:style="getLogoStyle()"
|
||||
>
|
||||
{{ content.layer5_logo_content.text }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, reactive, computed } from "vue";
|
||||
|
||||
// 导入layout.json和poster_content.json数据
|
||||
// 注意:实际使用时可能需要动态导入或通过API获取
|
||||
const layout = {
|
||||
canvas: {
|
||||
width: 1080,
|
||||
height: 1920,
|
||||
},
|
||||
images: {
|
||||
"background.png": {
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
size: {
|
||||
width: 1080,
|
||||
height: 1920,
|
||||
},
|
||||
},
|
||||
"nankai.png": {
|
||||
position: {
|
||||
x: 390,
|
||||
y: 200,
|
||||
},
|
||||
size: {
|
||||
width: 300,
|
||||
height: 300,
|
||||
},
|
||||
},
|
||||
"lotus.jpg": {
|
||||
position: {
|
||||
x: 270,
|
||||
y: 960,
|
||||
},
|
||||
size: {
|
||||
width: 540,
|
||||
height: 500,
|
||||
},
|
||||
},
|
||||
"stamp.jpg": {
|
||||
position: {
|
||||
x: 800,
|
||||
y: 1600,
|
||||
},
|
||||
size: {
|
||||
width: 200,
|
||||
height: 200,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const content = {
|
||||
layer5_logo_content: {
|
||||
text: "",
|
||||
color: "#7E0C6E",
|
||||
},
|
||||
layer6_title_content: {
|
||||
content: "南开风采",
|
||||
font_name: "FZLanTingHei-ExtraBold-GB",
|
||||
color: "#000000",
|
||||
},
|
||||
layer7_subtitle_content: {
|
||||
content: "百年学府,智慧之光",
|
||||
font_name: "Microsoft YaHei",
|
||||
color: "#333333",
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
name: "PosterLayout",
|
||||
setup() {
|
||||
const baseUrl = "../outputs/"; // 图像资源的基础路径
|
||||
|
||||
// 计算画布样式
|
||||
const containerStyle = computed(() => {
|
||||
return {
|
||||
width: `${layout.canvas.width}px`,
|
||||
height: `${layout.canvas.height}px`,
|
||||
position: "relative",
|
||||
overflow: "hidden",
|
||||
background: "#ffffff",
|
||||
};
|
||||
});
|
||||
|
||||
// 获取图像层样式
|
||||
const getImageStyle = (imageInfo, imageName) => {
|
||||
return {
|
||||
position: "absolute",
|
||||
left: `${imageInfo.position.x}px`,
|
||||
top: `${imageInfo.position.y}px`,
|
||||
width: `${imageInfo.size.width}px`,
|
||||
height: `${imageInfo.size.height}px`,
|
||||
backgroundImage: `url(${baseUrl}${imageName})`,
|
||||
backgroundSize: "cover",
|
||||
backgroundPosition: "center",
|
||||
backgroundRepeat: "no-repeat",
|
||||
zIndex: imageName.includes("background") ? 1 : 2, // 背景图片优先在底层
|
||||
};
|
||||
};
|
||||
|
||||
// 获取标题样式
|
||||
const getTitleStyle = () => {
|
||||
const titleContent = content.layer6_title_content;
|
||||
return {
|
||||
position: "absolute",
|
||||
left: "150px",
|
||||
top: "700px",
|
||||
width: "780px",
|
||||
textAlign: "center",
|
||||
color: titleContent.color || "#000000",
|
||||
fontFamily: titleContent.font_name || "SimHei",
|
||||
fontSize: "80px",
|
||||
fontWeight: "bold",
|
||||
zIndex: 10,
|
||||
textShadow: "2px 2px 4px rgba(0, 0, 0, 0.3)",
|
||||
};
|
||||
};
|
||||
|
||||
// 获取副标题样式
|
||||
const getSubtitleStyle = () => {
|
||||
const subtitleContent = content.layer7_subtitle_content;
|
||||
return {
|
||||
position: "absolute",
|
||||
left: "200px",
|
||||
top: "820px",
|
||||
width: "680px",
|
||||
textAlign: "center",
|
||||
color: subtitleContent.color || "#333333",
|
||||
fontFamily: subtitleContent.font_name || "Microsoft YaHei",
|
||||
fontSize: "40px",
|
||||
zIndex: 10,
|
||||
};
|
||||
};
|
||||
|
||||
// 获取logo文本样式
|
||||
const getLogoStyle = () => {
|
||||
const logoContent = content.layer5_logo_content;
|
||||
return {
|
||||
position: "absolute",
|
||||
left: "50px",
|
||||
top: "50px",
|
||||
color: logoContent.color || "#000000",
|
||||
fontFamily: "Arial, sans-serif",
|
||||
fontSize: "24px",
|
||||
fontWeight: "bold",
|
||||
zIndex: 10,
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
layout,
|
||||
content,
|
||||
containerStyle,
|
||||
getImageStyle,
|
||||
getTitleStyle,
|
||||
getSubtitleStyle,
|
||||
getLogoStyle,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.poster-container {
|
||||
margin: 0 auto;
|
||||
box-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.image-layer {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.text-layer {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 80px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 40px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
BIN
outputs/vue_generated.psd
Normal file
BIN
outputs/vue_generated_缩略图.png
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
outputs/vue_generated_预览.png
Normal file
After Width: | Height: | Size: 2.4 MiB |
@ -25,6 +25,12 @@ tqdm==4.66.1
|
||||
colorama==0.4.6
|
||||
loguru==0.7.2
|
||||
|
||||
# PSD文件支持
|
||||
psd-tools==1.10.0
|
||||
|
||||
# 日志和进度显示(可选)
|
||||
rich==13.3.5
|
||||
|
||||
# 数据处理和存储
|
||||
pandas==2.1.3
|
||||
sqlalchemy==2.0.23
|
||||
|
263
scripts/DeepSeekPromptGenerator.py
Normal file
@ -0,0 +1,263 @@
|
||||
'''
|
||||
* @file DeepSeekPromptGenerator.py
|
||||
* @brief Generate optimized image prompts using DeepSeek API
|
||||
*
|
||||
* @author WuYingwen
|
||||
* @GitHub @wuyingwen10
|
||||
* @Contact 2211537@mail.nankai.edu.cn
|
||||
* @date 2025-06-10
|
||||
* @version v1.0.0
|
||||
*
|
||||
* @note
|
||||
* - Uses DeepSeek API for prompt optimization
|
||||
* - Supports multiple API configurations
|
||||
*
|
||||
* @copyright
|
||||
* (c) 2025 Nankai University
|
||||
'''
|
||||
|
||||
import requests
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
SYSTEM_PROMPT_TEMPLATE = """
|
||||
As an AI prompt engineering expert, please generate a prompt that meets the following requirements based on the topic I provide. Note: You should follow the style of the example (emulating the writing style only, not the content) and transform the user's request into a detailed prompt.
|
||||
|
||||
Requirements (strictly adhere to all six):
|
||||
1: Use simple natural language sentences to describe the scene. Avoid overly long or complex sentence structures. Do not use special symbols like *.
|
||||
2: Express in English.
|
||||
3: Provide only the prompt content without any explanations or notes.
|
||||
4: Each prompt must be at least 50 words but no more than 200 words.
|
||||
5: Avoid ambiguous expressions.
|
||||
6: Add "no text, no AI style" at the beginning.
|
||||
|
||||
Example:
|
||||
no text, no AI style
|
||||
Cartoon-Style Nankai University Main Building,
|
||||
vividly depicted with rounded edges and pastel gradients, the iconic Gothic-Revival structure stands majestically. Crimson brick façade contrasts with golden-glowing arched windows, while whimsical cloud-shaped eaves drip melted clock details. A giant smiling sun hangs low, casting honey-golden rays through simplified pine trees, creating striped shadows dancing on marble stairs.
|
||||
|
||||
Translucent ghostly scholars from 1919 float near pillars holding glowing books, their outlines shimmering like liquid mercury. Oversized autumn leaves (stylized as maple-red origami) spiral around twin bell towers chiming visible musical notes. Puddles on the ground mirror upside-down building reflections rippling with calculus formulas.
|
||||
|
||||
Environment:
|
||||
Surreal candy-pink sunset gradients blend into starry indigo sky above. Playful squirrels wearing tiny graduation caps scamper across emerald lawns textured like green velvet.
|
||||
"""
|
||||
|
||||
API_CONFIGS = [
|
||||
{
|
||||
"name": "DeepSeek Official Chat API",
|
||||
"model": "deepseek-chat",
|
||||
"api_key": "sk-36de33a3827f43398ed027e733dbd74a",
|
||||
"base_url": "https://api.deepseek.com"
|
||||
},
|
||||
{
|
||||
"name": "DeepSeek-R1 Backup",
|
||||
"model": "deepseek-r1",
|
||||
"api_key": "sk-36de33a3827f43398ed027e733dbd74a",
|
||||
"base_url": "https://cloud.infini-ai.com/maas/v1/"
|
||||
},
|
||||
{
|
||||
"name": "DeepSeek-V3 Backup",
|
||||
"model": "deepseek-v3",
|
||||
"api_key": "sk-36de33a3827f43398ed027e733dbd74a",
|
||||
"base_url": "https://cloud.infini-ai.com/maas/v1/"
|
||||
}
|
||||
]
|
||||
|
||||
def generate_prompt(user_topic):
|
||||
"""Generate optimized prompt using DeepSeek API"""
|
||||
full_prompt = SYSTEM_PROMPT_TEMPLATE + f"\n\nTopic: {user_topic}"
|
||||
|
||||
for config in API_CONFIGS:
|
||||
try:
|
||||
print(f"Attempting API: {config['name']}...")
|
||||
endpoint = f"{config['base_url']}/chat/completions"
|
||||
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": f"Bearer {config['api_key']}"
|
||||
}
|
||||
|
||||
payload = {
|
||||
"model": config["model"],
|
||||
"messages": [{"role": "user", "content": full_prompt}],
|
||||
"temperature": 0.7,
|
||||
"max_tokens": 2000,
|
||||
"stream": False
|
||||
}
|
||||
|
||||
response = requests.post(endpoint, headers=headers, json=payload, timeout=30)
|
||||
response.raise_for_status()
|
||||
|
||||
result = response.json()
|
||||
return result['choices'][0]['message']['content'].strip()
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error with {config['name']}: {str(e)}")
|
||||
continue
|
||||
|
||||
raise Exception("All API attempts failed")
|
||||
|
||||
def save_deepseek_output(prompt_content, output_prefix):
|
||||
"""Save DeepSeek output to file with the same naming pattern as images"""
|
||||
output_dir = "../outputs/deepseek_output"
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
timestamp = datetime.now().strftime("%Y%m%d%H%M%S%f")[:-3]
|
||||
|
||||
filename = f"{output_prefix}_{timestamp}.txt"
|
||||
file_path = os.path.join(output_dir, filename)
|
||||
|
||||
with open(file_path, "w", encoding="utf-8") as f:
|
||||
f.write(prompt_content)
|
||||
|
||||
return file_path
|
||||
|
||||
def test_multiple_topics():
|
||||
"""测试多个主题的提示词生成"""
|
||||
test_topics = [
|
||||
"设计一张南开大学的海报,要求风格为卡通风格,包含南开大学的标志性建筑和校园元素。",
|
||||
"创建一个关于人工智能与未来科技的海报",
|
||||
"设计一张关于环保主题的宣传海报"
|
||||
]
|
||||
|
||||
print(f"{'-'*50}\n🧪 开始测试多个主题的提示词生成\n{'-'*50}")
|
||||
|
||||
results = []
|
||||
for i, topic in enumerate(test_topics, 1):
|
||||
print(f"\n📝 测试主题 {i}: {topic}")
|
||||
try:
|
||||
start_time = datetime.now()
|
||||
prompt = generate_prompt(topic)
|
||||
end_time = datetime.now()
|
||||
|
||||
# 计算执行时间
|
||||
execution_time = (end_time - start_time).total_seconds()
|
||||
|
||||
# 保存提示词
|
||||
prefix = f"测试_{i}"
|
||||
output_file = save_deepseek_output(prompt, prefix)
|
||||
|
||||
# 截断显示(如果太长)
|
||||
display_prompt = prompt[:200] + "..." if len(prompt) > 200 else prompt
|
||||
|
||||
results.append({
|
||||
"topic": topic,
|
||||
"success": True,
|
||||
"time": execution_time,
|
||||
"output_file": output_file,
|
||||
"prompt_length": len(prompt)
|
||||
})
|
||||
|
||||
print(f"✅ 成功生成提示词 ({len(prompt)} 字符, {execution_time:.2f}秒)")
|
||||
print(f"📄 预览: {display_prompt}")
|
||||
print(f"💾 已保存到: {output_file}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ 生成失败: {str(e)}")
|
||||
results.append({
|
||||
"topic": topic,
|
||||
"success": False,
|
||||
"error": str(e)
|
||||
})
|
||||
|
||||
# 打印汇总结果
|
||||
print(f"\n{'-'*50}\n📊 测试结果汇总\n{'-'*50}")
|
||||
success_count = sum(1 for r in results if r.get("success", False))
|
||||
print(f"✅ 成功: {success_count}/{len(test_topics)}")
|
||||
|
||||
if success_count > 0:
|
||||
avg_time = sum(r["time"] for r in results if r.get("success", False)) / success_count
|
||||
avg_length = sum(r["prompt_length"] for r in results if r.get("success", False)) / success_count
|
||||
print(f"⏱️ 平均执行时间: {avg_time:.2f}秒")
|
||||
print(f"📏 平均提示词长度: {avg_length:.0f}字符")
|
||||
|
||||
return results
|
||||
|
||||
def test_api_configs():
|
||||
"""测试所有API配置"""
|
||||
print(f"{'-'*50}\n🧪 测试所有API配置\n{'-'*50}")
|
||||
|
||||
test_topic = "测试API配置的简单主题"
|
||||
|
||||
for i, config in enumerate(API_CONFIGS, 1):
|
||||
print(f"\n🔌 测试API配置 {i}: {config['name']}")
|
||||
print(f" 模型: {config['model']}")
|
||||
print(f" URL: {config['base_url']}")
|
||||
|
||||
try:
|
||||
# 构建提示词
|
||||
full_prompt = SYSTEM_PROMPT_TEMPLATE + f"\n\nTopic: {test_topic}"
|
||||
|
||||
# 准备请求
|
||||
endpoint = f"{config['base_url']}/chat/completions"
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": f"Bearer {config['api_key']}"
|
||||
}
|
||||
payload = {
|
||||
"model": config["model"],
|
||||
"messages": [{"role": "user", "content": full_prompt}],
|
||||
"temperature": 0.7,
|
||||
"max_tokens": 100, # 减少token以加快测试
|
||||
"stream": False
|
||||
}
|
||||
|
||||
# 发送请求
|
||||
start_time = datetime.now()
|
||||
print(f" 🕒 发送请求...")
|
||||
response = requests.post(endpoint, headers=headers, json=payload, timeout=10)
|
||||
end_time = datetime.now()
|
||||
execution_time = (end_time - start_time).total_seconds()
|
||||
|
||||
# 检查响应
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
|
||||
# 输出结果
|
||||
print(f" ✅ API工作正常! 响应时间: {execution_time:.2f}秒")
|
||||
print(f" 🔑 响应状态码: {response.status_code}")
|
||||
print(f" 📦 模型回复: {result['choices'][0]['message']['content'][:50]}...")
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ API测试失败: {str(e)}")
|
||||
|
||||
def main():
|
||||
"""主函数,运行多个测试"""
|
||||
print(f"🚀 DeepSeek提示词生成器测试 - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
|
||||
|
||||
# 运行标准测试
|
||||
user_topic = "设计一张南开大学的海报,要求风格为卡通风格,包含南开大学的标志性建筑和校园元素。"
|
||||
print(f"🔍 标准测试 - 主题: {user_topic}")
|
||||
|
||||
try:
|
||||
prompt = generate_prompt(user_topic)
|
||||
output_file = save_deepseek_output(prompt, "南开大学海报")
|
||||
print(f"✅ 标准测试成功!")
|
||||
print(f"📄 生成的提示词: {prompt[:100]}...")
|
||||
print(f"💾 已保存到: {output_file}")
|
||||
except Exception as e:
|
||||
print(f"❌ 标准测试失败: {str(e)}")
|
||||
|
||||
# 询问用户是否运行更多测试
|
||||
print("\n是否运行更多测试? (输入数字选择)")
|
||||
print("1. 测试多个主题")
|
||||
print("2. 测试API配置")
|
||||
print("3. 运行所有测试")
|
||||
print("0. 退出")
|
||||
|
||||
choice = input("请选择 (默认0): ").strip() or "0"
|
||||
|
||||
if choice == "1":
|
||||
test_multiple_topics()
|
||||
elif choice == "2":
|
||||
test_api_configs()
|
||||
elif choice == "3":
|
||||
test_multiple_topics()
|
||||
test_api_configs()
|
||||
else:
|
||||
print("退出测试。")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
260
scripts/GenerateImagesForUser.py
Normal file
@ -0,0 +1,260 @@
|
||||
'''
|
||||
* @file GenerateImages.py
|
||||
* @brief Generate images from text descriptions.
|
||||
*
|
||||
* @author WuYingwen
|
||||
* @GitHub @wuyingwen10
|
||||
* @Contact 2211537@mail.nankai.edu.cn
|
||||
* @date 2025-06-08
|
||||
* @version v1.0.2
|
||||
*
|
||||
* @details
|
||||
* Core functionality:
|
||||
* - Generate images from user-provided text prompts;
|
||||
* - Generate optimized prompt statements based on user input;
|
||||
* - Provides a clean interface for generating images from text prompts
|
||||
*
|
||||
* @note
|
||||
* - For local server connections: Update COMFYUI_ENDPOINT with target address + port;
|
||||
* - Timestamps prevent filename conflicts during image generation,perform simple string matching if necessary;
|
||||
* - Filename format: "<file_prefix>_<timestamp>.png" (e.g., mountains_202507011210902.png);
|
||||
* - Contact author for technical support;
|
||||
*
|
||||
* @interface
|
||||
* generate_images_interface(
|
||||
* user_topic: str,
|
||||
* width: int,
|
||||
* height: int,
|
||||
* batch_size: int,
|
||||
* file_prefix: str
|
||||
* ) -> tuple
|
||||
*
|
||||
* @copyright
|
||||
* (c) 2025 Nankai University
|
||||
'''
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import uuid
|
||||
import random
|
||||
from datetime import datetime
|
||||
from websocket import create_connection, WebSocketTimeoutException, WebSocketConnectionClosedException
|
||||
import urllib.request
|
||||
import urllib.parse
|
||||
from DeepSeekPromptGenerator import generate_prompt, save_deepseek_output
|
||||
|
||||
|
||||
def generate_images_interface(user_topic, width, height, batch_size, file_prefix):
|
||||
deepseek_output_path = ""
|
||||
try:
|
||||
system_prompt = generate_prompt(user_topic)
|
||||
deepseek_output_path = save_deepseek_output(system_prompt, file_prefix)
|
||||
except Exception as e:
|
||||
print(f"Prompt optimization failed: {str(e)}")
|
||||
|
||||
output_dir = 'output'
|
||||
comfyui_server = '127.0.0.1:8188'
|
||||
default_workflow = './workflows/flux_work.json'
|
||||
temp_dir = './workflows/temp'
|
||||
|
||||
os.makedirs(temp_dir, exist_ok=True)
|
||||
processed_workflow = os.path.join(temp_dir, f"processed_workflow_{uuid.uuid4().hex}.json")
|
||||
|
||||
workflow_file = preprocess_workflow(
|
||||
system_prompt=user_topic,
|
||||
width=width,
|
||||
height=height,
|
||||
batch_size=batch_size,
|
||||
input_json=default_workflow,
|
||||
output_json=processed_workflow
|
||||
)
|
||||
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
client_id = str(uuid.uuid4())
|
||||
image_files = generate_images(
|
||||
workflow_file=workflow_file,
|
||||
server_address=comfyui_server,
|
||||
output_dir=output_dir,
|
||||
client_id=client_id,
|
||||
file_prefix=file_prefix
|
||||
)
|
||||
|
||||
return (deepseek_output_path, image_files)
|
||||
|
||||
|
||||
def generate_images_info(user_input_analysis, system_prompt):
|
||||
width = user_input_analysis.get('width', 1024)
|
||||
height = user_input_analysis.get('height', 768)
|
||||
batch_size = user_input_analysis.get('batch_size', 1)
|
||||
file_prefix = user_input_analysis.get('file_prefix', 'image')
|
||||
|
||||
OUTPUT_DIR = 'output'
|
||||
COMFYUI_SERVER = '127.0.0.1:8188'
|
||||
DEFAULT_WORKFLOW = './workflows/flux_work.json'
|
||||
TEMP_DIR = './workflows/temp'
|
||||
|
||||
os.makedirs(TEMP_DIR, exist_ok=True)
|
||||
PROCESSED_WORKFLOW = os.path.join(TEMP_DIR, f"processed_workflow_{uuid.uuid4().hex}.json")
|
||||
|
||||
workflow_file = preprocess_workflow(
|
||||
system_prompt=system_prompt,
|
||||
width=width,
|
||||
height=height,
|
||||
batch_size=batch_size,
|
||||
input_json=DEFAULT_WORKFLOW,
|
||||
output_json=PROCESSED_WORKFLOW
|
||||
)
|
||||
|
||||
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
||||
|
||||
client_id = str(uuid.uuid4())
|
||||
|
||||
image_files = generate_images(
|
||||
workflow_file=workflow_file,
|
||||
server_address=COMFYUI_SERVER,
|
||||
output_dir=OUTPUT_DIR,
|
||||
client_id=client_id,
|
||||
file_prefix=file_prefix
|
||||
)
|
||||
|
||||
image_list = []
|
||||
for file_path in image_files:
|
||||
filename = os.path.basename(file_path)
|
||||
name_without_ext = os.path.splitext(filename)[0]
|
||||
|
||||
image_info = {
|
||||
"image_name": name_without_ext,
|
||||
"image_type": "png",
|
||||
"image_description": system_prompt,
|
||||
"image_dimensions": f"{width}x{height}"
|
||||
}
|
||||
image_list.append(image_info)
|
||||
|
||||
return image_list
|
||||
|
||||
def preprocess_workflow(system_prompt, width, height, batch_size, input_json='flux_work.json', output_json='processed_workflow.json'):
|
||||
try:
|
||||
with open(input_json, 'r', encoding='utf-8') as f:
|
||||
workflow = json.load(f)
|
||||
|
||||
workflow['31']['inputs']['system_prompt'] = system_prompt
|
||||
|
||||
workflow['27']['inputs']['width'] = str(width)
|
||||
workflow['27']['inputs']['height'] = str(height)
|
||||
workflow['27']['inputs']['batch_size'] = str(batch_size)
|
||||
|
||||
with open(output_json, 'w', encoding='utf-8') as f:
|
||||
json.dump(workflow, f, indent=2, ensure_ascii=False)
|
||||
|
||||
print(f"Workflow updated and saved to: {output_json}")
|
||||
return output_json
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error processing workflow: {str(e)}")
|
||||
sys.exit(1)
|
||||
|
||||
def queue_prompt(prompt, server_address, client_id):
|
||||
payload = {"prompt": prompt, "client_id": client_id}
|
||||
data = json.dumps(payload).encode('utf-8')
|
||||
request = urllib.request.Request(f"http://{server_address}/prompt", data=data)
|
||||
return json.loads(urllib.request.urlopen(request).read())
|
||||
|
||||
def get_image(filename, subfolder, folder_type, server_address):
|
||||
params = {"filename": filename, "subfolder": subfolder, "type": folder_type}
|
||||
url_values = urllib.parse.urlencode(params)
|
||||
with urllib.request.urlopen(f"http://{server_address}/view?{url_values}") as response:
|
||||
return response.read()
|
||||
|
||||
def get_history(prompt_id, server_address):
|
||||
with urllib.request.urlopen(f"http://{server_address}/history/{prompt_id}") as response:
|
||||
return json.loads(response.read())
|
||||
|
||||
def retrieve_images(ws, prompt, server_address, client_id, timeout=600):
|
||||
prompt_id = queue_prompt(prompt, server_address, client_id)['prompt_id']
|
||||
print(f'Prompt ID: {prompt_id}')
|
||||
images_data = {}
|
||||
|
||||
start_time = time.time()
|
||||
while True:
|
||||
if time.time() - start_time > timeout:
|
||||
print(f"Timeout: Execution took longer than {timeout} seconds")
|
||||
break
|
||||
|
||||
try:
|
||||
data = ws.recv()
|
||||
if isinstance(data, str):
|
||||
message = json.loads(data)
|
||||
if message['type'] == 'executing':
|
||||
content = message['data']
|
||||
if content['node'] is None and content['prompt_id'] == prompt_id:
|
||||
print('Execution completed')
|
||||
break
|
||||
except Exception as e:
|
||||
print(f"Error receiving data: {str(e)}")
|
||||
break
|
||||
|
||||
history = get_history(prompt_id, server_address).get(prompt_id, {})
|
||||
if not history:
|
||||
print("No history found for this prompt")
|
||||
return {}
|
||||
|
||||
for node_id, node_data in history['outputs'].items():
|
||||
if 'images' in node_data:
|
||||
image_collection = []
|
||||
for image in node_data['images']:
|
||||
try:
|
||||
img_data = get_image(image['filename'], image['subfolder'], image['type'], server_address)
|
||||
image_collection.append({
|
||||
'data': img_data,
|
||||
'filename': image['filename'],
|
||||
'subfolder': image['subfolder'],
|
||||
'type': image['type']
|
||||
})
|
||||
except Exception as e:
|
||||
print(f"Error retrieving image: {str(e)}")
|
||||
images_data[node_id] = image_collection
|
||||
|
||||
print(f'Retrieved {len(images_data)} image outputs')
|
||||
return images_data
|
||||
|
||||
def generate_images(workflow_file, server_address, output_dir, client_id, file_prefix="image"):
|
||||
try:
|
||||
with open(workflow_file, 'r', encoding='utf-8') as f:
|
||||
workflow = json.load(f)
|
||||
|
||||
seed = random.randint(1, 10**8)
|
||||
print(f'Using seed: {seed}')
|
||||
|
||||
workflow['25']['inputs']['noise_seed'] = seed
|
||||
|
||||
ws_url = f"ws://{server_address}/ws?clientId={client_id}"
|
||||
ws = create_connection(ws_url, timeout=600)
|
||||
|
||||
images = retrieve_images(ws, workflow, server_address, client_id)
|
||||
ws.close()
|
||||
|
||||
saved_files = []
|
||||
if images:
|
||||
for node_id, img_list in images.items():
|
||||
for i, img in enumerate(img_list):
|
||||
timestamp = datetime.now().strftime("%Y%m%d%H%M%S%f")[:-3]
|
||||
|
||||
filename = f"{file_prefix}_{timestamp}.png"
|
||||
file_path = os.path.join(output_dir, filename)
|
||||
|
||||
try:
|
||||
with open(file_path, "wb") as f:
|
||||
f.write(img['data'])
|
||||
saved_files.append(file_path)
|
||||
print(f'Saved: {file_path}')
|
||||
except Exception as e:
|
||||
print(f"Error saving image: {str(e)}")
|
||||
|
||||
return saved_files
|
||||
|
||||
except Exception as e:
|
||||
print(f"Image generation failed: {str(e)}")
|
||||
return []
|
@ -1,14 +0,0 @@
|
||||
from export_psd import create_psd_from_images
|
||||
|
||||
if __name__ == "__main__":
|
||||
image_list = [
|
||||
'../images/background.jpg',
|
||||
'../images/nankai.jpg',
|
||||
'../images/aaai.png',
|
||||
# Add more images as needed
|
||||
]
|
||||
|
||||
create_psd_from_images(
|
||||
image_paths=image_list,
|
||||
output_path='../outputs/combined_output.psd'
|
||||
)
|
BIN
scripts/__pycache__/DeepSeekPromptGenerator.cpython-39.pyc
Normal file
@ -86,15 +86,15 @@ def create_psd_from_images(
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 示例用法
|
||||
image_list = [
|
||||
'../images/background.jpg', # 底层图片
|
||||
'../images/nankai.jpg', # 中间图片
|
||||
'../images/aaai.png', # 顶层图片
|
||||
# 可以根据需要添加更多图片
|
||||
]
|
||||
# 示例用法
|
||||
preassigned_img_list_path=[
|
||||
"../outputs/background.png",
|
||||
"../outputs/lotus.jpg",
|
||||
"../outputs/nankai.png",
|
||||
"../outputs/stamp.jpg"
|
||||
]
|
||||
|
||||
create_psd_from_images(
|
||||
image_paths=image_list,
|
||||
image_paths=preassigned_img_list_path,
|
||||
output_path='../outputs/combined_output.psd'
|
||||
)
|
@ -48,7 +48,7 @@ load_dotenv()
|
||||
deepseek_url = 'https://api.deepseek.com/v1' # set to be compatible with the OpenAI API
|
||||
deepseek_api = os.getenv("DEEPSEEK_API_KEY")
|
||||
if not deepseek_api:
|
||||
raise ValueError("DEEPSEEK_API_KEY not set!")
|
||||
raise ValueError("DEEPSEEK_API_KEY not set!")
|
||||
|
||||
def call_deepseek(
|
||||
messages=None,
|
||||
|
@ -156,9 +156,6 @@ def create_psd_from_fixed_images(output_path: str) -> Optional[str]:
|
||||
|
||||
|
||||
def run_pipeline(user_input: str = None) -> Optional[str]:
|
||||
"""
|
||||
简化的海报生成流程
|
||||
"""
|
||||
try:
|
||||
print(f"{Fore.MAGENTA}{'=' * 50}")
|
||||
print(f"{Fore.MAGENTA}🎨 海报生成流程启动 🎨")
|
||||
@ -269,9 +266,6 @@ def health_check():
|
||||
|
||||
@app.post("/api/generate-poster", response_model=ApiResponse)
|
||||
async def generate_poster_api(request: PosterRequest):
|
||||
"""
|
||||
简化的海报生成API接口
|
||||
"""
|
||||
try:
|
||||
session_folder, session_id = get_session_folder(request.session_id)
|
||||
|
||||
|
@ -1,208 +0,0 @@
|
||||
# 自动执行流程说明文档
|
||||
|
||||
本流程通过多个脚本与配置文件协作,自动生成海报的排版、文案、图像并输出 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)
|
||||
|
||||
```
|
@ -101,7 +101,7 @@ def save_vue_file(vue_code: str, file_path: str):
|
||||
print(f"{Fore.RED}❌ Vue文件保存失败: {e}{Style.RESET_ALL}")
|
||||
|
||||
|
||||
def create_temp_config(user_input: str = None) -> str:
|
||||
def create_temp_config(user_input: Optional[str] = None) -> str:
|
||||
"""动态生成临时配置文件"""
|
||||
if not user_input:
|
||||
user_input = "默认海报配置"
|
||||
@ -199,8 +199,11 @@ def llm_user_analysis(user_input: str) -> Dict:
|
||||
try:
|
||||
result, _ = call_deepseek(prompt=analysis_prompt, system_prompt=system_prompt, temperature=0.3)
|
||||
|
||||
# 确保result是字符串类型
|
||||
result_str = str(result) if result is not None else ""
|
||||
|
||||
# 解析JSON
|
||||
json_str = result.strip()
|
||||
json_str = result_str.strip()
|
||||
if "```json" in json_str:
|
||||
json_str = json_str.split("```json")[1].split("```")[0].strip()
|
||||
elif json_str.startswith("```") and json_str.endswith("```"):
|
||||
|
@ -0,0 +1,226 @@
|
||||
{
|
||||
"6": {
|
||||
"inputs": {
|
||||
"text": [
|
||||
"31",
|
||||
0
|
||||
],
|
||||
"clip": [
|
||||
"11",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "CLIPTextEncode",
|
||||
"_meta": {
|
||||
"title": "CLIP Text Encode (Positive Prompt)"
|
||||
}
|
||||
},
|
||||
"8": {
|
||||
"inputs": {
|
||||
"samples": [
|
||||
"13",
|
||||
0
|
||||
],
|
||||
"vae": [
|
||||
"10",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "VAEDecode",
|
||||
"_meta": {
|
||||
"title": "VAE解码"
|
||||
}
|
||||
},
|
||||
"9": {
|
||||
"inputs": {
|
||||
"filename_prefix": "ComfyUI",
|
||||
"images": [
|
||||
"8",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "SaveImage",
|
||||
"_meta": {
|
||||
"title": "保存图像"
|
||||
}
|
||||
},
|
||||
"10": {
|
||||
"inputs": {
|
||||
"vae_name": "ae.safetensors"
|
||||
},
|
||||
"class_type": "VAELoader",
|
||||
"_meta": {
|
||||
"title": "加载VAE"
|
||||
}
|
||||
},
|
||||
"11": {
|
||||
"inputs": {
|
||||
"clip_name1": "t5xxl_fp16.safetensors",
|
||||
"clip_name2": "clip_l.safetensors",
|
||||
"type": "flux",
|
||||
"device": "default"
|
||||
},
|
||||
"class_type": "DualCLIPLoader",
|
||||
"_meta": {
|
||||
"title": "双CLIP加载器"
|
||||
}
|
||||
},
|
||||
"12": {
|
||||
"inputs": {
|
||||
"unet_name": "flux1-dev.safetensors",
|
||||
"weight_dtype": "default"
|
||||
},
|
||||
"class_type": "UNETLoader",
|
||||
"_meta": {
|
||||
"title": "UNet加载器"
|
||||
}
|
||||
},
|
||||
"13": {
|
||||
"inputs": {
|
||||
"noise": [
|
||||
"25",
|
||||
0
|
||||
],
|
||||
"guider": [
|
||||
"22",
|
||||
0
|
||||
],
|
||||
"sampler": [
|
||||
"16",
|
||||
0
|
||||
],
|
||||
"sigmas": [
|
||||
"17",
|
||||
0
|
||||
],
|
||||
"latent_image": [
|
||||
"27",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "SamplerCustomAdvanced",
|
||||
"_meta": {
|
||||
"title": "自定义采样器(高级)"
|
||||
}
|
||||
},
|
||||
"16": {
|
||||
"inputs": {
|
||||
"sampler_name": "euler"
|
||||
},
|
||||
"class_type": "KSamplerSelect",
|
||||
"_meta": {
|
||||
"title": "K采样器选择"
|
||||
}
|
||||
},
|
||||
"17": {
|
||||
"inputs": {
|
||||
"scheduler": "simple",
|
||||
"steps": 25,
|
||||
"denoise": 1,
|
||||
"model": [
|
||||
"30",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "BasicScheduler",
|
||||
"_meta": {
|
||||
"title": "基本调度器"
|
||||
}
|
||||
},
|
||||
"22": {
|
||||
"inputs": {
|
||||
"model": [
|
||||
"30",
|
||||
0
|
||||
],
|
||||
"conditioning": [
|
||||
"26",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "BasicGuider",
|
||||
"_meta": {
|
||||
"title": "基本引导器"
|
||||
}
|
||||
},
|
||||
"25": {
|
||||
"inputs": {
|
||||
"noise_seed": 142213168350829
|
||||
},
|
||||
"class_type": "RandomNoise",
|
||||
"_meta": {
|
||||
"title": "随机噪波"
|
||||
}
|
||||
},
|
||||
"26": {
|
||||
"inputs": {
|
||||
"guidance": 3.5,
|
||||
"conditioning": [
|
||||
"6",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "FluxGuidance",
|
||||
"_meta": {
|
||||
"title": "Flux引导"
|
||||
}
|
||||
},
|
||||
"27": {
|
||||
"inputs": {
|
||||
"width": "1080",
|
||||
"height": "1920",
|
||||
"batch_size": "2"
|
||||
},
|
||||
"class_type": "EmptySD3LatentImage",
|
||||
"_meta": {
|
||||
"title": "空Latent图像(SD3)"
|
||||
}
|
||||
},
|
||||
"30": {
|
||||
"inputs": {
|
||||
"max_shift": 1.1500000000000001,
|
||||
"base_shift": 0.5000000000000001,
|
||||
"width": 1024,
|
||||
"height": 1024,
|
||||
"model": [
|
||||
"12",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "ModelSamplingFlux",
|
||||
"_meta": {
|
||||
"title": "采样算法(Flux)"
|
||||
}
|
||||
},
|
||||
"31": {
|
||||
"inputs": {
|
||||
"user_prompt": "作为一个AI提示词专家,请你仿照范例,根据我给出的主题,生成一条符合下列要求的提示词,来让CLIP模型可以更好地理解画面主体。注意:你需要仿照下面的示例详细分析(仅仿照写法,而不仿照任何内容),将用户的需求转化为详细的提示词。\\n 要求共六条,请严格遵守:\\n 1: 用自然语言简单句来描述画面,请避免出现过于长的,或者格式过于复杂的句子,句子中不要出现*等特殊符号。\\n 2.用英语表达。 \\n 3.直接给出prompt内容即可,不需要任何解释和说明。\\n 4. 每条prompt至少50词,不超过200词。\\n 5.避免模棱两可的说法。\\n 6.描述的最开始加入:“no text, no AI style”\\n 例如:\nCartoon-Style Nankai University Main Building,\nvividly depicted with rounded edges and pastel gradients, the iconic Gothic-Revival structure stands majestically. Crimson brick façade contrasts with golden-glowing arched windows, while whimsical cloud-shaped eaves drip melted clock details. A giant smiling sun hangs low, casting honey-golden rays through simplified pine trees, creating striped shadows dancing on marble stairs.\n\nTranslucent ghostly scholars from 1919 float near pillars holding glowing books, their outlines shimmering like liquid mercury. Oversized autumn leaves (stylized as maple-red origami) spiral around twin bell towers chiming visible musical notes. Puddles on the ground mirror upside-down building reflections rippling with calculus formulas.\n\nEnvironment:\nSurreal candy-pink sunset gradients blend into starry indigo sky above. Playful squirrels wearing tiny graduation caps scamper across emerald lawns textured like green velvet.",
|
||||
"system_prompt": "端午节庆祝",
|
||||
"enable_history": false,
|
||||
"max_history": 10,
|
||||
"history_json": "",
|
||||
"save_path": "./chat_history.json",
|
||||
"api_config": [
|
||||
"32",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "DeepSeekChat",
|
||||
"_meta": {
|
||||
"title": "LLM Model Input Box"
|
||||
}
|
||||
},
|
||||
"32": {
|
||||
"inputs": {
|
||||
"config_name": "DeepSeek官方Chat API",
|
||||
"temperature": 1,
|
||||
"max_tokens": 512,
|
||||
"stream": false,
|
||||
"api_key": ""
|
||||
},
|
||||
"class_type": "DeepSeekAPIConfig",
|
||||
"_meta": {
|
||||
"title": "LLM API Model Selector"
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,226 @@
|
||||
{
|
||||
"6": {
|
||||
"inputs": {
|
||||
"text": [
|
||||
"31",
|
||||
0
|
||||
],
|
||||
"clip": [
|
||||
"11",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "CLIPTextEncode",
|
||||
"_meta": {
|
||||
"title": "CLIP Text Encode (Positive Prompt)"
|
||||
}
|
||||
},
|
||||
"8": {
|
||||
"inputs": {
|
||||
"samples": [
|
||||
"13",
|
||||
0
|
||||
],
|
||||
"vae": [
|
||||
"10",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "VAEDecode",
|
||||
"_meta": {
|
||||
"title": "VAE解码"
|
||||
}
|
||||
},
|
||||
"9": {
|
||||
"inputs": {
|
||||
"filename_prefix": "ComfyUI",
|
||||
"images": [
|
||||
"8",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "SaveImage",
|
||||
"_meta": {
|
||||
"title": "保存图像"
|
||||
}
|
||||
},
|
||||
"10": {
|
||||
"inputs": {
|
||||
"vae_name": "ae.safetensors"
|
||||
},
|
||||
"class_type": "VAELoader",
|
||||
"_meta": {
|
||||
"title": "加载VAE"
|
||||
}
|
||||
},
|
||||
"11": {
|
||||
"inputs": {
|
||||
"clip_name1": "t5xxl_fp16.safetensors",
|
||||
"clip_name2": "clip_l.safetensors",
|
||||
"type": "flux",
|
||||
"device": "default"
|
||||
},
|
||||
"class_type": "DualCLIPLoader",
|
||||
"_meta": {
|
||||
"title": "双CLIP加载器"
|
||||
}
|
||||
},
|
||||
"12": {
|
||||
"inputs": {
|
||||
"unet_name": "flux1-dev.safetensors",
|
||||
"weight_dtype": "default"
|
||||
},
|
||||
"class_type": "UNETLoader",
|
||||
"_meta": {
|
||||
"title": "UNet加载器"
|
||||
}
|
||||
},
|
||||
"13": {
|
||||
"inputs": {
|
||||
"noise": [
|
||||
"25",
|
||||
0
|
||||
],
|
||||
"guider": [
|
||||
"22",
|
||||
0
|
||||
],
|
||||
"sampler": [
|
||||
"16",
|
||||
0
|
||||
],
|
||||
"sigmas": [
|
||||
"17",
|
||||
0
|
||||
],
|
||||
"latent_image": [
|
||||
"27",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "SamplerCustomAdvanced",
|
||||
"_meta": {
|
||||
"title": "自定义采样器(高级)"
|
||||
}
|
||||
},
|
||||
"16": {
|
||||
"inputs": {
|
||||
"sampler_name": "euler"
|
||||
},
|
||||
"class_type": "KSamplerSelect",
|
||||
"_meta": {
|
||||
"title": "K采样器选择"
|
||||
}
|
||||
},
|
||||
"17": {
|
||||
"inputs": {
|
||||
"scheduler": "simple",
|
||||
"steps": 25,
|
||||
"denoise": 1,
|
||||
"model": [
|
||||
"30",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "BasicScheduler",
|
||||
"_meta": {
|
||||
"title": "基本调度器"
|
||||
}
|
||||
},
|
||||
"22": {
|
||||
"inputs": {
|
||||
"model": [
|
||||
"30",
|
||||
0
|
||||
],
|
||||
"conditioning": [
|
||||
"26",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "BasicGuider",
|
||||
"_meta": {
|
||||
"title": "基本引导器"
|
||||
}
|
||||
},
|
||||
"25": {
|
||||
"inputs": {
|
||||
"noise_seed": 142213168350829
|
||||
},
|
||||
"class_type": "RandomNoise",
|
||||
"_meta": {
|
||||
"title": "随机噪波"
|
||||
}
|
||||
},
|
||||
"26": {
|
||||
"inputs": {
|
||||
"guidance": 3.5,
|
||||
"conditioning": [
|
||||
"6",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "FluxGuidance",
|
||||
"_meta": {
|
||||
"title": "Flux引导"
|
||||
}
|
||||
},
|
||||
"27": {
|
||||
"inputs": {
|
||||
"width": "1080",
|
||||
"height": "1920",
|
||||
"batch_size": "2"
|
||||
},
|
||||
"class_type": "EmptySD3LatentImage",
|
||||
"_meta": {
|
||||
"title": "空Latent图像(SD3)"
|
||||
}
|
||||
},
|
||||
"30": {
|
||||
"inputs": {
|
||||
"max_shift": 1.1500000000000001,
|
||||
"base_shift": 0.5000000000000001,
|
||||
"width": 1024,
|
||||
"height": 1024,
|
||||
"model": [
|
||||
"12",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "ModelSamplingFlux",
|
||||
"_meta": {
|
||||
"title": "采样算法(Flux)"
|
||||
}
|
||||
},
|
||||
"31": {
|
||||
"inputs": {
|
||||
"user_prompt": "作为一个AI提示词专家,请你仿照范例,根据我给出的主题,生成一条符合下列要求的提示词,来让CLIP模型可以更好地理解画面主体。注意:你需要仿照下面的示例详细分析(仅仿照写法,而不仿照任何内容),将用户的需求转化为详细的提示词。\\n 要求共六条,请严格遵守:\\n 1: 用自然语言简单句来描述画面,请避免出现过于长的,或者格式过于复杂的句子,句子中不要出现*等特殊符号。\\n 2.用英语表达。 \\n 3.直接给出prompt内容即可,不需要任何解释和说明。\\n 4. 每条prompt至少50词,不超过200词。\\n 5.避免模棱两可的说法。\\n 6.描述的最开始加入:“no text, no AI style”\\n 例如:\nCartoon-Style Nankai University Main Building,\nvividly depicted with rounded edges and pastel gradients, the iconic Gothic-Revival structure stands majestically. Crimson brick façade contrasts with golden-glowing arched windows, while whimsical cloud-shaped eaves drip melted clock details. A giant smiling sun hangs low, casting honey-golden rays through simplified pine trees, creating striped shadows dancing on marble stairs.\n\nTranslucent ghostly scholars from 1919 float near pillars holding glowing books, their outlines shimmering like liquid mercury. Oversized autumn leaves (stylized as maple-red origami) spiral around twin bell towers chiming visible musical notes. Puddles on the ground mirror upside-down building reflections rippling with calculus formulas.\n\nEnvironment:\nSurreal candy-pink sunset gradients blend into starry indigo sky above. Playful squirrels wearing tiny graduation caps scamper across emerald lawns textured like green velvet.",
|
||||
"system_prompt": "端午节海报,传统风格",
|
||||
"enable_history": false,
|
||||
"max_history": 10,
|
||||
"history_json": "",
|
||||
"save_path": "./chat_history.json",
|
||||
"api_config": [
|
||||
"32",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "DeepSeekChat",
|
||||
"_meta": {
|
||||
"title": "LLM Model Input Box"
|
||||
}
|
||||
},
|
||||
"32": {
|
||||
"inputs": {
|
||||
"config_name": "DeepSeek官方Chat API",
|
||||
"temperature": 1,
|
||||
"max_tokens": 512,
|
||||
"stream": false,
|
||||
"api_key": ""
|
||||
},
|
||||
"class_type": "DeepSeekAPIConfig",
|
||||
"_meta": {
|
||||
"title": "LLM API Model Selector"
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,226 @@
|
||||
{
|
||||
"6": {
|
||||
"inputs": {
|
||||
"text": [
|
||||
"31",
|
||||
0
|
||||
],
|
||||
"clip": [
|
||||
"11",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "CLIPTextEncode",
|
||||
"_meta": {
|
||||
"title": "CLIP Text Encode (Positive Prompt)"
|
||||
}
|
||||
},
|
||||
"8": {
|
||||
"inputs": {
|
||||
"samples": [
|
||||
"13",
|
||||
0
|
||||
],
|
||||
"vae": [
|
||||
"10",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "VAEDecode",
|
||||
"_meta": {
|
||||
"title": "VAE解码"
|
||||
}
|
||||
},
|
||||
"9": {
|
||||
"inputs": {
|
||||
"filename_prefix": "ComfyUI",
|
||||
"images": [
|
||||
"8",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "SaveImage",
|
||||
"_meta": {
|
||||
"title": "保存图像"
|
||||
}
|
||||
},
|
||||
"10": {
|
||||
"inputs": {
|
||||
"vae_name": "ae.safetensors"
|
||||
},
|
||||
"class_type": "VAELoader",
|
||||
"_meta": {
|
||||
"title": "加载VAE"
|
||||
}
|
||||
},
|
||||
"11": {
|
||||
"inputs": {
|
||||
"clip_name1": "t5xxl_fp16.safetensors",
|
||||
"clip_name2": "clip_l.safetensors",
|
||||
"type": "flux",
|
||||
"device": "default"
|
||||
},
|
||||
"class_type": "DualCLIPLoader",
|
||||
"_meta": {
|
||||
"title": "双CLIP加载器"
|
||||
}
|
||||
},
|
||||
"12": {
|
||||
"inputs": {
|
||||
"unet_name": "flux1-dev.safetensors",
|
||||
"weight_dtype": "default"
|
||||
},
|
||||
"class_type": "UNETLoader",
|
||||
"_meta": {
|
||||
"title": "UNet加载器"
|
||||
}
|
||||
},
|
||||
"13": {
|
||||
"inputs": {
|
||||
"noise": [
|
||||
"25",
|
||||
0
|
||||
],
|
||||
"guider": [
|
||||
"22",
|
||||
0
|
||||
],
|
||||
"sampler": [
|
||||
"16",
|
||||
0
|
||||
],
|
||||
"sigmas": [
|
||||
"17",
|
||||
0
|
||||
],
|
||||
"latent_image": [
|
||||
"27",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "SamplerCustomAdvanced",
|
||||
"_meta": {
|
||||
"title": "自定义采样器(高级)"
|
||||
}
|
||||
},
|
||||
"16": {
|
||||
"inputs": {
|
||||
"sampler_name": "euler"
|
||||
},
|
||||
"class_type": "KSamplerSelect",
|
||||
"_meta": {
|
||||
"title": "K采样器选择"
|
||||
}
|
||||
},
|
||||
"17": {
|
||||
"inputs": {
|
||||
"scheduler": "simple",
|
||||
"steps": 25,
|
||||
"denoise": 1,
|
||||
"model": [
|
||||
"30",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "BasicScheduler",
|
||||
"_meta": {
|
||||
"title": "基本调度器"
|
||||
}
|
||||
},
|
||||
"22": {
|
||||
"inputs": {
|
||||
"model": [
|
||||
"30",
|
||||
0
|
||||
],
|
||||
"conditioning": [
|
||||
"26",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "BasicGuider",
|
||||
"_meta": {
|
||||
"title": "基本引导器"
|
||||
}
|
||||
},
|
||||
"25": {
|
||||
"inputs": {
|
||||
"noise_seed": 142213168350829
|
||||
},
|
||||
"class_type": "RandomNoise",
|
||||
"_meta": {
|
||||
"title": "随机噪波"
|
||||
}
|
||||
},
|
||||
"26": {
|
||||
"inputs": {
|
||||
"guidance": 3.5,
|
||||
"conditioning": [
|
||||
"6",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "FluxGuidance",
|
||||
"_meta": {
|
||||
"title": "Flux引导"
|
||||
}
|
||||
},
|
||||
"27": {
|
||||
"inputs": {
|
||||
"width": "1080",
|
||||
"height": "1920",
|
||||
"batch_size": "2"
|
||||
},
|
||||
"class_type": "EmptySD3LatentImage",
|
||||
"_meta": {
|
||||
"title": "空Latent图像(SD3)"
|
||||
}
|
||||
},
|
||||
"30": {
|
||||
"inputs": {
|
||||
"max_shift": 1.1500000000000001,
|
||||
"base_shift": 0.5000000000000001,
|
||||
"width": 1024,
|
||||
"height": 1024,
|
||||
"model": [
|
||||
"12",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "ModelSamplingFlux",
|
||||
"_meta": {
|
||||
"title": "采样算法(Flux)"
|
||||
}
|
||||
},
|
||||
"31": {
|
||||
"inputs": {
|
||||
"user_prompt": "作为一个AI提示词专家,请你仿照范例,根据我给出的主题,生成一条符合下列要求的提示词,来让CLIP模型可以更好地理解画面主体。注意:你需要仿照下面的示例详细分析(仅仿照写法,而不仿照任何内容),将用户的需求转化为详细的提示词。\\n 要求共六条,请严格遵守:\\n 1: 用自然语言简单句来描述画面,请避免出现过于长的,或者格式过于复杂的句子,句子中不要出现*等特殊符号。\\n 2.用英语表达。 \\n 3.直接给出prompt内容即可,不需要任何解释和说明。\\n 4. 每条prompt至少50词,不超过200词。\\n 5.避免模棱两可的说法。\\n 6.描述的最开始加入:“no text, no AI style”\\n 例如:\nCartoon-Style Nankai University Main Building,\nvividly depicted with rounded edges and pastel gradients, the iconic Gothic-Revival structure stands majestically. Crimson brick façade contrasts with golden-glowing arched windows, while whimsical cloud-shaped eaves drip melted clock details. A giant smiling sun hangs low, casting honey-golden rays through simplified pine trees, creating striped shadows dancing on marble stairs.\n\nTranslucent ghostly scholars from 1919 float near pillars holding glowing books, their outlines shimmering like liquid mercury. Oversized autumn leaves (stylized as maple-red origami) spiral around twin bell towers chiming visible musical notes. Puddles on the ground mirror upside-down building reflections rippling with calculus formulas.\n\nEnvironment:\nSurreal candy-pink sunset gradients blend into starry indigo sky above. Playful squirrels wearing tiny graduation caps scamper across emerald lawns textured like green velvet.",
|
||||
"system_prompt": "端午节海报,传统风格",
|
||||
"enable_history": false,
|
||||
"max_history": 10,
|
||||
"history_json": "",
|
||||
"save_path": "./chat_history.json",
|
||||
"api_config": [
|
||||
"32",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "DeepSeekChat",
|
||||
"_meta": {
|
||||
"title": "LLM Model Input Box"
|
||||
}
|
||||
},
|
||||
"32": {
|
||||
"inputs": {
|
||||
"config_name": "DeepSeek官方Chat API",
|
||||
"temperature": 1,
|
||||
"max_tokens": 512,
|
||||
"stream": false,
|
||||
"api_key": ""
|
||||
},
|
||||
"class_type": "DeepSeekAPIConfig",
|
||||
"_meta": {
|
||||
"title": "LLM API Model Selector"
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,226 @@
|
||||
{
|
||||
"6": {
|
||||
"inputs": {
|
||||
"text": [
|
||||
"31",
|
||||
0
|
||||
],
|
||||
"clip": [
|
||||
"11",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "CLIPTextEncode",
|
||||
"_meta": {
|
||||
"title": "CLIP Text Encode (Positive Prompt)"
|
||||
}
|
||||
},
|
||||
"8": {
|
||||
"inputs": {
|
||||
"samples": [
|
||||
"13",
|
||||
0
|
||||
],
|
||||
"vae": [
|
||||
"10",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "VAEDecode",
|
||||
"_meta": {
|
||||
"title": "VAE解码"
|
||||
}
|
||||
},
|
||||
"9": {
|
||||
"inputs": {
|
||||
"filename_prefix": "ComfyUI",
|
||||
"images": [
|
||||
"8",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "SaveImage",
|
||||
"_meta": {
|
||||
"title": "保存图像"
|
||||
}
|
||||
},
|
||||
"10": {
|
||||
"inputs": {
|
||||
"vae_name": "ae.safetensors"
|
||||
},
|
||||
"class_type": "VAELoader",
|
||||
"_meta": {
|
||||
"title": "加载VAE"
|
||||
}
|
||||
},
|
||||
"11": {
|
||||
"inputs": {
|
||||
"clip_name1": "t5xxl_fp16.safetensors",
|
||||
"clip_name2": "clip_l.safetensors",
|
||||
"type": "flux",
|
||||
"device": "default"
|
||||
},
|
||||
"class_type": "DualCLIPLoader",
|
||||
"_meta": {
|
||||
"title": "双CLIP加载器"
|
||||
}
|
||||
},
|
||||
"12": {
|
||||
"inputs": {
|
||||
"unet_name": "flux1-dev.safetensors",
|
||||
"weight_dtype": "default"
|
||||
},
|
||||
"class_type": "UNETLoader",
|
||||
"_meta": {
|
||||
"title": "UNet加载器"
|
||||
}
|
||||
},
|
||||
"13": {
|
||||
"inputs": {
|
||||
"noise": [
|
||||
"25",
|
||||
0
|
||||
],
|
||||
"guider": [
|
||||
"22",
|
||||
0
|
||||
],
|
||||
"sampler": [
|
||||
"16",
|
||||
0
|
||||
],
|
||||
"sigmas": [
|
||||
"17",
|
||||
0
|
||||
],
|
||||
"latent_image": [
|
||||
"27",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "SamplerCustomAdvanced",
|
||||
"_meta": {
|
||||
"title": "自定义采样器(高级)"
|
||||
}
|
||||
},
|
||||
"16": {
|
||||
"inputs": {
|
||||
"sampler_name": "euler"
|
||||
},
|
||||
"class_type": "KSamplerSelect",
|
||||
"_meta": {
|
||||
"title": "K采样器选择"
|
||||
}
|
||||
},
|
||||
"17": {
|
||||
"inputs": {
|
||||
"scheduler": "simple",
|
||||
"steps": 25,
|
||||
"denoise": 1,
|
||||
"model": [
|
||||
"30",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "BasicScheduler",
|
||||
"_meta": {
|
||||
"title": "基本调度器"
|
||||
}
|
||||
},
|
||||
"22": {
|
||||
"inputs": {
|
||||
"model": [
|
||||
"30",
|
||||
0
|
||||
],
|
||||
"conditioning": [
|
||||
"26",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "BasicGuider",
|
||||
"_meta": {
|
||||
"title": "基本引导器"
|
||||
}
|
||||
},
|
||||
"25": {
|
||||
"inputs": {
|
||||
"noise_seed": 142213168350829
|
||||
},
|
||||
"class_type": "RandomNoise",
|
||||
"_meta": {
|
||||
"title": "随机噪波"
|
||||
}
|
||||
},
|
||||
"26": {
|
||||
"inputs": {
|
||||
"guidance": 3.5,
|
||||
"conditioning": [
|
||||
"6",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "FluxGuidance",
|
||||
"_meta": {
|
||||
"title": "Flux引导"
|
||||
}
|
||||
},
|
||||
"27": {
|
||||
"inputs": {
|
||||
"width": "1080",
|
||||
"height": "1920",
|
||||
"batch_size": "2"
|
||||
},
|
||||
"class_type": "EmptySD3LatentImage",
|
||||
"_meta": {
|
||||
"title": "空Latent图像(SD3)"
|
||||
}
|
||||
},
|
||||
"30": {
|
||||
"inputs": {
|
||||
"max_shift": 1.1500000000000001,
|
||||
"base_shift": 0.5000000000000001,
|
||||
"width": 1024,
|
||||
"height": 1024,
|
||||
"model": [
|
||||
"12",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "ModelSamplingFlux",
|
||||
"_meta": {
|
||||
"title": "采样算法(Flux)"
|
||||
}
|
||||
},
|
||||
"31": {
|
||||
"inputs": {
|
||||
"user_prompt": "作为一个AI提示词专家,请你仿照范例,根据我给出的主题,生成一条符合下列要求的提示词,来让CLIP模型可以更好地理解画面主体。注意:你需要仿照下面的示例详细分析(仅仿照写法,而不仿照任何内容),将用户的需求转化为详细的提示词。\\n 要求共六条,请严格遵守:\\n 1: 用自然语言简单句来描述画面,请避免出现过于长的,或者格式过于复杂的句子,句子中不要出现*等特殊符号。\\n 2.用英语表达。 \\n 3.直接给出prompt内容即可,不需要任何解释和说明。\\n 4. 每条prompt至少50词,不超过200词。\\n 5.避免模棱两可的说法。\\n 6.描述的最开始加入:“no text, no AI style”\\n 例如:\nCartoon-Style Nankai University Main Building,\nvividly depicted with rounded edges and pastel gradients, the iconic Gothic-Revival structure stands majestically. Crimson brick façade contrasts with golden-glowing arched windows, while whimsical cloud-shaped eaves drip melted clock details. A giant smiling sun hangs low, casting honey-golden rays through simplified pine trees, creating striped shadows dancing on marble stairs.\n\nTranslucent ghostly scholars from 1919 float near pillars holding glowing books, their outlines shimmering like liquid mercury. Oversized autumn leaves (stylized as maple-red origami) spiral around twin bell towers chiming visible musical notes. Puddles on the ground mirror upside-down building reflections rippling with calculus formulas.\n\nEnvironment:\nSurreal candy-pink sunset gradients blend into starry indigo sky above. Playful squirrels wearing tiny graduation caps scamper across emerald lawns textured like green velvet.",
|
||||
"system_prompt": "端午节海报,传统风格",
|
||||
"enable_history": false,
|
||||
"max_history": 10,
|
||||
"history_json": "",
|
||||
"save_path": "./chat_history.json",
|
||||
"api_config": [
|
||||
"32",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "DeepSeekChat",
|
||||
"_meta": {
|
||||
"title": "LLM Model Input Box"
|
||||
}
|
||||
},
|
||||
"32": {
|
||||
"inputs": {
|
||||
"config_name": "DeepSeek官方Chat API",
|
||||
"temperature": 1,
|
||||
"max_tokens": 512,
|
||||
"stream": false,
|
||||
"api_key": ""
|
||||
},
|
||||
"class_type": "DeepSeekAPIConfig",
|
||||
"_meta": {
|
||||
"title": "LLM API Model Selector"
|
||||
}
|
||||
}
|
||||
}
|