WatchOutForMike commited on
Commit
6e6e228
·
1 Parent(s): 3aff4ae
Files changed (1) hide show
  1. app.py +81 -368
app.py CHANGED
@@ -1,395 +1,108 @@
1
- #!/usr/bin/env python
2
 
3
- import os
4
- import random
5
- import uuid
6
- import json
7
 
8
- import gradio as gr
9
- import numpy as np
10
- from PIL import Image
11
- import spaces
12
- import torch
13
- from diffusers import DiffusionPipeline
14
- from typing import Tuple
15
-
16
- # Check for the Model Base..
17
-
18
- bad_words = json.loads(os.getenv('BAD_WORDS', "[]"))
19
- bad_words_negative = json.loads(os.getenv('BAD_WORDS_NEGATIVE', "[]"))
20
- default_negative = os.getenv("default_negative","")
21
-
22
- def check_text(prompt, negative=""):
23
- for i in bad_words:
24
- if i in prompt:
25
- return True
26
- for i in bad_words_negative:
27
- if i in negative:
28
- return True
29
- return False
30
-
31
- style_list = [
32
- {
33
- "name": "D&D Art",
34
- "prompt": "dungeons & dragons style artwork {prompt}. d&d style, key visual, vibrant, studio anime, highly detailed",
35
- "negative_prompt": "photo, deformed, black and white, realism, disfigured, low contrast"
36
- },
37
- {
38
- "name": "2560 x 1440",
39
- "prompt": "hyper-realistic 4K image of {prompt}. ultra-detailed, lifelike, high-resolution, sharp, vibrant colors, photorealistic, fantastical environments, epic scenery, rich textures",
40
- "negative_prompt": "cartoonish, low resolution, blurry, simplistic, abstract, sci-fi, modern cityscapes, deformed, ugly"
41
- },
42
- {
43
- "name": "Photo",
44
- "prompt": "cinematic photo of {prompt}. 35mm photograph, fantasy style, atmospheric lighting, magical elements, bokeh, professional, 4k, highly detailed",
45
- "negative_prompt": "modern day, sci-fi, minimalistic, noisy, blurry, overly dark, soft, deformed, low fantasy"
46
- },
47
- {
48
- "name": "Epic Battle",
49
- "prompt": "dynamic dungeons & dragons artwork of {prompt}. epic battle scene, legendary heroes, fierce monsters, intense action, dramatic lighting, high-detail environment, magical effects, vibrant colors",
50
- "negative_prompt": "peaceful, mundane, low energy, modern, sci-fi, simplistic, cartoonish, low contrast"
51
- },
52
- {
53
- "name": "Character Portrait",
54
- "prompt": "dungeons & dragons character portrait of {prompt}. intricate details, expressive faces, heroic poses, rich textures, elaborate costumes, iconic weapons, fantasy aesthetic, studio-quality rendering",
55
- "negative_prompt": "generic, overly stylized, blurry, simplistic, futuristic, deformed"
56
- },
57
- {
58
- "name": "Magical Realm",
59
- "prompt": "mystical dungeons & dragons artwork of {prompt}. enchanted forests, glowing runes, floating islands, otherworldly landscapes, magical auras, vibrant fantasy colors, ultra-detailed",
60
- "negative_prompt": "urban, dull, realistic, futuristic, lifeless, overly muted, minimalistic"
61
- },
62
- {
63
- "name": "Dark Fantasy",
64
- "prompt": "dark and moody dungeons & dragons artwork of {prompt}. gothic ruins, shadowy figures, haunting atmospheres, grim villains, cursed relics, muted colors, intricate textures, sinister undertones",
65
- "negative_prompt": "bright, cheerful, cartoonish, lighthearted, futuristic, deformed"
66
- },
67
- {
68
- "name": "Legendary Creatures",
69
- "prompt": "dungeons & dragons artwork of legendary creatures {prompt}. awe-inspiring dragons, ferocious beasts, mythical monsters, intricate scales, detailed textures, dynamic poses, magical auras, cinematic quality",
70
- "negative_prompt": "simplistic, dull, mundane creatures, low-detail, modern animals, cartoony"
71
- },
72
- {
73
- "name": "Ancient Ruins",
74
- "prompt": "dungeons & dragons artwork of {prompt}. ancient temples, crumbling ruins, arcane symbols, epic scale, mystical atmosphere, grand designs, dramatic perspective, ultra-detailed",
75
- "negative_prompt": "modern structures, low-detail, dull, untextured, non-fantasy elements, minimalistic"
76
- },
77
- {
78
- "name": "Spellcasting Scene",
79
- "prompt": "dungeons & dragons artwork of {prompt}. dramatic spellcasting, glowing magic effects, dynamic poses, swirling energy, vibrant light contrasts, powerful sorcerers, rich fantasy aesthetic",
80
- "negative_prompt": "low energy, non-magical, mundane, modern day, generic designs, dull colors"
81
- },
82
- {
83
- "name": "Tavern Life",
84
- "prompt": "dungeons & dragons artwork of {prompt}. lively medieval tavern scene, detailed character interactions, warm firelight, wooden interiors, mugs of ale, bard performances, rich textures, inviting atmosphere",
85
- "negative_prompt": "cold, empty, futuristic, lifeless, overly simplistic, boring"
86
- },
87
- {
88
- "name": "D&D Quest Art",
89
- "prompt": "dungeons & dragons quest artwork of {prompt}. heroic adventurers, perilous journeys, hidden treasures, legendary quests, immersive fantasy landscapes, intricate details, atmospheric lighting, grand scale, narrative-driven composition",
90
- "negative_prompt": "modern, futuristic, low-detail, overly abstract, mundane settings, simplistic, sci-fi, cartoony, lifeless, uninspired"
91
- },
92
- {
93
- "name": "D&D Anime Art",
94
- "prompt": "dungeons & dragons anime-style artwork of {prompt}. stylized characters, vibrant colors, expressive designs, dynamic action poses, magical effects, intricate fantasy backgrounds, studio-quality anime detailing",
95
- "negative_prompt": "photo-realistic, overly gritty, mundane, futuristic, overly dark, simplistic, deformed"
96
- },
97
- {
98
- "name": "D&D Map",
99
- "prompt": "dungeons & dragons map artwork of {prompt}. intricate fantasy map, visible grid layout for gameplay guidance, ancient cartography style, labeled locations, landmarks, topographic textures, rich colors, immersive design",
100
- "negative_prompt": "modern maps, bland, plain, low detail, futuristic, chaotic, inaccurate grids, unlabeled, minimalist"
101
- },
102
- {
103
- "name": "3D Model",
104
- "prompt": "professional 3D model of {prompt}. stylized fantasy character, legendary creatures, intricate armor, magical weapons, dynamic poses, volumetric lighting, epic fantasy feel, octane render, highly detailed",
105
- "negative_prompt": "low poly, blurry, noisy, simplistic, overly realistic, mundane objects, low effort"
106
- },
107
- {
108
- "name": "(No style)",
109
- "prompt": "{prompt}",
110
- "negative_prompt": "",
111
- },
112
- ]
113
-
114
- styles = {k["name"]: (k["prompt"], k["negative_prompt"]) for k in style_list}
115
- STYLE_NAMES = list(styles.keys())
116
- DEFAULT_STYLE_NAME = "D&D Quest Art"
117
-
118
- def apply_style(style_name: str, positive: str, negative: str = "") -> Tuple[str, str]:
119
- p, n = styles.get(style_name, styles[DEFAULT_STYLE_NAME])
120
- if not negative:
121
- negative = ""
122
- return p.replace("{prompt}", positive), n + negative
123
-
124
- DESCRIPTION = """## ChatDnD.net Dungeons & Dragons Fantasy Creator
125
- Forge your own epic adventures and legendary heroes. Generate custom artwork for characters, quests, and magical landscapes to bring your campaigns to life. Finetuned by <a href='https://chatdnd.net'>ChatDnD</a>. To support me, <a href='https://buymeacoffee.com/watchoutformike'>Buy me a coffee</a>
126
- """
127
-
128
- if not torch.cuda.is_available():
129
- DESCRIPTION += "\n<p>⚠️Running on CPU, This may not work on CPU.</p>"
130
-
131
- MAX_SEED = np.iinfo(np.int32).max
132
- CACHE_EXAMPLES = torch.cuda.is_available() and os.getenv("CACHE_EXAMPLES", "0") == "1"
133
- MAX_IMAGE_SIZE = int(os.getenv("MAX_IMAGE_SIZE", "2048"))
134
- USE_TORCH_COMPILE = os.getenv("USE_TORCH_COMPILE", "0") == "1"
135
- ENABLE_CPU_OFFLOAD = os.getenv("ENABLE_CPU_OFFLOAD", "0") == "1"
136
-
137
- device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
138
-
139
- NUM_IMAGES_PER_PROMPT = 1
140
-
141
- if torch.cuda.is_available():
142
- pipe = DiffusionPipeline.from_pretrained(
143
- "SG161222/RealVisXL_V3.0_Turbo",
144
- torch_dtype=torch.float16,
145
- use_safetensors=True,
146
- add_watermarker=False,
147
- variant="fp16"
148
- )
149
- pipe2 = DiffusionPipeline.from_pretrained(
150
- "SG161222/RealVisXL_V2.02_Turbo",
151
- torch_dtype=torch.float16,
152
- use_safetensors=True,
153
- add_watermarker=False,
154
- variant="fp16"
155
- )
156
- if ENABLE_CPU_OFFLOAD:
157
- pipe.enable_model_cpu_offload()
158
- pipe2.enable_model_cpu_offload()
159
- else:
160
- pipe.to(device)
161
- pipe2.to(device)
162
- print("Loaded on Device!")
163
-
164
- if USE_TORCH_COMPILE:
165
- pipe.unet = torch.compile(pipe.unet, mode="reduce-overhead", fullgraph=True)
166
- pipe2.unet = torch.compile(pipe2.unet, mode="reduce-overhead", fullgraph=True)
167
- print("Model Compiled!")
168
-
169
- def save_image(img):
170
- unique_name = str(uuid.uuid4()) + ".png"
171
- img.save(unique_name)
172
- return unique_name
173
-
174
- @spaces.GPU(enable_queue=True)
175
- def generate(
176
- prompt: str,
177
- negative_prompt: str = "",
178
- use_negative_prompt: bool = False,
179
- style: str = DEFAULT_STYLE_NAME,
180
- width: int = 1024,
181
- height: int = 1024,
182
- guidance_scale: float = 3,
183
- use_resolution_binning: bool = True,
184
- progress=gr.Progress(track_tqdm=True),
185
- ):
186
- if check_text(prompt, negative_prompt):
187
- raise ValueError("Prompt contains restricted words.")
188
-
189
- prompt, negative_prompt = apply_style(style, prompt, negative_prompt)
190
- generator = torch.Generator().manual_seed(42) # Fixed seed for reproducibility
191
-
192
- if not use_negative_prompt:
193
- negative_prompt = "" # type: ignore
194
- negative_prompt += default_negative
195
-
196
- options = {
197
- "prompt": prompt,
198
- "negative_prompt": negative_prompt,
199
- "width": width,
200
- "height": height,
201
- "guidance_scale": guidance_scale,
202
- "num_inference_steps": 25,
203
- "generator": generator,
204
- "num_images_per_prompt": NUM_IMAGES_PER_PROMPT,
205
- "use_resolution_binning": use_resolution_binning,
206
- "output_type": "pil",
207
- }
208
-
209
- images = pipe(**options).images + pipe2(**options).images
210
-
211
- image_paths = [save_image(img) for img in images]
212
- return image_paths
213
-
214
- examples = [
215
- "A grand Dungeons & Dragons quest scene: A heroic party of adventurers standing at the entrance of a towering, ancient stone castle covered in vines, under a sky lit by the fading orange hues of a setting sun. The characters include a fierce elven warrior in ornate armor, a wise wizard with a glowing staff, a stealthy halfling rogue with a bow, and a mighty dwarf cleric with a shining warhammer. In the background, a dark forest looms, and mist begins to rise from the ground. The ground around the castle is scattered with enchanted symbols and ancient runes. The atmosphere is tense and filled with magic, adventure, and mystery."
216
- ]
217
-
218
- css = '''
219
  body {
220
- background-color: #231f20;
221
- color: #f5f5f5;
222
- font-family: 'Arial', sans-serif;
 
 
 
 
 
 
 
223
  }
224
 
225
  .gradio-container {
226
- max-width: 900px !important; /* Increase width for a spacious layout */
227
- background: linear-gradient(180deg, #1a2332 0%, #08141e 100%);
 
 
 
228
  border-radius: 15px;
229
- box-shadow: 0 4px 15px rgba(0, 0, 0, 0.8);
230
- color: #d4e6f9;
231
- font-family: 'Roboto', sans-serif;
232
- padding: 20px;
233
  }
234
 
235
- h1, h2, h3 {
236
- color: #f4a261;
237
- font-family: 'Cinzel', serif; /* Give a medieval vibe */
238
  text-align: center;
239
- letter-spacing: 2px;
240
  }
241
 
242
- .gradio-slider {
243
- background-color: #0f1d29;
244
- border: 1px solid #3a506b;
245
- color: #d4e6f9;
 
 
 
 
246
  }
247
 
248
- .gr-checkbox label {
249
- color: #d4e6f9;
 
 
250
  }
251
 
252
- .gr-radio label {
253
- color: #f4a261;
254
- font-family: 'Cinzel', serif;
255
- }
256
-
257
- .gradio-button {
258
- background: #f4a261;
259
- color: #2a2a40;
260
  border-radius: 8px;
261
- box-shadow: 0 2px 10px rgba(244, 162, 97, 0.4);
262
- font-weight: bold;
263
- }
264
-
265
- .gradio-button:hover {
266
- background: #e76f51;
267
  }
268
 
269
- .gradio-gallery .label {
270
- color: #f4a261;
271
- font-family: 'Cinzel', serif;
272
- font-size: 1.2rem;
273
  }
274
 
275
- .accordion-content {
276
- background: #08141e;
277
- border: 1px solid #3a506b;
 
 
 
278
  padding: 15px;
 
279
  }
280
 
281
- .gr-row, .gr-column, .gr-group {
282
- border-radius: 10px;
 
 
 
283
  }
284
- '''
285
-
286
- with gr.Blocks(css=css) as demo:
287
- gr.Markdown(f"""
288
- # ⚔️ Dungeons & Dragons Fantasy Generator ⚔️
289
- **Unleash Your Imagination!** Create heroes, maps, quests, and epic scenes to bring your campaigns to life. Tailored for adventurers seeking inspiration or Dungeon Masters constructing their next grand story. <br>
290
- [Visit Our Website](https://chatdnd.net) | [Support Us](https://buymeacoffee.com/watchoutformike)
291
- *Roll for initiative and dive in!*
292
- """)
293
- with gr.Group():
294
- with gr.Row():
295
- prompt = gr.Text(
296
- label="🔮 Your Prompt",
297
- show_label=True,
298
- max_lines=1,
299
- placeholder="Describe your vision (e.g., 'Elven Archer battling a hydra')",
300
- container=False,
301
- )
302
- run_button = gr.Button("Generate 🎨")
303
- result = gr.Gallery(label="Your Results", columns=2, preview=True)
304
- with gr.Accordion("📜 Advanced Options", open=False):
305
- use_negative_prompt = gr.Checkbox(label="🔻 Use Negative Prompt", value=True, visible=True)
306
- negative_prompt = gr.Text(
307
- label="Negative Prompt",
308
- max_lines=2,
309
- placeholder="Describe what to avoid (e.g., blurry, modern style)",
310
- value="",
311
- visible=True,
312
- )
313
- with gr.Row():
314
- num_inference_steps = gr.Slider(
315
- label="⚙️ Steps",
316
- minimum=10,
317
- maximum=60,
318
- step=1,
319
- value=30,
320
- )
321
- with gr.Row():
322
- num_images_per_prompt = gr.Slider(
323
- label="🖼️ Images Per Prompt",
324
- minimum=1,
325
- maximum=4,
326
- step=1,
327
- value=2,
328
- )
329
- with gr.Row(visible=True):
330
- width = gr.Slider(
331
- label="Width (px)",
332
- minimum=512,
333
- maximum=2048,
334
- step=8,
335
- value=1024,
336
- )
337
- height = gr.Slider(
338
- label="Height (px)",
339
- minimum=512,
340
- maximum=2048,
341
- step=8,
342
- value=1024,
343
- )
344
- with gr.Row():
345
- guidance_scale = gr.Slider(
346
- label="🎨 Guidance Scale",
347
- minimum=1.0,
348
- maximum=20.0,
349
- step=0.5,
350
- value=7.5,
351
- )
352
- with gr.Row(visible=True):
353
- style_selection = gr.Radio(
354
- label="🎭 Select Your Style",
355
- choices=STYLE_NAMES,
356
- value=DEFAULT_STYLE_NAME,
357
- container=True,
358
- )
359
- gr.Examples(
360
- examples=examples,
361
- inputs=prompt,
362
- outputs=result,
363
- fn=generate,
364
- cache_examples=CACHE_EXAMPLES,
365
- )
366
 
