Spaces:
Running
Running
| import gradio as gr | |
| import requests | |
| import io | |
| import random | |
| import os | |
| from PIL import Image | |
| import json | |
| # Get API token from environment variable | |
| HF_TOKEN = os.getenv("HF_TOKEN") | |
| if not HF_TOKEN: | |
| raise ValueError("HF_TOKEN environment variable is not set") | |
| def query(prompt, model, custom_lora, is_negative=False, steps=35, cfg_scale=7, sampler="DPM++ 2M Karras", seed=-1, strength=0.7, width=1024, height=1024): | |
| print("Starting query function...") | |
| if not prompt: | |
| raise gr.Error("Prompt cannot be empty") | |
| # Set headers with API token | |
| headers = {"Authorization": f"Bearer {HF_TOKEN}"} | |
| # Generate a unique key for tracking | |
| key = random.randint(0, 999) | |
| # Enhance prompt | |
| prompt = f"{prompt} | ultra detail, ultra elaboration, ultra quality, perfect." | |
| print(f'Generation {key}: {prompt}') | |
| try: | |
| # Set API URL based on model selection | |
| if custom_lora.strip(): | |
| API_URL = f"https://api-inference.huggingface.co/models/{custom_lora.strip()}" | |
| else: | |
| if model == 'Stable Diffusion XL': | |
| API_URL = "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-xl-base-1.0" | |
| elif model == 'FLUX.1 [Dev]': | |
| API_URL = "https://api-inference.huggingface.co/models/black-forest-labs/FLUX.1-dev" | |
| elif model == 'FLUX.1 [Schnell]': | |
| API_URL = "https://api-inference.huggingface.co/models/black-forest-labs/FLUX.1-schnell" | |
| elif model == 'Flux Logo Design': | |
| API_URL = "https://api-inference.huggingface.co/models/Shakker-Labs/FLUX.1-dev-LoRA-Logo-Design" | |
| prompt = f"wablogo, logo, Minimalist, {prompt}" | |
| elif model == 'Flux Uncensored': | |
| API_URL = "https://api-inference.huggingface.co/models/enhanceaiteam/Flux-uncensored" | |
| elif model == 'Flux Uncensored V2': | |
| API_URL = "https://api-inference.huggingface.co/models/enhanceaiteam/Flux-Uncensored-V2" | |
| elif model == 'Flux Tarot Cards': | |
| API_URL = "https://api-inference.huggingface.co/models/prithivMLmods/Ton618-Tarot-Cards-Flux-LoRA" | |
| prompt = f"Tarot card, {prompt}" | |
| elif model == 'Pixel Art Sprites': | |
| API_URL = "https://api-inference.huggingface.co/models/sWizad/pokemon-trainer-sprites-pixelart-flux" | |
| prompt = f"a pixel image, {prompt}" | |
| elif model == '3D Sketchfab': | |
| API_URL = "https://api-inference.huggingface.co/models/prithivMLmods/Castor-3D-Sketchfab-Flux-LoRA" | |
| prompt = f"3D Sketchfab, {prompt}" | |
| elif model == 'Retro Comic Flux': | |
| API_URL = "https://api-inference.huggingface.co/models/renderartist/retrocomicflux" | |
| prompt = f"c0m1c, comic book panel, {prompt}" | |
| elif model == 'Caricature': | |
| API_URL = "https://api-inference.huggingface.co/models/TheAwakenOne/caricature" | |
| prompt = f"CCTUR3, {prompt}" | |
| elif model == 'Huggieverse': | |
| API_URL = "https://api-inference.huggingface.co/models/Chunte/flux-lora-Huggieverse" | |
| prompt = f"HGGRE, {prompt}" | |
| elif model == 'Propaganda Poster': | |
| API_URL = "https://api-inference.huggingface.co/models/AlekseyCalvin/Propaganda_Poster_Schnell_by_doctor_diffusion" | |
| prompt = f"propaganda poster, {prompt}" | |
| elif model == 'Flux Game Assets V2': | |
| API_URL = "https://api-inference.huggingface.co/models/gokaygokay/Flux-Game-Assets-LoRA-v2" | |
| prompt = f"wbgmsst, white background, {prompt}" | |
| elif model == 'SoftPasty Flux': | |
| API_URL = "https://api-inference.huggingface.co/models/alvdansen/softpasty-flux-dev" | |
| prompt = f"araminta_illus illustration style, {prompt}" | |
| elif model == 'Flux Stickers': | |
| API_URL = "https://api-inference.huggingface.co/models/diabolic6045/Flux_Sticker_Lora" | |
| prompt = f"5t1cker 5ty1e, {prompt}" | |
| elif model == 'Flux Animex V2': | |
| API_URL = "https://api-inference.huggingface.co/models/strangerzonehf/Flux-Animex-v2-LoRA" | |
| prompt = f"Animex, {prompt}" | |
| elif model == 'Flux Animeo V1': | |
| API_URL = "https://api-inference.huggingface.co/models/strangerzonehf/Flux-Animeo-v1-LoRA" | |
| prompt = f"Animeo, {prompt}" | |
| elif model == 'Movie Board': | |
| API_URL = "https://api-inference.huggingface.co/models/prithivMLmods/Flux.1-Dev-Movie-Boards-LoRA" | |
| prompt = f"movieboard, {prompt}" | |
| elif model == 'Purple Dreamy': | |
| API_URL = "https://api-inference.huggingface.co/models/prithivMLmods/Purple-Dreamy-Flux-LoRA" | |
| prompt = f"Purple Dreamy, {prompt}" | |
| elif model == 'PS1 Style Flux': | |
| API_URL = "https://api-inference.huggingface.co/models/veryVANYA/ps1-style-flux" | |
| prompt = f"ps1 game screenshot, {prompt}" | |
| elif model == 'Softserve Anime': | |
| API_URL = "https://api-inference.huggingface.co/models/alvdansen/softserve_anime" | |
| prompt = f"sftsrv style illustration, {prompt}" | |
| elif model == 'Flux Tarot v1': | |
| API_URL = "https://api-inference.huggingface.co/models/multimodalart/flux-tarot-v1" | |
| prompt = f"in the style of TOK a trtcrd tarot style, {prompt}" | |
| elif model == 'Half Illustration': | |
| API_URL = "https://api-inference.huggingface.co/models/davisbro/half_illustration" | |
| prompt = f"in the style of TOK, {prompt}" | |
| elif model == 'OpenDalle v1.1': | |
| API_URL = "https://api-inference.huggingface.co/models/dataautogpt3/OpenDalleV1.1" | |
| elif model == 'Flux Ghibsky Illustration': | |
| API_URL = "https://api-inference.huggingface.co/models/aleksa-codes/flux-ghibsky-illustration" | |
| prompt = f"GHIBSKY style, {prompt}" | |
| elif model == 'Flux Koda': | |
| API_URL = "https://api-inference.huggingface.co/models/alvdansen/flux-koda" | |
| prompt = f"flmft style, {prompt}" | |
| elif model == 'Soviet Diffusion XL': | |
| API_URL = "https://api-inference.huggingface.co/models/openskyml/soviet-diffusion-xl" | |
| prompt = f"soviet poster, {prompt}" | |
| elif model == 'Flux Realism LoRA': | |
| API_URL = "https://api-inference.huggingface.co/models/XLabs-AI/flux-RealismLora" | |
| elif model == 'Frosting Lane Flux': | |
| API_URL = "https://api-inference.huggingface.co/models/alvdansen/frosting_lane_flux" | |
| prompt = f"frstingln illustration, {prompt}" | |
| elif model == 'Phantasma Anime': | |
| API_URL = "https://api-inference.huggingface.co/models/alvdansen/phantasma-anime" | |
| elif model == 'Boreal': | |
| API_URL = "https://api-inference.huggingface.co/models/kudzueye/Boreal" | |
| prompt = f"photo, {prompt}" | |
| elif model == 'How2Draw': | |
| API_URL = "https://api-inference.huggingface.co/models/glif/how2draw" | |
| prompt = f"How2Draw, {prompt}" | |
| elif model == 'Flux AestheticAnime': | |
| API_URL = "https://api-inference.huggingface.co/models/dataautogpt3/FLUX-AestheticAnime" | |
| elif model == 'Fashion Hut Modeling LoRA': | |
| API_URL = "https://api-inference.huggingface.co/models/prithivMLmods/Fashion-Hut-Modeling-LoRA" | |
| prompt = f"Modeling of, {prompt}" | |
| elif model == 'Flux SyntheticAnime': | |
| API_URL = "https://api-inference.huggingface.co/models/dataautogpt3/FLUX-SyntheticAnime" | |
| prompt = f"1980s anime screengrab, VHS quality, syntheticanime, {prompt}" | |
| elif model == 'Flux Midjourney Anime': | |
| API_URL = "https://api-inference.huggingface.co/models/brushpenbob/flux-midjourney-anime" | |
| prompt = f"egmid, {prompt}" | |
| elif model == 'Coloring Book Generator': | |
| API_URL = "https://api-inference.huggingface.co/models/robert123231/coloringbookgenerator" | |
| elif model == 'Collage Flux': | |
| API_URL = "https://api-inference.huggingface.co/models/prithivMLmods/Castor-Collage-Dim-Flux-LoRA" | |
| prompt = f"collage, {prompt}" | |
| elif model == 'Flux Product Ad Backdrop': | |
| API_URL = "https://api-inference.huggingface.co/models/prithivMLmods/Flux-Product-Ad-Backdrop" | |
| prompt = f"Product Ad, {prompt}" | |
| elif model == 'Product Design': | |
| API_URL = "https://api-inference.huggingface.co/models/multimodalart/product-design" | |
| prompt = f"product designed by prdsgn, {prompt}" | |
| elif model == '90s Anime Art': | |
| API_URL = "https://api-inference.huggingface.co/models/glif/90s-anime-art" | |
| elif model == 'Brain Melt Acid Art': | |
| API_URL = "https://api-inference.huggingface.co/models/glif/Brain-Melt-Acid-Art" | |
| prompt = f"maximalism, in an acid surrealism style, {prompt}" | |
| elif model == 'Lustly Flux Uncensored v1': | |
| API_URL = "https://api-inference.huggingface.co/models/lustlyai/Flux_Lustly.ai_Uncensored_nsfw_v1" | |
| elif model == 'NSFW Master Flux': | |
| API_URL = "https://api-inference.huggingface.co/models/Keltezaa/NSFW_MASTER_FLUX" | |
| prompt = f"NSFW, {prompt}" | |
| elif model == 'Flux Outfit Generator': | |
| API_URL = "https://api-inference.huggingface.co/models/tryonlabs/FLUX.1-dev-LoRA-Outfit-Generator" | |
| elif model == 'Midjourney': | |
| API_URL = "https://api-inference.huggingface.co/models/Jovie/Midjourney" | |
| elif model == 'DreamPhotoGASM': | |
| API_URL = "https://api-inference.huggingface.co/models/Yntec/DreamPhotoGASM" | |
| elif model == 'Flux Super Realism LoRA': | |
| API_URL = "https://api-inference.huggingface.co/models/strangerzonehf/Flux-Super-Realism-LoRA" | |
| elif model == 'Stable Diffusion 2-1': | |
| API_URL = "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-2-1-base" | |
| elif model == 'Stable Diffusion 3.5 Large': | |
| API_URL = "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-3.5-large" | |
| elif model == 'Stable Diffusion 3.5 Large Turbo': | |
| API_URL = "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-3.5-large-turbo" | |
| elif model == 'Stable Diffusion 3 Medium': | |
| API_URL = "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-3-medium-diffusers" | |
| prompt = f"A, {prompt}" | |
| elif model == 'Duchaiten Real3D NSFW XL': | |
| API_URL = "https://api-inference.huggingface.co/models/stablediffusionapi/duchaiten-real3d-nsfw-xl" | |
| elif model == 'Pixel Art XL': | |
| API_URL = "https://api-inference.huggingface.co/models/nerijs/pixel-art-xl" | |
| prompt = f"pixel art, {prompt}" | |
| elif model == 'Character Design': | |
| API_URL = "https://api-inference.huggingface.co/models/KappaNeuro/character-design" | |
| prompt = f"Character Design, {prompt}" | |
| elif model == 'Sketched Out Manga': | |
| API_URL = "https://api-inference.huggingface.co/models/alvdansen/sketchedoutmanga" | |
| prompt = f"daiton, {prompt}" | |
| elif model == 'Archfey Anime': | |
| API_URL = "https://api-inference.huggingface.co/models/alvdansen/archfey_anime" | |
| elif model == 'Lofi Cuties': | |
| API_URL = "https://api-inference.huggingface.co/models/alvdansen/lofi-cuties" | |
| elif model == 'YiffyMix': | |
| API_URL = "https://api-inference.huggingface.co/models/Yntec/YiffyMix" | |
| elif model == 'Analog Madness Realistic v7': | |
| API_URL = "https://api-inference.huggingface.co/models/digiplay/AnalogMadness-realistic-model-v7" | |
| elif model == 'Selfie Photography': | |
| API_URL = "https://api-inference.huggingface.co/models/artificialguybr/selfiephotographyredmond-selfie-photography-lora-for-sdxl" | |
| prompt = f"instagram model, discord profile picture, {prompt}" | |
| elif model == 'Filmgrain': | |
| API_URL = "https://api-inference.huggingface.co/models/artificialguybr/filmgrain-redmond-filmgrain-lora-for-sdxl" | |
| prompt = f"Film Grain, FilmGrainAF, {prompt}" | |
| elif model == 'Leonardo AI Style Illustration': | |
| API_URL = "https://api-inference.huggingface.co/models/goofyai/Leonardo_Ai_Style_Illustration" | |
| prompt = f"leonardo style, illustration, vector art, {prompt}" | |
| elif model == 'Cyborg Style XL': | |
| API_URL = "https://api-inference.huggingface.co/models/goofyai/cyborg_style_xl" | |
| prompt = f"cyborg style, {prompt}" | |
| elif model == 'Little Tinies': | |
| API_URL = "https://api-inference.huggingface.co/models/alvdansen/littletinies" | |
| elif model == 'NSFW XL': | |
| API_URL = "https://api-inference.huggingface.co/models/Dremmar/nsfw-xl" | |
| elif model == 'Analog Redmond': | |
| API_URL = "https://api-inference.huggingface.co/models/artificialguybr/analogredmond" | |
| prompt = f"timeless style, {prompt}" | |
| elif model == 'Pixel Art Redmond': | |
| API_URL = "https://api-inference.huggingface.co/models/artificialguybr/PixelArtRedmond" | |
| prompt = f"Pixel Art, {prompt}" | |
| elif model == 'Ascii Art': | |
| API_URL = "https://api-inference.huggingface.co/models/CiroN2022/ascii-art" | |
| prompt = f"ascii art, {prompt}" | |
| elif model == 'Analog': | |
| API_URL = "https://api-inference.huggingface.co/models/Yntec/Analog" | |
| elif model == 'Maple Syrup': | |
| API_URL = "https://api-inference.huggingface.co/models/Yntec/MapleSyrup" | |
| elif model == 'Perfect Lewd Fantasy': | |
| API_URL = "https://api-inference.huggingface.co/models/digiplay/perfectLewdFantasy_v1.01" | |
| elif model == 'AbsoluteReality 1.8.1': | |
| API_URL = "https://api-inference.huggingface.co/models/digiplay/AbsoluteReality_v1.8.1" | |
| elif model == 'Disney': | |
| API_URL = "https://api-inference.huggingface.co/models/goofyai/disney_style_xl" | |
| prompt = f"Disney style, {prompt}" | |
| elif model == 'Redmond SDXL': | |
| API_URL = "https://api-inference.huggingface.co/models/artificialguybr/LogoRedmond-LogoLoraForSDXL-V2" | |
| elif model == 'epiCPhotoGasm': | |
| API_URL = "https://api-inference.huggingface.co/models/Yntec/epiCPhotoGasm" | |
| else: | |
| API_URL = "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-xl-base-1.0" | |
| # Prepare payload | |
| payload = { | |
| "inputs": prompt, | |
| "is_negative": is_negative, | |
| "steps": steps, | |
| "cfg_scale": cfg_scale, | |
| "seed": seed if seed != -1 else random.randint(1, 1000000000), | |
| "strength": strength, | |
| "parameters": { | |
| "width": width, | |
| "height": height | |
| } | |
| } | |
| # 타임아웃 값을 늘리고 재시도 로직 추가 | |
| max_retries = 3 | |
| current_retry = 0 | |
| while current_retry < max_retries: | |
| try: | |
| response = requests.post(API_URL, headers=headers, json=payload, timeout=180) # 타임아웃을 180초로 증가 | |
| response.raise_for_status() | |
| image = Image.open(io.BytesIO(response.content)) | |
| print(f'Generation {key} completed successfully') | |
| return image | |
| except requests.exceptions.Timeout: | |
| current_retry += 1 | |
| if current_retry < max_retries: | |
| print(f"Timeout occurred. Retrying... (Attempt {current_retry + 1}/{max_retries})") | |
| continue | |
| else: | |
| raise gr.Error(f"Request timed out after {max_retries} attempts. The model might be busy, please try again later.") | |
| except requests.exceptions.RequestException as e: | |
| raise gr.Error(f"Request failed: {str(e)}") | |
| except requests.exceptions.RequestException as e: | |
| error_message = f"Request failed: {str(e)}" | |
| if hasattr(e, 'response') and e.response is not None: | |
| if e.response.status_code == 401: | |
| error_message = "Invalid API token. Please check your Hugging Face API token." | |
| elif e.response.status_code == 403: | |
| error_message = "Access denied. Please check your API token permissions." | |
| elif e.response.status_code == 503: | |
| error_message = "Model is currently loading. Please try again in a few moments." | |
| raise gr.Error(error_message) | |
| except Exception as e: | |
| raise gr.Error(f"Unexpected error: {str(e)}") | |
| def generate_grid(prompt, selected_models, custom_lora, negative_prompt, steps, cfg_scale, seed, strength, width, height, progress=gr.Progress()): | |
| if len(selected_models) > 4: | |
| raise gr.Error("Please select up to 4 models") | |
| if len(selected_models) == 0: | |
| raise gr.Error("Please select at least 1 model") | |
| # 초기 이미지 배열 생성 | |
| images = [None] * 4 | |
| total_models = len(selected_models[:4]) | |
| def update_gallery(): | |
| # None이 아닌 이미지만 포함하여 갤러리 업데이트 | |
| return [img for img in images if img is not None] | |
| # 각 모델별로 이미지 생성 | |
| for idx, model_name in enumerate(selected_models[:4]): | |
| try: | |
| progress((idx + 1) / total_models, f"Generating image for {model_name}...") | |
| img = query(prompt, model_name, custom_lora, negative_prompt, steps, cfg_scale, seed, strength, width, height) | |
| images[idx] = img | |
| # 이미지가 생성될 때마다 갤러리 업데이트 | |
| yield update_gallery() | |
| except Exception as e: | |
| print(f"Error generating image for {model_name}: {str(e)}") | |
| continue | |
| # 남은 슬롯을 마지막 생성된 이미지로 채움 | |
| last_valid_image = next((img for img in reversed(images) if img is not None), None) | |
| if last_valid_image: | |
| for i in range(len(images)): | |
| if images[i] is None: | |
| images[i] = last_valid_image | |
| progress(1.0, "Generation complete!") | |
| yield update_gallery() | |
| css = """ | |
| footer { | |
| visibility: hidden; | |
| } | |
| """ | |
| with gr.Blocks(theme="Yntec/HaleyCH_Theme_Orange", css=css) as dalle: | |
| gr.Markdown("# ZeroWeight Studio") | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| text_prompt = gr.Textbox( | |
| label="Prompt", | |
| placeholder="Describe what you want to create...", | |
| lines=3 | |
| ) | |
| negative_prompt = gr.Textbox( | |
| label="Negative Prompt", | |
| placeholder="What should not be in the image", | |
| value="(deformed, distorted, disfigured), poorly drawn, bad anatomy, wrong anatomy, extra limb, missing limb, floating limbs, (mutated hands and fingers), disconnected limbs, mutation, mutated, ugly, disgusting, blurry, amputation", | |
| lines=2 | |
| ) | |
| custom_lora = gr.Textbox( | |
| label="Custom LoRA Path (Optional)", | |
| placeholder="e.g., multimodalart/vintage-ads-flux", | |
| lines=1 | |
| ) | |
| with gr.Column(scale=1): | |
| with gr.Group(): | |
| gr.Markdown("### Image Settings") | |
| width = gr.Slider(label="Width", value=1024, minimum=512, maximum=1216, step=64) | |
| height = gr.Slider(label="Height", value=1024, minimum=512, maximum=1216, step=64) | |
| with gr.Group(): | |
| gr.Markdown("### Generation Parameters") | |
| steps = gr.Slider(label="Steps", value=35, minimum=1, maximum=100, step=1) | |
| cfg = gr.Slider(label="CFG Scale", value=7, minimum=1, maximum=20, step=0.5) | |
| strength = gr.Slider(label="Strength", value=0.7, minimum=0, maximum=1, step=0.1) | |
| seed = gr.Slider(label="Seed (-1 for random)", value=-1, minimum=-1, maximum=1000000000, step=1) | |
| with gr.Accordion("Model Selection", open=False): | |
| model_search = gr.Textbox( | |
| label="Search Models", | |
| placeholder="Type to filter models...", | |
| lines=1 | |
| ) | |
| # 상위 4개 모델을 기본으로 설정 | |
| default_models = [ | |
| "FLUX.1 [Schnell]", # 모델 이름 통일 | |
| "Stable Diffusion 3.5 Large", | |
| "Stable Diffusion 3.5 Large Turbo", | |
| "Midjourney" | |
| ] | |
| # 전체 모델 리스트 | |
| models_list = [ | |
| "FLUX.1 [Schnell]", # 모델 이름 통일 | |
| "Stable Diffusion 3.5 Large", | |
| "Stable Diffusion 3.5 Large Turbo", | |
| "Stable Diffusion XL", | |
| "FLUX.1 [Dev]", | |
| "Midjourney", | |
| "DreamPhotoGASM", | |
| "Disney", | |
| "Leonardo AI Style Illustration", | |
| "AbsoluteReality 1.8.1", | |
| "Analog Redmond", | |
| "Stable Diffusion 3 Medium", | |
| "Flux Super Realism LoRA", | |
| "Flux Realism LoRA", | |
| "Selfie Photography", | |
| "Character Design", | |
| "Pixel Art XL", | |
| "3D Sketchfab", | |
| "Flux Animex V2", | |
| "Flux Animeo V1", | |
| "Flux AestheticAnime", | |
| "90s Anime Art", | |
| "Softserve Anime", | |
| "Brain Melt Acid Art", | |
| "Retro Comic Flux", | |
| "Purple Dreamy", | |
| "SoftPasty Flux", | |
| "Flux Logo Design", | |
| "Product Design", | |
| "Propaganda Poster", | |
| "Movie Board", | |
| "Collage Flux" | |
| ] | |
| model = gr.Checkboxgroup( | |
| label="Select Models (Choose up to 4)", | |
| choices=models_list, | |
| value=default_models, | |
| interactive=True | |
| ) | |
| with gr.Row(): | |
| generate_btn = gr.Button("Generate 2x2 Grid", variant="primary", size="lg") | |
| with gr.Row(): | |
| gallery = gr.Gallery( | |
| label="Generated Images", | |
| show_label=True, | |
| elem_id="gallery", | |
| columns=2, | |
| rows=2, | |
| height="auto", | |
| preview=True, # 실시간 프리뷰 활성화 | |
| ) | |
| # 이벤트 핸들러 수정 | |
| generate_btn.click( | |
| fn=generate_grid, | |
| inputs=[ | |
| text_prompt, | |
| model, | |
| custom_lora, | |
| negative_prompt, | |
| steps, | |
| cfg, | |
| seed, | |
| strength, | |
| width, | |
| height | |
| ], | |
| outputs=gallery, | |
| show_progress=True | |
| ) | |
| def filter_models(search_term): | |
| filtered_models = [m for m in models_list if search_term.lower() in m.lower()] | |
| return gr.update(choices=filtered_models, value=[]) | |
| model_search.change(filter_models, inputs=model_search, outputs=model) | |
| if __name__ == "__main__": | |
| dalle.launch(show_api=False, share=False) |