squaadai / app.py
TobDeBer's picture
Fine control for Turbo and Lightning models
0c2dc83 verified
raw
history blame
11 kB
#!/usr/bin/env python
from __future__ import annotations
import requests
import os
import random
import gradio as gr
import numpy as np
import spaces
import torch
import cv2
import xformers
import triton
from PIL import Image
from io import BytesIO
from diffusers.utils import load_image
from diffusers import StableDiffusionXLControlNetPipeline, StableDiffusionXLControlNetInpaintPipeline, ControlNetModel, AutoencoderKL, DiffusionPipeline, AutoPipelineForImage2Image, AutoPipelineForInpainting, EulerDiscreteScheduler, DPMSolverMultistepScheduler
if not torch.cuda.is_available():
DESCRIPTION += "\n<p>⚠️ This space is running on the CPU. This demo doesn't work on CPU 😞! Run on a GPU by duplicating this space or test our website for free and unlimited by <a href='https://squaadai.com'>clicking here</a>, which provides these and more options.</p>"
MAX_SEED = np.iinfo(np.int32).max
MAX_IMAGE_SIZE = int(os.getenv("MAX_IMAGE_SIZE", "1824"))
USE_TORCH_COMPILE = os.getenv("USE_TORCH_COMPILE") == "1"
ENABLE_CPU_OFFLOAD = os.getenv("ENABLE_CPU_OFFLOAD") == "1"
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
def randomize_seed_fn(seed: int, randomize_seed: bool) -> int:
if randomize_seed:
seed = random.randint(0, MAX_SEED)
return seed
@spaces.GPU
def generate(
prompt: str,
negative_prompt: str = "",
use_negative_prompt: bool = False,
seed: int = 0,
width: int = 1024,
height: int = 1024,
guidance_scale_base: float = 5.0,
num_inference_steps_base: int = 25,
use_vae: bool = False,
use_lora: bool = False,
use_lora2: bool = False,
model = 'stabilityai/stable-diffusion-xl-base-1.0',
vaemodel = 'madebyollin/sdxl-vae-fp16-fix',
lora = '',
lora2 = '',
lora_scale: float = 0.7,
lora_scale2: float = 0.7,
use_img2img: bool = False,
):
if torch.cuda.is_available():
if not use_img2img:
pipe = DiffusionPipeline.from_pretrained(model, torch_dtype=torch.float16)
if use_vae:
vae = AutoencoderKL.from_pretrained(vaemodel, torch_dtype=torch.float16)
pipe = DiffusionPipeline.from_pretrained(model, vae=vae, torch_dtype=torch.float16)
if use_lora:
pipe.load_lora_weights(lora)
pipe.fuse_lora(lora_scale)
if use_lora2:
pipe.load_lora_weights(lora, adapter_name="1")
pipe.load_lora_weights(lora2, adapter_name="2")
pipe.set_adapters(["1", "2"], adapter_weights=[lora_scale, lora_scale2])
if ENABLE_CPU_OFFLOAD:
pipe.enable_model_cpu_offload()
else:
pipe.to(device)
if USE_TORCH_COMPILE:
pipe.unet = torch.compile(pipe.unet, mode="reduce-overhead", fullgraph=True)
generator = torch.Generator().manual_seed(seed)
if not use_negative_prompt:
negative_prompt = None # type: ignore
return pipe(
prompt=prompt,
negative_prompt=negative_prompt,
width=width,
height=height,
guidance_scale=guidance_scale_base,
num_inference_steps=num_inference_steps_base,
generator=generator,
output_type="pil",
).images[0]
theme = gr.themes.Monochrome(
text_size=gr.themes.Size(lg="18px", md="15px", sm="13px", xl="22px", xs="12px", xxl="24px", xxs="9px"),
font=[gr.themes.GoogleFont('Source Sans Pro'), 'ui-sans-serif', 'system-ui', 'sans-serif'],
)
with gr.Blocks(theme=theme, css="style.css") as demo:
gr.HTML()
gr.Markdown("""# Squaad AI πŸ§™
### Run Stable Diffusion for free, in seconds
<small>Squaad AI was a free Artificial Intelligence website that brought together the best of the AI world in one place. Unfortunately, it had to temporarily cease operations after encountering compatibility issues. While it makes its comeback, this account sponsored by Hugging Face aims to make parts of its legacy available as open-source code and enable anyone to run SD easily and for free. We are currently adapting Squaad AI for Gradio... Controlnet, Img2Img, and Inpaint coming soon.</small>
<div style="display: flex; flex-direction: column; align-items: flex-start;">
<a target="_blank" href="https://discord.gg/CqXVwGDqFC"><img src="https://img.shields.io/badge/discord-join%20now-blue.svg?logo=discord" alt="discord.gg/CqXVwGDqFC"></a>
<a href="https://www.buymeacoffee.com/squaadai" target="_blank" style="margin-top: 10px;"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: auto !important;width: 130px !important;" ></a>
</div>""", elem_id="main_title")
with gr.Group():
model = gr.Text(label='Model', value='stabilityai/stable-diffusion-xl-base-1.0', placeholder='e.g. stabilityai/stable-diffusion-xl-base-1.0', info='Enter the HUB path for this model! The model must be converted to diffusers to work. We recommend SG161222/RealVisXL_V4.0 for realistic generations, for example. By default, SDXL 1.0 (stabilityai/stable-diffusion-xl-base-1.0) will be used.')
vaemodel = gr.Text(label='VAE', placeholder='e.g. madebyollin/sdxl-vae-fp16-fix', info='You can use the VAE that suits you best! Using an unfamiliar VAE or one that is not from the same base model mentioned above will result in errors or distorted images. You must enable "Use VAE" in advanced settings if you want to use a VAE.', visible=False)
with gr.Row():
width = gr.Slider(
label="Width",
minimum=256,
maximum=MAX_IMAGE_SIZE,
step=32,
value=1024,
)
height = gr.Slider(
label="Height",
minimum=256,
maximum=MAX_IMAGE_SIZE,
step=32,
value=1024,
)
num_inference_steps_base = gr.Slider(
info="Number of denoising steps",
label="Number of inference steps",
minimum=1,
maximum=100,
step=1,
value=25,
)
with gr.Row():
prompt = gr.Text(
placeholder="Input prompt",
label="Prompt",
show_label=False,
max_lines=1,
container=False,
)
run_button = gr.Button("Run", scale=0)
result = gr.Image(label="Result", show_label=False)
with gr.Accordion("Advanced options", open=False):
with gr.Row():
use_vae = gr.Checkbox(label='Use VAE', value=False)
use_lora = gr.Checkbox(label='Use 1 LoRA', value=False)
use_lora2 = gr.Checkbox(label='Use 2 LoRAs', value=False)
use_negative_prompt = gr.Checkbox(label="Use negative prompt", value=False)
with gr.Group():
negative_prompt = gr.Text(
placeholder="Input Negative Prompt",
label="Negative prompt",
max_lines=1,
visible=False,
)
seed = gr.Slider(
label="Seed",
minimum=0,
maximum=MAX_SEED,
step=1,
value=0,
)
randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
with gr.Group():
guidance_scale_base = gr.Slider(
info="Scale for classifier-free guidance",
label="Guidance scale",
minimum=1,
maximum=20,
step=0.01,
value=5.0,
)
with gr.Group():
gr.Markdown("""### LoRAs
<small>To activate the use of LoRAs, you should check only the 'Use 1 LoRA' checkbox if you want to use just one LoRA, and only the 'Use 2 LoRAs' checkbox if you want to use 2 LoRAs (i.e., blend styles)! It's important that all LoRAs are from the same base version of the selected model. For example, if the model is SDXL 1.0, the LoRA must also be.</small>"""
)
lora = gr.Text(label='LoRA 1', info='Make sure you are using the configured trigger word for the chosen LoRA, otherwise the style, person, object, animal... may not be applied correctly', placeholder='e.g. nerijs/pixel-art-xl', visible=False)
lora2 = gr.Text(label='LoRA 2', info='Make sure you are using the configured trigger word for the chosen LoRA, otherwise the style, person, object, animal... may not be applied correctly', placeholder='e.g. nerijs/pixel-art-xl', visible=False)
lora_scale = gr.Slider(
info="The closer to 1, the more it will resemble LoRA, but errors may be visible.",
label="Lora Scale 1",
minimum=0.01,
maximum=1,
step=0.01,
value=0.7,
visible=False,
)
lora_scale2 = gr.Slider(
info="The closer to 1, the more it will resemble LoRA, but errors may be visible.",
label="Lora Scale 2",
minimum=0.01,
maximum=1,
step=0.01,
value=0.7,
visible=False,
)
use_negative_prompt.change(
fn=lambda x: gr.update(visible=x),
inputs=use_negative_prompt,
outputs=negative_prompt,
queue=False,
api_name=False,
)
use_vae.change(
fn=lambda x: gr.update(visible=x),
inputs=use_vae,
outputs=vaemodel,
queue=False,
api_name=False,
)
use_lora.change(
fn=lambda x: [gr.update(visible=x), gr.update(visible=x)],
inputs=use_lora,
outputs=[lora, lora_scale],
queue=False,
api_name=False,
)
use_lora2.change(
fn=lambda x: [gr.update(visible=x), gr.update(visible=x), gr.update(visible=x), gr.update(visible=x)],
inputs=use_lora2,
outputs=[lora, lora2, lora_scale, lora_scale2],
queue=False,
api_name=False,
)
gr.on(
triggers=[
prompt.submit,
negative_prompt.submit,
run_button.click,
],
fn=randomize_seed_fn,
inputs=[seed, randomize_seed],
outputs=seed,
queue=False,
api_name=False,
).then(
fn=generate,
inputs=[
prompt,
negative_prompt,
use_negative_prompt,
seed,
width,
height,
guidance_scale_base,
num_inference_steps_base,
use_vae,
use_lora,
use_lora2,
model,
vaemodel,
lora,
lora2,
lora_scale,
lora_scale2,
],
outputs=result,
api_name="run",
)
if __name__ == "__main__":
demo.queue(max_size=20).launch()