import os import gc import gradio as gr import numpy as np import torch import json import spaces import config import utils import logging from PIL import Image, PngImagePlugin from datetime import datetime from diffusers.models import AutoencoderKL from diffusers import StableDiffusionXLPipeline, StableDiffusionXLImg2ImgPipeline # ... (keep the existing imports and configurations) logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) DESCRIPTION = "PonyDiffusion V6 XL" if not torch.cuda.is_available(): DESCRIPTION += "\n

Running on CPU 🥶 This demo does not work on CPU.

" IS_COLAB = utils.is_google_colab() or os.getenv("IS_COLAB") == "1" HF_TOKEN = os.getenv("HF_TOKEN") CACHE_EXAMPLES = torch.cuda.is_available() and os.getenv("CACHE_EXAMPLES") == "1" MIN_IMAGE_SIZE = int(os.getenv("MIN_IMAGE_SIZE", "512")) MAX_IMAGE_SIZE = int(os.getenv("MAX_IMAGE_SIZE", "2048")) USE_TORCH_COMPILE = os.getenv("USE_TORCH_COMPILE") == "1" ENABLE_CPU_OFFLOAD = os.getenv("ENABLE_CPU_OFFLOAD") == "1" OUTPUT_DIR = os.getenv("OUTPUT_DIR", "./outputs") MODEL = os.getenv( "MODEL", "https://huggingface.co/AstraliteHeart/pony-diffusion-v6/blob/main/v6.safetensors", ) torch.backends.cudnn.deterministic = True torch.backends.cudnn.benchmark = False device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") def load_pipeline(model_name): vae = AutoencoderKL.from_pretrained( "madebyollin/sdxl-vae-fp16-fix", torch_dtype=torch.float16, ) pipeline = ( StableDiffusionXLPipeline.from_single_file if MODEL.endswith(".safetensors") else StableDiffusionXLPipeline.from_pretrained ) pipe = pipeline( model_name, vae=vae, torch_dtype=torch.float16, custom_pipeline="lpw_stable_diffusion_xl", use_safetensors=True, add_watermarker=False, use_auth_token=HF_TOKEN, variant="fp16", ) pipe.to(device) return pipe # Add a new function to parse and validate JSON input def parse_json_parameters(json_str): try: params = json.loads(json_str) required_keys = ['prompt', 'negative_prompt', 'seed', 'width', 'height', 'guidance_scale', 'num_inference_steps', 'sampler'] for key in required_keys: if key not in params: raise ValueError(f"Missing required key: {key}") return params except json.JSONDecodeError: raise ValueError("Invalid JSON format") except Exception as e: raise ValueError(f"Error parsing JSON: {str(e)}") # Modify the generate function to accept JSON parameters @spaces.GPU def generate( prompt: str, negative_prompt: str = "", seed: int = 0, custom_width: int = 1024, custom_height: int = 1024, guidance_scale: float = 7.0, num_inference_steps: int = 30, sampler: str = "DPM++ 2M SDE Karras", aspect_ratio_selector: str = "1024 x 1024", use_upscaler: bool = False, upscaler_strength: float = 0.55, upscale_by: float = 1.5, json_params: str = "", progress=gr.Progress(track_tqdm=True), ) -> Image: if json_params: try: params = parse_json_parameters(json_params) prompt = params['prompt'] negative_prompt = params['negative_prompt'] seed = params['seed'] custom_width = params['width'] custom_height = params['height'] guidance_scale = params['guidance_scale'] num_inference_steps = params['num_inference_steps'] sampler = params['sampler'] except ValueError as e: raise gr.Error(str(e)) generator = utils.seed_everything(seed) width, height = utils.aspect_ratio_handler( aspect_ratio_selector, custom_width, custom_height, ) width, height = utils.preprocess_image_dimensions(width, height) backup_scheduler = pipe.scheduler pipe.scheduler = utils.get_scheduler(pipe.scheduler.config, sampler) if use_upscaler: upscaler_pipe = StableDiffusionXLImg2ImgPipeline(**pipe.components) metadata = { "prompt": prompt, "negative_prompt": negative_prompt, "resolution": f"{width} x {height}", "guidance_scale": guidance_scale, "num_inference_steps": num_inference_steps, "seed": seed, "sampler": sampler, } if use_upscaler: new_width = int(width * upscale_by) new_height = int(height * upscale_by) metadata["use_upscaler"] = { "upscale_method": "nearest-exact", "upscaler_strength": upscaler_strength, "upscale_by": upscale_by, "new_resolution": f"{new_width} x {new_height}", } else: metadata["use_upscaler"] = None logger.info(json.dumps(metadata, indent=4)) try: if use_upscaler: latents = pipe( prompt=prompt, negative_prompt=negative_prompt, width=width, height=height, guidance_scale=guidance_scale, num_inference_steps=num_inference_steps, generator=generator, output_type="latent", ).images upscaled_latents = utils.upscale(latents, "nearest-exact", upscale_by) images = upscaler_pipe( prompt=prompt, negative_prompt=negative_prompt, image=upscaled_latents, guidance_scale=guidance_scale, num_inference_steps=num_inference_steps, strength=upscaler_strength, generator=generator, output_type="pil", ).images else: images = pipe( prompt=prompt, negative_prompt=negative_prompt, width=width, height=height, guidance_scale=guidance_scale, num_inference_steps=num_inference_steps, generator=generator, output_type="pil", ).images if images and IS_COLAB: for image in images: filepath = utils.save_image(image, metadata, OUTPUT_DIR) logger.info(f"Image saved as {filepath} with metadata") return images, metadata except Exception as e: logger.exception(f"An error occurred: {e}") raise finally: if use_upscaler: del upscaler_pipe pipe.scheduler = backup_scheduler utils.free_memory() # Initialize an empty list to store the generation history generation_history = [] # Function to update the history dropdown def update_history_dropdown(): return gr.Dropdown.update(choices=[f"{item['prompt']} ({item['timestamp']})" for item in generation_history]) # Modify the generate function to add results to the history def generate_and_update_history(*args, **kwargs): images, metadata = generate(*args, **kwargs) timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") generation_history.insert(0, {"prompt": metadata["prompt"], "timestamp": timestamp, "image": images[0], "metadata": metadata}) if len(generation_history) > 10: # Limit history to 10 items generation_history.pop() return images, metadata, update_history_dropdown() # Function to display selected history item def display_history_item(selected_item): if not selected_item: return None, None for item in generation_history: if f"{item['prompt']} ({item['timestamp']})" == selected_item: return item['image'], json.dumps(item['metadata'], indent=2) return None, None if torch.cuda.is_available(): pipe = load_pipeline(MODEL) logger.info("Loaded on Device!") else: pipe = None with gr.Blocks(css="style.css") as demo: title = gr.HTML( f"""

{DESCRIPTION}

""", elem_id="title", ) gr.Markdown( f"""Gradio demo for [Pony Diffusion V6](https://civitai.com/models/257749/pony-diffusion-v6-xl/)""", elem_id="subtitle", ) gr.DuplicateButton( value="Duplicate Space for private use", elem_id="duplicate-button", visible=os.getenv("SHOW_DUPLICATE_BUTTON") == "1", ) with gr.Group(): with gr.Row(): prompt = gr.Text( label="Prompt", show_label=False, max_lines=5, placeholder="Enter your prompt", container=False, ) run_button = gr.Button( "Generate", variant="primary", scale=0 ) result = gr.Gallery( label="Result", columns=1, preview=True, show_label=False ) with gr.Accordion(label="Advanced Settings", open=False): negative_prompt = gr.Text( label="Negative Prompt", max_lines=5, placeholder="Enter a negative prompt", value="" ) aspect_ratio_selector = gr.Radio( label="Aspect Ratio", choices=config.aspect_ratios, value="1024 x 1024", container=True, ) with gr.Group(visible=False) as custom_resolution: with gr.Row(): custom_width = gr.Slider( label="Width", minimum=MIN_IMAGE_SIZE, maximum=MAX_IMAGE_SIZE, step=8, value=1024, ) custom_height = gr.Slider( label="Height", minimum=MIN_IMAGE_SIZE, maximum=MAX_IMAGE_SIZE, step=8, value=1024, ) use_upscaler = gr.Checkbox(label="Use Upscaler", value=False) with gr.Row() as upscaler_row: upscaler_strength = gr.Slider( label="Strength", minimum=0, maximum=1, step=0.05, value=0.55, visible=False, ) upscale_by = gr.Slider( label="Upscale by", minimum=1, maximum=1.5, step=0.1, value=1.5, visible=False, ) sampler = gr.Dropdown( label="Sampler", choices=config.sampler_list, interactive=True, value="DPM++ 2M SDE Karras", ) with gr.Row(): seed = gr.Slider( label="Seed", minimum=0, maximum=utils.MAX_SEED, step=1, value=0 ) randomize_seed = gr.Checkbox(label="Randomize seed", value=True) with gr.Group(): with gr.Row(): guidance_scale = gr.Slider( label="Guidance scale", minimum=1, maximum=12, step=0.1, value=7.0, ) num_inference_steps = gr.Slider( label="Number of inference steps", minimum=1, maximum=50, step=1, value=28, ) with gr.Accordion(label="Generation Parameters", open=False): gr_metadata = gr.JSON(label="Metadata", show_label=False) json_input = gr.TextArea(label="Edit/Paste JSON Parameters", placeholder="Paste or edit JSON parameters here") generate_from_json = gr.Button("Generate from JSON") # Add history dropdown history_dropdown = gr.Dropdown(label="Generation History", choices=[], interactive=True) history_image = gr.Image(label="Selected Image", interactive=False) history_metadata = gr.JSON(label="Selected Metadata", show_label=False) gr.Examples( examples=config.examples, inputs=prompt, outputs=[result, gr_metadata], fn=lambda *args, **kwargs: generate_and_update_history(*args, use_upscaler=True, **kwargs), cache_examples=CACHE_EXAMPLES, ) use_upscaler.change( fn=lambda x: [gr.update(visible=x), gr.update(visible=x)], inputs=use_upscaler, outputs=[upscaler_strength, upscale_by], queue=False, api_name=False, ) aspect_ratio_selector.change( fn=lambda x: gr.update(visible=x == "Custom"), inputs=aspect_ratio_selector, outputs=custom_resolution, queue=False, api_name=False, ) inputs = [ prompt, negative_prompt, seed, custom_width, custom_height, guidance_scale, num_inference_steps, sampler, aspect_ratio_selector, use_upscaler, upscaler_strength, upscale_by, json_input, # Add JSON input to the list of inputs ] prompt.submit( fn=utils.randomize_seed_fn, inputs=[seed, randomize_seed], outputs=seed, queue=False, api_name=False, ).then( fn=generate_and_update_history, # Use the new function inputs=inputs, outputs=[result, gr_metadata, history_dropdown], # Add history_dropdown to outputs api_name="run", ) negative_prompt.submit( fn=utils.randomize_seed_fn, inputs=[seed, randomize_seed], outputs=seed, queue=False, api_name=False, ).then( fn=generate_and_update_history, # Use the new function inputs=inputs, outputs=[result, gr_metadata, history_dropdown], # Add history_dropdown to outputs api_name=False, ) run_button.click( fn=utils.randomize_seed_fn, inputs=[seed, randomize_seed], outputs=seed, queue=False, api_name=False, ).then( fn=generate_and_update_history, # Use the new function inputs=inputs, outputs=[result, gr_metadata, history_dropdown], # Add history_dropdown to outputs api_name=False, ) # Add event handler for generate_from_json button generate_from_json.click( fn=generate_and_update_history, inputs=inputs, outputs=[result, gr_metadata, history_dropdown], api_name=False, ) # Add event handler for history_dropdown history_dropdown.change( fn=display_history_item, inputs=[history_dropdown], outputs=[history_image, history_metadata], ) demo.queue(max_size=20).launch(debug=IS_COLAB, share=IS_COLAB)