Spaces:
Runtime error
Runtime error
import spaces | |
import torch | |
from diffusers import FluxPipeline | |
import gradio as gr | |
import random | |
import numpy as np | |
import os | |
if torch.cuda.is_available(): | |
device = "cuda" | |
print("GPU를 사용합니다") | |
else: | |
device = "cpu" | |
print("CPU를 사용합니다") | |
HF_TOKEN = os.getenv("HF_TOKEN") | |
MAX_SEED = np.iinfo(np.int32).max | |
CACHE_EXAMPLES = torch.cuda.is_available() and os.getenv("CACHE_EXAMPLES", "0") == "1" | |
pipe = FluxPipeline.from_pretrained("black-forest-labs/FLUX.1-dev", torch_dtype=torch.bfloat16) | |
pipe.to(device) | |
def generate_image(prompt, num_inference_steps, height, width, guidance_scale, seed, num_images_per_prompt, progress=gr.Progress(track_tqdm=True)): | |
if seed is None or seed == 0: | |
seed = random.randint(1, MAX_SEED) | |
generator = torch.Generator().manual_seed(seed) | |
with torch.inference_mode(): | |
output = pipe( | |
prompt=prompt, | |
num_inference_steps=num_inference_steps, | |
height=height, | |
width=width, | |
guidance_scale=guidance_scale, | |
generator=generator, | |
num_images_per_prompt=num_images_per_prompt | |
).images | |
return output | |
def random_seed(): | |
return random.randint(1, MAX_SEED) | |
def create_random_seed(): | |
new_seed = random_seed() | |
return [gr.Number.update(value=new_seed), f"현재 시드: {new_seed}"] | |
examples = [ | |
["A cat holding a sign that says hello world"], | |
["a tiny astronaut hatching from an egg on the moon"], | |
["An astronaut on mars in a futuristic cyborg suit"], | |
] | |
css = """ | |
.gradio-container { | |
max-width: 1400px !important; | |
margin: auto; | |
} | |
.image-container img { | |
max-height: 600px !important; | |
} | |
.image-slider { | |
height: 600px !important; | |
max-height: 600px !important; | |
} | |
h1 { | |
text-align: center; | |
font-family: 'Pretendard', sans-serif; | |
color: #EA580C; | |
font-size: 2.5rem; | |
font-weight: 700; | |
margin-bottom: 1.5rem; | |
text-shadow: 0 2px 4px rgba(0,0,0,0.1); | |
} | |
.subtitle { | |
text-align: center; | |
color: #4B5563; | |
font-size: 1.1rem; | |
margin-bottom: 2rem; | |
font-family: 'Pretendard', sans-serif; | |
} | |
.gr-button-primary { | |
background-color: #F97316 !important; | |
border: none !important; | |
box-shadow: 0 2px 4px rgba(234, 88, 12, 0.2) !important; | |
} | |
.gr-button-primary:hover { | |
background-color: #EA580C !important; | |
transform: translateY(-1px); | |
box-shadow: 0 4px 6px rgba(234, 88, 12, 0.25) !important; | |
} | |
.footer-content { | |
text-align: center; | |
margin-top: 3rem; | |
padding: 2rem; | |
background: linear-gradient(to bottom, #FFF7ED, white); | |
border-radius: 12px; | |
font-family: 'Pretendard', sans-serif; | |
} | |
.footer-content a { | |
color: #EA580C; | |
text-decoration: none; | |
font-weight: 500; | |
transition: all 0.2s; | |
} | |
.footer-content a:hover { | |
color: #C2410C; | |
} | |
.visit-button { | |
background-color: #EA580C; | |
color: white !important; | |
padding: 12px 24px; | |
border-radius: 8px; | |
font-weight: 600; | |
text-decoration: none; | |
display: inline-block; | |
transition: all 0.3s; | |
margin-top: 1rem; | |
box-shadow: 0 2px 4px rgba(234, 88, 12, 0.2); | |
font-size: 1.1rem; | |
} | |
.visit-button:hover { | |
background-color: #C2410C; | |
transform: translateY(-2px); | |
box-shadow: 0 4px 6px rgba(234, 88, 12, 0.25); | |
color: white !important; | |
} | |
.container-wrapper { | |
background: white; | |
border-radius: 16px; | |
padding: 2rem; | |
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); | |
} | |
.image-container { | |
border-radius: 12px; | |
overflow: hidden; | |
border: 2px solid #F3F4F6; | |
} | |
.seed-button { | |
background-color: #F3F4F6 !important; | |
color: #374151 !important; | |
border: 1px solid #E5E7EB !important; | |
border-radius: 8px !important; | |
padding: 8px 16px !important; | |
font-size: 0.9rem !important; | |
font-weight: 500 !important; | |
transition: all 0.2s ease-in-out !important; | |
} | |
.seed-button:hover { | |
background-color: #E5E7EB !important; | |
transform: translateY(-1px); | |
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | |
} | |
.seed-text { | |
font-family: 'Pretendard', sans-serif; | |
color: #4B5563; | |
font-size: 0.9rem; | |
margin: 0; | |
line-height: 2.5; | |
font-weight: 500; | |
} | |
""" | |
with gr.Blocks( | |
theme=gr.themes.Soft( | |
primary_hue=gr.themes.Color( | |
c50="#FFF7ED", | |
c100="#FFEDD5", | |
c200="#FED7AA", | |
c300="#FDBA74", | |
c400="#FB923C", | |
c500="#F97316", | |
c600="#EA580C", | |
c700="#C2410C", | |
c800="#9A3412", | |
c900="#7C2D12", | |
c950="#431407", | |
), | |
secondary_hue="zinc", | |
neutral_hue="zinc", | |
font=("Pretendard", "sans-serif") | |
), | |
css=css | |
) as demo: | |
with gr.Row(): | |
with gr.Column(): | |
gr.HTML( | |
""" | |
<h1>끝장AI FLUX.1 이미지 생성기</h1> | |
<div class="subtitle"> | |
강력한 AI 기술로 당신의 상상을 현실로 만들어보세요 | |
</div> | |
""" | |
) | |
with gr.Group(elem_classes="container-wrapper"): | |
with gr.Column(): | |
prompt = gr.Textbox( | |
label="프롬프트", | |
info="원하는 이미지를 설명해주세요", | |
placeholder="고양이..." | |
) | |
run_button = gr.Button("생성하기", variant="primary") | |
result = gr.Gallery( | |
label="생성된 AI 이미지", | |
elem_id="gallery", | |
elem_classes="image-container" | |
) | |
with gr.Accordion("고급 설정", open=False): | |
with gr.Row(): | |
num_inference_steps = gr.Slider( | |
label="추론 단계 수", | |
info="이미지의 디노이징 단계 수입니다. 더 많은 단계는 더 높은 품질의 이미지를 생성하지만 시간이 더 걸립니다", | |
minimum=1, | |
maximum=50, | |
value=25, | |
step=1, | |
interactive=True, | |
show_label=True, | |
container=True, | |
randomize=False | |
) | |
guidance_scale = gr.Slider( | |
label="가이던스 스케일", | |
info="텍스트 프롬프트를 얼마나 충실히 따를지 제어합니다. 높은 값은 입력 텍스트에 더 가깝게 생성됩니다", | |
minimum=0.0, | |
maximum=7.0, | |
value=3.5, | |
step=0.1, | |
interactive=True, | |
show_label=True, | |
container=True, | |
randomize=False | |
) | |
with gr.Row(): | |
width = gr.Slider( | |
label="너비", | |
info="이미지의 너비", | |
minimum=256, | |
maximum=1024, | |
step=32, | |
value=1024, | |
interactive=True, | |
show_label=True, | |
container=True, | |
randomize=False | |
) | |
height = gr.Slider( | |
label="높이", | |
info="이미지의 높이", | |
minimum=256, | |
maximum=1024, | |
step=32, | |
value=1024, | |
interactive=True, | |
show_label=True, | |
container=True, | |
randomize=False | |
) | |
with gr.Row(): | |
seed = gr.Slider( | |
label="시드", | |
info="생성 프로세스를 시작하는 시작점입니다. 무작위는 0을 입력하세요", | |
value=42, | |
minimum=0, | |
maximum=MAX_SEED, | |
step=1 | |
) | |
num_images_per_prompt = gr.Slider( | |
label="프롬프트당 이미지 수", | |
info="설정된 값으로 생성할 이미지의 수", | |
minimum=1, | |
maximum=4, | |
step=1, | |
value=2 | |
) | |
gr.Examples( | |
examples=examples, | |
fn=generate_image, | |
inputs=[prompt, num_inference_steps, height, width, guidance_scale, seed, num_images_per_prompt], | |
outputs=[result], | |
cache_examples=CACHE_EXAMPLES | |
) | |
seed_button.click( | |
fn=create_random_seed, | |
outputs=[seed, seed_text] | |
) | |
gr.on( | |
triggers=[ | |
prompt.submit, | |
run_button.click, | |
], | |
fn=generate_image, | |
inputs=[prompt, num_inference_steps, height, width, guidance_scale, seed, num_images_per_prompt], | |
outputs=[result], | |
) | |
gr.HTML( | |
""" | |
<div class="footer-content"> | |
<p style="font-size: 1.1rem; font-weight: 500; color: #1F2937;">끝장AI가 제공하는 고급 AI 도구를 더 경험하고 싶으신가요?</p> | |
<a href="https://finalendai.com" target="_blank" class="visit-button"> | |
끝장AI 방문하기 | |
</a> | |
<p style="margin-top: 1.5rem; color: #6B7280; font-size: 0.9rem;"> | |
© 2024 끝장AI. All rights reserved. | |
</p> | |
</div> | |
""" | |
) | |
demo.queue().launch(share=False) |