Spaces:
Running
on
Zero
Running
on
Zero
| import spaces | |
| import gradio as gr | |
| import torch | |
| from diffusers import ZImagePipeline | |
| import os | |
| from pathlib import Path | |
| # Global variable to store the pipeline | |
| pipe = None | |
| def load_model(): | |
| """ | |
| Load the Z-Image Turbo model before inference. | |
| This ensures the model is downloaded and ready before any generation requests. | |
| """ | |
| global pipe | |
| if pipe is not None: | |
| return pipe | |
| print("Loading Z-Image Turbo model...") | |
| print("This may take a few minutes on first run while the model downloads...") | |
| try: | |
| # Load the pipeline with optimal settings | |
| pipe = ZImagePipeline.from_pretrained( | |
| "Tongyi-MAI/Z-Image-Turbo", | |
| torch_dtype=torch.bfloat16, | |
| low_cpu_mem_usage=False, | |
| ) | |
| # Move to GPU if available | |
| device = "cuda" if torch.cuda.is_available() else "cpu" | |
| pipe.to(device) | |
| print(f"Model loaded on {device}") | |
| # Optional: Enable Flash Attention for better efficiency | |
| try: | |
| pipe.transformer.set_attention_backend("flash") | |
| print("Flash Attention enabled") | |
| except Exception as e: | |
| print(f"Flash Attention not available: {e}") | |
| print("Using default attention backend") | |
| print("Model loaded successfully!") | |
| return pipe | |
| except Exception as e: | |
| print(f"Error loading model: {e}") | |
| raise | |
| # Pre-load the model when the app starts | |
| print("Initializing model on startup...") | |
| try: | |
| load_model() | |
| print("Model initialization complete!") | |
| except Exception as e: | |
| print(f"Warning: Could not pre-load model: {e}") | |
| print("Model will be loaded on first generation request") | |
| def generate_image( | |
| prompt, | |
| progress=gr.Progress(track_tqdm=True) | |
| ): | |
| """ | |
| Generate an image using Z-Image Turbo model. | |
| Args: | |
| prompt: Text description of the desired image | |
| Returns: | |
| Generated PIL Image | |
| """ | |
| global pipe | |
| # Ensure model is loaded | |
| if pipe is None: | |
| progress(0, desc="Loading model...") | |
| load_model() | |
| if not prompt.strip(): | |
| raise gr.Error("Please enter a prompt to generate an image.") | |
| # Determine device | |
| device = "cuda" if torch.cuda.is_available() else "cpu" | |
| # Set random seed for reproducibility | |
| generator = torch.Generator(device).manual_seed(42) | |
| # Generate the image with optimal settings | |
| progress(0.1, desc="Generating image...") | |
| try: | |
| result = pipe( | |
| prompt=prompt, | |
| negative_prompt=None, | |
| height=1024, | |
| width=1024, | |
| num_inference_steps=9, | |
| guidance_scale=0.0, | |
| generator=generator, | |
| ) | |
| image = result.images[0] | |
| progress(1.0, desc="Complete!") | |
| return image | |
| except Exception as e: | |
| raise gr.Error(f"Generation failed: {str(e)}") | |
| # Create a custom theme based on Soft theme with Apple-inspired colors | |
| custom_theme = gr.themes.Soft( | |
| primary_hue=gr.themes.colors.blue, | |
| secondary_hue=gr.themes.colors.slate, | |
| neutral_hue=gr.themes.colors.gray, | |
| spacing_size=gr.themes.sizes.spacing_lg, | |
| radius_size=gr.themes.sizes.radius_md, | |
| text_size=gr.themes.sizes.text_lg, | |
| font=[gr.themes.GoogleFont("Inter"), "ui-sans-serif", "system-ui", "sans-serif"], | |
| font_mono=[gr.themes.GoogleFont("IBM Plex Mono"), "ui-monospace", "Consolas", "monospace"], | |
| ).set( | |
| # Button styling | |
| button_primary_background_fill="#0071e3", | |
| button_primary_background_fill_hover="#0077ed", | |
| button_primary_text_color="white", | |
| button_large_padding="16px 40px", | |
| button_large_radius="12px", | |
| button_shadow="0 2px 8px rgba(0, 113, 227, 0.2)", | |
| button_shadow_hover="0 4px 12px rgba(0, 113, 227, 0.3)", | |
| # Input styling | |
| input_background_fill="#fbfbfd", | |
| input_background_fill_focus="white", | |
| input_border_color="#d2d2d7", | |
| input_border_color_focus="#0071e3", | |
| input_radius="12px", | |
| input_padding="16px", | |
| input_shadow_focus="0 0 0 4px rgba(0, 113, 227, 0.1)", | |
| # Container styling | |
| block_background_fill="white", | |
| block_border_width="1px", | |
| block_border_color="#e5e5e7", | |
| block_radius="12px", | |
| block_padding="24px", | |
| # Body styling | |
| body_background_fill="#f5f5f7", | |
| body_text_color="#1d1d1f", | |
| # Link styling | |
| link_text_color="#0071e3", | |
| link_text_color_hover="#0077ed", | |
| ) | |
| # Minimal additional CSS for layout refinements | |
| minimal_css = """ | |
| .gradio-container { | |
| max-width: 900px !important; | |
| margin: 0 auto !important; | |
| } | |
| .main-header { | |
| text-align: center; | |
| margin-bottom: 2rem; | |
| padding-bottom: 2rem; | |
| border-bottom: 1px solid #e5e5e7; | |
| } | |
| .main-header h1 { | |
| font-size: 3rem !important; | |
| font-weight: 600 !important; | |
| color: #1d1d1f !important; | |
| margin: 0 0 0.5rem 0 !important; | |
| letter-spacing: -1px; | |
| } | |
| .main-header .subtitle { | |
| font-size: 1.25rem !important; | |
| color: #86868b !important; | |
| margin: 0.5rem 0 !important; | |
| } | |
| .attribution { | |
| margin-top: 1rem; | |
| font-size: 0.875rem; | |
| color: #86868b; | |
| } | |
| .attribution a { | |
| color: #0071e3 !important; | |
| text-decoration: none; | |
| font-weight: 500; | |
| } | |
| .footer-info { | |
| text-align: center; | |
| padding: 2rem 1rem; | |
| color: #86868b; | |
| font-size: 0.875rem; | |
| margin-top: 2rem; | |
| border-top: 1px solid #e5e5e7; | |
| } | |
| .footer-info p { | |
| margin: 0.25rem 0; | |
| } | |
| @media (max-width: 768px) { | |
| .main-header h1 { | |
| font-size: 2rem !important; | |
| } | |
| .main-header .subtitle { | |
| font-size: 1rem !important; | |
| } | |
| } | |
| """ | |
| # Create the Gradio interface | |
| with gr.Blocks( | |
| title="Z-Image Turbo", | |
| theme=custom_theme, | |
| css=minimal_css, | |
| fill_height=False | |
| ) as demo: | |
| # Header | |
| with gr.Column(elem_classes="main-header"): | |
| gr.Markdown( | |
| """ | |
| # Z-Image Turbo | |
| ### Create stunning images from text | |
| """, | |
| elem_classes="main-header" | |
| ) | |
| gr.HTML(""" | |
| <div class="attribution"> | |
| Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">anycoder</a> | |
| </div> | |
| """) | |
| # Prompt input | |
| prompt = gr.Textbox( | |
| placeholder="Describe the image you want to create...", | |
| lines=3, | |
| max_lines=6, | |
| label="Prompt", | |
| show_label=False, | |
| container=True | |
| ) | |
| # Generate button | |
| generate_btn = gr.Button( | |
| "Generate", | |
| variant="primary", | |
| size="lg", | |
| scale=1 | |
| ) | |
| # Output image | |
| output_image = gr.Image( | |
| type="pil", | |
| label="Generated Image", | |
| show_label=False, | |
| show_download_button=True, | |
| show_share_button=False, | |
| container=True | |
| ) | |
| # Footer | |
| gr.HTML(""" | |
| <div class="footer-info"> | |
| <p>Powered by Z-Image Turbo from Tongyi-MAI</p> | |
| <p>Optimized for fast, high-quality image generation</p> | |
| </div> | |
| """) | |
| # Event handlers | |
| generate_btn.click( | |
| fn=generate_image, | |
| inputs=prompt, | |
| outputs=output_image, | |
| api_name="generate" | |
| ) | |
| # Also allow generation on Enter key | |
| prompt.submit( | |
| fn=generate_image, | |
| inputs=prompt, | |
| outputs=output_image | |
| ) | |
| # Launch the app | |
| if __name__ == "__main__": | |
| demo.launch( | |
| share=False, | |
| show_error=True | |
| ) |