import os import torch import gradio as gr from PIL import Image from diffusers import StableDiffusionPipeline, EulerAncestralDiscreteScheduler model_id = "Maseshi/Animistatics" auth_token = os.getenv("auth_token") device = "cuda" if torch.cuda.is_available() else "cpu" dtype = torch.half if torch.cuda.is_available() else torch.float # Assets unsafe_image = Image.open(r"unsafe.png") # Model pipeline = StableDiffusionPipeline.from_pretrained( model_id, torch_dtype=dtype, use_auth_token=auth_token ) pipeline.to(device) pipeline.unet.to(memory_format=torch.channels_last) pipeline.enable_vae_slicing() if device == "cuda": pipeline.enable_attention_slicing(1) pipeline.enable_xformers_memory_efficient_attention() pipeline.vae.enable_xformers_memory_efficient_attention() else: pipeline.enable_attention_slicing() pipeline.scheduler = EulerAncestralDiscreteScheduler.from_config(pipeline.scheduler.config) def infer(prompt, negative, samples, steps, guidance_scale, seed): prompt = str(prompt) negative = str(negative) samples = int(samples) steps = int(steps) guidance_scale = int(guidance_scale) seed = int(seed) seeds = [] gallery = [] generator = torch.Generator(device=device) if seed <= 0 or seed is None: for _ in range(samples): seed = generator.seed() seeds.append(seed) generator = generator.manual_seed(seed) pil = pipeline( prompt=prompt, negative_prompt=negative, generator=generator, num_images_per_prompt=samples, guidance_scale=guidance_scale, num_inference_steps=steps ) for i, image in enumerate(pil.images): if pil.nsfw_content_detected[i]: gallery.append(unsafe_image) else: gallery.append(image) return gallery # UI Setup with gr.Blocks( css=""" .gradio-container { font-family: 'IBM Plex Sans', sans-serif; } .gr-button { color: white; border-color: black; background: black; } input[type='range'] { accent-color: black; } .dark input[type='range'] { accent-color: #dfdfdf; } .container { max-width: 730px; margin: auto; padding-top: 1.5rem; } #gallery { min-height: 30rem; margin-bottom: 15px; margin-left: auto; margin-right: auto; border-bottom-right-radius: .5rem !important; border-bottom-left-radius: .5rem !important; } #gallery>div>.h-full { min-height: 20rem; } .animate-spin { animation: spin 1s linear infinite; } @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } #share-btn-container { display: flex; padding-left: 0.5rem !important; padding-right: 0.5rem !important; background-color: #000000; border: 1.5px solid #222222; justify-content: center; align-items: center; border-radius: 9999px !important; width: 13rem; margin-top: 10px; margin-left: auto; margin-right: auto; } #share-btn { all: initial; color: #ffffff; font-weight: 600; cursor: pointer; font-family: 'IBM Plex Sans', sans-serif; margin-left: 0.5rem !important; margin-left: 0.5rem !important; padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; right: 0; } #share-btn * { all: unset; } #share-btn-container div:nth-child(-n+2){ width: auto !important; min-height: 0px !important; } #share-btn-container .wrap { display: none !important; } """ ) as demo: gr.Markdown( """

Animistatics Demo

Animistatics is the latest text-to-image model from Maseshi. Access Animistatics Space here
For faster generation and API access you can try it at Google Colab.

