prithivMLmods commited on
Commit
f06faee
·
verified ·
1 Parent(s): 764dc74

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +182 -311
app.py CHANGED
@@ -1,7 +1,7 @@
1
  import os
2
  import random
3
  import uuid
4
- from typing import Tuple, Dict
5
  import gradio as gr
6
  import numpy as np
7
  from PIL import Image
@@ -9,31 +9,44 @@ import spaces
9
  import torch
10
  from diffusers import StableDiffusionXLPipeline, EulerAncestralDiscreteScheduler
11
 
12
- DESCRIPTIONz= """## SDXL-LoRA-DLC
13
- Select a base model, choose a LoRA, and generate images!
14
  """
15
 
16
- # --- Constants ---
 
 
 
 
 
 
 
 
 
 
 
17
  MAX_SEED = np.iinfo(np.int32).max
18
- DEFAULT_STYLE_NAME = "3840 x 2160"
19
- USE_TORCH_COMPILE = False # Set to True if you want to try torch compile (might be faster but requires compatible hardware/drivers)
20
- ENABLE_CPU_OFFLOAD = False # Set to True to offload parts of the model to CPU (saves VRAM but slower)
21
 
22
- # --- Model Definitions ---
23
- # Dictionary mapping user-friendly names to Hugging Face model IDs
24
- pipelines_info = {
 
 
 
 
 
 
 
25
  "RealVisXL V4.0 Lightning": "SG161222/RealVisXL_V4.0_Lightning",
26
  "RealVisXL V5.0 Lightning": "SG161222/RealVisXL_V5.0_Lightning",
27
- # Add more SDXL base models here if desired
28
- # "Another SDXL Model": "stabilityai/stable-diffusion-xl-base-1.0", # Example
29
  }
30
 
31
- # Dictionary to cache loaded pipelines
32
- loaded_pipelines: Dict[str, StableDiffusionXLPipeline] = {}
 
33
 
