import gradio as gr import torch from diffusers import ( StableDiffusionXLPipeline, EulerDiscreteScheduler, AutoencoderKL, DPMSolverSinglestepScheduler, ) # --- Configuration --- # The base model your LoRA was trained on. base_model_id = "stabilityai/stable-diffusion-xl-base-1.0" # --- The file is local, so we just need its name --- # The safetensors file is in the same directory as this script. lora_file_path = "emilyh.safetensors" # --- Load the Pipeline --- # Use a recommended VAE for SDXL vae = AutoencoderKL.from_pretrained("madebyollin/sdxl-vae-fp16-fix", torch_dtype=torch.float16) pipe = StableDiffusionXLPipeline.from_pretrained( base_model_id, vae=vae, torch_dtype=torch.float16, variant="fp16", use_safetensors=True ) # --- Load the local LoRA file --- # No download needed. We just load the local file directly. pipe.load_lora_weights(lora_file_path) # Move the pipeline to the GPU pipe.to("cuda") # --- Default Settings from your Recommendations --- default_positive_prompt = "masterpiece, best quality, ultra-detailed, realistic skin, intricate details, highres" default_negative_prompt = "low quality, worst quality, blurry, (deformed:1.3), extra fingers, cartoon, 3d, anime, bad anatomy" default_sampler = "DPM++ 2M Karras" default_cfg = 6.0 default_steps = 30 trigger_word = "emilyh" lora_tag_main = "" # --- Define the Inference Function --- def generate_image(prompt, negative_prompt, sampler, steps, cfg, width, height, seed): """ Function to generate an image based on user inputs. """ # Combine the user prompt with the trigger word and LoRA tag full_prompt = f"{lora_tag_main}, {trigger_word}, {prompt}" # Set the scheduler (sampler) if sampler == "DPM++ 2M Karras": pipe.scheduler = EulerDiscreteScheduler.from_config(pipe.scheduler.config, use_karras_sigmas=True) elif sampler == "DPM++ SDE Karras": pipe.scheduler = DPMSolverSinglestepScheduler.from_config(pipe.scheduler.config, use_karras_sigmas=True, algorithm_type="sde-dpmsolver++") else: # Default to DPM++ 2M Karras pipe.scheduler = EulerDiscreteScheduler.from_config(pipe.scheduler.config, use_karras_sigmas=True) # Set seed for reproducibility generator = torch.Generator("cuda").manual_seed(seed) if seed != -1 else None # Generate the image image = pipe( prompt=full_prompt, negative_prompt=negative_prompt, width=width, height=height, guidance_scale=cfg, num_inference_steps=steps, generator=generator, cross_attention_kwargs={"scale": 0.9} ).images[0] return image # --- Create the Gradio Interface --- with gr.Blocks(css="style.css") as demo: gr.Markdown("# `emilyh` LoRA Image Generator") gr.Markdown( "A Gradio interface for the `emilyh` LoRA. " "Based on the recommendations provided." ) with gr.Row(): with gr.Column(): prompt = gr.Textbox(label="Positive Prompt", value=default_positive_prompt, lines=3) negative_prompt = gr.Textbox(label="Negative Prompt", value=default_negative_prompt, lines=3) with gr.Row(): sampler = gr.Radio( label="Sampler", choices=["DPM++ 2M Karras", "DPM++ SDE Karras"], value=default_sampler, ) steps = gr.Slider(label="Steps", minimum=15, maximum=50, value=default_steps, step=1) cfg = gr.Slider(label="CFG Scale", minimum=1.0, maximum=10.0, value=default_cfg, step=0.5) with gr.Row(): width = gr.Slider(label="Width", minimum=512, maximum=1024, value=1024, step=64) height = gr.Slider(label="Height", minimum=512, maximum=1024, value=1024, step=64) seed = gr.Slider(label="Seed", minimum=-1, maximum=999999999, step=1, value=-1, info="Use -1 for a random seed.") generate_button = gr.Button("Generate Image", variant="primary") with gr.Column(): output_image = gr.Image(label="Generated Image", type="pil") gr.Markdown( """ ### 🔧 Usage Guide * The trigger word `emilyh` and the LoRA tag `` are automatically added to your prompt. * For best results, generate images in batches and choose the most consistent ones. * The LoRA captures the subject's appearance well across various poses and outfits. * A weight of 0.9 provides a good balance of likeness and flexibility. Using a weight closer to 1.0 can increase consistency but may cause stiffness. * This interface does not include ADetailer, which is recommended for final face refinement. """ ) generate_button.click( fn=generate_image, inputs=[prompt, negative_prompt, sampler, steps, cfg, width, height, seed], outputs=output_image ) demo.launch()