K1Z3M1112 commited on
Commit
1cc4460
·
verified ·
1 Parent(s): 5e7a71d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +512 -157
app.py CHANGED
@@ -29,7 +29,9 @@ from diffusers import (
29
  StableDiffusionControlNetPipeline,
30
  ControlNetModel,
31
  StableDiffusionPipeline,
32
- StableDiffusionXLPipeline
 
 
33
  )
34
  from diffusers import UniPCMultistepScheduler, DPMSolverMultistepScheduler, EulerAncestralDiscreteScheduler
35
  from controlnet_aux import (
@@ -60,11 +62,14 @@ CURRENT_CONTROLNET_KEY = None
60
  CURRENT_T2I_PIPE = None
61
  CURRENT_T2I_MODEL = None
62
  CURRENT_SDXL_REFINER = None
 
 
63
 
64
  # Enhanced SDXL Models (including NSFW-capable)
65
  SDXL_MODELS = [
66
  "stabilityai/stable-diffusion-xl-base-1.0",
67
  "stabilityai/stable-diffusion-xl-refiner-1.0",
 
68
  "Laxhar/noobai-XL-1.1",
69
  "RunDiffusion/Juggernaut-XL-v9",
70
  "dataautogpt3/ProteusV0.4",
@@ -76,6 +81,12 @@ SDXL_MODELS = [
76
  "digiplay/Pony_Diffusion_V6_XL"
77
  ]
78
 
 
 
 
 
 
 
79
  # Enhanced SD1.5 Models (including NSFW-capable)
80
  SD15_MODELS = [
81
  # Original models
@@ -117,6 +128,11 @@ SD15_MODELS = [
117
  "Fictiverse/Stable_Diffusion_VoxelArt_Model"
118
  ]
119
 
 
 
 
 
 
120
  # Chinese Models
121
  CHINESE_MODELS = [
122
  "AI-Chen/Chinese-Stable-Diffusion",
@@ -144,7 +160,8 @@ CONTROLNET_MODELS_SD15 = {
144
  CONTROLNET_MODELS_SDXL = {
145
  "canny_sdxl": "diffusers/controlnet-canny-sdxl-1.0",
146
  "depth_sdxl": "diffusers/controlnet-depth-sdxl-1.0",
147
- "openpose_sdxl": "thibaud/controlnet-openpose-sdxl-1.0"
 
148
  }
149
 
150
  # แก้ไข LoRA models ให้ใช้ชื่อที่ไม่มีช่องว่าง
@@ -189,7 +206,9 @@ LORA_MODELS = {
189
  "realistic-nsfw": "digiplay/RealisticNSFW_v1",
190
  "anime-nsfw": "Linaqruf/anime-nsfw-lora",
191
  "hentai-diffusion": "Deltaadams/Hentai-Diffusion",
192
- "sexy-pose": "alvdansen/sexy-pose-lora"
 
 
193
  }
194
 
195
  # VAE models for better quality
@@ -197,7 +216,8 @@ VAE_MODELS = {
197
  "None": None,
198
  "SD1.5 VAE": "stabilityai/sd-vae-ft-mse",
199
  "Anime VAE": "hakurei/waifu-diffusion-v1-4",
200
- "SDXL VAE": "madebyollin/sdxl-vae-fp16-fix"
 
201
  }
202
 
203
  # Detector instances
@@ -207,6 +227,10 @@ def is_sdxl_model(model_name: str) -> bool:
207
  """Check if model is SDXL"""
208
  return model_name in SDXL_MODELS or "xl" in model_name.lower() or "XL" in model_name
209
 
 
 
 
 
210
  def load_detector(detector_type: str):
211
  """Lazy load detector"""
212
  global DETECTORS
@@ -250,14 +274,19 @@ def load_detector(detector_type: str):
250
  def get_controlnet_model(controlnet_type: str, is_sdxl: bool = False):
251
  """Get ControlNet model based on type"""
252
  if is_sdxl:
 
 
253
  return CONTROLNET_MODELS_SDXL[controlnet_type]
254
  else:
 
 
255
  return CONTROLNET_MODELS_SD15[controlnet_type]
256
 
257
  def prepare_condition_image(image, controlnet_type, is_sdxl=False):
258
  """Prepare condition image for ControlNet"""
259
- if controlnet_type in ["lineart", "lineart_anime"]:
260
- detector = load_detector("lineart_anime" if controlnet_type == "lineart_anime" else "lineart")
 
261
  if detector:
262
  result = detector(image, detect_resolution=512 if not is_sdxl else 1024, image_resolution=512 if not is_sdxl else 1024)
263
  return Image.fromarray(result) if isinstance(result, np.ndarray) else result
@@ -312,11 +341,7 @@ def get_pipeline(model_name: str, controlnet_type: str = "lineart", lora_model:
312
 
313
  try:
314
  is_sdxl = is_sdxl_model(model_name)
315
-
316
- if is_sdxl and controlnet_type not in CONTROLNET_MODELS_SDXL:
317
- raise ValueError(f"SDXL model only supports: {list(CONTROLNET_MODELS_SDXL.keys())}")
318
- elif not is_sdxl and controlnet_type not in CONTROLNET_MODELS_SD15:
319
- raise ValueError(f"SD1.5 model only supports: {list(CONTROLNET_MODELS_SD15.keys())}")
320
 
321
  controlnet_model_name = get_controlnet_model(controlnet_type, is_sdxl)
322
  controlnet = ControlNetModel.from_pretrained(
@@ -325,15 +350,27 @@ def get_pipeline(model_name: str, controlnet_type: str = "lineart", lora_model:
325
  ).to(device)
326
 
327
  if is_sdxl:
328
- pipe = StableDiffusionXLPipeline.from_pretrained(
329
- model_name,
330
- controlnet=controlnet,
331
- torch_dtype=dtype,
332
- safety_checker=None,
333
- requires_safety_checker=False,
334
- use_safetensors=True,
335
- variant="fp16" if dtype == torch.float16 else None
336
- ).to(device)
 
 
 
 
 
 
 
 
 
 
 
 
337
  else:
338
  pipe = StableDiffusionControlNetPipeline.from_pretrained(
339
  model_name,
@@ -388,14 +425,23 @@ def get_pipeline(model_name: str, controlnet_type: str = "lineart", lora_model:
388
  pass
389
  pipe.enable_model_cpu_offload()
390
 
391
- try:
392
- pipe.scheduler = EulerAncestralDiscreteScheduler.from_config(pipe.scheduler.config)
393
- print("✅ Using Euler Ancestral scheduler")
394
- except:
395
  try:
396
- pipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)
 
397
  except:
398
  pass
 
 
 
 
 
 
 
 
 
399
 
400
  CURRENT_CONTROLNET_PIPE = pipe
401
  CURRENT_CONTROLNET_KEY = key
@@ -410,29 +456,55 @@ def get_pipeline(model_name: str, controlnet_type: str = "lineart", lora_model:
410
  def load_t2i_model(model_name: str, lora_model: str = None, lora_weight: float = 0.8,
411
  vae_model: str = None):
412
  """Load text-to-image model with optional LoRA and VAE"""
413
- global CURRENT_T2I_PIPE, CURRENT_T2I_MODEL, CURRENT_SDXL_REFINER
414
 
415
- use_refiner = "refiner" in model_name.lower()
416
- key = (model_name, lora_model, lora_weight, vae_model, use_refiner)
417
 
418
- if CURRENT_T2I_MODEL == key and CURRENT_T2I_PIPE is not None:
419
- return
420
 
421
- if CURRENT_T2I_PIPE is not None:
422
- print(f"🗑️ Unloading old T2I model: {CURRENT_T2I_MODEL}")
423
- del CURRENT_T2I_PIPE
424
- CURRENT_T2I_PIPE = None
425
- if CURRENT_SDXL_REFINER is not None:
426
- del CURRENT_SDXL_REFINER
427
- CURRENT_SDXL_REFINER = None
428
- gc.collect()
429
- if torch.cuda.is_available():
430
- torch.cuda.empty_cache()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
431
 
432
  print(f"📥 Loading T2I model: {model_name}")
433
 
434
  try:
435
- if is_sdxl_model(model_name):
 
 
 
 
 
 
 
 
 
 
 
 
 
436
  if use_refiner:
437
  CURRENT_T2I_PIPE = StableDiffusionXLPipeline.from_pretrained(
438
  "stabilityai/stable-diffusion-xl-base-1.0",
@@ -462,6 +534,9 @@ def load_t2i_model(model_name: str, lora_model: str = None, lora_weight: float =
462
  use_safetensors=True,
463
  variant="fp16" if dtype == torch.float16 else None
464
  ).to(device)
 
 
 
465
  else:
466
  CURRENT_T2I_PIPE = StableDiffusionPipeline.from_pretrained(
467
  model_name,
@@ -471,6 +546,9 @@ def load_t2i_model(model_name: str, lora_model: str = None, lora_weight: float =
471
  use_safetensors=True,
472
  variant="fp16" if dtype == torch.float16 else None
473
  ).to(device)
 
 
 
474
 
475
  # Load custom VAE
476
  if vae_model and vae_model != "None":
@@ -478,7 +556,7 @@ def load_t2i_model(model_name: str, lora_model: str = None, lora_weight: float =
478
  from diffusers import AutoencoderKL
479
  print(f"🔄 Loading custom VAE: {vae_model}")
480
  vae = AutoencoderKL.from_pretrained(vae_model, torch_dtype=dtype).to(device)
481
- CURRENT_T2I_PIPE.vae = vae
482
  except Exception as e:
483
  print(f"⚠️ Error loading VAE: {e}")
484
 
@@ -488,43 +566,53 @@ def load_t2i_model(model_name: str, lora_model: str = None, lora_weight: float =
488
  try:
489
  if lora_model in LORA_MODELS:
490
  lora_path = LORA_MODELS[lora_model]
491
- CURRENT_T2I_PIPE.load_lora_weights(lora_path)
492
- CURRENT_T2I_PIPE.fuse_lora(lora_scale=lora_weight)
493
  else:
494
- CURRENT_T2I_PIPE.load_lora_weights(lora_model)
495
- CURRENT_T2I_PIPE.fuse_lora(lora_scale=lora_weight)
496
  except Exception as e:
497
  print(f"⚠️ Error loading LoRA: {e}")
498
 
499
  # Optimizations
500
- CURRENT_T2I_PIPE.enable_attention_slicing(slice_size="max")
501
 
502
- if hasattr(CURRENT_T2I_PIPE, 'vae') and hasattr(CURRENT_T2I_PIPE.vae, 'enable_slicing'):
503
- CURRENT_T2I_PIPE.vae.enable_slicing()
504
  else:
505
  try:
506
- CURRENT_T2I_PIPE.enable_vae_slicing()
507
  except:
508
  pass
509
 
510
  if device.type == "cuda":
511
  try:
512
- CURRENT_T2I_PIPE.enable_xformers_memory_efficient_attention()
513
  except:
514
  pass
515
- CURRENT_T2I_PIPE.enable_model_cpu_offload()
516
-
517
- try:
518
- CURRENT_T2I_PIPE.scheduler = EulerAncestralDiscreteScheduler.from_config(CURRENT_T2I_PIPE.scheduler.config)
519
- except:
520
- pass
521
 
522
- CURRENT_T2I_MODEL = key
 
 
 
 
 
 
 
 
 
 
 
523
 
524
  except Exception as e:
525
  print(f"❌ Error loading T2I model: {e}")
526
- CURRENT_T2I_PIPE = None
527
- CURRENT_T2I_MODEL = None
 
 
 
 
528
  raise
529
 
530
  def colorize_sd15(sketch, base_model, controlnet_type, lora_model, lora_weight, vae_model,
@@ -617,6 +705,47 @@ def colorize_sdxl(sketch, base_model, controlnet_type, lora_model, lora_weight,
617
  error_img = Image.new('RGB', (1024, 1024), color='red')
618
  return error_img, Image.new('RGB', (1024, 1024), color='gray')
619
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
620
  def t2i_sd15(prompt, negative_prompt, model, lora_model, lora_weight, vae_model,
621
  seed, steps, scale, w, h):
622
  """Text-to-image for SD1.5 models"""
@@ -669,7 +798,7 @@ def t2i_sdxl(prompt, negative_prompt, model, lora_model, lora_weight, vae_model,
669
  return error_img
670
 
671
  model_to_load = model
672
- if use_refiner and "refiner" not in model.lower():
673
  model_to_load = "stabilityai/stable-diffusion-xl-refiner-1.0"
674
 
675
  load_t2i_model(model_to_load, lora_model, lora_weight, vae_model)
@@ -683,7 +812,7 @@ def t2i_sdxl(prompt, negative_prompt, model, lora_model, lora_weight, vae_model,
683
  gen = torch.Generator(device=device).manual_seed(int(seed))
684
 
685
  with torch.inference_mode():
686
- if use_refiner and CURRENT_SDXL_REFINER is not None:
687
  image = CURRENT_T2I_PIPE(
688
  prompt=prompt,
689
  negative_prompt=negative_prompt,
@@ -704,12 +833,84 @@ def t2i_sdxl(prompt, negative_prompt, model, lora_model, lora_weight, vae_model,
704
  generator=gen
705
  ).images[0]
706
  else:
707
- result = CURRENT_T2I_PIPE(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
708
  prompt,
709
  negative_prompt=negative_prompt,
710
  width=int(w),
711
  height=int(h),
712
- num_inference_steps=int(steps),
 
 
 
 
 
 
 
 
 
 
 
713
  guidance_scale=float(scale),
714
  generator=gen
715
  ).images[0]
@@ -719,7 +920,7 @@ def t2i_sdxl(prompt, negative_prompt, model, lora_model, lora_weight, vae_model,
719
 
720
  return result
721
  except Exception as e:
722
- print(f"❌ Error in t2i_sdxl: {e}")
723
  error_img = Image.new('RGB', (int(w), int(h)), color='red')
724
  from PIL import ImageDraw, ImageFont
725
  draw = ImageDraw.Draw(error_img)
@@ -734,6 +935,7 @@ def unload_all_models():
734
  global CURRENT_CONTROLNET_PIPE, CURRENT_CONTROLNET_KEY
735
  global DETECTORS
736
  global CURRENT_T2I_PIPE, CURRENT_T2I_MODEL, CURRENT_SDXL_REFINER
 
737
 
738
  print("🗑️ Unloading all models from memory...")
739
 
@@ -766,7 +968,15 @@ def unload_all_models():
766
  except:
767
  pass
768
 
 
 
 
 
 
 
 
769
  CURRENT_T2I_MODEL = None
 
770
 
771
  gc.collect()
772
  if torch.cuda.is_available():
@@ -867,7 +1077,7 @@ with gr.Blocks(title="🎨 AI Image Generator Pro", theme=gr.themes.Soft()) as d
867
  with gr.Tab("🎨 SDXL ControlNet"):
868
  gr.Markdown("""
869
  ### Transform sketches/images using SDXL with ControlNet
870
- - **Supports:** canny_sdxl, depth_sdxl, openpose_sdxl
871
  - **Best Resolution:** 1024x1024
872
  - **Higher quality, more VRAM required**
873
  """)
@@ -884,7 +1094,7 @@ with gr.Blocks(title="🎨 AI Image Generator Pro", theme=gr.themes.Soft()) as d
884
  )
885
  controlnet_type_sdxl = gr.Dropdown(
886
  choices=list(CONTROLNET_MODELS_SDXL.keys()),
887
- value="canny_sdxl",
888
  label="ControlNet Type"
889
  )
890
 
@@ -898,7 +1108,7 @@ with gr.Blocks(title="🎨 AI Image Generator Pro", theme=gr.themes.Soft()) as d
898
  lora_weight_sdxl = gr.Slider(0.1, 2.0, 0.8, step=0.1, label="LoRA Weight")
899
 
900
  vae_model_sdxl = gr.Dropdown(
901
- choices=["None", "SDXL VAE"],
902
  value="None",
903
  label="VAE Model (Optional)"
904
  )
@@ -934,6 +1144,73 @@ with gr.Blocks(title="🎨 AI Image Generator Pro", theme=gr.themes.Soft()) as d
934
  [out_sdxl, condition_out_sdxl]
935
  )
936
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
937
  with gr.Tab("🖼️ SD1.5 Text-to-Image"):
938
  gr.Markdown("""
939
  ### Generate images from text descriptions using SD1.5
@@ -999,6 +1276,81 @@ with gr.Blocks(title="🎨 AI Image Generator Pro", theme=gr.themes.Soft()) as d
999
  t2i_out_sd15
1000
  )
1001
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1002
  with gr.Tab("🖼️ SDXL Text-to-Image"):
1003
  gr.Markdown("""
1004
  ### Generate images from text descriptions using SDXL
@@ -1010,7 +1362,7 @@ with gr.Blocks(title="🎨 AI Image Generator Pro", theme=gr.themes.Soft()) as d
1010
  with gr.Column(scale=1):
1011
  gr.Markdown("### Model Configuration")
1012
  t2i_model_sdxl = gr.Dropdown(
1013
- choices=SDXL_MODELS,
1014
  value="stabilityai/stable-diffusion-xl-base-1.0",
1015
  label="SDXL Base Model"
1016
  )
@@ -1073,104 +1425,107 @@ with gr.Blocks(title="🎨 AI Image Generator Pro", theme=gr.themes.Soft()) as d
1073
  gr.Markdown("""
1074
  # Model & Feature Guide
1075
 
1076
- ## 🎯 SD1.5 vs SDXL Comparison
1077
 
1078
  ### SD1.5 (Stable Diffusion 1.5)
1079
- - **Pros:** Faster, lower VRAM usage, many specialized models
1080
- - **Cons:** Lower quality, less detail
1081
- - **Best for:** Quick generations, testing, lower-end hardware
1082
- - **Resolution:** 512x512 optimal
1083
 
1084
  ### SDXL (Stable Diffusion XL)
1085
- - **Pros:** Higher quality, better composition, more detail
1086
- - **Cons:** Slower, higher VRAM usage
1087
- - **Best for:** Final quality images, professional work
1088
- - **Resolution:** 1024x1024 optimal
1089
-
1090
- ## 🎨 ControlNet Types
1091
-
1092
- ### SD1.5 ControlNet (12 types)
1093
- - **lineart/lineart_anime**: Line art to image
1094
- - **canny**: Edge detection
1095
- - **depth**: Depth map based
1096
- - **openpose**: Human pose
1097
- - **normal**: Normal map
1098
- - **softedge**: Soft edges
1099
- - **segmentation**: Semantic segmentation
1100
- - **mlsd**: Straight line detection
1101
- - **shuffle**: Color shuffle
1102
- - **scribble**: Scribble to image
1103
- - **tile**: Upscaling
1104
-
1105
- ### SDXL ControlNet (3 types)
1106
- - **canny_sdxl**: Edge detection
1107
- - **depth_sdxl**: Depth map
1108
- - **openpose_sdxl**: Human pose
1109
-
1110
- ## 💎 Recommended Model Combinations
1111
-
1112
- ### SD1.5 - Realistic Portraits
1113
- - Base: `digiplay/majicMIX_realistic_v7`
1114
- - LoRA: `detail-tweaker`
1115
- - VAE: `SD1.5 VAE`
1116
- - Steps: 30-40
1117
- - CFG: 7-9
1118
-
1119
- ### SD1.5 - Anime Style
1120
- - Base: `digiplay/ChikMix_V3`
1121
- - LoRA: `anime-art`
1122
- - VAE: `Anime VAE`
1123
- - Steps: 25-35
1124
- - CFG: 6-8
1125
-
1126
- ### SDXL - Photorealistic
1127
- - Base: `SG161222/RealVisXL_V4.0`
1128
- - LoRA: `photorealistic`
1129
- - VAE: `SDXL VAE`
1130
- - Use Refiner: Yes
1131
- - Steps: 35-45
1132
- - CFG: 7-10
1133
-
1134
- ### SDXL - Artistic
1135
- - Base: `Lykon/dreamshaper-xl-1-0`
1136
- - LoRA: `watercolor-style`
1137
- - VAE: `SDXL VAE`
1138
- - Steps: 30-40
1139
- - CFG: 6-8
1140
-
1141
- ## ⚙️ Parameter Guidelines
1142
-
1143
- ### Steps
1144
- - **SD1.5:** 20-35 (fast), 35-50 (quality)
1145
- - **SDXL:** 30-45 (fast), 45-60 (quality)
1146
-
1147
- ### CFG Scale
1148
- - **4-6:** Creative, loose interpretation
1149
- - **6-9:** Balanced (recommended)
1150
- - **9-12:** Strict prompt adherence
1151
- - **12+:** Very strict
1152
-
1153
- ### Resolution
1154
- - **SD1.5:** 512x512, 512x768, 768x512 (max 1024x1024)
1155
- - **SDXL:** 1024x1024, 1024x1536, 1536x1024 (max 2048x2048)
1156
-
1157
- ## 🚀 Performance Tips
1158
-
1159
- ### For Low VRAM (<8GB)
1160
  - Use SD1.5 models only
 
1161
  - Enable attention slicing
1162
- - Use lower resolutions (512x512)
1163
- - Reduce steps (20-30)
1164
 
1165
- ### For Medium VRAM (8-12GB)
1166
- - Can use SD1.5 and some SDXL
1167
- - For SDXL, use 1024x1024
1168
  - Enable xFormers
1169
 
1170
- ### For High VRAM (12GB+)
1171
- - Can use all models
1172
- - SDXL with refiner
1173
  - Higher resolutions
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1174
  """)
1175
 
1176
  try:
 
29
  StableDiffusionControlNetPipeline,
30
  ControlNetModel,
31
  StableDiffusionPipeline,
32
+ StableDiffusionXLPipeline,
33
+ StableDiffusionXLControlNetPipeline,
34
+ AutoPipelineForText2Image
35
  )
36
  from diffusers import UniPCMultistepScheduler, DPMSolverMultistepScheduler, EulerAncestralDiscreteScheduler
37
  from controlnet_aux import (
 
62
  CURRENT_T2I_PIPE = None
63
  CURRENT_T2I_MODEL = None
64
  CURRENT_SDXL_REFINER = None
65
+ CURRENT_TURBO_PIPE = None
66
+ CURRENT_TURBO_MODEL = None
67
 
68
  # Enhanced SDXL Models (including NSFW-capable)
69
  SDXL_MODELS = [
70
  "stabilityai/stable-diffusion-xl-base-1.0",
71
  "stabilityai/stable-diffusion-xl-refiner-1.0",
72
+ "stabilityai/sdxl-turbo", # เพิ่ม SDXL-Turbo
73
  "Laxhar/noobai-XL-1.1",
74
  "RunDiffusion/Juggernaut-XL-v9",
75
  "dataautogpt3/ProteusV0.4",
 
81
  "digiplay/Pony_Diffusion_V6_XL"
82
  ]
83
 
84
+ # Turbo models (fast generation)
85
+ TURBO_MODELS = [
86
+ "stabilityai/sdxl-turbo",
87
+ "stabilityai/sd-turbo"
88
+ ]
89
+
90
  # Enhanced SD1.5 Models (including NSFW-capable)
91
  SD15_MODELS = [
92
  # Original models
 
128
  "Fictiverse/Stable_Diffusion_VoxelArt_Model"
129
  ]
130
 
131
+ # Specialized models
132
+ SPECIAL_MODELS = {
133
+ "waifu_colorize": "ShinoharaHare/Waifu-Colorize-XL" # โมเดลสำหรับ colorize โดยเฉพาะ
134
+ }
135
+
136
  # Chinese Models
137
  CHINESE_MODELS = [
138
  "AI-Chen/Chinese-Stable-Diffusion",
 
160
  CONTROLNET_MODELS_SDXL = {
161
  "canny_sdxl": "diffusers/controlnet-canny-sdxl-1.0",
162
  "depth_sdxl": "diffusers/controlnet-depth-sdxl-1.0",
163
+ "openpose_sdxl": "thibaud/controlnet-openpose-sdxl-1.0",
164
+ "lineart_sdxl": "ShermanG/ControlNet-Standard-Lineart-for-SDXL" # เพิ่ม ControlNet Lineart สำหรับ SDXL
165
  }
166
 
167
  # แก้ไข LoRA models ให้ใช้ชื่อที่ไม่มีช่องว่าง
 
206
  "realistic-nsfw": "digiplay/RealisticNSFW_v1",
207
  "anime-nsfw": "Linaqruf/anime-nsfw-lora",
208
  "hentai-diffusion": "Deltaadams/Hentai-Diffusion",
209
+ "sexy-pose": "alvdansen/sexy-pose-lora",
210
+ # Colorize LoRAs
211
+ "colorize-xl": "ShinoharaHare/Waifu-Colorize-XL"
212
  }
213
 
214
  # VAE models for better quality
 
216
  "None": None,
217
  "SD1.5 VAE": "stabilityai/sd-vae-ft-mse",
218
  "Anime VAE": "hakurei/waifu-diffusion-v1-4",
219
+ "SDXL VAE": "madebyollin/sdxl-vae-fp16-fix",
220
+ "Turbo VAE": "madebyollin/sdxl-vae-fp16-fix"
221
  }
222
 
223
  # Detector instances
 
227
  """Check if model is SDXL"""
228
  return model_name in SDXL_MODELS or "xl" in model_name.lower() or "XL" in model_name
229
 
230
+ def is_turbo_model(model_name: str) -> bool:
231
+ """Check if model is Turbo"""
232
+ return model_name in TURBO_MODELS or "turbo" in model_name.lower()
233
+
234
  def load_detector(detector_type: str):
235
  """Lazy load detector"""
236
  global DETECTORS
 
274
  def get_controlnet_model(controlnet_type: str, is_sdxl: bool = False):
275
  """Get ControlNet model based on type"""
276
  if is_sdxl:
277
+ if controlnet_type not in CONTROLNET_MODELS_SDXL:
278
+ raise ValueError(f"SDXL ControlNet type must be one of: {list(CONTROLNET_MODELS_SDXL.keys())}")
279
  return CONTROLNET_MODELS_SDXL[controlnet_type]
280
  else:
281
+ if controlnet_type not in CONTROLNET_MODELS_SD15:
282
+ raise ValueError(f"SD1.5 ControlNet type must be one of: {list(CONTROLNET_MODELS_SD15.keys())}")
283
  return CONTROLNET_MODELS_SD15[controlnet_type]
284
 
285
  def prepare_condition_image(image, controlnet_type, is_sdxl=False):
286
  """Prepare condition image for ControlNet"""
287
+ if "lineart" in controlnet_type:
288
+ detector_type = "lineart_anime" if "anime" in controlnet_type else "lineart"
289
+ detector = load_detector(detector_type)
290
  if detector:
291
  result = detector(image, detect_resolution=512 if not is_sdxl else 1024, image_resolution=512 if not is_sdxl else 1024)
292
  return Image.fromarray(result) if isinstance(result, np.ndarray) else result
 
341
 
342
  try:
343
  is_sdxl = is_sdxl_model(model_name)
344
+ is_turbo = is_turbo_model(model_name)
 
 
 
 
345
 
346
  controlnet_model_name = get_controlnet_model(controlnet_type, is_sdxl)
347
  controlnet = ControlNetModel.from_pretrained(
 
350
  ).to(device)
351
 
352
  if is_sdxl:
353
+ if is_turbo:
354
+ # สำหรับ Turbo models ใช้ pipeline ที่เหมาะสม
355
+ pipe = StableDiffusionXLControlNetPipeline.from_pretrained(
356
+ model_name,
357
+ controlnet=controlnet,
358
+ torch_dtype=dtype,
359
+ safety_checker=None,
360
+ requires_safety_checker=False,
361
+ use_safetensors=True,
362
+ variant="fp16" if dtype == torch.float16 else None
363
+ ).to(device)
364
+ else:
365
+ pipe = StableDiffusionXLControlNetPipeline.from_pretrained(
366
+ model_name,
367
+ controlnet=controlnet,
368
+ torch_dtype=dtype,
369
+ safety_checker=None,
370
+ requires_safety_checker=False,
371
+ use_safetensors=True,
372
+ variant="fp16" if dtype == torch.float16 else None
373
+ ).to(device)
374
  else:
375
  pipe = StableDiffusionControlNetPipeline.from_pretrained(
376
  model_name,
 
425
  pass
426
  pipe.enable_model_cpu_offload()
427
 
428
+ # ใช้ scheduler ที่เหมาะสมสำหรับแต่ละโมเดล
429
+ if is_turbo:
430
+ # สำหรับ Turbo models ใช้ scheduler ที่เร็วขึ้น
 
431
  try:
432
+ pipe.scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.config)
433
+ print("✅ Using UniPC scheduler for Turbo")
434
  except:
435
  pass
436
+ else:
437
+ try:
438
+ pipe.scheduler = EulerAncestralDiscreteScheduler.from_config(pipe.scheduler.config)
439
+ print("✅ Using Euler Ancestral scheduler")
440
+ except:
441
+ try:
442
+ pipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)
443
+ except:
444
+ pass
445
 
446
  CURRENT_CONTROLNET_PIPE = pipe
447
  CURRENT_CONTROLNET_KEY = key
 
456
  def load_t2i_model(model_name: str, lora_model: str = None, lora_weight: float = 0.8,
457
  vae_model: str = None):
458
  """Load text-to-image model with optional LoRA and VAE"""
459
+ global CURRENT_T2I_PIPE, CURRENT_T2I_MODEL, CURRENT_SDXL_REFINER, CURRENT_TURBO_PIPE, CURRENT_TURBO_MODEL
460
 
461
+ is_turbo = is_turbo_model(model_name)
462
+ use_refiner = "refiner" in model_name.lower() and not is_turbo
463
 
464
+ key = (model_name, lora_model, lora_weight, vae_model, use_refiner, is_turbo)
 
465
 
466
+ if is_turbo:
467
+ if CURRENT_TURBO_MODEL == key and CURRENT_TURBO_PIPE is not None:
468
+ return
469
+ else:
470
+ if CURRENT_T2I_MODEL == key and CURRENT_T2I_PIPE is not None:
471
+ return
472
+
473
+ if is_turbo:
474
+ if CURRENT_TURBO_PIPE is not None:
475
+ print(f"🗑️ Unloading old Turbo model: {CURRENT_TURBO_MODEL}")
476
+ del CURRENT_TURBO_PIPE
477
+ CURRENT_TURBO_PIPE = None
478
+ else:
479
+ if CURRENT_T2I_PIPE is not None:
480
+ print(f"🗑️ Unloading old T2I model: {CURRENT_T2I_MODEL}")
481
+ del CURRENT_T2I_PIPE
482
+ CURRENT_T2I_PIPE = None
483
+ if CURRENT_SDXL_REFINER is not None:
484
+ del CURRENT_SDXL_REFINER
485
+ CURRENT_SDXL_REFINER = None
486
+
487
+ gc.collect()
488
+ if torch.cuda.is_available():
489
+ torch.cuda.empty_cache()
490
 
491
  print(f"📥 Loading T2I model: {model_name}")
492
 
493
  try:
494
+ if is_turbo:
495
+ # โหลด Turbo model
496
+ CURRENT_TURBO_PIPE = AutoPipelineForText2Image.from_pretrained(
497
+ model_name,
498
+ torch_dtype=dtype,
499
+ safety_checker=None,
500
+ requires_safety_checker=False,
501
+ use_safetensors=True,
502
+ variant="fp16" if dtype == torch.float16 else None
503
+ ).to(device)
504
+
505
+ CURRENT_TURBO_MODEL = key
506
+ pipe = CURRENT_TURBO_PIPE
507
+ elif is_sdxl_model(model_name):
508
  if use_refiner:
509
  CURRENT_T2I_PIPE = StableDiffusionXLPipeline.from_pretrained(
510
  "stabilityai/stable-diffusion-xl-base-1.0",
 
534
  use_safetensors=True,
535
  variant="fp16" if dtype == torch.float16 else None
536
  ).to(device)
537
+
538
+ CURRENT_T2I_MODEL = key
539
+ pipe = CURRENT_T2I_PIPE
540
  else:
541
  CURRENT_T2I_PIPE = StableDiffusionPipeline.from_pretrained(
542
  model_name,
 
546
  use_safetensors=True,
547
  variant="fp16" if dtype == torch.float16 else None
548
  ).to(device)
549
+
550
+ CURRENT_T2I_MODEL = key
551
+ pipe = CURRENT_T2I_PIPE
552
 
553
  # Load custom VAE
554
  if vae_model and vae_model != "None":
 
556
  from diffusers import AutoencoderKL
557
  print(f"🔄 Loading custom VAE: {vae_model}")
558
  vae = AutoencoderKL.from_pretrained(vae_model, torch_dtype=dtype).to(device)
559
+ pipe.vae = vae
560
  except Exception as e:
561
  print(f"⚠️ Error loading VAE: {e}")
562
 
 
566
  try:
567
  if lora_model in LORA_MODELS:
568
  lora_path = LORA_MODELS[lora_model]
569
+ pipe.load_lora_weights(lora_path)
570
+ pipe.fuse_lora(lora_scale=lora_weight)
571
  else:
572
+ pipe.load_lora_weights(lora_model)
573
+ pipe.fuse_lora(lora_scale=lora_weight)
574
  except Exception as e:
575
  print(f"⚠️ Error loading LoRA: {e}")
576
 
577
  # Optimizations
578
+ pipe.enable_attention_slicing(slice_size="max")
579
 
580
+ if hasattr(pipe, 'vae') and hasattr(pipe.vae, 'enable_slicing'):
581
+ pipe.vae.enable_slicing()
582
  else:
583
  try:
584
+ pipe.enable_vae_slicing()
585
  except:
586
  pass
587
 
588
  if device.type == "cuda":
589
  try:
590
+ pipe.enable_xformers_memory_efficient_attention()
591
  except:
592
  pass
593
+ pipe.enable_model_cpu_offload()
 
 
 
 
 
594
 
595
+ # ตั้งค่า scheduler
596
+ if is_turbo:
597
+ try:
598
+ pipe.scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.config)
599
+ print("✅ Using UniPC scheduler for Turbo")
600
+ except:
601
+ pass
602
+ else:
603
+ try:
604
+ pipe.scheduler = EulerAncestralDiscreteScheduler.from_config(pipe.scheduler.config)
605
+ except:
606
+ pass
607
 
608
  except Exception as e:
609
  print(f"❌ Error loading T2I model: {e}")
610
+ if is_turbo:
611
+ CURRENT_TURBO_PIPE = None
612
+ CURRENT_TURBO_MODEL = None
613
+ else:
614
+ CURRENT_T2I_PIPE = None
615
+ CURRENT_T2I_MODEL = None
616
  raise
617
 
618
  def colorize_sd15(sketch, base_model, controlnet_type, lora_model, lora_weight, vae_model,
 
705
  error_img = Image.new('RGB', (1024, 1024), color='red')
706
  return error_img, Image.new('RGB', (1024, 1024), color='gray')
707
 
708
+ def colorize_waifu_xl(sketch, lora_weight, vae_model, prompt, negative_prompt, seed, steps, scale, cn_weight):
709
+ """Colorize function specifically for Waifu-Colorize-XL model"""
710
+ try:
711
+ model_name = "stabilityai/stable-diffusion-xl-base-1.0"
712
+ controlnet_type = "lineart_sdxl"
713
+ lora_model = "colorize-xl"
714
+
715
+ pipe = get_pipeline(model_name, controlnet_type, lora_model, lora_weight, vae_model)
716
+
717
+ status_msg = f"🎨 Using: Waifu-Colorize-XL (Lineart ControlNet)"
718
+ print(status_msg)
719
+
720
+ condition_img = prepare_condition_image(sketch, controlnet_type, is_sdxl=True)
721
+
722
+ gen = torch.Generator(device=device).manual_seed(int(seed))
723
+
724
+ # สำหรับ Waifu-Colorize-XL ใช้ prompt พิเศษ
725
+ enhanced_prompt = f"colorized, vibrant colors, anime style, {prompt}" if prompt else "colorized, vibrant colors, anime style, masterpiece"
726
+
727
+ with torch.inference_mode():
728
+ out = pipe(
729
+ enhanced_prompt,
730
+ negative_prompt=negative_prompt,
731
+ image=condition_img,
732
+ num_inference_steps=int(steps),
733
+ guidance_scale=float(scale),
734
+ controlnet_conditioning_scale=float(cn_weight),
735
+ generator=gen,
736
+ height=1024,
737
+ width=1024
738
+ ).images[0]
739
+
740
+ if device.type == "cuda":
741
+ torch.cuda.empty_cache()
742
+
743
+ return out, condition_img
744
+ except Exception as e:
745
+ print(f"❌ Error in colorize_waifu_xl: {e}")
746
+ error_img = Image.new('RGB', (1024, 1024), color='red')
747
+ return error_img, Image.new('RGB', (1024, 1024), color='gray')
748
+
749
  def t2i_sd15(prompt, negative_prompt, model, lora_model, lora_weight, vae_model,
750
  seed, steps, scale, w, h):
751
  """Text-to-image for SD1.5 models"""
 
798
  return error_img
799
 
800
  model_to_load = model
801
+ if use_refiner and "refiner" not in model.lower() and not is_turbo_model(model):
802
  model_to_load = "stabilityai/stable-diffusion-xl-refiner-1.0"
803
 
804
  load_t2i_model(model_to_load, lora_model, lora_weight, vae_model)
 
812
  gen = torch.Generator(device=device).manual_seed(int(seed))
813
 
814
  with torch.inference_mode():
815
+ if use_refiner and CURRENT_SDXL_REFINER is not None and not is_turbo_model(model):
816
  image = CURRENT_T2I_PIPE(
817
  prompt=prompt,
818
  negative_prompt=negative_prompt,
 
833
  generator=gen
834
  ).images[0]
835
  else:
836
+ if is_turbo_model(model):
837
+ # สำหรับ Turbo models ใช้ steps น้อยลง
838
+ turbo_steps = max(1, min(10, int(steps)))
839
+ result = CURRENT_TURBO_PIPE(
840
+ prompt,
841
+ negative_prompt=negative_prompt,
842
+ width=int(w),
843
+ height=int(h),
844
+ num_inference_steps=turbo_steps,
845
+ guidance_scale=float(scale),
846
+ generator=gen
847
+ ).images[0]
848
+ else:
849
+ result = CURRENT_T2I_PIPE(
850
+ prompt,
851
+ negative_prompt=negative_prompt,
852
+ width=int(w),
853
+ height=int(h),
854
+ num_inference_steps=int(steps),
855
+ guidance_scale=float(scale),
856
+ generator=gen
857
+ ).images[0]
858
+
859
+ if device.type == "cuda":
860
+ torch.cuda.empty_cache()
861
+
862
+ return result
863
+ except Exception as e:
864
+ print(f"❌ Error in t2i_sdxl: {e}")
865
+ error_img = Image.new('RGB', (int(w), int(h)), color='red')
866
+ from PIL import ImageDraw, ImageFont
867
+ draw = ImageDraw.Draw(error_img)
868
+ try:
869
+ font = ImageFont.truetype("arial.ttf", 20)
870
+ except:
871
+ font = ImageFont.load_default()
872
+ draw.text((50, 50), f"Error: {str(e)[:50]}...", fill="white", font=font)
873
+ return error_img
874
+
875
+ def t2i_turbo(prompt, negative_prompt, model, lora_model, lora_weight, vae_model,
876
+ seed, steps, scale, w, h):
877
+ """Text-to-image for Turbo models (fast generation)"""
878
+ try:
879
+ if model not in TURBO_MODELS:
880
+ error_img = Image.new('RGB', (int(w), int(h)), color='red')
881
+ return error_img
882
+
883
+ load_t2i_model(model, lora_model, lora_weight, vae_model)
884
+
885
+ print(f"⚡ Using Turbo model: {model}")
886
+ if lora_model and lora_model != "None":
887
+ print(f" with LoRA: {lora_model} (weight: {lora_weight})")
888
+
889
+ gen = torch.Generator(device=device).manual_seed(int(seed))
890
+
891
+ with torch.inference_mode():
892
+ # สำหรับ Turbo models ใช้ steps น้อยลง (1-10 steps)
893
+ turbo_steps = max(1, min(10, int(steps)))
894
+
895
+ if is_sdxl_model(model):
896
+ # SDXL-Turbo
897
+ result = CURRENT_TURBO_PIPE(
898
  prompt,
899
  negative_prompt=negative_prompt,
900
  width=int(w),
901
  height=int(h),
902
+ num_inference_steps=turbo_steps,
903
+ guidance_scale=float(scale),
904
+ generator=gen
905
+ ).images[0]
906
+ else:
907
+ # SD-Turbo
908
+ result = CURRENT_TURBO_PIPE(
909
+ prompt,
910
+ negative_prompt=negative_prompt,
911
+ width=int(w),
912
+ height=int(h),
913
+ num_inference_steps=turbo_steps,
914
  guidance_scale=float(scale),
915
  generator=gen
916
  ).images[0]
 
920
 
921
  return result
922
  except Exception as e:
923
+ print(f"❌ Error in t2i_turbo: {e}")
924
  error_img = Image.new('RGB', (int(w), int(h)), color='red')
925
  from PIL import ImageDraw, ImageFont
926
  draw = ImageDraw.Draw(error_img)
 
935
  global CURRENT_CONTROLNET_PIPE, CURRENT_CONTROLNET_KEY
936
  global DETECTORS
937
  global CURRENT_T2I_PIPE, CURRENT_T2I_MODEL, CURRENT_SDXL_REFINER
938
+ global CURRENT_TURBO_PIPE, CURRENT_TURBO_MODEL
939
 
940
  print("🗑️ Unloading all models from memory...")
941
 
 
968
  except:
969
  pass
970
 
971
+ try:
972
+ if CURRENT_TURBO_PIPE is not None:
973
+ del CURRENT_TURBO_PIPE
974
+ CURRENT_TURBO_PIPE = None
975
+ except:
976
+ pass
977
+
978
  CURRENT_T2I_MODEL = None
979
+ CURRENT_TURBO_MODEL = None
980
 
981
  gc.collect()
982
  if torch.cuda.is_available():
 
1077
  with gr.Tab("🎨 SDXL ControlNet"):
1078
  gr.Markdown("""
1079
  ### Transform sketches/images using SDXL with ControlNet
1080
+ - **Supports:** canny_sdxl, depth_sdxl, openpose_sdxl, lineart_sdxl (new!)
1081
  - **Best Resolution:** 1024x1024
1082
  - **Higher quality, more VRAM required**
1083
  """)
 
1094
  )
1095
  controlnet_type_sdxl = gr.Dropdown(
1096
  choices=list(CONTROLNET_MODELS_SDXL.keys()),
1097
+ value="lineart_sdxl",
1098
  label="ControlNet Type"
1099
  )
1100
 
 
1108
  lora_weight_sdxl = gr.Slider(0.1, 2.0, 0.8, step=0.1, label="LoRA Weight")
1109
 
1110
  vae_model_sdxl = gr.Dropdown(
1111
+ choices=["None", "SDXL VAE", "Turbo VAE"],
1112
  value="None",
1113
  label="VAE Model (Optional)"
1114
  )
 
1144
  [out_sdxl, condition_out_sdxl]
1145
  )
1146
 
1147
+ with gr.Tab("🌸 Waifu-Colorize-XL"):
1148
+ gr.Markdown("""
1149
+ ### Specialized Anime Lineart Colorization
1150
+ - **Model:** ShinoharaHare/Waifu-Colorize-XL
1151
+ - **Specialized for:** Anime/manga lineart coloring
1152
+ - **Features:** Automatic colorization with vibrant anime colors
1153
+ - **Best Resolution:** 1024x1024
1154
+ """)
1155
+
1156
+ with gr.Row():
1157
+ with gr.Column(scale=1):
1158
+ inp_waifu = gr.Image(label="Input Lineart/Sketch", type="pil")
1159
+
1160
+ gr.Markdown("### Model Settings")
1161
+ gr.Markdown("**Using:** ShinoharaHare/Waifu-Colorize-XL (Specialized Anime Colorization)")
1162
+
1163
+ gr.Markdown("### Enhancement Options")
1164
+ with gr.Row():
1165
+ lora_weight_waifu = gr.Slider(0.1, 2.0, 1.0, step=0.1, label="LoRA Weight")
1166
+
1167
+ vae_model_waifu = gr.Dropdown(
1168
+ choices=["None", "SDXL VAE"],
1169
+ value="None",
1170
+ label="VAE Model (Optional)"
1171
+ )
1172
+
1173
+ with gr.Column(scale=1):
1174
+ out_waifu = gr.Image(label="Colorized Output")
1175
+ condition_out_waifu = gr.Image(label="Processed Lineart", type="pil")
1176
+
1177
+ gr.Markdown("### Generation Parameters")
1178
+ with gr.Row():
1179
+ prompt_waifu = gr.Textbox(
1180
+ label="Color Style Prompt (Optional)",
1181
+ placeholder="vibrant colors, anime style, beautiful coloring, masterpiece",
1182
+ lines=2
1183
+ )
1184
+ negative_prompt_waifu = gr.Textbox(
1185
+ label="Negative Prompt",
1186
+ placeholder="monochrome, grayscale, black and white, sketch, lineart only",
1187
+ lines=2,
1188
+ value="monochrome, grayscale, black and white, sketch, lineart only"
1189
+ )
1190
+
1191
+ with gr.Row():
1192
+ seed_waifu = gr.Number(value=-1, label="Seed (-1 for random)")
1193
+ steps_waifu = gr.Slider(10, 50, 25, step=1, label="Steps")
1194
+ scale_waifu = gr.Slider(1, 20, 7.5, step=0.5, label="CFG Scale")
1195
+ cn_weight_waifu = gr.Slider(0.1, 2.0, 1.2, step=0.1, label="ControlNet Weight")
1196
+
1197
+ gr.Markdown("### Tips for Best Results:")
1198
+ gr.Markdown("""
1199
+ 1. Use clean lineart for best results
1200
+ 2. Higher ControlNet weight (1.0-1.5) for better line following
1201
+ 3. Lower CFG scale (5-8) for more natural coloring
1202
+ 4. Add color hints in prompt (e.g., "blue hair, red eyes, pink dress")
1203
+ 5. Keep prompts simple for this specialized model
1204
+ """)
1205
+
1206
+ run_waifu = gr.Button("🌸 Colorize with Waifu-Colorize-XL", variant="primary", size="lg")
1207
+ run_waifu.click(
1208
+ colorize_waifu_xl,
1209
+ [inp_waifu, lora_weight_waifu, vae_model_waifu,
1210
+ prompt_waifu, negative_prompt_waifu, seed_waifu, steps_waifu, scale_waifu, cn_weight_waifu],
1211
+ [out_waifu, condition_out_waifu]
1212
+ )
1213
+
1214
  with gr.Tab("🖼️ SD1.5 Text-to-Image"):
1215
  gr.Markdown("""
1216
  ### Generate images from text descriptions using SD1.5
 
1276
  t2i_out_sd15
1277
  )
1278
 
1279
+ with gr.Tab("⚡ SDXL-Turbo Text-to-Image"):
1280
+ gr.Markdown("""
1281
+ ### Ultra-Fast Image Generation with SDXL-Turbo
1282
+ - **Model:** stabilityai/sdxl-turbo
1283
+ - **Features:** 1-4 steps generation, extremely fast
1284
+ - **Best Resolution:** 512x512 to 1024x1024
1285
+ - **Warning:** Lower quality than full SDXL but much faster
1286
+ """)
1287
+
1288
+ with gr.Row():
1289
+ with gr.Column(scale=1):
1290
+ gr.Markdown("### Model Configuration")
1291
+ t2i_model_turbo = gr.Dropdown(
1292
+ choices=TURBO_MODELS,
1293
+ value="stabilityai/sdxl-turbo",
1294
+ label="Turbo Model"
1295
+ )
1296
+
1297
+ gr.Markdown("### Enhancement Options")
1298
+ with gr.Row():
1299
+ t2i_lora_turbo = gr.Dropdown(
1300
+ choices=list(LORA_MODELS.keys()),
1301
+ value="None",
1302
+ label="LoRA Model"
1303
+ )
1304
+ t2i_lora_weight_turbo = gr.Slider(0.1, 2.0, 0.8, step=0.1, label="LoRA Weight")
1305
+
1306
+ t2i_vae_turbo = gr.Dropdown(
1307
+ choices=["None", "Turbo VAE", "SDXL VAE"],
1308
+ value="None",
1309
+ label="VAE Model"
1310
+ )
1311
+
1312
+ with gr.Column(scale=1):
1313
+ t2i_out_turbo = gr.Image(label="Generated Image", type="pil")
1314
+
1315
+ gr.Markdown("### Prompts")
1316
+ with gr.Row():
1317
+ t2i_prompt_turbo = gr.Textbox(
1318
+ label="Prompt",
1319
+ lines=4,
1320
+ placeholder="masterpiece, best quality, highly detailed, beautiful, 1girl"
1321
+ )
1322
+ t2i_negative_prompt_turbo = gr.Textbox(
1323
+ label="Negative Prompt",
1324
+ lines=4,
1325
+ placeholder="lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality"
1326
+ )
1327
+
1328
+ gr.Markdown("### Generation Parameters (Turbo needs only 1-4 steps!)")
1329
+ with gr.Row():
1330
+ t2i_seed_turbo = gr.Number(value=-1, label="Seed (-1 for random)")
1331
+ t2i_steps_turbo = gr.Slider(1, 10, 4, step=1, label="Steps (1-4 recommended)")
1332
+ t2i_scale_turbo = gr.Slider(0, 10, 0.0, step=0.5, label="CFG Scale (0-2 recommended)")
1333
+
1334
+ with gr.Row():
1335
+ w_turbo = gr.Slider(256, 1024, 512, step=64, label="Width")
1336
+ h_turbo = gr.Slider(256, 1024, 512, step=64, label="Height")
1337
+
1338
+ gr.Markdown("### Turbo Model Tips:")
1339
+ gr.Markdown("""
1340
+ 1. **Use very few steps:** 1-4 steps is enough!
1341
+ 2. **Low CFG Scale:** 0.0-2.0 works best
1342
+ 3. **Fast but lower quality:** For quick previews/testing
1343
+ 4. **Works well with:** Simple prompts, concept testing
1344
+ """)
1345
+
1346
+ gen_btn_turbo = gr.Button("⚡ Generate with Turbo (Fast!)", variant="primary", size="lg")
1347
+ gen_btn_turbo.click(
1348
+ t2i_turbo,
1349
+ [t2i_prompt_turbo, t2i_negative_prompt_turbo, t2i_model_turbo, t2i_lora_turbo, t2i_lora_weight_turbo,
1350
+ t2i_vae_turbo, t2i_seed_turbo, t2i_steps_turbo, t2i_scale_turbo, w_turbo, h_turbo],
1351
+ t2i_out_turbo
1352
+ )
1353
+
1354
  with gr.Tab("🖼️ SDXL Text-to-Image"):
1355
  gr.Markdown("""
1356
  ### Generate images from text descriptions using SDXL
 
1362
  with gr.Column(scale=1):
1363
  gr.Markdown("### Model Configuration")
1364
  t2i_model_sdxl = gr.Dropdown(
1365
+ choices=[m for m in SDXL_MODELS if m not in TURBO_MODELS], # ไม่รวม Turbo models
1366
  value="stabilityai/stable-diffusion-xl-base-1.0",
1367
  label="SDXL Base Model"
1368
  )
 
1425
  gr.Markdown("""
1426
  # Model & Feature Guide
1427
 
1428
+ ## 🎯 Model Comparison
1429
 
1430
  ### SD1.5 (Stable Diffusion 1.5)
1431
+ - **Pros:** Fast, low VRAM, many models
1432
+ - **Cons:** 512px max, lower quality
1433
+ - **Best for:** Quick tests, anime, lower-end hardware
 
1434
 
1435
  ### SDXL (Stable Diffusion XL)
1436
+ - **Pros:** 1024px+, high quality, better composition
1437
+ - **Cons:** High VRAM, slower
1438
+ - **Best for:** Final quality, professional work
1439
+
1440
+ ### SDXL-Turbo
1441
+ - **Pros:** Extremely fast (1-4 steps!)
1442
+ - **Cons:** Lower quality than full SDXL
1443
+ - **Best for:** Quick previews, concept testing
1444
+
1445
+ ### Waifu-Colorize-XL
1446
+ - **Pros:** Specialized for anime lineart coloring
1447
+ - **Cons:** Anime-only, requires clean lineart
1448
+ - **Best for:** Anime/manga colorization
1449
+
1450
+ ## 🎨 New ControlNet for SDXL
1451
+
1452
+ ### Lineart ControlNet for SDXL
1453
+ - **Model:** ShermanG/ControlNet-Standard-Lineart-for-SDXL
1454
+ - **Purpose:** Convert lineart to colored images
1455
+ - **Best with:** Clean lineart, anime/manga styles
1456
+ - **Used in:** Waifu-Colorize-XL Tab
1457
+
1458
+ ## 💎 Recommended Workflows
1459
+
1460
+ ### For Anime/Manga Artists
1461
+ 1. Draw lineart
1462
+ 2. Use **Waifu-Colorize-XL** Tab for automatic coloring
1463
+ 3. Or use **SDXL ControlNet** with lineart_sdxl
1464
+
1465
+ ### For Quick Concepts
1466
+ 1. Use **SDXL-Turbo** Tab for 1-4 step generation
1467
+ 2. Refine in **SDXL Text-to-Image** if needed
1468
+
1469
+ ### For Professional Work
1470
+ 1. Use **SDXL Text-to-Image** with Refiner
1471
+ 2. High steps (40-50), CFG 7-9
1472
+ 3. 1024x1024 resolution
1473
+
1474
+ ## Turbo Model Tips
1475
+
1476
+ ### SDXL-Turbo Best Practices:
1477
+ - **Steps:** 1-4 only!
1478
+ - **CFG Scale:** 0.0-2.0
1479
+ - **Prompts:** Keep simple
1480
+ - **Resolution:** 512x512 to 1024x1024
1481
+ - **Use case:** Storyboarding, concept art, quick iterations
1482
+
1483
+ ## 🌸 Waifu-Colorize-XL Tips
1484
+
1485
+ ### For Best Results:
1486
+ 1. **Clean lineart:** No stray marks
1487
+ 2. **ControlNet weight:** 1.0-1.5
1488
+ 3. **CFG Scale:** 5-8
1489
+ 4. **Simple prompts:** "vibrant colors, anime style"
1490
+ 5. **Resolution:** 1024x1024
1491
+
1492
+ ### Example Workflow:
1493
+ 1. Draw/sketch in your favorite app
1494
+ 2. Export as clean lineart (black on white)
1495
+ 3. Upload to Waifu-Colorize-XL Tab
1496
+ 4. Adjust parameters as needed
1497
+ 5. Generate and refine
1498
+
1499
+ ## 🚀 Performance Optimization
1500
+
1501
+ ### Low VRAM (<8GB)
 
 
 
 
 
 
 
 
 
1502
  - Use SD1.5 models only
1503
+ - 512x512 resolution
1504
  - Enable attention slicing
 
 
1505
 
1506
+ ### Medium VRAM (8-12GB)
1507
+ - SD1.5 and SDXL (no refiner)
1508
+ - 1024x1024 for SDXL
1509
  - Enable xFormers
1510
 
1511
+ ### High VRAM (12GB+)
1512
+ - All models including SDXL with refiner
 
1513
  - Higher resolutions
1514
+ - Multiple LoRAs
1515
+
1516
+ ## 🔄 Memory Management
1517
+
1518
+ ### When to Unload Models:
1519
+ 1. Switching between SD1.5 and SDXL
1520
+ 2. Getting "out of memory" errors
1521
+ 3. Changing ControlNet types
1522
+ 4. After long generation sessions
1523
+
1524
+ ### Memory Saving Tips:
1525
+ 1. Use "Unload All Models" button
1526
+ 2. Generate in batches
1527
+ 3. Lower resolution for testing
1528
+ 4. Close other GPU applications
1529
  """)
1530
 
1531
  try: