Cagliostro commited on
Commit
e0b1273
·
1 Parent(s): 2f5948c

Upload 12 files

Browse files
Files changed (12) hide show
  1. LICENSE +21 -0
  2. README.md +10 -5
  3. app.py +399 -0
  4. config.py +111 -0
  5. demo.ipynb +93 -0
  6. requirements.txt +10 -0
  7. style.css +63 -0
  8. utils.py +179 -0
  9. wildcard/artist30.txt +2139 -0
  10. wildcard/artist31.txt +3697 -0
  11. wildcard/character30.txt +0 -0
  12. wildcard/character31.txt +2111 -0
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2023 hysts
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README.md CHANGED
@@ -1,12 +1,17 @@
1
  ---
2
- title: Animagine Xl 3.1
3
- emoji: 📊
4
- colorFrom: purple
5
- colorTo: blue
6
  sdk: gradio
7
- sdk_version: 4.21.0
8
  app_file: app.py
 
9
  pinned: false
 
 
10
  ---
11
 
12
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
1
  ---
2
+ title: Animagine XL 3.1
3
+ emoji: 🌍
4
+ colorFrom: gray
5
+ colorTo: purple
6
  sdk: gradio
7
+ sdk_version: 4.20.0
8
  app_file: app.py
9
+ license: mit
10
  pinned: false
11
+ suggested_hardware: a10g-small
12
+ short_description: The most opinionated, anime-themed SDXL model
13
  ---
14
 
