# ๐ŸŽจ Connect AI LAB โ€” ๋ฌด๋ฃŒ ์˜คํ”ˆ์†Œ์Šค AI ์ด๋ฏธ์ง€ ์ƒ์„ฑ + ํŽธ์ง‘ (ZeroGPU) # ๐ŸŽจ ์ƒ์„ฑ = Krea-2-Turbo (12B) ยท โœ๏ธ ํŽธ์ง‘ = FLUX.1-Kontext(์ตœ๊ณ ๊ธ‰, ํ† ํฐ ์žˆ์œผ๋ฉด) / InstructPix2Pix(ํด๋ฐฑ) # ์œ ํŠœ๋ธŒ(@CONNECT-AI-LAB) ํ™๋ณด ยท ๋””์ž์ธ์€ ๊ธฐ๋ณธ ํ…Œ๋งˆ + ์ƒ๋‹จ ๋ฐฐ๋„ˆ. import random import gradio as gr import numpy as np import spaces import torch GEN_ID = "krea/Krea-2-Turbo" EDIT_ID = "black-forest-labs/FLUX.2-klein-4B" # ์ตœ์‹ ยทungatedยทApache 2.0ยท์ƒ์„ฑ+ํŽธ์ง‘ ํ†ตํ•ฉ(4B) IP2P_ID = "timbrooks/instruct-pix2pix" # ํด๋ฐฑ(ungated) YOUTUBE = "https://www.youtube.com/@CONNECT-AI-LAB" DEVICE = "cuda" if torch.cuda.is_available() else "cpu" MAX_SEED = np.iinfo(np.int32).max # โ”€โ”€ ๐ŸŽจ ์ƒ์„ฑ (Krea-2-Turbo) โ”€โ”€ try: from diffusers import Krea2Pipeline gen_pipe = Krea2Pipeline.from_pretrained(GEN_ID, torch_dtype=torch.bfloat16) except Exception: from diffusers import DiffusionPipeline gen_pipe = DiffusionPipeline.from_pretrained(GEN_ID, torch_dtype=torch.bfloat16, trust_remote_code=True) gen_pipe = gen_pipe.to(DEVICE) # โ”€โ”€ โœ๏ธ ํŽธ์ง‘: FLUX.2-klein-4B(์ตœ์‹ ยทungated) ์šฐ์„ , ์‹คํŒจ ์‹œ InstructPix2Pix ํด๋ฐฑ โ”€โ”€ EDIT_MODE = "ip2p" try: from diffusers import Flux2KleinPipeline edit_pipe = Flux2KleinPipeline.from_pretrained(EDIT_ID, torch_dtype=torch.bfloat16) EDIT_MODE = "flux2" except Exception as e: print(f"[edit] FLUX.2-klein ๋ถˆ๊ฐ€({e}); InstructPix2Pix๋กœ ํด๋ฐฑ") from diffusers import StableDiffusionInstructPix2PixPipeline edit_pipe = StableDiffusionInstructPix2PixPipeline.from_pretrained( IP2P_ID, torch_dtype=torch.float16, safety_checker=None) edit_pipe = edit_pipe.to(DEVICE) @spaces.GPU(duration=50) def generate(prompt, seed, randomize_seed, steps, progress=gr.Progress(track_tqdm=True)): if not prompt or not prompt.strip(): raise gr.Error("๋ฌด์—‡์„ ๊ทธ๋ฆด์ง€ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š” ๐Ÿ™‚ (์˜ˆ: ๋ˆˆ ์†์˜ ๊ท€์—ฌ์šด ์—ฌ์šฐ)") if randomize_seed: seed = random.randint(0, MAX_SEED) g = torch.Generator(device=DEVICE).manual_seed(int(seed)) image = gen_pipe(prompt, num_inference_steps=int(steps), generator=g).images[0] return image, seed @spaces.GPU(duration=55) def edit(image, instruction, steps, strength, progress=gr.Progress(track_tqdm=True)): if image is None: raise gr.Error("ํŽธ์ง‘ํ•  ์ด๋ฏธ์ง€๋ฅผ ๋จผ์ € ์˜ฌ๋ ค์ฃผ์„ธ์š” ๐Ÿ™‚") if not instruction or not instruction.strip(): raise gr.Error("์–ด๋–ป๊ฒŒ ๋ฐ”๊ฟ€์ง€ ์ ์–ด์ฃผ์„ธ์š” (์˜ˆ: ํ•˜๋Š˜์„ ๋ณด๋ผ์ƒ‰์œผ๋กœ, ๊ฒจ์šธ๋กœ ๋ฐ”๊ฟ”์ค˜)") img = image.convert("RGB") img.thumbnail((1024, 1024)) if EDIT_MODE == "flux2": out = edit_pipe(image=img, prompt=instruction, guidance_scale=float(strength), num_inference_steps=int(steps)).images[0] else: out = edit_pipe(instruction, image=img, num_inference_steps=int(steps), image_guidance_scale=1.5, guidance_scale=7.5).images[0] return out GEN_EXAMPLES = [ "๋ˆˆ ์†์„ ๊ฑท๋Š” ๊ท€์—ฌ์šด ์•„๊ธฐ ์—ฌ์šฐ, ๋”ฐ๋œปํ•œ ์กฐ๋ช…, ์‹œ๋„ค๋งˆํ‹ฑ, ๊ณ ํ™”์งˆ", "๋„ค์˜จ ์‚ฌ์ธ ๊ฐ€๋“ํ•œ ๋ฐค์˜ ์„œ์šธ ๊ฑฐ๋ฆฌ, ๋น„ ์˜ค๋Š” ์‚ฌ์ด๋ฒ„ํŽ‘ํฌ, ๋””ํ…Œ์ผ", "๋ฏธ๋‹ˆ๋ฉ€ํ•œ ๋กœ๊ณ : ์ดˆ๋ก๋น› AI ๋‘๋‡Œ, ์‹ฌํ”Œ, ๋ฒกํ„ฐ ์Šคํƒ€์ผ, ํฐ ๋ฐฐ๊ฒฝ", "์šฐ์ฃผ์—์„œ ์ง€๊ตฌ๋ฅผ ๋ฐ”๋ผ๋ณด๋Š” ์šฐ์ฃผ๋น„ํ–‰์‚ฌ, ์‚ฌ์‹ค์ , 4k, ์˜ํ™” ๊ฐ™์€", ] EDIT_EXAMPLES = ["ํ•˜๋Š˜์„ ๋ณด๋ผ์ƒ‰ ๋…ธ์„๋กœ ๋ฐ”๊ฟ”์ค˜", "๊ฒจ์šธ ๋ˆˆ ๋‚ด๋ฆฌ๋Š” ์žฅ๋ฉด์œผ๋กœ", "์ˆ˜์ฑ„ํ™” ๊ทธ๋ฆผ ์Šคํƒ€์ผ๋กœ", "๋„ค์˜จ ์‚ฌ์ด๋ฒ„ํŽ‘ํฌ ๋А๋‚Œ์œผ๋กœ", "๋ฐฐ๊ฒฝ์„ ์šฐ์ฃผ๋กœ ๋ฐ”๊ฟ”์ค˜"] CSS = """ .gradio-container {max-width: 960px !important; margin: auto !important;} #hero {text-align:center; padding: 26px 16px; margin-bottom: 8px; border-radius: 18px; background: linear-gradient(135deg, #0c2a1a, #0a1830); border: 1px solid rgba(57,255,20,.25);} #hero .brand {font-family: ui-monospace, monospace; letter-spacing: 6px; color: #58ff86; font-size: 12px;} #hero h1 {color:#ffffff; font-size: 34px; font-weight: 800; margin: 8px 0 4px;} #hero .sub {color:#bfeecf; font-size: 14px; margin: 2px 0 0;} #hero .grn {color:#39ff14; font-weight:700;} .yt-btn {display:inline-flex; align-items:center; gap:8px; margin-top:14px; padding:12px 24px; border-radius:12px; text-decoration:none; font-weight:800; font-size:14px; color:#ffffff !important; background:linear-gradient(135deg,#ff2d55,#ff0000); box-shadow:0 6px 22px rgba(255,0,0,.35);} .yt-btn:hover {filter:brightness(1.08);} #foot {text-align:center; color:#8a8f98; font-size:13px; padding:16px 8px;} #foot a {color:#e11d48; text-decoration:none; font-weight:700;} """ _edit_note = ("โœ๏ธ ํŽธ์ง‘: FLUX.2-klein (์ตœ์‹ ยท๊ณ ๊ธ‰)" if EDIT_MODE == "flux2" else "โœ๏ธ ํŽธ์ง‘: ๊ธฐ๋ณธ ๋ชจ๋“œ (FLUX.2 ๋กœ๋“œ ๋Œ€๊ธฐ)") with gr.Blocks(css=CSS, theme=gr.themes.Soft(primary_hue="green"), title="Connect AI LAB") as demo: gr.HTML(f"""
โ—ˆ CONNECT ยท AI ยท LAB

๐ŸŽจ AI ์ด๋ฏธ์ง€ ์ƒ์„ฑ & ํŽธ์ง‘

ํ…์ŠคํŠธ๋กœ ๊ทธ๋ฆฌ๊ณ , ์ด๋ฏธ์ง€๋ฅผ ํŽธ์ง‘๊นŒ์ง€ ยท ๋ฌด๋ฃŒ ยท ์˜คํ”ˆ์†Œ์Šค
โ–ถ ์œ ํŠœ๋ธŒ ๊ตฌ๋… ยท @CONNECT-AI-LAB
""") with gr.Tabs(): with gr.TabItem("๐ŸŽจ ์ƒ์„ฑ"): with gr.Row(): g_prompt = gr.Textbox(label="๋ฌด์—‡์„ ๊ทธ๋ฆด๊นŒ์š”?", placeholder="์˜ˆ: ๋ˆˆ ์†์˜ ๊ท€์—ฌ์šด ์•„๊ธฐ ์—ฌ์šฐ, ๋”ฐ๋œปํ•œ ์กฐ๋ช…, ์‹œ๋„ค๋งˆํ‹ฑ", scale=5, lines=2) g_run = gr.Button("๐ŸŽจ ๊ทธ๋ฆฌ๊ธฐ", variant="primary", scale=1) g_result = gr.Image(label="๊ฒฐ๊ณผ", height=520) with gr.Accordion("โš™๏ธ ์„ธ๋ถ€ ์„ค์ •", open=False): with gr.Row(): g_steps = gr.Slider(4, 16, value=8, step=1, label="์Šคํ…") g_seed = gr.Slider(0, MAX_SEED, value=42, step=1, label="์‹œ๋“œ") g_rand = gr.Checkbox(label="์‹œ๋“œ ๋žœ๋ค(๋งค๋ฒˆ ๋‹ค๋ฅธ ๊ทธ๋ฆผ)", value=True) gr.Examples(examples=GEN_EXAMPLES, inputs=[g_prompt], label="โœจ ์˜ˆ์‹œ") g_in = [g_prompt, g_seed, g_rand, g_steps] g_run.click(generate, inputs=g_in, outputs=[g_result, g_seed]) g_prompt.submit(generate, inputs=g_in, outputs=[g_result, g_seed]) with gr.TabItem("โœ๏ธ ํŽธ์ง‘"): gr.Markdown(f"##### {_edit_note}") with gr.Row(): e_img = gr.Image(label="ํŽธ์ง‘ํ•  ์ด๋ฏธ์ง€ ์˜ฌ๋ฆฌ๊ธฐ", type="pil", height=340) e_out = gr.Image(label="ํŽธ์ง‘ ๊ฒฐ๊ณผ", height=340) with gr.Row(): e_inst = gr.Textbox(label="์–ด๋–ป๊ฒŒ ๋ฐ”๊ฟ€๊นŒ์š”? (์ง€์‹œ)", placeholder="์˜ˆ: ํ•˜๋Š˜์„ ๋ณด๋ผ์ƒ‰ ๋…ธ์„๋กœ, ๊ฒจ์šธ๋กœ ๋ฐ”๊ฟ”์ค˜, ์ˆ˜์ฑ„ํ™” ์Šคํƒ€์ผ๋กœ", scale=5, lines=2) e_run = gr.Button("โœ๏ธ ํŽธ์ง‘", variant="primary", scale=1) with gr.Accordion("โš™๏ธ ์„ธ๋ถ€ ์„ค์ •", open=False): e_steps = gr.Slider(8, 40, value=18, step=1, label="์Šคํ…(๋‚ฎ์„์ˆ˜๋ก ๋น ๋ฆ„ยท์ฟผํ„ฐ ์ ˆ์•ฝ)") e_str = gr.Slider(1.0, 5.0, value=2.5, step=0.1, label="์ง€์‹œ ๋ฐ˜์˜ ๊ฐ•๋„") gr.Examples(examples=EDIT_EXAMPLES, inputs=[e_inst], label="โœจ ํŽธ์ง‘ ์˜ˆ์‹œ") e_run.click(edit, inputs=[e_img, e_inst, e_steps, e_str], outputs=[e_out]) gr.HTML(f""" """) if __name__ == "__main__": demo.launch()