Upload app.py with huggingface_hub
Browse files
app.py
CHANGED
|
@@ -237,16 +237,17 @@ def resolve_scheduler_name(scheduler_name):
|
|
| 237 |
logger.warning(f"Unknown scheduler: {scheduler_name}, using default: {DEFAULT_SCHEDULER}")
|
| 238 |
return DEFAULT_SCHEDULER
|
| 239 |
|
| 240 |
-
def
|
| 241 |
"""
|
| 242 |
-
|
|
|
|
| 243 |
|
| 244 |
Args:
|
| 245 |
-
|
| 246 |
scheduler_name: Имя scheduler или его алиас
|
| 247 |
|
| 248 |
Returns:
|
| 249 |
-
|
| 250 |
"""
|
| 251 |
# Разрешаем алиас
|
| 252 |
scheduler_name = resolve_scheduler_name(scheduler_name)
|
|
@@ -260,20 +261,20 @@ def switch_scheduler(pipeline, scheduler_name):
|
|
| 260 |
scheduler_config = scheduler_info["config"]
|
| 261 |
|
| 262 |
try:
|
| 263 |
-
# Создаем
|
|
|
|
| 264 |
new_scheduler = scheduler_class.from_config(
|
| 265 |
-
|
| 266 |
**scheduler_config
|
| 267 |
)
|
| 268 |
|
| 269 |
-
|
| 270 |
-
|
| 271 |
|
| 272 |
except Exception as e:
|
| 273 |
-
logger.error(f" [X] Error
|
| 274 |
-
logger.
|
| 275 |
-
|
| 276 |
-
return pipeline
|
| 277 |
|
| 278 |
# =================================================================
|
| 279 |
# HELPER FUNCTIONS
|
|
@@ -449,9 +450,6 @@ def generate_text2img(
|
|
| 449 |
logger.info("TEXT-TO-IMAGE GENERATION")
|
| 450 |
logger.info("=" * 60)
|
| 451 |
|
| 452 |
-
# Switch scheduler if needed
|
| 453 |
-
switch_scheduler(pipe_txt2img, scheduler_name)
|
| 454 |
-
|
| 455 |
if randomize_seed:
|
| 456 |
seed = random.randint(0, MAX_SEED)
|
| 457 |
|
|
@@ -462,7 +460,16 @@ def generate_text2img(
|
|
| 462 |
logger.info(f" Scheduler: {scheduler_name}")
|
| 463 |
logger.info(f" LoRA: {lora_name} (scale: {lora_scale})")
|
| 464 |
|
|
|
|
|
|
|
|
|
|
| 465 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 466 |
# Загружаем LoRA если выбрана
|
| 467 |
trigger_word = None
|
| 468 |
if lora_name != "None":
|
|
@@ -496,6 +503,9 @@ def generate_text2img(
|
|
| 496 |
except Exception as e:
|
| 497 |
logger.error(f" [X] Error: {e}")
|
| 498 |
raise
|
|
|
|
|
|
|
|
|
|
| 499 |
|
| 500 |
@gpu_decorator(duration=180)
|
| 501 |
def generate_img2img(
|
|
@@ -518,9 +528,6 @@ def generate_img2img(
|
|
| 518 |
logger.info("IMAGE-TO-IMAGE GENERATION")
|
| 519 |
logger.info("=" * 60)
|
| 520 |
|
| 521 |
-
# Switch scheduler if needed
|
| 522 |
-
switch_scheduler(pipe_img2img, scheduler_name)
|
| 523 |
-
|
| 524 |
if input_image is None:
|
| 525 |
raise gr.Error("Please upload an input image")
|
| 526 |
|
|
@@ -537,10 +544,19 @@ def generate_img2img(
|
|
| 537 |
logger.info(f" Scheduler: {scheduler_name}")
|
| 538 |
logger.info(f" LoRA: {lora_name}")
|
| 539 |
|
|
|
|
|
|
|
|
|
|
| 540 |
try:
|
| 541 |
if pipe_img2img is None:
|
| 542 |
raise gr.Error("Image2Image pipeline not available")
|
| 543 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 544 |
# Загружаем LoRA если выбрана
|
| 545 |
trigger_word = None
|
| 546 |
if lora_name != "None":
|
|
@@ -573,6 +589,10 @@ def generate_img2img(
|
|
| 573 |
except Exception as e:
|
| 574 |
logger.error(f" [X] Error: {e}")
|
| 575 |
raise
|
|
|
|
|
|
|
|
|
|
|
|
|
| 576 |
|
| 577 |
# ControlNet функция убрана - не используется
|
| 578 |
|
|
|
|
| 237 |
logger.warning(f"Unknown scheduler: {scheduler_name}, using default: {DEFAULT_SCHEDULER}")
|
| 238 |
return DEFAULT_SCHEDULER
|
| 239 |
|
| 240 |
+
def get_scheduler(base_scheduler, scheduler_name):
|
| 241 |
"""
|
| 242 |
+
Создает новый scheduler на основе базового
|
| 243 |
+
Thread-safe: создает новый объект вместо изменения существующего
|
| 244 |
|
| 245 |
Args:
|
| 246 |
+
base_scheduler: Базовый scheduler из pipeline
|
| 247 |
scheduler_name: Имя scheduler или его алиас
|
| 248 |
|
| 249 |
Returns:
|
| 250 |
+
Новый scheduler объект
|
| 251 |
"""
|
| 252 |
# Разрешаем алиас
|
| 253 |
scheduler_name = resolve_scheduler_name(scheduler_name)
|
|
|
|
| 261 |
scheduler_config = scheduler_info["config"]
|
| 262 |
|
| 263 |
try:
|
| 264 |
+
# Создаем НОВЫЙ scheduler с конфигом базового + дополнительными параметрами
|
| 265 |
+
# Это thread-safe подход - не меняем глобальный pipeline
|
| 266 |
new_scheduler = scheduler_class.from_config(
|
| 267 |
+
base_scheduler.config,
|
| 268 |
**scheduler_config
|
| 269 |
)
|
| 270 |
|
| 271 |
+
logger.info(f" Created scheduler: {scheduler_name} ({scheduler_info['alias']})")
|
| 272 |
+
return new_scheduler
|
| 273 |
|
| 274 |
except Exception as e:
|
| 275 |
+
logger.error(f" [X] Error creating scheduler: {e}")
|
| 276 |
+
logger.warning(f" Using base scheduler instead")
|
| 277 |
+
return base_scheduler
|
|
|
|
| 278 |
|
| 279 |
# =================================================================
|
| 280 |
# HELPER FUNCTIONS
|
|
|
|
| 450 |
logger.info("TEXT-TO-IMAGE GENERATION")
|
| 451 |
logger.info("=" * 60)
|
| 452 |
|
|
|
|
|
|
|
|
|
|
| 453 |
if randomize_seed:
|
| 454 |
seed = random.randint(0, MAX_SEED)
|
| 455 |
|
|
|
|
| 460 |
logger.info(f" Scheduler: {scheduler_name}")
|
| 461 |
logger.info(f" LoRA: {lora_name} (scale: {lora_scale})")
|
| 462 |
|
| 463 |
+
# Сохраняем оригинальный scheduler ДО try блока (для finally)
|
| 464 |
+
original_scheduler = pipe_txt2img.scheduler
|
| 465 |
+
|
| 466 |
try:
|
| 467 |
+
# Создаем scheduler (thread-safe)
|
| 468 |
+
current_scheduler = get_scheduler(pipe_txt2img.scheduler, scheduler_name)
|
| 469 |
+
|
| 470 |
+
# Устанавливаем новый scheduler
|
| 471 |
+
pipe_txt2img.scheduler = current_scheduler
|
| 472 |
+
|
| 473 |
# Загружаем LoRA если выбрана
|
| 474 |
trigger_word = None
|
| 475 |
if lora_name != "None":
|
|
|
|
| 503 |
except Exception as e:
|
| 504 |
logger.error(f" [X] Error: {e}")
|
| 505 |
raise
|
| 506 |
+
finally:
|
| 507 |
+
# Восстанавливаем оригинальный scheduler (thread-safety)
|
| 508 |
+
pipe_txt2img.scheduler = original_scheduler
|
| 509 |
|
| 510 |
@gpu_decorator(duration=180)
|
| 511 |
def generate_img2img(
|
|
|
|
| 528 |
logger.info("IMAGE-TO-IMAGE GENERATION")
|
| 529 |
logger.info("=" * 60)
|
| 530 |
|
|
|
|
|
|
|
|
|
|
| 531 |
if input_image is None:
|
| 532 |
raise gr.Error("Please upload an input image")
|
| 533 |
|
|
|
|
| 544 |
logger.info(f" Scheduler: {scheduler_name}")
|
| 545 |
logger.info(f" LoRA: {lora_name}")
|
| 546 |
|
| 547 |
+
# Сохраняем оригинальный scheduler ДО try блока (для finally)
|
| 548 |
+
original_scheduler = pipe_img2img.scheduler if pipe_img2img else None
|
| 549 |
+
|
| 550 |
try:
|
| 551 |
if pipe_img2img is None:
|
| 552 |
raise gr.Error("Image2Image pipeline not available")
|
| 553 |
|
| 554 |
+
# Создаем scheduler (thread-safe)
|
| 555 |
+
current_scheduler = get_scheduler(pipe_img2img.scheduler, scheduler_name)
|
| 556 |
+
|
| 557 |
+
# Устанавливаем новый scheduler
|
| 558 |
+
pipe_img2img.scheduler = current_scheduler
|
| 559 |
+
|
| 560 |
# Загружаем LoRA если выбрана
|
| 561 |
trigger_word = None
|
| 562 |
if lora_name != "None":
|
|
|
|
| 589 |
except Exception as e:
|
| 590 |
logger.error(f" [X] Error: {e}")
|
| 591 |
raise
|
| 592 |
+
finally:
|
| 593 |
+
# Восстанавливаем оригинальный scheduler (thread-safety)
|
| 594 |
+
if original_scheduler is not None and pipe_img2img is not None:
|
| 595 |
+
pipe_img2img.scheduler = original_scheduler
|
| 596 |
|
| 597 |
# ControlNet функция убрана - не используется
|
| 598 |
|