awacke1 commited on
Commit
6faa434
·
verified ·
1 Parent(s): 18c7cf7

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +351 -0
app.py ADDED
@@ -0,0 +1,351 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import random
7
+ import glob
8
+ from datetime import datetime
9
+
10
+ import gradio as gr
11
+ import numpy as np
12
+ import PIL.Image
13
+ import spaces
14
+ import torch
15
+ from diffusers import AutoencoderKL, DiffusionPipeline
16
+
17
+ DESCRIPTION = """
18
+ # OpenDalle 1.1 with Gallery
19
+
20
+ **Demo by [mrfakename](https://mrfake.name/) - [Twitter](https://twitter.com/realmrfakename) - [GitHub](https://github.com/fakerybakery/) - [Hugging Face](https://huggingface.co/mrfakename)**
21
+
22
+ This is a demo of <a href="https://huggingface.co/dataautogpt3/OpenDalleV1.1">OpenDalle V1.1</a> by @dataautogpt3.
23
+
24
+ It's a merge of several different models and is supposed to provide excellent performance. Try it out!
25
+
26
+ [Not Working?](https://huggingface.co/spaces/mrfakename/OpenDalleV1.1-GPU-Demo/discussions/4)
27
+
28
+ **The code for this demo is based on [@hysts's SD-XL demo](https://huggingface.co/spaces/hysts/SD-XL) running on a A10G GPU.**
29
+
30
+ **NOTE: The model is licensed under a non-commercial license**
31
+
32
+ Also see [OpenDalle Original Demo](https://huggingface.co/spaces/mrfakename/OpenDalle-GPU-Demo/)
33
+ """
34
+ if not torch.cuda.is_available():
35
+ DESCRIPTION += "\n<h1>Running on CPU 🥶 This demo does not work on CPU. Please use <a href=\"https://huggingface.co/spaces/mrfakename/OpenDalleV1.1-GPU-Demo\">the online demo</a> instead</h1>"
36
+
37
+ MAX_SEED = np.iinfo(np.int32).max
38
+ CACHE_EXAMPLES = torch.cuda.is_available() and os.getenv("CACHE_EXAMPLES", "0") == "1"
39
+ MAX_IMAGE_SIZE = int(os.getenv("MAX_IMAGE_SIZE", "1024"))
40
+ USE_TORCH_COMPILE = os.getenv("USE_TORCH_COMPILE") == "1"
41
+ ENABLE_CPU_OFFLOAD = os.getenv("ENABLE_CPU_OFFLOAD") == "1"
42
+ ENABLE_REFINER = os.getenv("ENABLE_REFINER", "0") == "1"
43
+
44
+ device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
45
+ if torch.cuda.is_available():
46
+ vae = AutoencoderKL.from_pretrained("madebyollin/sdxl-vae-fp16-fix", torch_dtype=torch.float16)
47
+ pipe = DiffusionPipeline.from_pretrained(
48
+ "dataautogpt3/OpenDalleV1.1",
49
+ vae=vae,
50
+ torch_dtype=torch.float16,
51
+ use_safetensors=True,
52
+ variant="fp16",
53
+ )
54
+ if ENABLE_REFINER:
55
+ refiner = DiffusionPipeline.from_pretrained(
56
+ "stabilityai/stable-diffusion-xl-refiner-1.0",
57
+ vae=vae,
58
+ torch_dtype=torch.float16,
59
+ use_safetensors=True,
60
+ variant="fp16",
61
+ )
62
+
63
+ if ENABLE_CPU_OFFLOAD:
64
+ pipe.enable_model_cpu_offload()
65
+ if ENABLE_REFINER:
66
+ refiner.enable_model_cpu_offload()
67
+ else:
68
+ pipe.to(device)
69
+ if ENABLE_REFINER:
70
+ refiner.to(device)
71
+
72
+ if USE_TORCH_COMPILE:
73
+ pipe.unet = torch.compile(pipe.unet, mode="reduce-overhead", fullgraph=True)
74
+ if ENABLE_REFINER:
75
+ refiner.unet = torch.compile(refiner.unet, mode="reduce-overhead", fullgraph=True)
76
+
77
+ def randomize_seed_fn(seed: int, randomize_seed: bool) -> int:
78
+ if randomize_seed:
79
+ seed = random.randint(0, MAX_SEED)
80
+ return seed
81
+
82
+ def save_image(image: PIL.Image.Image, prompt: str) -> str:
83
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
84
+ filename = f"{timestamp}_{prompt[:50]}.png" # Limit filename length
85
+ image.save(filename)
86
+ return filename
87
+
88
+ def get_image_gallery():
89
+ image_files = glob.glob("*.png")
90
+ image_files.sort(key=os.path.getmtime, reverse=True)
91
+ return image_files
92
+
93
+ @spaces.GPU(enable_queue=True)
94
+ def generate(
95
+ prompt: str,
96
+ negative_prompt: str = "",
97
+ prompt_2: str = "",
98
+ negative_prompt_2: str = "",
99
+ use_negative_prompt: bool = False,
100
+ use_prompt_2: bool = False,
101
+ use_negative_prompt_2: bool = False,
102
+ seed: int = 0,
103
+ width: int = 1024,
104
+ height: int = 1024,
105
+ guidance_scale_base: float = 5.0,
106
+ guidance_scale_refiner: float = 5.0,
107
+ num_inference_steps_base: int = 25,
108
+ num_inference_steps_refiner: int = 25,
109
+ apply_refiner: bool = False,
110
+ progress=gr.Progress(track_tqdm=True),
111
+ ) -> PIL.Image.Image:
112
+ print(f"** Generating image for: \"{prompt}\" **")
113
+ generator = torch.Generator().manual_seed(seed)
114
+
115
+ if not use_negative_prompt:
116
+ negative_prompt = None # type: ignore
117
+ if not use_prompt_2:
118
+ prompt_2 = None # type: ignore
119
+ if not use_negative_prompt_2:
120
+ negative_prompt_2 = None # type: ignore
121
+
122
+ if not apply_refiner:
123
+ image = pipe(
124
+ prompt=prompt,
125
+ negative_prompt=negative_prompt,
126
+ prompt_2=prompt_2,
127
+ negative_prompt_2=negative_prompt_2,
128
+ width=width,
129
+ height=height,
130
+ guidance_scale=guidance_scale_base,
131
+ num_inference_steps=num_inference_steps_base,
132
+ generator=generator,
133
+ output_type="pil",
134
+ ).images[0]
135
+ else:
136
+ latents = pipe(
137
+ prompt=prompt,
138
+ negative_prompt=negative_prompt,
139
+ prompt_2=prompt_2,
140
+ negative_prompt_2=negative_prompt_2,
141
+ width=width,
142
+ height=height,
143
+ guidance_scale=guidance_scale_base,
144
+ num_inference_steps=num_inference_steps_base,
145
+ generator=generator,
146
+ output_type="latent",
147
+ ).images
148
+ image = refiner(
149
+ prompt=prompt,
150
+ negative_prompt=negative_prompt,
151
+ prompt_2=prompt_2,
152
+ negative_prompt_2=negative_prompt_2,
153
+ guidance_scale=guidance_scale_refiner,
154
+ num_inference_steps=num_inference_steps_refiner,
155
+ image=latents,
156
+ generator=generator,
157
+ ).images[0]
158
+
159
+ save_image(image, prompt)
160
+ return image, get_image_gallery()
161
+
162
+ examples = [
163
+ f"{random.choice(['Impressionist', 'Cubist', 'Surrealist', 'Abstract Expressionist', 'Pop Art', 'Minimalist', 'Baroque', 'Art Nouveau', 'Pointillist', 'Fauvism'])} painting of a majestic lighthouse on a rocky coast. Use bold brushstrokes and a vibrant color palette to capture the interplay of light and shadow as the lighthouse beam cuts through a stormy night sky.",
164
+ f"{random.choice(['Impressionist', 'Cubist', 'Surrealist', 'Abstract Expressionist', 'Pop Art', 'Minimalist', 'Baroque', 'Art Nouveau', 'Pointillist', 'Fauvism'])} still life featuring a pair of vintage eyeglasses. Focus on the intricate details of the frames and lenses, using a warm color scheme to evoke a sense of nostalgia and wisdom.",
165
+ f"{random.choice(['Impressionist', 'Cubist', 'Surrealist', 'Abstract Expressionist', 'Pop Art', 'Minimalist', 'Baroque', 'Art Nouveau', 'Pointillist', 'Fauvism'])} depiction of a rustic wooden stool in a sunlit artist's studio. Emphasize the texture of the wood and the interplay of light and shadow, using a mix of earthy tones and highlights.",
166
+ f"{random.choice(['Impressionist', 'Cubist', 'Surrealist', 'Abstract Expressionist', 'Pop Art', 'Minimalist', 'Baroque', 'Art Nouveau', 'Pointillist', 'Fauvism'])} scene viewed through an ornate window frame. Contrast the intricate details of the window with a dreamy, soft-focus landscape beyond, using a palette that transitions from cool interior tones to warm exterior hues.",
167
+ f"{random.choice(['Impressionist', 'Cubist', 'Surrealist', 'Abstract Expressionist', 'Pop Art', 'Minimalist', 'Baroque', 'Art Nouveau', 'Pointillist', 'Fauvism'])} close-up study of interlaced fingers. Use a monochromatic color scheme to emphasize the form and texture of the hands, with dramatic lighting to create depth and emotion.",
168
+ f"{random.choice(['Impressionist', 'Cubist', 'Surrealist', 'Abstract Expressionist', 'Pop Art', 'Minimalist', 'Baroque', 'Art Nouveau', 'Pointillist', 'Fauvism'])} composition featuring a set of dice in motion. Capture the energy and randomness of the throw, using a dynamic color palette and blurred lines to convey movement.",
169
+ f"{random.choice(['Impressionist', 'Cubist', 'Surrealist', 'Abstract Expressionist', 'Pop Art', 'Minimalist', 'Baroque', 'Art Nouveau', 'Pointillist', 'Fauvism'])} interpretation of heaven. Create an ethereal atmosphere with soft, billowing clouds and radiant light, using a palette of celestial blues, golds, and whites.",
170
+ f"{random.choice(['Impressionist', 'Cubist', 'Surrealist', 'Abstract Expressionist', 'Pop Art', 'Minimalist', 'Baroque', 'Art Nouveau', 'Pointillist', 'Fauvism'])} portrayal of an ancient, mystical gate. Combine architectural details with elements of fantasy, using a rich, jewel-toned palette to create an air of mystery and magic.",
171
+ f"{random.choice(['Impressionist', 'Cubist', 'Surrealist', 'Abstract Expressionist', 'Pop Art', 'Minimalist', 'Baroque', 'Art Nouveau', 'Pointillist', 'Fauvism'])} portrait of a curious cat. Focus on capturing the feline's expressive eyes and sleek form, using a mix of bold and subtle colors to bring out the cat's personality.",
172
+ f"{random.choice(['Impressionist', 'Cubist', 'Surrealist', 'Abstract Expressionist', 'Pop Art', 'Minimalist', 'Baroque', 'Art Nouveau', 'Pointillist', 'Fauvism'])} abstract representation of toes in sand. Use textured brushstrokes to convey the feeling of warm sand, with a palette inspired by a sun-drenched beach.",
173
+ ]
174
+
175
+ theme = gr.themes.Base(
176
+ font=[gr.themes.GoogleFont('Libre Franklin'), gr.themes.GoogleFont('Public Sans'), 'system-ui', 'sans-serif'],
177
+ )
178
+ with gr.Blocks(css="footer{display:none !important}", theme=theme) as demo:
179
+ gr.Markdown(DESCRIPTION)
180
+ gr.DuplicateButton(
181
+ value="Duplicate Space for private use",
182
+ elem_id="duplicate-button",
183
+ visible=os.getenv("SHOW_DUPLICATE_BUTTON") == "1",
184
+ )
185
+ with gr.Group():
186
+ prompt = gr.Text(
187
+ label="Prompt",
188
+ show_label=False,
189
+ max_lines=1,
190
+ container=False,
191
+ placeholder="Enter your prompt",
192
+ )
193
+ run_button = gr.Button("Generate")
194
+ result = gr.Image(label="Result", show_label=False)
195
+ gallery = gr.Gallery(label="Generated Images", show_label=True, columns=4, height="auto")
196
+ with gr.Accordion("Advanced options", open=False):
197
+ with gr.Row():
198
+ use_negative_prompt = gr.Checkbox(label="Use negative prompt", value=False)
199
+ use_prompt_2 = gr.Checkbox(label="Use prompt 2", value=False)
200
+ use_negative_prompt_2 = gr.Checkbox(label="Use negative prompt 2", value=False)
201
+ negative_prompt = gr.Text(
202
+ label="Negative prompt",
203
+ max_lines=1,
204
+ placeholder="Enter a negative prompt",
205
+ visible=False,
206
+ )
207
+ prompt_2 = gr.Text(
208
+ label="Prompt 2",
209
+ max_lines=1,
210
+ placeholder="Enter your prompt",
211
+ visible=False,
212
+ )
213
+ negative_prompt_2 = gr.Text(
214
+ label="Negative prompt 2",
215
+ max_lines=1,
216
+ placeholder="Enter a negative prompt",
217
+ visible=False,
218
+ )
219
+
220
+ seed = gr.Slider(
221
+ label="Seed",
222
+ minimum=0,
223
+ maximum=MAX_SEED,
224
+ step=1,
225
+ value=0,
226
+ )
227
+ randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
228
+ with gr.Row():
229
+ width = gr.Slider(
230
+ label="Width",
231
+ minimum=256,
232
+ maximum=MAX_IMAGE_SIZE,
233
+ step=32,
234
+ value=1024,
235
+ )
236
+ height = gr.Slider(
237
+ label="Height",
238
+ minimum=256,
239
+ maximum=MAX_IMAGE_SIZE,
240
+ step=32,
241
+ value=1024,
242
+ )
243
+ apply_refiner = gr.Checkbox(label="Apply refiner", value=False, visible=ENABLE_REFINER)
244
+ with gr.Row():
245
+ guidance_scale_base = gr.Slider(
246
+ label="Guidance scale for base",
247
+ minimum=1,
248
+ maximum=20,
249
+ step=0.1,
250
+ value=5.0,
251
+ )
252
+ num_inference_steps_base = gr.Slider(
253
+ label="Number of inference steps for base",
254
+ minimum=10,
255
+ maximum=100,
256
+ step=1,
257
+ value=25,
258
+ )
259
+ with gr.Row(visible=False) as refiner_params:
260
+ guidance_scale_refiner = gr.Slider(
261
+ label="Guidance scale for refiner",
262
+ minimum=1,
263
+ maximum=20,
264
+ step=0.1,
265
+ value=5.0,
266
+ )
267
+ num_inference_steps_refiner = gr.Slider(
268
+ label="Number of inference steps for refiner",
269
+ minimum=10,
270
+ maximum=100,
271
+ step=1,
272
+ value=25,
273
+ )
274
+
275
+ gr.Examples(
276
+ examples=examples,
277
+ inputs=prompt,
278
+ outputs=[result, gallery],
279
+ fn=generate,
280
+ cache_examples=CACHE_EXAMPLES,
281
+ )
282
+
283
+ use_negative_prompt.change(
284
+ fn=lambda x: gr.update(visible=x),
285
+ inputs=use_negative_prompt,
286
+ outputs=negative_prompt,
287
+ queue=False,
288
+ api_name=False,
289
+ )
290
+ use_prompt_2.change(
291
+ fn=lambda x: gr.update(visible=x),
292
+ inputs=use_prompt_2,
293
+ outputs=prompt_2,
294
+ queue=False,
295
+ api_name=False,
296
+ )
297
+ use_negative_prompt_2.change(
298
+ fn=lambda x: gr.update(visible=x),
299
+ inputs=use_negative_prompt_2,
300
+ outputs=negative_prompt_2,
301
+ queue=False,
302
+ api_name=False,
303
+ )
304
+ apply_refiner.change(
305
+ fn=lambda x: gr.update(visible=x),
306
+ inputs=apply_refiner,
307
+ outputs=refiner_params,
308
+ queue=False,
309
+ api_name=False,
310
+ )
311
+
312
+ gr.on(
313
+ triggers=[
314
+ prompt.submit,
315
+ negative_prompt.submit,
316
+ prompt_2.submit,
317
+ negative_prompt_2.submit,
318
+ run_button.click,
319
+ ],
320
+ fn=randomize_seed_fn,
321
+ inputs=[seed, randomize_seed],
322
+ outputs=seed,
323
+ queue=False,
324
+ api_name=False,
325
+ ).then(
326
+ fn=generate,
327
+ inputs=[
328
+ prompt,
329
+ negative_prompt,
330
+ prompt_2,
331
+ negative_prompt_2,
332
+ use_negative_prompt,
333
+ use_prompt_2,
334
+ use_negative_prompt_2,
335
+ seed,
336
+ width,
337
+ height,
338
+ guidance_scale_base,
339
+ guidance_scale_refiner,
340
+ num_inference_steps_base,
341
+ num_inference_steps_refiner,
342
+ apply_refiner,
343
+ ],
344
+ outputs=[result, gallery],
345
+ api_name="run",
346
+ )
347
+
348
+ demo.load(fn=get_image_gallery, outputs=gallery)
349
+
350
+ if __name__ == "__main__":
351
+ demo.queue(max_size=20, api_open=False).launch(show_api=False)