Spaces:
Running
on
Zero
Running
on
Zero
Update app.py
Browse files
app.py
CHANGED
|
@@ -4,6 +4,7 @@ import numpy as np
|
|
| 4 |
import spaces
|
| 5 |
import torch
|
| 6 |
import random
|
|
|
|
| 7 |
from PIL import Image
|
| 8 |
from typing import Iterable
|
| 9 |
from gradio.themes import Soft
|
|
@@ -185,11 +186,17 @@ def translate_prompt(text):
|
|
| 185 |
return text
|
| 186 |
|
| 187 |
# ==========================================
|
| 188 |
-
# 4. بارگذاری مدل و LoRA ها
|
| 189 |
# ==========================================
|
| 190 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 191 |
dtype = torch.bfloat16
|
| 192 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 193 |
from diffusers import FlowMatchEulerDiscreteScheduler
|
| 194 |
from qwenimage.pipeline_qwenimage_edit_plus import QwenImageEditPlusPipeline
|
| 195 |
from qwenimage.transformer_qwenimage import QwenImageTransformer2DModel
|
|
@@ -319,6 +326,9 @@ def infer(
|
|
| 319 |
subscription_status,
|
| 320 |
progress=gr.Progress(track_tqdm=True)
|
| 321 |
):
|
|
|
|
|
|
|
|
|
|
| 322 |
# 1. بررسی اعتبار
|
| 323 |
if subscription_status != 'paid':
|
| 324 |
user_record = get_user_record(fingerprint)
|
|
@@ -340,7 +350,6 @@ def infer(
|
|
| 340 |
if not check_text_safety(english_prompt):
|
| 341 |
return None, seed, get_error_html("متن درخواست شامل کلمات غیرمجاز است."), gr.update(visible=True), gr.update(visible=False)
|
| 342 |
|
| 343 |
-
# اگر پرامپت خالی بود، پرامپت پیشفرض انگلیسی تنظیم میشود (نیاز به ترجمه ندارد)
|
| 344 |
if not english_prompt:
|
| 345 |
if lora_adapter == "Cloth-Design-Fuse": english_prompt = "Put this design on their shirt."
|
| 346 |
elif lora_adapter == "Texture Edit": english_prompt = "Apply texture to object."
|
|
@@ -349,7 +358,7 @@ def infer(
|
|
| 349 |
elif lora_adapter == "Material-Transfer": english_prompt = "change materials of image1 to match the reference in image2"
|
| 350 |
elif lora_adapter == "Light-Migration": english_prompt = "Refer to the color tone, remove the original lighting from Image 1, and relight Image 1 based on the lighting and color tone of Image 2."
|
| 351 |
|
| 352 |
-
# 5. کسر اعتبار
|
| 353 |
if subscription_status != 'paid':
|
| 354 |
consume_quota(fingerprint)
|
| 355 |
|
|
@@ -419,13 +428,17 @@ def infer(
|
|
| 419 |
except Exception as e:
|
| 420 |
error_str = str(e)
|
| 421 |
if "quota" in error_str.lower() or "exceeded" in error_str.lower():
|
| 422 |
-
raise e
|
| 423 |
return None, seed, get_error_html(f"خطا در پردازش: {error_str}"), gr.update(visible=True), gr.update(visible=False)
|
|
|
|
|
|
|
|
|
|
| 424 |
|
| 425 |
@spaces.GPU(duration=30)
|
| 426 |
def infer_example(image_1, image_2, prompt, lora_adapter):
|
| 427 |
-
#
|
| 428 |
res, s, status, btn1, btn2 = infer(image_1, image_2, prompt, lora_adapter, 0, True, 1.0, 4, "خودکار (پیشفرض)", 1024, 1024, "example", "paid")
|
|
|
|
| 429 |
return res, s
|
| 430 |
|
| 431 |
# ==========================================
|
|
@@ -443,7 +456,7 @@ async (image) => {
|
|
| 443 |
|
| 444 |
js_upgrade_func = """() => { window.parent.postMessage({ type: 'NAVIGATE_TO_PREMIUM' }, '*'); }"""
|
| 445 |
|
| 446 |
-
# جاوا اسکریپت
|
| 447 |
js_global = """
|
| 448 |
<script>
|
| 449 |
document.addEventListener('DOMContentLoaded', () => {
|
|
@@ -512,21 +525,40 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
| 512 |
init();
|
| 513 |
|
| 514 |
// ---------------------------------------------
|
| 515 |
-
// GPU QUOTA HANDLER
|
| 516 |
// ---------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
| 517 |
window.retryGeneration = function() {
|
| 518 |
const modal = document.getElementById('custom-quota-modal');
|
| 519 |
if (modal) modal.remove();
|
|
|
|
|
|
|
| 520 |
const runBtn = document.getElementById('run-btn');
|
| 521 |
-
if(runBtn)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 522 |
};
|
|
|
|
| 523 |
window.closeErrorModal = function() {
|
| 524 |
const modal = document.getElementById('custom-quota-modal');
|
| 525 |
if (modal) modal.remove();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 526 |
};
|
| 527 |
|
| 528 |
const showQuotaModal = () => {
|
| 529 |
-
if (document.getElementById('custom-quota-modal')) return;
|
|
|
|
| 530 |
|
| 531 |
const modalHtml = `
|
| 532 |
<div id="custom-quota-modal" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.6); backdrop-filter: blur(5px); z-index: 99999; display: flex; align-items: center; justify-content: center; font-family: 'Vazirmatn', sans-serif;">
|
|
@@ -586,7 +618,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
| 586 |
`;
|
| 587 |
|
| 588 |
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
| 589 |
-
|
| 590 |
};
|
| 591 |
|
| 592 |
setInterval(() => {
|
|
|
|
| 4 |
import spaces
|
| 5 |
import torch
|
| 6 |
import random
|
| 7 |
+
import gc
|
| 8 |
from PIL import Image
|
| 9 |
from typing import Iterable
|
| 10 |
from gradio.themes import Soft
|
|
|
|
| 186 |
return text
|
| 187 |
|
| 188 |
# ==========================================
|
| 189 |
+
# 4. بارگذاری مدل و LoRA ها + مدیریت حافظه
|
| 190 |
# ==========================================
|
| 191 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 192 |
dtype = torch.bfloat16
|
| 193 |
|
| 194 |
+
# تابع مهم برای خالی کردن حافظه و جلوگیری از ارور NVML
|
| 195 |
+
def flush():
|
| 196 |
+
gc.collect()
|
| 197 |
+
torch.cuda.empty_cache()
|
| 198 |
+
torch.cuda.ipc_collect()
|
| 199 |
+
|
| 200 |
from diffusers import FlowMatchEulerDiscreteScheduler
|
| 201 |
from qwenimage.pipeline_qwenimage_edit_plus import QwenImageEditPlusPipeline
|
| 202 |
from qwenimage.transformer_qwenimage import QwenImageTransformer2DModel
|
|
|
|
| 326 |
subscription_status,
|
| 327 |
progress=gr.Progress(track_tqdm=True)
|
| 328 |
):
|
| 329 |
+
# پاکسازی حافظه قبل از شروع
|
| 330 |
+
flush()
|
| 331 |
+
|
| 332 |
# 1. بررسی اعتبار
|
| 333 |
if subscription_status != 'paid':
|
| 334 |
user_record = get_user_record(fingerprint)
|
|
|
|
| 350 |
if not check_text_safety(english_prompt):
|
| 351 |
return None, seed, get_error_html("متن درخواست شامل کلمات غیرمجاز است."), gr.update(visible=True), gr.update(visible=False)
|
| 352 |
|
|
|
|
| 353 |
if not english_prompt:
|
| 354 |
if lora_adapter == "Cloth-Design-Fuse": english_prompt = "Put this design on their shirt."
|
| 355 |
elif lora_adapter == "Texture Edit": english_prompt = "Apply texture to object."
|
|
|
|
| 358 |
elif lora_adapter == "Material-Transfer": english_prompt = "change materials of image1 to match the reference in image2"
|
| 359 |
elif lora_adapter == "Light-Migration": english_prompt = "Refer to the color tone, remove the original lighting from Image 1, and relight Image 1 based on the lighting and color tone of Image 2."
|
| 360 |
|
| 361 |
+
# 5. کسر اعتبار
|
| 362 |
if subscription_status != 'paid':
|
| 363 |
consume_quota(fingerprint)
|
| 364 |
|
|
|
|
| 428 |
except Exception as e:
|
| 429 |
error_str = str(e)
|
| 430 |
if "quota" in error_str.lower() or "exceeded" in error_str.lower():
|
| 431 |
+
raise e
|
| 432 |
return None, seed, get_error_html(f"خطا در پردازش: {error_str}"), gr.update(visible=True), gr.update(visible=False)
|
| 433 |
+
finally:
|
| 434 |
+
# پاکسازی حافظه بعد از پایان (موفق یا ناموفق)
|
| 435 |
+
flush()
|
| 436 |
|
| 437 |
@spaces.GPU(duration=30)
|
| 438 |
def infer_example(image_1, image_2, prompt, lora_adapter):
|
| 439 |
+
flush() # پاکسازی قبل از مثال
|
| 440 |
res, s, status, btn1, btn2 = infer(image_1, image_2, prompt, lora_adapter, 0, True, 1.0, 4, "خودکار (پیشفرض)", 1024, 1024, "example", "paid")
|
| 441 |
+
flush() # پاکسازی بعد از مثال
|
| 442 |
return res, s
|
| 443 |
|
| 444 |
# ==========================================
|
|
|
|
| 456 |
|
| 457 |
js_upgrade_func = """() => { window.parent.postMessage({ type: 'NAVIGATE_TO_PREMIUM' }, '*'); }"""
|
| 458 |
|
| 459 |
+
# جاوا اسکریپت اصلاح شده برای رفع باگ دکمهها
|
| 460 |
js_global = """
|
| 461 |
<script>
|
| 462 |
document.addEventListener('DOMContentLoaded', () => {
|
|
|
|
| 525 |
init();
|
| 526 |
|
| 527 |
// ---------------------------------------------
|
| 528 |
+
// GPU QUOTA HANDLER & UI FIXES
|
| 529 |
// ---------------------------------------------
|
| 530 |
+
|
| 531 |
+
// پرچم برای جلوگیری از باز شدن مجدد مودال
|
| 532 |
+
window.quotaModalActive = false;
|
| 533 |
+
|
| 534 |
window.retryGeneration = function() {
|
| 535 |
const modal = document.getElementById('custom-quota-modal');
|
| 536 |
if (modal) modal.remove();
|
| 537 |
+
window.quotaModalActive = false; // Reset flag
|
| 538 |
+
|
| 539 |
const runBtn = document.getElementById('run-btn');
|
| 540 |
+
if(runBtn) {
|
| 541 |
+
runBtn.click();
|
| 542 |
+
// گاهی اوقات نیاز به کلیک دوم هست، این کد اطمینان حاصل میکند
|
| 543 |
+
setTimeout(() => runBtn.click(), 100);
|
| 544 |
+
}
|
| 545 |
};
|
| 546 |
+
|
| 547 |
window.closeErrorModal = function() {
|
| 548 |
const modal = document.getElementById('custom-quota-modal');
|
| 549 |
if (modal) modal.remove();
|
| 550 |
+
window.quotaModalActive = false; // Reset flag
|
| 551 |
+
|
| 552 |
+
// پاک کردن متن ارورها برای جلوگیری از تریگر مجدد اسکنر
|
| 553 |
+
document.querySelectorAll('.toast-body, .error, div[class*="error"]').forEach(el => {
|
| 554 |
+
el.innerText = '';
|
| 555 |
+
el.style.display = 'none';
|
| 556 |
+
});
|
| 557 |
};
|
| 558 |
|
| 559 |
const showQuotaModal = () => {
|
| 560 |
+
if (window.quotaModalActive || document.getElementById('custom-quota-modal')) return;
|
| 561 |
+
window.quotaModalActive = true;
|
| 562 |
|
| 563 |
const modalHtml = `
|
| 564 |
<div id="custom-quota-modal" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.6); backdrop-filter: blur(5px); z-index: 99999; display: flex; align-items: center; justify-content: center; font-family: 'Vazirmatn', sans-serif;">
|
|
|
|
| 618 |
`;
|
| 619 |
|
| 620 |
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
| 621 |
+
// اتوماتیک بسته نمیشود تا کاربر دکمه بازگشت را بزند
|
| 622 |
};
|
| 623 |
|
| 624 |
setInterval(() => {
|