Spaces:
ginigen
/
Runtime error

Design / app.py
ginipick's picture
Update app.py
25537ba verified
raw
history blame
9.79 kB
import gradio as gr
import numpy as np
import random
import torch
from diffusers import DiffusionPipeline
import spaces
from transformers import pipeline
# κΈ°λ³Έ μ„€μ •
dtype = torch.bfloat16
device = "cuda" if torch.cuda.is_available() else "cpu"
# ν•œκ΅­μ–΄-μ˜μ–΄ λ²ˆμ—­ λͺ¨λΈ λ‘œλ“œ (CPUμ—μ„œ μ‹€ν–‰)
translator = pipeline("translation", model="Helsinki-NLP/opus-mt-ko-en", device="cpu")
# λͺ¨λΈ λ‘œλ“œ
pipe = DiffusionPipeline.from_pretrained(
"black-forest-labs/FLUX.1-schnell",
torch_dtype=dtype
).to(device)
MAX_SEED = np.iinfo(np.int32).max
MAX_IMAGE_SIZE = 2048
# μ œν’ˆ λ””μžμΈ 컨셉 μ˜ˆμ‹œ
EXAMPLES = [
{
"title": "Smart Coffee Machine",
"prompt": """A sleek industrial design concept for a coffee machine:
- Curved metallic body with minimal bezel
- Touchscreen panel for settings
- Modern matte black finish
- Hand-drawn concept sketch style""",
"width": 1024,
"height": 1024
},
{
"title": "AI Speaker",
"prompt": """A futuristic AI speaker concept:
- Cylindrical shape with LED ring near top
- Voice assistant concept, floating panel controls
- Smooth glossy finish with minimal seams
- Techy, modern look in grayscale""",
"width": 1024,
"height": 1024
},
{
"title": "Next-Gen Smartphone",
"prompt": """A wireframe-style concept for a bezel-less smartphone:
- Edge-to-edge display
- Integrated camera under screen
- Metallic frame, minimal ports
- Sleek, glossy black design""",
"width": 1024,
"height": 1024
},
{
"title": "Futuristic Electric Bicycle",
"prompt": """An industrial design sketch of an electric bike:
- Lightweight carbon frame, aerodynamic lines
- Integrated battery, sleek display on handlebars
- Neon color highlights on wheels
- High-tech vibe, minimal clutter""",
"width": 1024,
"height": 1024
},
{
"title": "Concept Car Interior",
"prompt": """A luxurious and futuristic car interior concept:
- Wrap-around digital dashboard
- Minimalistic steering control, seat controls on touchscreen
- Ambient LED accent lights
- Soft leather seats, bright accent stitching""",
"width": 1024,
"height": 1024
}
]
# Convert examples to Gradio format (if needed)
GRADIO_EXAMPLES = [
[example["prompt"], example["width"], example["height"]]
for example in EXAMPLES
]
# ν•œκ΅­μ–΄ 감지 ν•¨μˆ˜
def contains_korean(text):
for char in text:
if ord('κ°€') <= ord(char) <= ord('힣'):
return True
return False
# ν•„μš”μ‹œ λ²ˆμ—­ ν›„ μΆ”λ‘  ν•¨μˆ˜
@spaces.GPU()
def infer(prompt, seed=42, randomize_seed=False, width=1024, height=1024, num_inference_steps=4, progress=gr.Progress(track_tqdm=True)):
# ν•œκ΅­μ–΄ 감지 및 λ²ˆμ—­
original_prompt = prompt
translated = False
if contains_korean(prompt):
translated = True
translation = translator(prompt)
prompt = translation[0]['translation_text']
# 랜덀 μ‹œλ“œ μ„€μ •
if randomize_seed:
seed = random.randint(0, MAX_SEED)
generator = torch.Generator().manual_seed(seed)
# λͺ¨λΈ μ‹€ν–‰
image = pipe(
prompt=prompt,
width=width,
height=height,
num_inference_steps=num_inference_steps,
generator=generator,
guidance_scale=0.0
).images[0]
# λ²ˆμ—­ 정보 λ°˜ν™˜
if translated:
return image, seed, original_prompt, prompt
else:
return image, seed, None, None
# CSS μŠ€νƒ€μΌ (κΈ°μ‘΄ ꡬ쑰 μœ μ§€)
css = """
.container {
display: flex;
flex-direction: row;
height: 100%;
}
.input-column {
flex: 1;
padding: 20px;
border-right: 2px solid #eee;
max-width: 800px;
}
.examples-column {
flex: 1;
padding: 20px;
overflow-y: auto;
background: #f7f7f7;
}
.title {
text-align: center;
color: #2a2a2a;
padding: 20px;
font-size: 2.5em;
font-weight: bold;
background: linear-gradient(90deg, #f0f0f0 0%, #ffffff 100%);
border-bottom: 3px solid #ddd;
margin-bottom: 30px;
}
.subtitle {
text-align: center;
color: #666;
margin-bottom: 30px;
}
.input-box {
background: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
margin-bottom: 20px;
width: 100%;
}
.input-box textarea {
width: 100% !important;
min-width: 600px !important;
font-size: 14px !important;
line-height: 1.5 !important;
padding: 12px !important;
}
.example-card {
background: white;
padding: 15px;
margin: 10px 0;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0,0,0,0.05);
}
.example-title {
font-weight: bold;
color: #2a2a2a;
margin-bottom: 10px;
}
.contain {
max-width: 1400px !important;
margin: 0 auto !important;
}
.input-area {
flex: 2 !important;
}
.examples-area {
flex: 1 !important;
}
.translation-info {
background-color: #f8f9fa;
border-left: 4px solid #17a2b8;
padding: 10px 15px;
margin-top: 10px;
border-radius: 4px;
font-size: 14px;
}
"""
with gr.Blocks(css=css) as demo:
gr.Markdown(
"""
<div class="title">GINI Design</div>
<div class="subtitle">Generate sleek industrial/product design concepts with FLUX AI</div>
""")
with gr.Row(equal_height=True):
# μ™Όμͺ½ μž…λ ₯ 컬럼
with gr.Column(elem_id="input-column", scale=2):
with gr.Group(elem_classes="input-box"):
prompt = gr.Text(
label="Design Prompt (ν•œκ΅­μ–΄ λ˜λŠ” μ˜μ–΄λ‘œ μž…λ ₯ν•˜μ„Έμš”)",
placeholder="Enter your product design concept details in Korean or English...",
lines=10,
elem_classes="prompt-input"
)
run_button = gr.Button("Generate Design", variant="primary")
result = gr.Image(label="Generated Design")
# λ²ˆμ—­ 정보 ν‘œμ‹œ μ˜μ—­
original_prompt = gr.Textbox(visible=False)
translated_prompt = gr.Textbox(visible=False)
translation_info = gr.Markdown(visible=False, elem_classes="translation-info")
# λ²ˆμ—­ 정보 μ—…λ°μ΄νŠΈ ν•¨μˆ˜
def update_translation_info(original, translated):
if original and translated:
return gr.update(visible=True, value=f"πŸ”„ Korean prompt was translated to English:\n\n**Original:** {original}\n\n**Translated:** {translated}")
else:
return gr.update(visible=False)
with gr.Accordion("Advanced Settings", open=False):
seed = gr.Slider(
label="Seed",
minimum=0,
maximum=MAX_SEED,
step=1,
value=0,
)
randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
with gr.Row():
width = gr.Slider(
label="Width",
minimum=256,
maximum=MAX_IMAGE_SIZE,
step=32,
value=1024,
)
height = gr.Slider(
label="Height",
minimum=256,
maximum=MAX_IMAGE_SIZE,
step=32,
value=1024,
)
num_inference_steps = gr.Slider(
label="Number of inference steps",
minimum=1,
maximum=50,
step=1,
value=4,
)
# 였λ₯Έμͺ½ 예제 컬럼
with gr.Column(elem_id="examples-column", scale=1):
gr.Markdown("### Example Product Designs")
for example in EXAMPLES:
with gr.Group(elem_classes="example-card"):
gr.Markdown(f"#### {example['title']}")
gr.Markdown(f"```\n{example['prompt']}\n```")
def create_example_handler(ex):
def handler():
return {
prompt: ex["prompt"],
width: ex["width"],
height: ex["height"]
}
return handler
gr.Button("Use This Example", size="sm").click(
fn=create_example_handler(example),
outputs=[prompt, width, height]
)
# 이벀트 바인딩 (λ²„νŠΌ 클릭 & ν…μŠ€νŠΈλ°•μŠ€ μ—”ν„°)
gr.on(
triggers=[run_button.click, prompt.submit],
fn=infer,
inputs=[prompt, seed, randomize_seed, width, height, num_inference_steps],
outputs=[result, seed, original_prompt, translated_prompt]
)
# λ²ˆμ—­ 정보 μ—…λ°μ΄νŠΈ 이벀트
gr.on(
triggers=[original_prompt.change, translated_prompt.change],
fn=update_translation_info,
inputs=[original_prompt, translated_prompt],
outputs=[translation_info]
)
if __name__ == "__main__":
demo.queue()
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=False,
show_error=True,
debug=True
)