34
- # --- LoRA Definitions ---
35
  LORA_OPTIONS = {
36
- # Name: (HuggingFace Repo ID, Weight Filename, Adapter Name)
37
  "Realism (face/character)👦🏻": ("prithivMLmods/Canopus-Realism-LoRA", "Canopus-Realism-LoRA.safetensors", "rlms"),
38
  "Pixar (art/toons)🙀": ("prithivMLmods/Canopus-Pixar-Art", "Canopus-Pixar-Art.safetensors", "pixar"),
39
  "Photoshoot (camera/film)📸": ("prithivMLmods/Canopus-Photo-Shoot-Mini-LoRA", "Canopus-Photo-Shoot-Mini-LoRA.safetensors", "photo"),
@@ -49,88 +62,47 @@ LORA_OPTIONS = {
49
  "Art Minimalistic (paint/semireal)🎨": ("prithivMLmods/Canopus-Art-Medium-LoRA", "Canopus-Art-Medium-LoRA.safetensors", "mdm"),
50
  }
51
 
52
- # --- Style Definitions ---
53
  style_list = [
54
  {
55
  "name": "3840 x 2160",
56
  "prompt": "hyper-realistic 8K image of {prompt}. ultra-detailed, lifelike, high-resolution, sharp, vibrant colors, photorealistic",
57
- "negative_prompt": "cartoonish, low resolution, blurry, simplistic, abstract, deformed, ugly, bad anatomy, worst quality, low quality",
58
  },
59
  {
60
  "name": "2560 x 1440",
61
  "prompt": "hyper-realistic 4K image of {prompt}. ultra-detailed, lifelike, high-resolution, sharp, vibrant colors, photorealistic",
62
- "negative_prompt": "cartoonish, low resolution, blurry, simplistic, abstract, deformed, ugly, bad anatomy, worst quality, low quality",
63
  },
64
  {
65
  "name": "HD+",
66
  "prompt": "hyper-realistic 2K image of {prompt}. ultra-detailed, lifelike, high-resolution, sharp, vibrant colors, photorealistic",
67
- "negative_prompt": "cartoonish, low resolution, blurry, simplistic, abstract, deformed, ugly, bad anatomy, worst quality, low quality",
68
  },
69
  {
70
  "name": "Style Zero",
71
  "prompt": "{prompt}",
72
- "negative_prompt": "worst quality, low quality", # Added basic negative prompt
73
  },
74
  ]
 
75
  styles = {k["name"]: (k["prompt"], k["negative_prompt"]) for k in style_list}
 
76
  STYLE_NAMES = list(styles.keys())
77
 
78
- # --- Utility Functions ---
79
- def save_image(img):
80
- unique_name = str(uuid.uuid4()) + ".png"
81
- img.save(unique_name)
82
- return unique_name
83
-
84
- def randomize_seed_fn(seed: int, randomize_seed: bool) -> int:
85
- if randomize_seed:
86
- seed = random.randint(0, MAX_SEED)
87
- return seed
88
-
89
  def apply_style(style_name: str, positive: str, negative: str = "") -> Tuple[str, str]:
90
- # Get the base style prompt and negative prompt
91
- base_p, base_n = styles.get(style_name, styles[DEFAULT_STYLE_NAME])
92
-
93
- # Combine the base negative prompt with the user's negative prompt
94
- # Ensure user's negative prompt is appended correctly
95
- if negative and base_n:
96
- combined_n = f"{base_n}, {negative}"
97
- elif negative:
98
- combined_n = negative
99
- else:
100
- combined_n = base_n
101
-
102
- # Apply the positive prompt template
103
- final_p = base_p.replace("{prompt}", positive)
104
-
105
- return final_p, combined_n
106
-
107
- def load_predefined_images():
108
- # Ensure the assets directory and images exist
109
- asset_dir = "assets"
110
- image_files = [
111
- "1.png", "2.png", "3.png",
112
- "4.png", "5.png", "6.png",
113
- "7.png", "8.png", "9.png",
114
- ]
115
- predefined_images = []
116
- if os.path.exists(asset_dir):
117
- for img_file in image_files:
118
- img_path = os.path.join(asset_dir, img_file)
119
- if os.path.exists(img_path):
120
- predefined_images.append(img_path)
121
- else:
122
- print(f"Warning: Predefined image not found: {img_path}")
123
  else:
124
- print(f"Warning: Asset directory not found: {asset_dir}")
125
- # If no images were found, return None or an empty list
126
- # to avoid errors in gr.Gallery
127
- return predefined_images if predefined_images else None
128
-
129
 
130
- # --- Core Generation Function ---
131
  @spaces.GPU(duration=180, enable_queue=True)
132
  def generate(
133
- selected_base_model_name: str, # New input for base model selection
134
  prompt: str,
135
  negative_prompt: str = "",
136
  use_negative_prompt: bool = False,
@@ -138,212 +110,110 @@ def generate(
138
  width: int = 1024,
139
  height: int = 1024,
140
  guidance_scale: float = 3,
141
- num_inference_steps: int = 4, # Lightning models use fewer steps
142
  randomize_seed: bool = False,
143
  style_name: str = DEFAULT_STYLE_NAME,
144
- lora_choice: str = "Realism (face/character)👦🏻",
 
145
  progress=gr.Progress(track_tqdm=True),
146
  ):
147
- if not torch.cuda.is_available():
148
- raise gr.Error("GPU not available. This Space requires a GPU to run.")
149
 
150
- seed = int(randomize_seed_fn(seed, randomize_seed))
151
- torch.manual_seed(seed) # Ensure reproducibility if seed is fixed
152
-
153
- # --- Pipeline Loading and Caching ---
154
- pipe = None
155
- if selected_base_model_name in loaded_pipelines:
156
- print(f"Using cached pipeline: {selected_base_model_name}")
157
- pipe = loaded_pipelines[selected_base_model_name]
158
- else:
159
- print(f"Loading pipeline: {selected_base_model_name}")
160
- model_id = pipelines_info[selected_base_model_name]
161
- pipe = StableDiffusionXLPipeline.from_pretrained(
162
- model_id,
163
- torch_dtype=torch.float16,
164
- use_safetensors=True,
165
- variant="fp16" if torch.cuda.is_available() else None # Use fp16 variant if available on GPU
166
  )
 
 
 
 
 
 
 
 
 
167
 
168
- # Apply optimizations based on flags
169
- if ENABLE_CPU_OFFLOAD:
170
- print("Enabling CPU Offload")
171
- pipe.enable_model_cpu_offload()
172
- else:
173
- pipe.to("cuda") # Default: move entire pipeline to GPU
174
-
175
- # Configure scheduler (important for Lightning models)
176
- pipe.scheduler = EulerAncestralDiscreteScheduler.from_config(pipe.scheduler.config)
177
-
178
- # Load ALL LoRAs onto this newly loaded pipeline instance
179
- print(f"Loading LoRAs for {selected_base_model_name}...")
180
- for lora_name, (model_repo, weight_file, adapter_tag) in LORA_OPTIONS.items():
181
- try:
182
- print(f" Loading LoRA: {lora_name} ({adapter_tag})")
183
- pipe.load_lora_weights(model_repo, weight_name=weight_file, adapter_name=adapter_tag)
184
- except Exception as e:
185
- print(f" Failed to load LoRA {lora_name}: {e}")
186
- # Optionally raise an error or continue without this LoRA
187
- # raise gr.Error(f"Failed to load LoRA {lora_name}. Check repo/file names.")
188
-
189
- if USE_TORCH_COMPILE:
190
- print("Attempting to compile UNet (may take time)...")
191
- try:
192
- pipe.unet = torch.compile(pipe.unet, mode="reduce-overhead", fullgraph=True)
193
- print("UNet compiled successfully.")
194
- except Exception as e:
195
- print(f"Torch compile failed: {e}. Running without compilation.")
196
-
197
- # Cache the fully loaded and configured pipeline
198
- loaded_pipelines[selected_base_model_name] = pipe
199
- print(f"Pipeline {selected_base_model_name} loaded and cached.")
200
-
201
- # --- Prompt Styling ---
202
- positive_prompt, effective_negative_prompt = apply_style(style_name, prompt, negative_prompt if use_negative_prompt else "")
203
-
204
- # --- LoRA Selection ---
205
- if lora_choice not in LORA_OPTIONS:
206
- raise gr.Error(f"Selected LoRA '{lora_choice}' not found in options.")
207
 
208
- _lora_repo, _lora_weight, lora_adapter_name = LORA_OPTIONS[lora_choice]
209
- print(f"Activating LoRA: {lora_choice} (Adapter: {lora_adapter_name})")
210
- pipe.set_adapters(lora_adapter_name)
211
- # Note: LoRA weight/scale is often handled within the pipeline or during loading.
212
- # If you need adjustable LoRA scale, you might need `add_weighted_adapter` or similar.
213
- # For simplicity here, we assume the default scale is used.
214
- # cross_attention_kwargs={"scale": 0.8} # Example if you need to set scale explicitly
215
 
216
- # --- Image Generation ---
217
- print("Starting image generation...")
218
- generator = torch.Generator("cuda").manual_seed(seed)
219
- images = pipe(
220
  prompt=positive_prompt,
221
  negative_prompt=effective_negative_prompt,
222
  width=width,
223
  height=height,
224
  guidance_scale=guidance_scale,
225
- num_inference_steps=num_inference_steps, # Use steps suitable for Lightning
226
- generator=generator,
227
  num_images_per_prompt=1,
228
- # cross_attention_kwargs=cross_attention_kwargs, # Add if scale needed
229
  output_type="pil",
230
  ).images
231
-
232
  image_paths = [save_image(img) for img in images]
233
- print("Image generation complete.")
234
  return image_paths, seed
235
 
236
- # --- Gradio UI ---
 
 
 
 
 
 
 
237
  css = '''
238
- .gradio-container{max-width: 860px !important; margin: auto;}
239
  h1{text-align:center}
240
- .gr-prose { text-align: center; }
241
- #model-select-row { justify-content: center; } /* Center dropdowns */
242
- /* Make gallery taller */
243
- #result_gallery .h-\[400px\] {
244
- height: 600px !important; /* Adjust height as needed */
245
  }
246
- #predefined_gallery .h-\[400px\] {
247
- height: 300px !important; /* Adjust height as needed */
248
- }
249
- footer { visibility: hidden }
250
  '''
251
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
252
  with gr.Blocks(css=css) as demo:
253
  gr.Markdown(DESCRIPTIONz)
254
-
255
- with gr.Row(elem_id="model-select-row"):
256
- model_selector = gr.Dropdown(
257
- label="Select Base Model",
258
- choices=list(pipelines_info.keys()),
259
- value=list(pipelines_info.keys())[0], # Default to the first model
260
- scale=1
261
- )
262
- model_choice = gr.Dropdown(
263
- label="Select LoRA Style",
264
- choices=list(LORA_OPTIONS.keys()),
265
- value="Realism (face/character)👦🏻", # Default LoRA
266
- scale=1
267
- )
268
-
269
  with gr.Group():
270
  with gr.Row():
271
  prompt = gr.Text(
272
  label="Prompt",
273
  show_label=False,
274
- max_lines=2, # Allow slightly more room for prompt
275
- placeholder="Enter your prompt (e.g., 'Astronaut riding a horse')",
276
  container=False,
277
- scale=5, # Make prompt input wider
278
  )
279
- run_button = gr.Button("Generate", scale=1, variant="primary") # Make button stand out
280
-
281
- # Use Tabs for Main Result and Examples/Gallery
282
- with gr.Tabs():
283
- with gr.TabItem("Result", id="result_tab"):
284
- result = gr.Gallery(
285
- label="Generated Image", elem_id="result_gallery",
286
- columns=1, preview=True, show_label=False, height=600 # Make gallery taller
287
- )
288
- # Display the seed used for the generated image
289
- used_seed = gr.Number(label="Seed Used", interactive=False)
290
-
291
- with gr.TabItem("Examples & Predefined Gallery", id="examples_tab"):
292
- gr.Markdown("### Prompt Examples")
293
- gr.Examples(
294
- examples=[
295
- "cinematic photo, a man sitting on a chair in a dark room, realistic", # Realism example
296
- "pixar style 3d render of a cute cat astronaut exploring mars", # Pixar example
297
- "studio photography, high fashion model wearing a futuristic silver hoodie, dramatic lighting", # Photoshoot/Clothing example
298
- "minimalist vector art illustration of a mountain range at sunset, liquid style", # Minimalist/Liquid example
299
- "pencil sketch drawing of an old wise wizard with a long beard", # Pencil Art example
300
- ],
301
- inputs=[prompt], # Only update the prompt field from examples
302
- outputs=[result, used_seed], # Define outputs for example generation
303
- fn=lambda p: generate( # Need a lambda to pass default values for other args
304
- selected_base_model_name=list(pipelines_info.keys())[0], # Use default model for examples
305
- prompt=p,
306
- lora_choice="Realism (face/character)👦🏻", # Use default LoRA for examples
307
- # Add other default args from 'generate' signature if needed
308
- negative_prompt="(deformed, distorted, disfigured:1.3), poorly drawn, bad anatomy, wrong anatomy, extra limb, missing limb, floating limbs, (mutated hands and fingers:1.4), disconnected limbs, mutation, mutated, ugly, disgusting, blurry, amputation",
309
- use_negative_prompt=True,
310
- seed=0, # Or make examples use random seed?
311
- width=1024,
312
- height=1024,
313
- guidance_scale=3.0,
314
- num_inference_steps=4,
315
- randomize_seed=True, # Randomize seed for examples
316
- style_name=DEFAULT_STYLE_NAME,
317
- ),
318
- cache_examples=False, # Recalculate examples if needed
319
- label="Click an example to generate"
320
- )
321
- gr.Markdown("### Predefined Image Gallery")
322
- predefined_gallery = gr.Gallery(
323
- label="Image Gallery", elem_id="predefined_gallery",
324
- columns=3, show_label=False, value=load_predefined_images(), height=300
325
- )
326
-
327
-
328
- with gr.Accordion("⚙️ Advanced Settings", open=False):
329
- style_selection = gr.Radio(
330
- show_label=True,
331
- container=True,
332
- interactive=True,
333
- choices=STYLE_NAMES,
334
- value=DEFAULT_STYLE_NAME,
335
- label="Image Quality Style",
336
- )
337
- with gr.Row():
338
- use_negative_prompt = gr.Checkbox(label="Use Negative Prompt", value=True)
339
- randomize_seed = gr.Checkbox(label="Randomize Seed", value=True)
340
 
 
 
341
  negative_prompt = gr.Text(
342
- label="Negative Prompt",
343
- max_lines=2,
344
- value="(deformed, distorted, disfigured:1.3), poorly drawn, bad anatomy, wrong anatomy, extra limb, missing limb, floating limbs, (mutated hands and fingers:1.4), disconnected limbs, mutation, mutated, ugly, disgusting, blurry, amputation, worst quality, low quality",
345
- placeholder="Enter concepts to avoid...",
346
- visible=True, # Initially visible, controlled by checkbox change
 
347
  )
348
  seed = gr.Slider(
349
  label="Seed",
@@ -351,45 +221,62 @@ with gr.Blocks(css=css) as demo:
351
  maximum=MAX_SEED,
352
  step=1,
353
  value=0,
354
- visible=True, # Initially visible, maybe hide if randomize is checked?
355
- interactive=True
356
  )
357
-
358
- with gr.Row():
359
  width = gr.Slider(
360
  label="Width",
361
  minimum=512,
362
- maximum=1536, # Adjusted max based on typical SDXL use
363
- step=64,
364
  value=1024,
365
  )
366
  height = gr.Slider(
367
  label="Height",
368
  minimum=512,
369
- maximum=1536, # Adjusted max based on typical SDXL use
370
- step=64,
371
  value=1024,
372
  )
373
-
374
  with gr.Row():
375
  guidance_scale = gr.Slider(
376
- label="Guidance Scale (CFG)",
377
- minimum=0.0,
378
- maximum=10.0, # Lightning models often use low CFG
379
  step=0.1,
380
- value=1.5, # Default low CFG for Lightning
381
- )
382
- num_inference_steps = gr.Slider(
383
- label="Inference Steps",
384
- minimum=1,
385
- maximum=20, # Lightning models need very few steps
386
- step=1,
387
- value=4, # Default steps for Lightning
388
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
389
 
390
- # --- Event Listeners ---
 
 
 
 
 
 
391
 
392
- # Show/hide negative prompt input based on checkbox
393
  use_negative_prompt.change(
394
  fn=lambda x: gr.update(visible=x),
395
  inputs=use_negative_prompt,
@@ -397,54 +284,38 @@ with gr.Blocks(css=css) as demo:
397
  api_name=False,
398
  )
399
 
400
- # Show/hide seed slider based on randomize checkbox
401
- randomize_seed.change(
402
- fn=lambda x: gr.update(interactive=not x), # Make slider non-interactive if randomizing
403
- inputs=randomize_seed,
404
- outputs=seed,
405
- api_name=False,
406
- )
407
-
408
- # Main generation trigger
409
- inputs_list = [
410
- model_selector, # Add model selector
411
- prompt,
412
- negative_prompt,
413
- use_negative_prompt,
414
- seed,
415
- width,
416
- height,
417
- guidance_scale,
418
- num_inference_steps, # Add steps slider
419
- randomize_seed,
420
- style_selection,
421
- model_choice, # This is the LoRA choice dropdown
422
- ]
423
- outputs_list = [result, used_seed] # Output gallery and the seed number
424
-
425
- prompt.submit(
426
  fn=generate,
427
- inputs=inputs_list,
428
- outputs=outputs_list,
429
- api_name="run_prompt_submit" # Optional: Define API name
 
 
 
 
 
 
 
 
 
 
 
 
430
  )
431
- run_button.click(
432
- fn=generate,
433
- inputs=inputs_list,
434
- outputs=outputs_list,
435
- api_name="run_button_click" # Optional: Define API name
436
- )
437
-
438
- # --- Launch ---
439
- if __name__ == "__main__":
440
- if not torch.cuda.is_available():
441
- print("Warning: No CUDA GPU detected. Running on CPU will be extremely slow or may fail.")
442
- DESCRIPTIONz += "\n<p>⚠️<b>WARNING: No GPU detected. Running on CPU is very slow and may not work reliably.</b> Consider using a GPU instance.</p>"
443
- # Optionally disable parts of the UI or exit if CPU is unacceptable
444
- # exit()
445
 
446
- # Ensure asset directory exists for predefined images (optional but good practice)
447
- if not os.path.exists("assets"):
448
- print("Warning: 'assets' directory not found. Predefined images will not load.")
 
 
 
 
 
449
 
450
- demo.queue(max_size=20).launch(debug=False) # Set debug=True for more logs if needed
 
 
1
  import os
2
  import random
3
  import uuid
4
+ from typing import Tuple
5
  import gradio as gr
6
  import numpy as np
7
  from PIL import Image
 
9
  import torch
10
  from diffusers import StableDiffusionXLPipeline, EulerAncestralDiscreteScheduler
11
 
12
+ # Description for the Gradio interface
13
+ DESCRIPTIONz = """## SDXL-LoRA-DLC
14
  """
15
 
16
+ # Function to save generated images
17
+ def save_image(img):
18
+ unique_name = str(uuid.uuid4()) + ".png"
19
+ img.save(unique_name)
20
+ return unique_name
21
+
22
+ # Function to handle seed randomization
23
+ def randomize_seed_fn(seed: int, randomize_seed: bool) -> int:
24
+ if randomize_seed:
25
+ seed = random.randint(0, MAX_SEED)
26
+ return seed
27
+
28
  MAX_SEED = np.iinfo(np.int32).max
 
 
 
29
 
30
+ # Warning if running on CPU
31
+ if not torch.cuda.is_available():
32
+ DESCRIPTIONz += "\n<p>⚠️Running on CPU, This may not work on CPU. If it runs for an extended time or if you encounter errors, try running it on a GPU by duplicating the space using @spaces.GPU(). +import spaces.📍</p>"
33
+
34
+ # Configuration flags (unchanged)
35
+ USE_TORCH_COMPILE = 0
36
+ ENABLE_CPU_OFFLOAD = 0
37
+
38
+ # Define available base models
39
+ base_models = {
40
  "RealVisXL V4.0 Lightning": "SG161222/RealVisXL_V4.0_Lightning",
41
  "RealVisXL V5.0 Lightning": "SG161222/RealVisXL_V5.0_Lightning",
 
 
42
  }
43
 
44
+ # Global variables to manage the current pipeline
45
+ current_base_model = None
46
+ current_pipeline = None
47
 
48
+ # Define LoRA options
49
  LORA_OPTIONS = {
 
50
  "Realism (face/character)👦🏻": ("prithivMLmods/Canopus-Realism-LoRA", "Canopus-Realism-LoRA.safetensors", "rlms"),
51
  "Pixar (art/toons)🙀": ("prithivMLmods/Canopus-Pixar-Art", "Canopus-Pixar-Art.safetensors", "pixar"),
52
  "Photoshoot (camera/film)📸": ("prithivMLmods/Canopus-Photo-Shoot-Mini-LoRA", "Canopus-Photo-Shoot-Mini-LoRA.safetensors", "photo"),
 
62
  "Art Minimalistic (paint/semireal)🎨": ("prithivMLmods/Canopus-Art-Medium-LoRA", "Canopus-Art-Medium-LoRA.safetensors", "mdm"),
63
  }
64
 
65
+ # Define style options
66
  style_list = [
67
  {
68
  "name": "3840 x 2160",
69
  "prompt": "hyper-realistic 8K image of {prompt}. ultra-detailed, lifelike, high-resolution, sharp, vibrant colors, photorealistic",
70
+ "negative_prompt": "cartoonish, low resolution, blurry, simplistic, abstract, deformed, ugly",
71
  },
72
  {
73
  "name": "2560 x 1440",
74
  "prompt": "hyper-realistic 4K image of {prompt}. ultra-detailed, lifelike, high-resolution, sharp, vibrant colors, photorealistic",
75
+ "negative_prompt": "cartoonish, low resolution, blurry, simplistic, abstract, deformed, ugly",
76
  },
77
  {
78
  "name": "HD+",
79
  "prompt": "hyper-realistic 2K image of {prompt}. ultra-detailed, lifelike, high-resolution, sharp, vibrant colors, photorealistic",
80
+ "negative_prompt": "cartoonish, low resolution, blurry, simplistic, abstract, deformed, ugly",
81
  },
82
  {
83
  "name": "Style Zero",
84
  "prompt": "{prompt}",
85
+ "negative_prompt": "",
86
  },
87
  ]
88
+
89
  styles = {k["name"]: (k["prompt"], k["negative_prompt"]) for k in style_list}
90
+ DEFAULT_STYLE_NAME = "3840 x 2160"
91
  STYLE_NAMES = list(styles.keys())
92
 
93
+ # Function to apply selected style
 
 
 
 
 
 
 
 
 
 
94
  def apply_style(style_name: str, positive: str, negative: str = "") -> Tuple[str, str]:
95
+ if style_name in styles:
96
+ p, n = styles.get(style_name, styles[DEFAULT_STYLE_NAME])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  else:
98
+ p, n = styles[DEFAULT_STYLE_NAME]
99
+ if not negative:
100
+ negative = ""
101
+ return p.replace("{prompt}", positive), n + negative
 
102
 
103
+ # Generation function with model selection
104
  @spaces.GPU(duration=180, enable_queue=True)
105
  def generate(
 
106
  prompt: str,
107
  negative_prompt: str = "",
108
  use_negative_prompt: bool = False,
 
110
  width: int = 1024,
111
  height: int = 1024,
112
  guidance_scale: float = 3,
 
113
  randomize_seed: bool = False,
114
  style_name: str = DEFAULT_STYLE_NAME,
115
+ lora_model: str = "Realism (face/character)👦🏻",
116
+ base_model: str = "RealVisXL V5.0 Lightning",
117
  progress=gr.Progress(track_tqdm=True),
118
  ):
119
+ global current_base_model, current_pipeline
 
120
 
121
+ # Load the pipeline if the base model has changed
122
+ if base_model != current_base_model:
123
+ model_id = base_models[base_model]
124
+ current_pipeline = StableDiffusionXLPipeline.from_pretrained(
125
+ model_id, torch_dtype=torch.float16, use_safetensors=True
 
 
 
 
 
 
 
 
 
 
 
126
  )
127
+ current_pipeline.scheduler = EulerAncestralDiscreteScheduler.from_config(
128
+ current_pipeline.scheduler.config
129
+ )
130
+ for lora_display_name, (lora_model, lora_weight, adapter_name) in LORA_OPTIONS.items():
131
+ current_pipeline.load_lora_weights(
132
+ lora_model, weight_name=lora_weight, adapter_name=adapter_name
133
+ )
134
+ current_pipeline.to("cuda")
135
+ current_base_model = base_model
136
 
137
+ # Handle seed and prompts
138
+ seed = int(randomize_seed_fn(seed, randomize_seed))
139
+ positive_prompt, effective_negative_prompt = apply_style(style_name, prompt, negative_prompt)
140
+ if not use_negative_prompt:
141
+ effective_negative_prompt = ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
 
143
+ # Set the LoRA adapter
144
+ _, _, adapter_name = LORA_OPTIONS[lora_model]
145
+ current_pipeline.set_adapters(adapter_name)
 
 
 
 
146
 
147
+ # Generate the image
148
+ images = current_pipeline(
 
 
149
  prompt=positive_prompt,
150
  negative_prompt=effective_negative_prompt,
151
  width=width,
152
  height=height,
153
  guidance_scale=guidance_scale,
154
+ num_inference_steps=20,
 
155
  num_images_per_prompt=1,
156
+ cross_attention_kwargs={"scale": 0.65},
157
  output_type="pil",
158
  ).images
 
159
  image_paths = [save_image(img) for img in images]
 
160
  return image_paths, seed
161
 
162
+ # Example prompts
163
+ examples = [
164
+ "Realism: Man in the style of dark beige and brown, uhd image, youthful protagonists, nonrepresentational ",
165
+ "Pixar: A young man with light brown wavy hair and light brown eyes sitting in an armchair and looking directly at the camera, pixar style, disney pixar, office background, ultra detailed, 1 man",
166
+ "Hoodie: Front view, capture a urban style, Superman Hoodie, technical materials, fabric small point label on text Blue theory, the design is minimal, with a raised collar, fabric is a Light yellow, low angle to capture the Hoodies form and detailing, f/5.6 to focus on the hoodies craftsmanship, solid grey background, studio light setting, with batman logo in the chest region of the t-shirt",
167
+ ]
168
+
169
+ # CSS styling
170
  css = '''
171
+ .gradio-container{max-width: 545px !important}
172
  h1{text-align:center}
173
+ footer {
174
+ visibility: hidden
 
 
 
175
  }
 
 
 
 
176
  '''
177
 
178
+ # Function to load predefined images
179
+ def load_predefined_images():
180
+ predefined_images = [
181
+ "assets/1.png",
182
+ "assets/2.png",
183
+ "assets/3.png",
184
+ "assets/4.png",
185
+ "assets/5.png",
186
+ "assets/6.png",
187
+ "assets/7.png",
188
+ "assets/8.png",
189
+ "assets/9.png",
190
+ ]
191
+ return predefined_images
192
+
193
+ # Gradio interface
194
  with gr.Blocks(css=css) as demo:
195
  gr.Markdown(DESCRIPTIONz)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
  with gr.Group():
197
  with gr.Row():
198
  prompt = gr.Text(
199
  label="Prompt",
200
  show_label=False,
201
+ max_lines=1,
202
+ placeholder="Enter your prompt with resp. tag!",
203
  container=False,
 
204
  )
205
+ run_button = gr.Button("Run", scale=0)
206
+ result = gr.Gallery(label="Result", columns=1, preview=True, show_label=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207
 
208
+ with gr.Accordion("Advanced options", open=False, visible=False):
209
+ use_negative_prompt = gr.Checkbox(label="Use negative prompt", value=True)
210
  negative_prompt = gr.Text(
211
+ label="Negative prompt",
212
+ lines=4,
213
+ max_lines=6,
214
+ value="(deformed, distorted, disfigured:1.3), poorly drawn, bad anatomy, wrong anatomy, extra limb, missing limb, floating limbs, (mutated hands and fingers:1.4), disconnected limbs, mutation, mutated, ugly, disgusting, blurry, amputation",
215
+ placeholder="Enter a negative prompt",
216
+ visible=True,
217
  )
218
  seed = gr.Slider(
219
  label="Seed",
 
221
  maximum=MAX_SEED,
222
  step=1,
223
  value=0,
224
+ visible=True
 
225
  )
226
+ randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
227
+ with gr.Row(visible=True):
228
  width = gr.Slider(
229
  label="Width",
230
  minimum=512,
231
+ maximum=2048,
232
+ step=8,
233
  value=1024,
234
  )
235
  height = gr.Slider(
236
  label="Height",
237
  minimum=512,
238
+ maximum=2048,
239
+ step=8,
240
  value=1024,
241
  )
 
242
  with gr.Row():
243
  guidance_scale = gr.Slider(
244
+ label="Guidance Scale",
245
+ minimum=0.1,
246
+ maximum=20.0,
247
  step=0.1,
248
+ value=3.0,
 
 
 
 
 
 
 
249
  )
250
+ style_selection = gr.Radio(
251
+ show_label=True,
252
+ container=True,
253
+ interactive=True,
254
+ choices=STYLE_NAMES,
255
+ value=DEFAULT_STYLE_NAME,
256
+ label="Quality Style",
257
+ )
258
+
259
+ # Add base model and LoRA selection dropdowns
260
+ with gr.Row():
261
+ base_model_choice = gr.Dropdown(
262
+ label="Base Model",
263
+ choices=list(base_models.keys()),
264
+ value="RealVisXL V5.0 Lightning"
265
+ )
266
+ model_choice = gr.Dropdown(
267
+ label="LoRA Selection",
268
+ choices=list(LORA_OPTIONS.keys()),
269
+ value="Realism (face/character)👦🏻"
270
+ )
271
 
272
+ gr.Examples(
273
+ examples=examples,
274
+ inputs=prompt,
275
+ outputs=[result, seed],
276
+ fn=generate,
277
+ cache_examples=False,
278
+ )
279
 
 
280
  use_negative_prompt.change(
281
  fn=lambda x: gr.update(visible=x),
282
  inputs=use_negative_prompt,
 
284
  api_name=False,
285
  )
286
 
287
+ gr.on(
288
+ triggers=[
289
+ prompt.submit,
290
+ negative_prompt.submit,
291
+ run_button.click,
292
+ ],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
293
  fn=generate,
294
+ inputs=[
295
+ prompt,
296
+ negative_prompt,
297
+ use_negative_prompt,
298
+ seed,
299
+ width,
300
+ height,
301
+ guidance_scale,
302
+ randomize_seed,
303
+ style_selection,
304
+ model_choice,
305
+ base_model_choice,
306
+ ],
307
+ outputs=[result, seed],
308
+ api_name="run",
309
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
310
 
311
+ with gr.Column(scale=3):
312
+ gr.Markdown("### Image Gallery")
313
+ predefined_gallery = gr.Gallery(
314
+ label="Image Gallery",
315
+ columns=3,
316
+ show_label=False,
317
+ value=load_predefined_images()
318
+ )
319
 
320
+ if __name__ == "__main__":
321
+ demo.queue(max_size=30).launch()