""" ) with gr.Group(): with gr.Box(): with gr.Row(): with gr.Column(): prompt = gr.Textbox( label="Enter your prompt", show_label=False, placeholder="Enter your prompt" ).style( border=(True, False, True, True), rounded=(True, False, False, True), container=False, ) negative = gr.Textbox( label="Enter your negative prompt", show_label=False, placeholder="Enter a negative prompt" ).style( border=(True, False, True, True), rounded=(True, False, False, True), container=False, ) generate_button = gr.Button( "Generate image" ).style( margin=False, rounded=(False, True, True, False), full_width=True, ) gallery = gr.Gallery( label="Generated images", show_label=False ).style( grid=2, height="auto" ) with gr.Accordion( "Advanced settings", open=False ): with gr.Group(): with gr.Row(): samples = gr.Slider( label="Images", minimum=1, maximum=4, value=1, step=1 ) steps = gr.Slider( label="Steps", minimum=1, maximum=50, value=25, step=1 ) guidance_scale = gr.Slider( label="Guidance Scale", minimum=0, maximum=50, value=7, step=0.1 ) seed = gr.Slider( label="Seed", minimum=0, maximum=2147483647, step=1, randomize=True, ) with gr.Group(elem_id="share-btn-container"): community_icon = gr.HTML( """ """ ) loading_icon = gr.HTML( """ """ ) share_button = gr.Button( "Share to community", elem_id="share-btn" ) examples = gr.Examples( examples=[ [ 'girl, cafe, plants, coffee, lighting, steam, blue eyes, brown hair', 'low quality' ], [ 'boy, blonde hair, blue eyes, colorful, cumulonimbus clouds, lighting, medium hair, plants, city, hoodie, cool', 'low quality' ], [ 'cityscape, concept art, sun shining through clouds, crepuscular rays, trending on art station, 8k', 'low quality' ] ], inputs=[ prompt, negative ] ) prompt.submit( fn=infer, inputs=[ prompt, negative, samples, steps, guidance_scale, seed ], outputs=gallery ) negative.submit( fn=infer, inputs=[ prompt, negative, samples, steps, guidance_scale, seed ], outputs=gallery ) generate_button.click( fn=infer, inputs=[ prompt, negative, samples, steps, guidance_scale, seed ], outputs=gallery ) share_button.click( fn=None, inputs=[], outputs=[], _js=""" async () => { async function uploadFile(file){ const UPLOAD_URL = 'https://huggingface.co/uploads'; const response = await fetch(UPLOAD_URL, { method: 'POST', headers: { 'Content-Type': file.type, 'X-Requested-With': 'XMLHttpRequest', }, body: file, /// <- File inherits from Blob }); const url = await response.text(); return url; } const gradioEl = document.querySelector('body > gradio-app'); const imgEls = gradioEl.querySelectorAll('#gallery img'); const promptTxt = gradioEl.querySelector('#prompt-text-input input').value; const shareBtnEl = gradioEl.querySelector('#share-btn'); const shareIconEl = gradioEl.querySelector('#share-btn-share-icon'); const loadingIconEl = gradioEl.querySelector('#share-btn-loading-icon'); if(!imgEls.length){ return; }; shareBtnEl.style.pointerEvents = 'none'; shareIconEl.style.display = 'none'; loadingIconEl.style.removeProperty('display'); const files = await Promise.all( [...imgEls].map(async (imgEl) => { const res = await fetch(imgEl.src); const blob = await res.blob(); const imgId = Date.now() % 200; const fileName = `diffuse-the-rest-${{imgId}}.jpg`; return new File([blob], fileName, { type: 'image/jpeg' }); }) ); const urls = await Promise.all(files.map((f) => uploadFile(f))); const htmlImgs = urls.map(url => ``); const descriptionMd = `
${htmlImgs.join(`\n`)}
`; const params = new URLSearchParams({ title: promptTxt, description: descriptionMd, }); const paramsStr = params.toString(); window.open(`https://huggingface.co/spaces/stabilityai/stable-diffusion/discussions/new?${paramsStr}`, '_blank'); shareBtnEl.style.removeProperty('pointer-events'); shareIconEl.style.removeProperty('display'); loadingIconEl.style.display = 'none'; } """, ) examples.dataset.headers = [""] gr.Markdown( """
#### LICENSE The model is licensed with a CreativeML Open RAIL-M license. The authors claim no rights on the outputs you generate, you are free to use them and are accountable for their use which must not go against the provisions set in this license. The license forbids you from sharing any content that violates any laws, produce any harm to a person, disseminate any personal information that would be meant for harm, spread misinformation and target vulnerable groups. For the full list of restrictions please read the license #### Biases and content acknowledgment Despite how impressive being able to turn text into image is, beware to the fact that this model may output content that reinforces or exacerbates societal biases, as well as realistic faces, pornography and violence. The model was trained on the Anime dataset, which scraped non-curated image-text-pairs from the internet (the exception being the removal of illegal content) and is meant for research purposes. You can read more in the model card """ ) # Launch Gradio demo.queue( api_open=False, max_size=150 ) demo.launch( max_threads=150, show_api=False )