15
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
16
+
17
+ https://arxiv.org/abs/2307.01952
app.py ADDED
@@ -0,0 +1,399 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gc
3
+ import gradio as gr
4
+ import numpy as np
5
+ import torch
6
+ import json
7
+ import spaces
8
+ import config
9
+ import utils
10
+ import logging
11
+ from PIL import Image, PngImagePlugin
12
+ from datetime import datetime
13
+ from diffusers.models import AutoencoderKL
14
+ from diffusers import (
15
+ StableDiffusionXLPipeline,
16
+ StableDiffusionXLImg2ImgPipeline
17
+ )
18
+
19
+ logging.basicConfig(level=logging.INFO)
20
+ logger = logging.getLogger(__name__)
21
+
22
+ DESCRIPTION = "Animagine XL 3.1"
23
+ if not torch.cuda.is_available():
24
+ DESCRIPTION += "\n<p>Running on CPU 🥶 This demo does not work on CPU. </p>"
25
+ IS_COLAB = utils.is_google_colab() or os.getenv("IS_COLAB") == "1"
26
+ HF_TOKEN = os.getenv("HF_TOKEN")
27
+ CACHE_EXAMPLES = torch.cuda.is_available() and os.getenv("CACHE_EXAMPLES") == "1"
28
+ MIN_IMAGE_SIZE = int(os.getenv("MIN_IMAGE_SIZE", "512"))
29
+ MAX_IMAGE_SIZE = int(os.getenv("MAX_IMAGE_SIZE", "2048"))
30
+ USE_TORCH_COMPILE = os.getenv("USE_TORCH_COMPILE") == "1"
31
+ ENABLE_CPU_OFFLOAD = os.getenv("ENABLE_CPU_OFFLOAD") == "1"
32
+ OUTPUT_DIR = os.getenv("OUTPUT_DIR", "./outputs")
33
+
34
+ MODEL = os.getenv("MODEL", "cagliostrolab/animagine-xl-3.1")
35
+
36
+ torch.backends.cudnn.deterministic = True
37
+ torch.backends.cudnn.benchmark = False
38
+
39
+ device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
40
+
41
+
42
+ def load_pipeline(model_name):
43
+ vae = AutoencoderKL.from_pretrained(
44
+ "madebyollin/sdxl-vae-fp16-fix",
45
+ torch_dtype=torch.float16,
46
+ )
47
+ pipeline = (
48
+ StableDiffusionXLPipeline.from_single_file
49
+ if MODEL.endswith(".safetensors")
50
+ else StableDiffusionXLPipeline.from_pretrained
51
+ )
52
+
53
+ pipe = pipeline(
54
+ model_name,
55
+ vae=vae,
56
+ torch_dtype=torch.float16,
57
+ custom_pipeline="lpw_stable_diffusion_xl",
58
+ use_safetensors=True,
59
+ add_watermarker=False,
60
+ use_auth_token=HF_TOKEN,
61
+ variant="fp16",
62
+ )
63
+
64
+ pipe.to(device)
65
+ return pipe
66
+
67
+
68
+ @spaces.GPU
69
+ def generate(
70
+ prompt: str,
71
+ negative_prompt: str = "",
72
+ seed: int = 0,
73
+ custom_width: int = 1024,
74
+ custom_height: int = 1024,
75
+ guidance_scale: float = 7.0,
76
+ num_inference_steps: int = 28,
77
+ sampler: str = "Euler a",
78
+ aspect_ratio_selector: str = "896 x 1152",
79
+ style_selector: str = "(None)",
80
+ quality_selector: str = "Standard v3.1",
81
+ use_upscaler: bool = False,
82
+ upscaler_strength: float = 0.5,
83
+ upscale_by: float = 1.5,
84
+ add_quality_tags: bool = True,
85
+ progress=gr.Progress(track_tqdm=True),
86
+ ) -> Image:
87
+ generator = utils.seed_everything(seed)
88
+
89
+ width, height = utils.aspect_ratio_handler(
90
+ aspect_ratio_selector,
91
+ custom_width,
92
+ custom_height,
93
+ )
94
+
95
+ prompt = utils.add_wildcard(prompt, wildcard_files)
96
+
97
+ prompt, negative_prompt = utils.preprocess_prompt(
98
+ quality_prompt, quality_selector, prompt, negative_prompt, add_quality_tags
99
+ )
100
+ prompt, negative_prompt = utils.preprocess_prompt(
101
+ styles, style_selector, prompt, negative_prompt
102
+ )
103
+
104
+ width, height = utils.preprocess_image_dimensions(width, height)
105
+
106
+ backup_scheduler = pipe.scheduler
107
+ pipe.scheduler = utils.get_scheduler(pipe.scheduler.config, sampler)
108
+
109
+ if use_upscaler:
110
+ upscaler_pipe = StableDiffusionXLImg2ImgPipeline(**pipe.components)
111
+ metadata = {
112
+ "prompt": prompt,
113
+ "negative_prompt": negative_prompt,
114
+ "resolution": f"{width} x {height}",
115
+ "guidance_scale": guidance_scale,
116
+ "num_inference_steps": num_inference_steps,
117
+ "seed": seed,
118
+ "sampler": sampler,
119
+ "sdxl_style": style_selector,
120
+ "add_quality_tags": add_quality_tags,
121
+ "quality_tags": quality_selector,
122
+ }
123
+
124
+ if use_upscaler:
125
+ new_width = int(width * upscale_by)
126
+ new_height = int(height * upscale_by)
127
+ metadata["use_upscaler"] = {
128
+ "upscale_method": "nearest-exact",
129
+ "upscaler_strength": upscaler_strength,
130
+ "upscale_by": upscale_by,
131
+ "new_resolution": f"{new_width} x {new_height}",
132
+ }
133
+ else:
134
+ metadata["use_upscaler"] = None
135
+ logger.info(json.dumps(metadata, indent=4))
136
+
137
+ try:
138
+ if use_upscaler:
139
+ latents = pipe(
140
+ prompt=prompt,
141
+ negative_prompt=negative_prompt,
142
+ width=width,
143
+ height=height,
144
+ guidance_scale=guidance_scale,
145
+ num_inference_steps=num_inference_steps,
146
+ generator=generator,
147
+ output_type="latent",
148
+ ).images
149
+ upscaled_latents = utils.upscale(latents, "nearest-exact", upscale_by)
150
+ image = upscaler_pipe(
151
+ prompt=prompt,
152
+ negative_prompt=negative_prompt,
153
+ image=upscaled_latents,
154
+ guidance_scale=guidance_scale,
155
+ num_inference_steps=num_inference_steps,
156
+ strength=upscaler_strength,
157
+ generator=generator,
158
+ output_type="pil",
159
+ ).images[0]
160
+ else:
161
+ image = pipe(
162
+ prompt=prompt,
163
+ negative_prompt=negative_prompt,
164
+ width=width,
165
+ height=height,
166
+ guidance_scale=guidance_scale,
167
+ num_inference_steps=num_inference_steps,
168
+ generator=generator,
169
+ output_type="pil",
170
+ ).images[0]
171
+
172
+ if image and IS_COLAB:
173
+ filepath = utils.save_image(image, metadata, OUTPUT_DIR)
174
+ logger.info(f"Image saved as {filepath} with metadata")
175
+
176
+ return image, metadata
177
+ except Exception as e:
178
+ logger.exception(f"An error occurred: {e}")
179
+ raise
180
+ finally:
181
+ if use_upscaler:
182
+ del upscaler_pipe
183
+ pipe.scheduler = backup_scheduler
184
+ utils.free_memory()
185
+
186
+
187
+ if torch.cuda.is_available():
188
+ pipe = load_pipeline(MODEL)
189
+ logger.info("Loaded on Device!")
190
+ else:
191
+ pipe = None
192
+
193
+ styles = {k["name"]: (k["prompt"], k["negative_prompt"]) for k in config.style_list}
194
+ quality_prompt = {
195
+ k["name"]: (k["prompt"], k["negative_prompt"]) for k in config.quality_prompt_list
196
+ }
197
+
198
+ wildcard_files = utils.load_wildcard_files("wildcard")
199
+
200
+ with gr.Blocks(css="style.css", theme="NoCrypt/miku@1.2.1") as demo:
201
+ title = gr.HTML(
202
+ f"""<h1><span>{DESCRIPTION}</span></h1>""",
203
+ elem_id="title",
204
+ )
205
+ gr.Markdown(
206
+ f"""Gradio demo for [cagliostrolab/animagine-xl-3.1](https://huggingface.co/cagliostrolab/animagine-xl-3.1)""",
207
+ elem_id="subtitle",
208
+ )
209
+ gr.DuplicateButton(
210
+ value="Duplicate Space for private use",
211
+ elem_id="duplicate-button",
212
+ visible=os.getenv("SHOW_DUPLICATE_BUTTON") == "1",
213
+ )
214
+ with gr.Row():
215
+ with gr.Column(scale=2):
216
+ with gr.Tab("Txt2img"):
217
+ with gr.Group():
218
+ prompt = gr.Text(
219
+ label="Prompt",
220
+ max_lines=5,
221
+ placeholder="Enter your prompt",
222
+ )
223
+ negative_prompt = gr.Text(
224
+ label="Negative Prompt",
225
+ max_lines=5,
226
+ placeholder="Enter a negative prompt",
227
+ )
228
+ with gr.Accordion(label="Quality Tags", open=True):
229
+ add_quality_tags = gr.Checkbox(
230
+ label="Add Quality Tags", value=True
231
+ )
232
+ quality_selector = gr.Dropdown(
233
+ label="Quality Tags Presets",
234
+ interactive=True,
235
+ choices=list(quality_prompt.keys()),
236
+ value="Standard v3.1",
237
+ )
238
+ with gr.Tab("Advanced Settings"):
239
+ with gr.Group():
240
+ style_selector = gr.Radio(
241
+ label="Style Preset",
242
+ container=True,
243
+ interactive=True,
244
+ choices=list(styles.keys()),
245
+ value="(None)",
246
+ )
247
+ with gr.Group():
248
+ aspect_ratio_selector = gr.Radio(
249
+ label="Aspect Ratio",
250
+ choices=config.aspect_ratios,
251
+ value="896 x 1152",
252
+ container=True,
253
+ )
254
+ with gr.Group():
255
+ use_upscaler = gr.Checkbox(label="Use Upscaler", value=False)
256
+ with gr.Row() as upscaler_row:
257
+ upscaler_strength = gr.Slider(
258
+ label="Strength",
259
+ minimum=0,
260
+ maximum=1,
261
+ step=0.05,
262
+ value=0.55,
263
+ visible=False,
264
+ )
265
+ upscale_by = gr.Slider(
266
+ label="Upscale by",
267
+ minimum=1,
268
+ maximum=1.5,
269
+ step=0.1,
270
+ value=1.5,
271
+ visible=False,
272
+ )
273
+ with gr.Group(visible=False) as custom_resolution:
274
+ with gr.Row():
275
+ custom_width = gr.Slider(
276
+ label="Width",
277
+ minimum=MIN_IMAGE_SIZE,
278
+ maximum=MAX_IMAGE_SIZE,
279
+ step=8,
280
+ value=1024,
281
+ )
282
+ custom_height = gr.Slider(
283
+ label="Height",
284
+ minimum=MIN_IMAGE_SIZE,
285
+ maximum=MAX_IMAGE_SIZE,
286
+ step=8,
287
+ value=1024,
288
+ )
289
+ with gr.Group():
290
+ sampler = gr.Dropdown(
291
+ label="Sampler",
292
+ choices=config.sampler_list,
293
+ interactive=True,
294
+ value="Euler a",
295
+ )
296
+ with gr.Group():
297
+ seed = gr.Slider(
298
+ label="Seed", minimum=0, maximum=utils.MAX_SEED, step=1, value=0
299
+ )
300
+ randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
301
+ with gr.Group():
302
+ with gr.Row():
303
+ guidance_scale = gr.Slider(
304
+ label="Guidance scale",
305
+ minimum=1,
306
+ maximum=12,
307
+ step=0.1,
308
+ value=7.0,
309
+ )
310
+ num_inference_steps = gr.Slider(
311
+ label="Number of inference steps",
312
+ minimum=1,
313
+ maximum=50,
314
+ step=1,
315
+ value=28,
316
+ )
317
+ with gr.Column(scale=3):
318
+ with gr.Blocks():
319
+ run_button = gr.Button("Generate", variant="primary")
320
+ result = gr.Image(label="Result", show_label=False)
321
+ with gr.Accordion(label="Generation Parameters", open=False):
322
+ gr_metadata = gr.JSON(label="Metadata", show_label=False)
323
+ gr.Examples(
324
+ examples=config.examples,
325
+ inputs=prompt,
326
+ outputs=[result, gr_metadata],
327
+ fn=lambda *args, **kwargs: generate(*args, use_upscaler=True, **kwargs),
328
+ cache_examples=CACHE_EXAMPLES,
329
+ )
330
+ use_upscaler.change(
331
+ fn=lambda x: [gr.update(visible=x), gr.update(visible=x)],
332
+ inputs=use_upscaler,
333
+ outputs=[upscaler_strength, upscale_by],
334
+ queue=False,
335
+ api_name=False,
336
+ )
337
+ aspect_ratio_selector.change(
338
+ fn=lambda x: gr.update(visible=x == "Custom"),
339
+ inputs=aspect_ratio_selector,
340
+ outputs=custom_resolution,
341
+ queue=False,
342
+ api_name=False,
343
+ )
344
+
345
+ inputs = [
346
+ prompt,
347
+ negative_prompt,
348
+ seed,
349
+ custom_width,
350
+ custom_height,
351
+ guidance_scale,
352
+ num_inference_steps,
353
+ sampler,
354
+ aspect_ratio_selector,
355
+ style_selector,
356
+ quality_selector,
357
+ use_upscaler,
358
+ upscaler_strength,
359
+ upscale_by,
360
+ add_quality_tags,
361
+ ]
362
+
363
+ prompt.submit(
364
+ fn=utils.randomize_seed_fn,
365
+ inputs=[seed, randomize_seed],
366
+ outputs=seed,
367
+ queue=False,
368
+ api_name=False,
369
+ ).then(
370
+ fn=generate,
371
+ inputs=inputs,
372
+ outputs=result,
373
+ api_name="run",
374
+ )
375
+ negative_prompt.submit(
376
+ fn=utils.randomize_seed_fn,
377
+ inputs=[seed, randomize_seed],
378
+ outputs=seed,
379
+ queue=False,
380
+ api_name=False,
381
+ ).then(
382
+ fn=generate,
383
+ inputs=inputs,
384
+ outputs=result,
385
+ api_name=False,
386
+ )
387
+ run_button.click(
388
+ fn=utils.randomize_seed_fn,
389
+ inputs=[seed, randomize_seed],
390
+ outputs=seed,
391
+ queue=False,
392
+ api_name=False,
393
+ ).then(
394
+ fn=generate,
395
+ inputs=inputs,
396
+ outputs=[result, gr_metadata],
397
+ api_name=False,
398
+ )
399
+ demo.queue(max_size=20).launch(debug=IS_COLAB, share=IS_COLAB)
config.py ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ examples = [
2
+ "1girl, souryuu asuka langley, neon genesis evangelion, plugsuit, pilot suit, red bodysuit, sitting, crossing legs, black eye patch, cat hat, throne, symmetrical, looking down, from bottom, looking at viewer, outdoors",
3
+ "1boy, male focus, yuuki makoto \(persona 3\), persona 3, black jacket, white shirt, long sleeves, closed mouth, glowing eyes, gun, hair over one eye, holding gun, handgun, looking at viewer, solo, upper body",
4
+ "1girl, makima \(chainsaw man\), chainsaw man, black jacket, black necktie, black pants, braid, business suit, fingernails, formal, hand on own chin, jacket on shoulders, light smile, long sleeves, looking at viewer, looking up, medium breasts, office lady, smile, solo, suit, upper body, white shirt, outdoors",
5
+ "1boy, male focus, gojou satoru, jujutsu kaisen, black jacket, blindfold lift, blue eyes, glowing, glowing eyes, high collar, jacket, jujutsu tech uniform, solo, grin, white hair",
6
+ "1girl, cagliostro, granblue fantasy, violet eyes, standing, hand on own chin, looking at object, smile, closed mouth, table, beaker, glass tube, experiment apparatus, dark room, laboratory",
7
+ "kimi no na wa., building, cityscape, cloud, cloudy sky, gradient sky, lens flare, no humans, outdoors, power lines, scenery, shooting star, sky, sparkle, star \(sky\), starry sky, sunset, tree, utility pole",
8
+ ]
9
+
10
+ quality_prompt_list = [
11
+ {
12
+ "name": "(None)",
13
+ "prompt": "{prompt}",
14
+ "negative_prompt": "nsfw, lowres",
15
+ },
16
+ {
17
+ "name": "Standard v3.0",
18
+ "prompt": "{prompt}, masterpiece, best quality",
19
+ "negative_prompt": "nsfw, lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry, artist name",
20
+ },
21
+ {
22
+ "name": "Standard v3.1",
23
+ "prompt": "{prompt}, masterpiece, best quality, very aesthetic, absurdres",
24
+ "negative_prompt": "nsfw, lowres, (bad), text, error, fewer, extra, missing, worst quality, jpeg artifacts, low quality, watermark, unfinished, displeasing, oldest, early, chromatic aberration, signature, extra digits, artistic error, username, scan, [abstract]",
25
+ },
26
+ {
27
+ "name": "Light v3.1",
28
+ "prompt": "{prompt}, (masterpiece), best quality, very aesthetic, perfect face",
29
+ "negative_prompt": "nsfw, (low quality, worst quality:1.2), very displeasing, 3d, watermark, signature, ugly, poorly drawn",
30
+ },
31
+ {
32
+ "name": "Heavy v3.1",
33
+ "prompt": "{prompt}, (masterpiece), (best quality), (ultra-detailed), very aesthetic, illustration, disheveled hair, perfect composition, moist skin, intricate details",
34
+ "negative_prompt": "nsfw, longbody, lowres, bad anatomy, bad hands, missing fingers, pubic hair, extra digit, fewer digits, cropped, worst quality, low quality, very displeasing",
35
+ },
36
+ ]
37
+
38
+ sampler_list = [
39
+ "DPM++ 2M Karras",
40
+ "DPM++ SDE Karras",
41
+ "DPM++ 2M SDE Karras",
42
+ "Euler",
43
+ "Euler a",
44
+ "DDIM",
45
+ ]
46
+
47
+ aspect_ratios = [
48
+ "1024 x 1024",
49
+ "1152 x 896",
50
+ "896 x 1152",
51
+ "1216 x 832",
52
+ "832 x 1216",
53
+ "1344 x 768",
54
+ "768 x 1344",
55
+ "1536 x 640",
56
+ "640 x 1536",
57
+ "Custom",
58
+ ]
59
+
60
+ style_list = [
61
+ {
62
+ "name": "(None)",
63
+ "prompt": "{prompt}",
64
+ "negative_prompt": "",
65
+ },
66
+ {
67
+ "name": "Cinematic",
68
+ "prompt": "{prompt}, cinematic still, emotional, harmonious, vignette, highly detailed, high budget, bokeh, cinemascope, moody, epic, gorgeous, film grain, grainy",
69
+ "negative_prompt": "nsfw, cartoon, graphic, text, painting, crayon, graphite, abstract, glitch, deformed, mutated, ugly, disfigured",
70
+ },
71
+ {
72
+ "name": "Photographic",
73
+ "prompt": "{prompt}, cinematic photo, 35mm photograph, film, bokeh, professional, 4k, highly detailed",
74
+ "negative_prompt": "nsfw, drawing, painting, crayon, sketch, graphite, impressionist, noisy, blurry, soft, deformed, ugly",
75
+ },
76
+ {
77
+ "name": "Anime",
78
+ "prompt": "{prompt}, anime artwork, anime style, key visual, vibrant, studio anime, highly detailed",
79
+ "negative_prompt": "nsfw, photo, deformed, black and white, realism, disfigured, low contrast",
80
+ },
81
+ {
82
+ "name": "Manga",
83
+ "prompt": "{prompt}, manga style, vibrant, high-energy, detailed, iconic, Japanese comic style",
84
+ "negative_prompt": "nsfw, ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, Western comic style",
85
+ },
86
+ {
87
+ "name": "Digital Art",
88
+ "prompt": "{prompt}, concept art, digital artwork, illustrative, painterly, matte painting, highly detailed",
89
+ "negative_prompt": "nsfw, photo, photorealistic, realism, ugly",
90
+ },
91
+ {
92
+ "name": "Pixel art",
93
+ "prompt": "{prompt}, pixel-art, low-res, blocky, pixel art style, 8-bit graphics",
94
+ "negative_prompt": "nsfw, sloppy, messy, blurry, noisy, highly detailed, ultra textured, photo, realistic",
95
+ },
96
+ {
97
+ "name": "Fantasy art",
98
+ "prompt": "{prompt}, ethereal fantasy concept art, magnificent, celestial, ethereal, painterly, epic, majestic, magical, fantasy art, cover art, dreamy",
99
+ "negative_prompt": "nsfw, photographic, realistic, realism, 35mm film, dslr, cropped, frame, text, deformed, glitch, noise, noisy, off-center, deformed, cross-eyed, closed eyes, bad anatomy, ugly, disfigured, sloppy, duplicate, mutated, black and white",
100
+ },
101
+ {
102
+ "name": "Neonpunk",
103
+ "prompt": "{prompt}, neonpunk style, cyberpunk, vaporwave, neon, vibes, vibrant, stunningly beautiful, crisp, detailed, sleek, ultramodern, magenta highlights, dark purple shadows, high contrast, cinematic, ultra detailed, intricate, professional",
104
+ "negative_prompt": "nsfw, painting, drawing, illustration, glitch, deformed, mutated, cross-eyed, ugly, disfigured",
105
+ },
106
+ {
107
+ "name": "3D Model",
108
+ "prompt": "{prompt}, professional 3d model, octane render, highly detailed, volumetric, dramatic lighting",
109
+ "negative_prompt": "nsfw, ugly, deformed, noisy, low poly, blurry, painting",
110
+ },
111
+ ]
demo.ipynb ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "id": "538a3f0c-50c1-4952-9fcc-070d365c9a0f",
7
+ "metadata": {
8
+ "scrolled": true
9
+ },
10
+ "outputs": [],
11
+ "source": [
12
+ "import os\n",
13
+ "import subprocess\n",
14
+ "from threading import Timer\n",
15
+ "from queue import Queue\n",
16
+ "\n",
17
+ "ROOT_DIR = \"/content\"\n",
18
+ "REPO_URL = \"https://huggingface.co/spaces/Linaqruf/animagine-xl\"\n",
19
+ "REPO_DIR = os.path.join(ROOT_DIR, \"cagliostro-webui\")\n",
20
+ "NGROK_TOKEN = \"\"\n",
21
+ "\n",
22
+ "os.environ[\"HF_TOKEN\"] = \"\"\n",
23
+ "os.environ[\"IS_COLAB\"] = \"1\"\n",
24
+ "os.environ[\"MODEL\"] = \"https://huggingface.co/cagliostrolab/animagine-xl-3.0/blob/main/animagine-xl-3.0.safetensors\"\n",
25
+ "os.environ[\"CACHE_EXAMPLES\"] = \"1\"\n",
26
+ "\n",
27
+ "def clone(url, dir, branch=None):\n",
28
+ " subprocess.run([\"git\", \"clone\", url, dir], check=True)\n",
29
+ " if branch:\n",
30
+ " subprocess.run([\"git\", \"checkout\", branch], cwd=dir, check=True)\n",
31
+ "\n",
32
+ "def install_deps(dir):\n",
33
+ " subprocess.run([\"pip\", \"install\", \"-r\", \"requirements.txt\"], cwd=dir, check=True)\n",
34
+ "\n",
35
+ "def ngrok_tunnel(port,queue,auth_token):\n",
36
+ " ngrok.set_auth_token(auth_token)\n",
37
+ " url = ngrok.connect(port)\n",
38
+ " queue.put(url)\n",
39
+ "\n",
40
+ "def main():\n",
41
+ " if not os.path.exists(REPO_DIR):\n",
42
+ " print(f\"Cloning Repository to {REPO_DIR}\")\n",
43
+ " clone(REPO_URL, REPO_DIR)\n",
44
+ " print(f\"Installing required python libraries\")\n",
45
+ " install_deps(REPO_DIR)\n",
46
+ " print(\"Done!\")\n",
47
+ "\n",
48
+ " os.chdir(REPO_DIR)\n",
49
+ " \n",
50
+ " if NGROK_TOKEN:\n",
51
+ " try:\n",
52
+ " from pyngrok import conf,ngrok\n",
53
+ " except:\n",
54
+ " !pip install -qqqq --upgrade setuptools\n",
55
+ " !pip install -qqqq -U pyngrok\n",
56
+ " from pyngrok import conf,ngrok\n",
57
+ " \n",
58
+ " ngrok_output_queue = Queue()\n",
59
+ " ngrok_thread = Timer(2, ngrok_tunnel, args=(7860, ngrok_output_queue, NGROK_TOKEN))\n",
60
+ " ngrok_thread.start()\n",
61
+ " ngrok_thread.join()\n",
62
+ " \n",
63
+ " print(ngrok_output_queue.get()) \n",
64
+ " \n",
65
+ " !python app.py\n",
66
+ "\n",
67
+ "if __name__ == \"__main__\":\n",
68
+ " main()"
69
+ ]
70
+ }
71
+ ],
72
+ "metadata": {
73
+ "kernelspec": {
74
+ "display_name": "Python 3 (ipykernel)",
75
+ "language": "python",
76
+ "name": "python3"
77
+ },
78
+ "language_info": {
79
+ "codemirror_mode": {
80
+ "name": "ipython",
81
+ "version": 3
82
+ },
83
+ "file_extension": ".py",
84
+ "mimetype": "text/x-python",
85
+ "name": "python",
86
+ "nbconvert_exporter": "python",
87
+ "pygments_lexer": "ipython3",
88
+ "version": "3.10.12"
89
+ }
90
+ },
91
+ "nbformat": 4,
92
+ "nbformat_minor": 5
93
+ }
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ accelerate==0.27.2
2
+ diffusers==0.26.3
3
+ gradio==4.20.0
4
+ invisible-watermark==0.2.0
5
+ Pillow==10.2.0
6
+ spaces==0.24.0
7
+ torch==2.0.1
8
+ transformers==4.38.1
9
+ omegaconf==2.3.0
10
+ timm==0.9.10
style.css ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root {
2
+ --title-font-size: clamp(1.5rem, 6vw, 3rem);
3
+ --subtitle-font-size: clamp(1rem, 2vw, 1.2rem);
4
+ }
5
+
6
+ h1 {
7
+ text-align: center;
8
+ font-size: var(--title-font-size);
9
+ display: block;
10
+ }
11
+
12
+ h2 {
13
+ text-align: center;
14
+ font-size: 2rem;
15
+ display: block;
16
+ }
17
+
18
+ #duplicate-button {
19
+ display: block;
20
+ margin: 1rem auto;
21
+ color: #fff;
22
+ background: #1565c0;
23
+ border-radius: 100vh;
24
+ padding: 0.5rem 1rem;
25
+ }
26
+
27
+ #component-0 {
28
+ max-width: 85%;
29
+ margin: 2rem auto;
30
+ padding: 2rem;
31
+ }
32
+
33
+ @media (max-width: 600px) {
34
+ #component-0 {
35
+ max-width: 100%;
36
+ padding: 0.5rem;
37
+ }
38
+ }
39
+
40
+ #title-container {
41
+ text-align: center;
42
+ padding: 2rem 0;
43
+ }
44
+
45
+ #title {
46
+ font-size: var(--title-font-size);
47
+ color: #333;
48
+ font-family: 'Helvetica Neue', sans-serif;
49
+ text-transform: uppercase;
50
+ background: transparent;
51
+ }
52
+
53
+ #title span {
54
+ background: linear-gradient(45deg, #4EACEF, #28b485);
55
+ background-clip: text;
56
+ color: transparent;
57
+ }
58
+
59
+ #subtitle {
60
+ text-align: center;
61
+ font-size: var(--subtitle-font-size);
62
+ margin-top: 1rem;
63
+ }
utils.py ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gc
2
+ import os
3
+ import random
4
+ import numpy as np
5
+ import json
6
+ import torch
7
+ from PIL import Image, PngImagePlugin
8
+ from datetime import datetime
9
+ from dataclasses import dataclass
10
+ from typing import Callable, Dict, Optional, Tuple
11
+ from diffusers import (
12
+ DDIMScheduler,
13
+ DPMSolverMultistepScheduler,
14
+ DPMSolverSinglestepScheduler,
15
+ EulerAncestralDiscreteScheduler,
16
+ EulerDiscreteScheduler,
17
+ )
18
+
19
+ MAX_SEED = np.iinfo(np.int32).max
20
+
21
+
22
+ @dataclass
23
+ class StyleConfig:
24
+ prompt: str
25
+ negative_prompt: str
26
+
27
+
28
+ def randomize_seed_fn(seed: int, randomize_seed: bool) -> int:
29
+ if randomize_seed:
30
+ seed = random.randint(0, MAX_SEED)
31
+ return seed
32
+
33
+
34
+ def seed_everything(seed: int) -> torch.Generator:
35
+ torch.manual_seed(seed)
36
+ torch.cuda.manual_seed_all(seed)
37
+ np.random.seed(seed)
38
+ generator = torch.Generator()
39
+ generator.manual_seed(seed)
40
+ return generator
41
+
42
+
43
+ def parse_aspect_ratio(aspect_ratio: str) -> Optional[Tuple[int, int]]:
44
+ if aspect_ratio == "Custom":
45
+ return None
46
+ width, height = aspect_ratio.split(" x ")
47
+ return int(width), int(height)
48
+
49
+
50
+ def aspect_ratio_handler(
51
+ aspect_ratio: str, custom_width: int, custom_height: int
52
+ ) -> Tuple[int, int]:
53
+ if aspect_ratio == "Custom":
54
+ return custom_width, custom_height
55
+ else:
56
+ width, height = parse_aspect_ratio(aspect_ratio)
57
+ return width, height
58
+
59
+
60
+ def get_scheduler(scheduler_config: Dict, name: str) -> Optional[Callable]:
61
+ scheduler_factory_map = {
62
+ "DPM++ 2M Karras": lambda: DPMSolverMultistepScheduler.from_config(
63
+ scheduler_config, use_karras_sigmas=True
64
+ ),
65
+ "DPM++ SDE Karras": lambda: DPMSolverSinglestepScheduler.from_config(
66
+ scheduler_config, use_karras_sigmas=True
67
+ ),
68
+ "DPM++ 2M SDE Karras": lambda: DPMSolverMultistepScheduler.from_config(
69
+ scheduler_config, use_karras_sigmas=True, algorithm_type="sde-dpmsolver++"
70
+ ),
71
+ "Euler": lambda: EulerDiscreteScheduler.from_config(scheduler_config),
72
+ "Euler a": lambda: EulerAncestralDiscreteScheduler.from_config(
73
+ scheduler_config
74
+ ),
75
+ "DDIM": lambda: DDIMScheduler.from_config(scheduler_config),
76
+ }
77
+ return scheduler_factory_map.get(name, lambda: None)()
78
+
79
+
80
+ def free_memory() -> None:
81
+ torch.cuda.empty_cache()
82
+ gc.collect()
83
+
84
+
85
+ def preprocess_prompt(
86
+ style_dict,
87
+ style_name: str,
88
+ positive: str,
89
+ negative: str = "",
90
+ add_style: bool = True,
91
+ ) -> Tuple[str, str]:
92
+ p, n = style_dict.get(style_name, style_dict["(None)"])
93
+
94
+ if add_style and positive.strip():
95
+ formatted_positive = p.format(prompt=positive)
96
+ else:
97
+ formatted_positive = positive
98
+
99
+ combined_negative = n
100
+ if negative.strip():
101
+ if combined_negative:
102
+ combined_negative += ", " + negative
103
+ else:
104
+ combined_negative = negative
105
+
106
+ return formatted_positive, combined_negative
107
+
108
+
109
+ def common_upscale(
110
+ samples: torch.Tensor,
111
+ width: int,
112
+ height: int,
113
+ upscale_method: str,
114
+ ) -> torch.Tensor:
115
+ return torch.nn.functional.interpolate(
116
+ samples, size=(height, width), mode=upscale_method
117
+ )
118
+
119
+
120
+ def upscale(
121
+ samples: torch.Tensor, upscale_method: str, scale_by: float
122
+ ) -> torch.Tensor:
123
+ width = round(samples.shape[3] * scale_by)
124
+ height = round(samples.shape[2] * scale_by)
125
+ return common_upscale(samples, width, height, upscale_method)
126
+
127
+
128
+ def load_wildcard_files(wildcard_dir: str) -> Dict[str, str]:
129
+ wildcard_files = {}
130
+ for file in os.listdir(wildcard_dir):
131
+ if file.endswith(".txt"):
132
+ key = f"__{file.split('.')[0]}__" # Create a key like __character__
133
+ wildcard_files[key] = os.path.join(wildcard_dir, file)
134
+ return wildcard_files
135
+
136
+
137
+ def get_random_line_from_file(file_path: str) -> str:
138
+ with open(file_path, "r") as file:
139
+ lines = file.readlines()
140
+ if not lines:
141
+ return ""
142
+ return random.choice(lines).strip()
143
+
144
+
145
+ def add_wildcard(prompt: str, wildcard_files: Dict[str, str]) -> str:
146
+ for key, file_path in wildcard_files.items():
147
+ if key in prompt:
148
+ wildcard_line = get_random_line_from_file(file_path)
149
+ prompt = prompt.replace(key, wildcard_line)
150
+ return prompt
151
+
152
+
153
+ def preprocess_image_dimensions(width, height):
154
+ if width % 8 != 0:
155
+ width = width - (width % 8)
156
+ if height % 8 != 0:
157
+ height = height - (height % 8)
158
+ return width, height
159
+
160
+
161
+ def save_image(image, metadata, output_dir):
162
+ current_time = datetime.now().strftime("%Y%m%d_%H%M%S")
163
+ os.makedirs(output_dir, exist_ok=True)
164
+ filename = f"image_{current_time}.png"
165
+ filepath = os.path.join(output_dir, filename)
166
+
167
+ metadata_str = json.dumps(metadata)
168
+ info = PngImagePlugin.PngInfo()
169
+ info.add_text("metadata", metadata_str)
170
+ image.save(filepath, "PNG", pnginfo=info)
171
+ return filepath
172
+
173
+
174
+ def is_google_colab():
175
+ try:
176
+ import google.colab
177
+ return True
178
+ except:
179
+ return False
wildcard/artist30.txt ADDED
@@ -0,0 +1,2139 @@