367
- use_negative_prompt.change(
368
- fn=lambda x: gr.update(visible=x),
369
- inputs=use_negative_prompt,
370
- outputs=negative_prompt,
371
- api_name=False,
372
- )
373
-
374
- gr.on(
375
- triggers=[
376
- prompt.submit,
377
- negative_prompt.submit,
378
- run_button.click,
379
- ],
380
- fn=generate,
381
- inputs=[
382
- prompt,
383
- negative_prompt,
384
- use_negative_prompt,
385
- style_selection,
386
- width,
387
- height,
388
- guidance_scale,
389
- ],
390
- outputs=result,
391
- api_name="run",
392
- )
393
 
394
- if __name__ == "__main__":
395
- demo.queue(max_size=20).launch()
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
 
3
+ # Load the model
4
+ model = gr.load("models/strangerzonehf/Flux-Midjourney-Mix2-LoRA")
 
 
5
 
6
+ # Define D&D-specific CSS with rich theming
7
+ custom_css = """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  body {
9
+ background-color: #1b1b1b; /* A dark, dungeon-like background */
10
+ color: #f0e6d2; /* Off-white text to mimic aged parchment */
11
+ font-family: 'Palatino Linotype', serif; /* Adds a fantasy-inspired font style */
12
+ margin: 0;
13
+ padding: 0;
14
+ display: flex;
15
+ flex-direction: column;
16
+ align-items: center;
17
+ justify-content: center;
18
+ height: 100vh;
19
  }
20
 
21
  .gradio-container {
22
+ max-width: 900px;
23
+ margin: auto;
24
+ padding: 25px;
25
+ background: linear-gradient(145deg, #2e2b2a, #3a3433); /* Subtle gradient for depth */
26
+ border: 3px solid #a0522d; /* Bronze/gold-tone border resembling ancient artifacts */
27
  border-radius: 15px;
28
+ box-shadow: 0 0 15px rgba(0, 0, 0, 0.8); /* Shadowing for a mysterious effect */
 
 
 
29
  }
30
 
31
+ h1, h2 {
32
+ color: #ffd700; /* Gold to evoke a high-fantasy vibe */
33
+ text-shadow: 2px 2px #7c5200; /* Slight shadow for richness */
34
  text-align: center;
 
35
  }
36
 
37
+ textarea, input[type="text"] {
38
+ background-color: #2a2927; /* Dark stone-like input background */
39
+ color: #f5e6ca; /* Light text for easy readability */
40
+ border: 2px solid #8b4513; /* Earthy brown border */
41
+ border-radius: 5px;
42
+ padding: 10px;
43
+ font-family: 'Palatino Linotype', serif; /* Matches fantasy feel */
44
+ font-size: 16px;
45
  }
46
 
47
+ textarea:focus, input[type="text"]:focus {
48
+ outline: none;
49
+ border-color: #ffd700; /* Highlight effect when focused */
50
+ box-shadow: 0 0 5px #ffd700;
51
  }
52
 
53
+ button {
54
+ background: #8b4513; /* Button styled in earthy tones */
55
+ color: #f0e6d2;
56
+ font-family: 'Palatino Linotype', serif;
57
+ font-size: 18px;
58
+ border: none;
 
 
59
  border-radius: 8px;
60
+ padding: 12px 25px;
61
+ cursor: pointer;
62
+ transition: 0.3s ease-in-out;
63
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
 
 
64
  }
65
 
66
+ button:hover {
67
+ background: #a0522d; /* Lighter tone for hover */
68
+ box-shadow: 0 0 10px #ffd700;
 
69
  }
70
 
71
+ .gradio-output {
72
+ background-color: #292828; /* Keeps output aligned with the theme */
73
+ color: #ffd700;
74
+ border: 1px solid #8b4513;
75
+ border-radius: 8px;
76
+ margin-top: 20px;
77
  padding: 15px;
78
+ text-align: center;
79
  }
80
 
81
+ .gradio-output img {
82
+ max-width: 100%;
83
+ border: 2px solid #a0522d;
84
+ border-radius: 8px;
85
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
86
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
+ .footer {
89
+ margin-top: 20px;
90
+ font-size: 14px;
91
+ text-align: center;
92
+ color: #ffd700;
93
+ text-shadow: 1px 1px #7c5200;
94
+ }
95
+ """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
 
97
+ # Define Gradio interface
98
+ iface = gr.Interface(
99
+ fn=model, # Model function
100
+ inputs=gr.Textbox(lines=3, label="Enter Your Quest Here:", placeholder="Describe the scene, character, or item..."),
101
+ outputs=gr.Image(type="pil", label="Your Epic Creation"),
102
+ title="🛡️ Dungeons & Dragons Image Generator ⚔️",
103
+ description="Step into the Forgotten Realms and summon visuals straight out of your imagination. Powered by Flux-Midjourney-Mix2-LoRA!",
104
+ css=custom_css
105
+ )
106
+
107
+ # Launch the interface
108
+ iface.launch()