GINI-Deck / app-BACKUP.py
ginipick's picture
Rename app.py to app-BACKUP.py
dc97528 verified
raw
history blame
16.7 kB
import gradio as gr
import replicate
import requests
import os
import json
import asyncio
import concurrent.futures
from io import BytesIO
from PIL import Image
from typing import List, Tuple, Dict
# ν™˜κ²½ λ³€μˆ˜μ—μ„œ 토큰 κ°€μ Έμ˜€κΈ°
REPLICATE_API_TOKEN = os.getenv("RAPI_TOKEN")
FRIENDLI_TOKEN = os.getenv("FRIENDLI_TOKEN")
# μŠ€νƒ€μΌ μ •μ˜
STYLE_TEMPLATES = {
"3D Style (Pixar-like)": {
"name": "3D Style",
"description": "Pixar-esque 3D render with volumetric lighting",
"example": "A fluffy ginger cat wearing a tiny spacesuit, floating amidst a vibrant nebula in a 3D render. The cat is gazing curiously at a swirling planet with rings made of candy. Background is filled with sparkling stars and colorful gas clouds, lit with soft, volumetric lighting. Style: Pixar-esque, highly detailed, playful. Colors: Deep blues, purples, oranges, and pinks. Rendered in Octane, 8k resolution."
},
"Elegant SWOT Quadrant": {
"name": "SWOT Analysis",
"description": "Flat-design 4-grid layout with minimal shadows",
"example": "Elegant SWOT quadrant: flat-design 4-grid on matte-white backdrop, thin pastel separators, top-left 'Strengths' panel shows glowing shield icon and subtle motif, top-right 'Weaknesses' panel with cracked chain icon in soft crimson, bottom-left 'Opportunities' panel with sunrise-over-horizon icon in optimistic teal, bottom-right 'Threats' panel with storm-cloud & lightning icon in deep indigo, minimal shadows, no text, no watermark, 16:9, 4K"
},
"Colorful Mind Map": {
"name": "Mind Map",
"description": "Hand-drawn educational style with vibrant colors",
"example": "A handrawn colorful mind map diagram: educational style, vibrant colors, clear hierarchy, golden ratio layout. Central concept with branching sub-topics, each branch with unique color coding, organic flowing connections, doodle-style icons for each node"
},
"Business Workflow": {
"name": "Business Process",
"description": "End-to-end business workflow with clear phases",
"example": "A detailed hand-drawn diagram illustrating an end-to-end business workflow with Market Analysis, Strategy Development, Product Design, Implementation, and Post-Launch Review phases. Clear directional arrows, iconography for each component, vibrant educational yet professional style"
},
"Industrial Design": {
"name": "Product Design",
"description": "Sleek industrial design concept sketch",
"example": "A sleek industrial design concept: Curved metallic body with minimal bezel, Touchscreen panel for settings, Modern matte black finish, Hand-drawn concept sketch style with annotations and dimension lines"
},
"3D Bubble Chart": {
"name": "Bubble Chart",
"description": "Clean 3D bubble visualization",
"example": "3-D bubble chart on clean white 2Γ—2 grid, quadrant titles hidden, four translucent spheres in lime, azure, amber, magenta, gentle depth-of-field, modern consulting aesthetic, no text, 4K"
},
"Timeline Ribbon": {
"name": "Timeline",
"description": "Horizontal ribbon timeline with cyber-futuristic vibe",
"example": "Horizontal ribbon timeline, milestone pins glowing hot pink on charcoal, year markers as circles, faint motion streaks, cyber-futuristic vibe, no text, 1920Γ—1080"
},
"Risk Heat Map": {
"name": "Heat Map",
"description": "Risk assessment heat map with gradient colors",
"example": "Risk Heat Map: square grid, smooth gradient from mint to fire-red, cells beveled, simple legend strip hidden, long subtle shadow, sterile white frame, no text"
},
"Pyramid/Funnel": {
"name": "Funnel Chart",
"description": "Multi-layer gradient funnel visualization",
"example": "Pyramid / Funnel: 5-layer gradient funnel narrowing downwards, top vivid sky-blue, mid mint-green, bottom sunset-orange, glass reflection, minimal background, no text"
},
"KPI Dashboard": {
"name": "Dashboard",
"description": "Dark-mode analytics dashboard with sci-fi interface",
"example": "KPI Dashboard: Dark-mode analytic dashboard, three glass speedometers glowing neon lime, two sparkline charts under, black glass background, sci-fi interface, no text, 4K"
},
"Value Chain": {
"name": "Value Chain",
"description": "Horizontal value chain with industrial look",
"example": "Value Chain Diagram: Horizontal value chain blocks, steel-blue gradient bars with subtle bevel, small gear icons above each segment, sleek industrial look, shadow cast, no text"
},
"Gantt Chart": {
"name": "Gantt Chart",
"description": "Hand-drawn style Gantt chart with playful colors",
"example": "Gantt Chart: Hand-drawn style Gantt bars sketched with vibrant markers on dotted grid notebook page, sticky-note color palette, playful yet organized, perspective tilt, no text"
},
"Mobile App Mockup": {
"name": "App Mockup",
"description": "Clean wireframe for mobile app design",
"example": "MOCKUP DESIGN: A clean hand-drawn style wireframe for a mobile app with Title screen, Login screen, Dashboard with sections, Bottom navigation bar, minimalist design with annotations"
},
"Flowchart": {
"name": "Flowchart",
"description": "Vibrant flowchart with minimalistic icons",
"example": "FLOWCHART DESIGN: A hand-drawn style flowchart, vibrant colors, minimalistic icons showing process flow from START to END with decision points, branches, and clear directional arrows"
}
}
def generate_prompt_with_llm(topic: str, style_example: str = None) -> str:
"""μ£Όμ œμ™€ μŠ€νƒ€μΌ 예제λ₯Ό λ°›μ•„μ„œ LLM을 μ‚¬μš©ν•΄ 이미지 ν”„λ‘¬ν”„νŠΈλ₯Ό 생성"""
url = "https://api.friendli.ai/dedicated/v1/chat/completions"
headers = {
"Authorization": f"Bearer {FRIENDLI_TOKEN}",
"Content-Type": "application/json"
}
# κ°•ν™”λœ μ‹œμŠ€ν…œ ν”„λ‘¬ν”„νŠΈ
system_prompt = """You are an expert image prompt engineer specializing in creating detailed, visually rich prompts for AI image generation.
Your task is to create prompts that:
1. Are highly specific and visual, describing exact details, colors, lighting, and composition
2. Include style references (e.g., "3D render", "hand-drawn", "flat design", "industrial sketch")
3. Specify technical details like resolution, aspect ratio, or rendering style when appropriate
4. Use descriptive adjectives for materials, textures, and atmospheres
5. Avoid abstract concepts - focus on concrete visual elements
Important guidelines:
- If given a style example, adapt the topic to match that specific visual style
- Maintain the technical vocabulary and visual descriptors from the style example
- Always output ONLY the prompt without any explanation or additional text
- Make prompts between 50-150 words for optimal results"""
user_message = f"Topic: {topic}"
if style_example:
user_message += f"\n\nStyle reference to follow:\n{style_example}\n\nAdapt the topic to match this exact visual style."
payload = {
"model": "dep89a2fld32mcm",
"messages": [
{
"role": "system",
"content": system_prompt
},
{
"role": "user",
"content": user_message
}
],
"max_tokens": 300,
"top_p": 0.8,
"temperature": 0.7,
"stream": False
}
try:
response = requests.post(url, json=payload, headers=headers)
if response.status_code == 200:
result = response.json()
return result['choices'][0]['message']['content'].strip()
else:
return f"ν”„λ‘¬ν”„νŠΈ 생성 μ‹€νŒ¨: {response.status_code}"
except Exception as e:
return f"ν”„λ‘¬ν”„νŠΈ 생성 쀑 였λ₯˜ λ°œμƒ: {str(e)}"
def translate_to_english(text: str) -> str:
"""ν•œκΈ€ ν…μŠ€νŠΈλ₯Ό μ˜μ–΄λ‘œ λ²ˆμ—­ (LLM μ‚¬μš©)"""
if not any(ord('κ°€') <= ord(char) <= ord('힣') for char in text):
return text
url = "https://api.friendli.ai/dedicated/v1/chat/completions"
headers = {
"Authorization": f"Bearer {FRIENDLI_TOKEN}",
"Content-Type": "application/json"
}
payload = {
"model": "dep89a2fld32mcm",
"messages": [
{
"role": "system",
"content": "You are a translator. Translate the given Korean text to English. Only return the translation without any explanation."
},
{
"role": "user",
"content": text
}
],
"max_tokens": 500,
"top_p": 0.8,
"stream": False
}
try:
response = requests.post(url, json=payload, headers=headers)
if response.status_code == 200:
result = response.json()
return result['choices'][0]['message']['content'].strip()
else:
return text
except Exception as e:
return text
def generate_image(prompt: str, seed: int = 10) -> Tuple[Image.Image, str]:
"""Replicate APIλ₯Ό μ‚¬μš©ν•΄ 이미지 생성"""
try:
english_prompt = translate_to_english(prompt)
if not REPLICATE_API_TOKEN:
return None, "RAPI_TOKEN ν™˜κ²½λ³€μˆ˜κ°€ μ„€μ •λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€."
client = replicate.Client(api_token=REPLICATE_API_TOKEN)
input_params = {
"seed": seed,
"prompt": english_prompt,
"speed_mode": "Extra Juiced πŸš€ (even more speed)",
"output_quality": 80
}
output = client.run(
"prunaai/hidream-l1-fast:17c237d753218fed0ed477cb553902b6b75735f48c128537ab829096ef3d3645",
input=input_params
)
if output:
if isinstance(output, str) and output.startswith('http'):
response = requests.get(output)
img = Image.open(BytesIO(response.content))
return img, english_prompt
else:
img = Image.open(BytesIO(output.read()))
return img, english_prompt
else:
return None, "이미지 생성 μ‹€νŒ¨"
except Exception as e:
return None, f"였λ₯˜: {str(e)}"
def generate_images_parallel(topic: str, selected_styles: List[str], seed: int) -> List[Dict]:
"""μ„ νƒλœ μŠ€νƒ€μΌλ“€μ— λŒ€ν•΄ λ³‘λ ¬λ‘œ 이미지 생성"""
results = []
# 각 μŠ€νƒ€μΌμ— λŒ€ν•œ ν”„λ‘¬ν”„νŠΈ 생성
prompts = []
for style_name in selected_styles:
if style_name in STYLE_TEMPLATES:
style_info = STYLE_TEMPLATES[style_name]
prompt = generate_prompt_with_llm(topic, style_info["example"])
prompts.append({
"style": style_name,
"prompt": prompt,
"style_info": style_info
})
# λ³‘λ ¬λ‘œ 이미지 생성
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
future_to_style = {}
for prompt_data in prompts:
future = executor.submit(generate_image, prompt_data["prompt"], seed)
future_to_style[future] = prompt_data
for future in concurrent.futures.as_completed(future_to_style):
prompt_data = future_to_style[future]
try:
img, used_prompt = future.result()
results.append({
"style": prompt_data["style"],
"image": img,
"prompt": prompt_data["prompt"],
"used_prompt": used_prompt,
"success": img is not None
})
except Exception as e:
results.append({
"style": prompt_data["style"],
"image": None,
"prompt": prompt_data["prompt"],
"used_prompt": str(e),
"success": False
})
return results
def process_multiple_styles(topic: str, selected_styles: List[str], seed: int):
"""μ—¬λŸ¬ μŠ€νƒ€μΌλ‘œ 이미지 생성 처리"""
if not topic.strip():
return [], "주제λ₯Ό μž…λ ₯ν•΄μ£Όμ„Έμš”."
if not selected_styles:
return [], "μ΅œμ†Œ ν•˜λ‚˜μ˜ μŠ€νƒ€μΌμ„ μ„ νƒν•΄μ£Όμ„Έμš”."
status = f"μ„ νƒλœ {len(selected_styles)}개 μŠ€νƒ€μΌλ‘œ 이미지 생성 쀑..."
# λ³‘λ ¬λ‘œ 이미지 생성
results = generate_images_parallel(topic, selected_styles, seed)
# κ²°κ³Ό 정리
images = []
prompts_info = []
for result in results:
if result["success"]:
images.append((result["image"], result["style"]))
prompts_info.append(f"**{result['style']}**\nν”„λ‘¬ν”„νŠΈ: {result['prompt']}\n")
else:
prompts_info.append(f"**{result['style']}** - 생성 μ‹€νŒ¨: {result['used_prompt']}\n")
final_status = f"총 {len(images)}개 이미지 생성 μ™„λ£Œ\n\n" + "\n".join(prompts_info)
return images, final_status
# Gradio μΈν„°νŽ˜μ΄μŠ€ 생성
with gr.Blocks(title="AI λ©€ν‹°μŠ€νƒ€μΌ 이미지 생성기", theme=gr.themes.Soft()) as demo:
gr.Markdown("""
# 🎨 AI λ©€ν‹°μŠ€νƒ€μΌ 이미지 생성기
주제λ₯Ό μž…λ ₯ν•˜κ³  μ›ν•˜λŠ” μŠ€νƒ€μΌμ„ μ„ νƒν•˜λ©΄, 각 μŠ€νƒ€μΌμ— λ§žλŠ” 이미지λ₯Ό λ™μ‹œμ— μƒμ„±ν•©λ‹ˆλ‹€.
""")
with gr.Row():
with gr.Column(scale=1):
topic_input = gr.Textbox(
label="주제 μž…λ ₯",
placeholder="예: 우주λ₯Ό μ—¬ν–‰ν•˜λŠ” 고양이, 미래의 λ„μ‹œ, ν˜μ‹ μ μΈ μ œν’ˆ λ””μžμΈ",
lines=2
)
gr.Markdown("### μŠ€νƒ€μΌ 선택 (볡수 선택 κ°€λŠ₯)")
# μŠ€νƒ€μΌ μ²΄ν¬λ°•μŠ€ κ·Έλ£Ή
style_checkboxes = gr.CheckboxGroup(
choices=list(STYLE_TEMPLATES.keys()),
label="생성할 μŠ€νƒ€μΌ",
value=["3D Style (Pixar-like)"],
info="각 μŠ€νƒ€μΌμ€ κ³ μœ ν•œ μ‹œκ°μ  νŠΉμ„±μ„ κ°€μ§€κ³  μžˆμŠ΅λ‹ˆλ‹€"
)
seed_input = gr.Slider(
minimum=1,
maximum=100,
value=10,
step=1,
label="μ‹œλ“œ κ°’ (λ™μΌν•œ μ‹œλ“œλŠ” λ™μΌν•œ 이미지 생성)"
)
generate_btn = gr.Button("πŸš€ μ„ νƒν•œ μŠ€νƒ€μΌλ‘œ 이미지 생성", variant="primary", size="lg")
with gr.Column(scale=2):
# 가러리둜 μ—¬λŸ¬ 이미지 ν‘œμ‹œ
output_gallery = gr.Gallery(
label="μƒμ„±λœ 이미지듀",
show_label=True,
elem_id="gallery",
columns=2,
rows=3,
object_fit="contain",
height="auto"
)
status_text = gr.Markdown(
value="생성 μƒνƒœ 및 ν”„λ‘¬ν”„νŠΈ 정보가 여기에 ν‘œμ‹œλ©λ‹ˆλ‹€."
)
# μŠ€νƒ€μΌ μ„€λͺ… μ„Ήμ…˜
with gr.Accordion("πŸ“š μŠ€νƒ€μΌ κ°€μ΄λ“œ", open=False):
style_guide_text = "### μ‚¬μš© κ°€λŠ₯ν•œ μŠ€νƒ€μΌ:\n\n"
for style_name, style_info in STYLE_TEMPLATES.items():
style_guide_text += f"**{style_name}**: {style_info['description']}\n\n"
gr.Markdown(style_guide_text)
# 이미지 생성 이벀트
generate_btn.click(
fn=process_multiple_styles,
inputs=[topic_input, style_checkboxes, seed_input],
outputs=[output_gallery, status_text]
)
gr.Markdown("""
---
### πŸ’‘ μ‚¬μš© 팁:
- **주제**: ꡬ체적일수둝 쒋은 κ²°κ³Όλ₯Ό 얻을 수 μžˆμŠ΅λ‹ˆλ‹€
- **μŠ€νƒ€μΌ μ‘°ν•©**: μ—¬λŸ¬ μŠ€νƒ€μΌμ„ μ„ νƒν•˜λ©΄ λ‹€μ–‘ν•œ μ‹œκ°μ  ν‘œν˜„μ„ 비ꡐ할 수 μžˆμŠ΅λ‹ˆλ‹€
- **병렬 처리**: μ„ νƒν•œ λͺ¨λ“  μŠ€νƒ€μΌμ˜ 이미지가 λ™μ‹œμ— μƒμ„±λ©λ‹ˆλ‹€
- **μ‹œλ“œ κ°’**: λ™μΌν•œ μ‹œλ“œλ‘œ μž¬ν˜„ κ°€λŠ₯ν•œ κ²°κ³Όλ₯Ό 얻을 수 μžˆμŠ΅λ‹ˆλ‹€
각 μŠ€νƒ€μΌμ€ μ „λ¬Έμ μœΌλ‘œ νλ ˆμ΄μ…˜λœ 예제λ₯Ό 기반으둜 ν”„λ‘¬ν”„νŠΈλ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.
""")
# μ•± μ‹€ν–‰
if __name__ == "__main__":
# ν™˜κ²½ λ³€μˆ˜ 확인
if not REPLICATE_API_TOKEN:
print("κ²½κ³ : RAPI_TOKEN ν™˜κ²½ λ³€μˆ˜κ°€ μ„€μ •λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.")
if not FRIENDLI_TOKEN:
print("κ²½κ³ : FRIENDLI_TOKEN ν™˜κ²½ λ³€μˆ˜κ°€ μ„€μ •λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.")
demo.launch()