Opera8 commited on
Commit
8f59b64
·
verified ·
1 Parent(s): 3e616f3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +107 -42
app.py CHANGED
@@ -31,10 +31,13 @@ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
31
 
32
  # --- بارگذاری مدل تشخیص محتوای نامناسب (NSFW) ---
33
  print("Loading Safety Checker...")
34
- safety_classifier = pipeline("image-classification", model="Falconsai/nsfw_image_detection", device=-1)
 
 
 
35
 
36
  def is_image_nsfw(image):
37
- if image is None: return False
38
  try:
39
  results = safety_classifier(image)
40
  for result in results:
@@ -265,7 +268,7 @@ async (image) => {
265
  }
266
  """
267
 
268
- # --- جاوااسکریپت سراسری (Aggressive Scanner & Cleaner) ---
269
  js_global_content = """
270
  <script>
271
  document.addEventListener('DOMContentLoaded', () => {
@@ -282,45 +285,41 @@ document.addEventListener('DOMContentLoaded', () => {
282
  forceLight();
283
  setInterval(forceLight, 1000);
284
 
285
- // 2. RETRY FUNCTIONALITY
286
- window.retryGeneration = function(btn) {
 
 
 
287
  // Find the main run button and click it to retry
288
  const runBtn = document.getElementById('run-btn');
289
- if(runBtn) {
290
- runBtn.click();
291
- }
292
 
293
- // IMPORTANT: Forcefully remove ALL error containers immediately.
294
- // This ensures that when Gradio renders the next error, it creates a new element
295
- // or updates the DOM in a way our scanner will definitely catch.
296
- document.querySelectorAll('.toast-body, .toast-wrap, .error').forEach(el => {
297
- el.remove();
298
- });
299
 
300
- // Also find any parent containers that might be holding the error
301
- const parents = document.querySelectorAll('.gradio-container .prose');
302
- parents.forEach(p => {
303
- if (p.innerText.includes("quota") || p.innerText.includes("Error")) {
304
- p.innerHTML = "";
305
- }
306
  });
307
  };
308
 
309
- // Close function for Back button
310
  window.closeErrorToast = function(btn) {
311
  const toast = btn.closest('.toast-wrap') || btn.closest('.toast-body') || btn.closest('.error');
312
  if(toast) toast.remove();
313
  };
314
 
315
- // 3. REPLACEMENT LOGIC
316
  const replaceErrorContent = (node) => {
317
- // Safety check: if already has our custom container, do nothing
318
  if (node.querySelector('.ip-reset-guide-container')) return;
319
 
320
  const text = node.innerText || "";
321
 
322
- // Check triggers: "quota", "exceeded", or even just "Error" if it's in the status bar area
323
- // We are aggressive here to catch the "red bar" shown in your video
324
  if (text.toLowerCase().includes('quota') || text.toLowerCase().includes('exceeded') || (text.includes('Error') && node.classList.contains('error'))) {
325
 
326
  const prettyHtml = `
@@ -370,7 +369,7 @@ document.addEventListener('DOMContentLoaded', () => {
370
  <svg class="action-button-icon" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M19 12H5M12 19l-7-7 7-7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>
371
  <span>بازگشت</span>
372
  </button>
373
- <button class="action-button retry-button" onclick="window.retryGeneration(this)">
374
  <svg class="action-button-icon" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M23 4v6h-6M1 20v-6h6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><path d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 0 1 3.51 15" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>
375
  <span>تلاش مجدد</span>
376
  </button>
@@ -381,31 +380,26 @@ document.addEventListener('DOMContentLoaded', () => {
381
  // Inject the HTML
382
  node.innerHTML = prettyHtml;
383
 
384
- // Clean up styles to prevent double boxes and red backgrounds
385
  node.style.padding = '0';
386
  node.style.border = 'none';
387
  node.style.backgroundColor = 'transparent';
388
  node.style.boxShadow = 'none';
389
- node.classList.remove('error'); // Remove error class to stop red styling
390
  }
391
  };
392
 
393
- // 4. SCANNER: Check continuously
394
- // We scan very fast (50ms) to catch the error element the moment it appears
395
  setInterval(() => {
396
- // We look for both toasts AND the inline error status bar (which was likely the red bar in your video)
397
- const potentialErrors = document.querySelectorAll('.toast-body, .error, .toast-wrap, .eta-bar.error');
398
 
399
  potentialErrors.forEach(el => {
400
- // If it has our text triggers and hasn't been replaced yet, replace it
401
- if (el.innerText && (el.innerText.includes('quota') || el.innerText.includes('exceeded') || el.innerText.includes('Error'))) {
402
- // Check if we already injected our card
403
  if (!el.querySelector('.ip-reset-guide-container')) {
404
  replaceErrorContent(el);
405
  }
406
  }
407
  });
408
- }, 50);
409
  });
410
  </script>
411
  """
@@ -428,7 +422,7 @@ css_code = """
428
  color-scheme: light !important;
429
  }
430
 
431
- /* --- IP Reset Guide CSS Variables & Styles --- */
432
  :root {
433
  --guide-bg: rgba(255, 255, 255, 0.98);
434
  --guide-border: rgba(102, 126, 234, 0.2);
@@ -494,7 +488,7 @@ css_code = """
494
  .summary-title { font-weight: 600; color: #2f5a33; font-size: 0.95rem; }
495
  .summary-text { color: #2f5a33; font-size: 0.85rem; line-height: 1.6; }
496
 
497
- /* Tutorial Button Styles - BEAUTIFIED */
498
  .video-button-container { text-align: center; margin: 25px 0 15px 0; width: 100%; }
499
  .elegant-video-button {
500
  display: inline-flex !important;
@@ -505,7 +499,7 @@ css_code = """
505
  color: var(--guide-accent) !important;
506
  border: 1px solid #e2e8f0 !important;
507
  text-decoration: none;
508
- border-radius: 50px !important; /* Capsule shape */
509
  font-weight: 600 !important;
510
  font-size: 0.9rem !important;
511
  cursor: pointer !important;
@@ -523,7 +517,7 @@ css_code = """
523
  }
524
  .elegant-video-button-icon { width: 18px; height: 18px; margin-left: 8px; fill: currentColor; }
525
 
526
- /* Action Buttons Styles (Back & Retry) - FIXED */
527
  .guide-actions {
528
  display: flex !important;
529
  gap: 12px !important;
@@ -713,7 +707,7 @@ textarea:focus, input[type="text"]:focus {
713
  footer { display: none !important; }
714
  .flagging { display: none !important; }
715
 
716
- /* General Toast Override - Forces transparency so our card looks good */
717
  .toast-body {
718
  direction: rtl !important;
719
  text-align: right !important;
@@ -783,4 +777,75 @@ with gr.Blocks() as demo:
783
  value="تبدیل عکس به انیمه"
784
  )
785
 
786
- with gr.Accordion("تنظیمات پیشرفته", open=Fa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
  # --- بارگذاری مدل تشخیص محتوای نامناسب (NSFW) ---
33
  print("Loading Safety Checker...")
34
+ try:
35
+ safety_classifier = pipeline("image-classification", model="Falconsai/nsfw_image_detection", device=-1)
36
+ except:
37
+ safety_classifier = None # Fallback if model fails to load
38
 
39
  def is_image_nsfw(image):
40
+ if image is None or safety_classifier is None: return False
41
  try:
42
  results = safety_classifier(image)
43
  for result in results:
 
268
  }
269
  """
270
 
271
+ # --- جاوااسکریپت سراسری (استراتژی حذف کامل برای رفع مشکل رفرش) ---
272
  js_global_content = """
273
  <script>
274
  document.addEventListener('DOMContentLoaded', () => {
 
285
  forceLight();
286
  setInterval(forceLight, 1000);
287
 
288
+ // 2. HELPER: Completely destroy the error element
289
+ window.destroyErrorToast = function(btn) {
290
+ // Try to find the container
291
+ const toast = btn.closest('.toast-wrap') || btn.closest('.toast-body') || btn.closest('.error');
292
+
293
  // Find the main run button and click it to retry
294
  const runBtn = document.getElementById('run-btn');
295
+ if(runBtn) runBtn.click();
 
 
296
 
297
+ // Remove the error UI immediately
298
+ if (toast) {
299
+ toast.remove();
300
+ }
 
 
301
 
302
+ // Aggressive cleanup: remove ANY other error toasts visible
303
+ document.querySelectorAll('.toast-body, .toast-wrap, .error').forEach(el => {
304
+ if(el.innerText.includes("قدم تا ساخت") || el.innerText.includes("quota")) {
305
+ el.remove();
306
+ }
 
307
  });
308
  };
309
 
310
+ // Just remove toast (for Back button)
311
  window.closeErrorToast = function(btn) {
312
  const toast = btn.closest('.toast-wrap') || btn.closest('.toast-body') || btn.closest('.error');
313
  if(toast) toast.remove();
314
  };
315
 
316
+ // 3. LOGIC: Replace content logic
317
  const replaceErrorContent = (node) => {
 
318
  if (node.querySelector('.ip-reset-guide-container')) return;
319
 
320
  const text = node.innerText || "";
321
 
322
+ // Check triggers
 
323
  if (text.toLowerCase().includes('quota') || text.toLowerCase().includes('exceeded') || (text.includes('Error') && node.classList.contains('error'))) {
324
 
325
  const prettyHtml = `
 
369
  <svg class="action-button-icon" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M19 12H5M12 19l-7-7 7-7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>
370
  <span>بازگشت</span>
371
  </button>
372
+ <button class="action-button retry-button" onclick="window.destroyErrorToast(this)">
373
  <svg class="action-button-icon" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M23 4v6h-6M1 20v-6h6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><path d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 0 1 3.51 15" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>
374
  <span>تلاش مجدد</span>
375
  </button>
 
380
  // Inject the HTML
381
  node.innerHTML = prettyHtml;
382
 
 
383
  node.style.padding = '0';
384
  node.style.border = 'none';
385
  node.style.backgroundColor = 'transparent';
386
  node.style.boxShadow = 'none';
387
+ node.classList.remove('error');
388
  }
389
  };
390
 
391
+ // 4. AGGRESSIVE SCANNER
 
392
  setInterval(() => {
393
+ const potentialErrors = document.querySelectorAll('.toast-body, .error, .toast-wrap, .eta-bar');
 
394
 
395
  potentialErrors.forEach(el => {
396
+ if (el.innerText && (el.innerText.includes('quota') || el.innerText.includes('exceeded') || (el.innerText.includes('Error') && el.classList.contains('error')))) {
 
 
397
  if (!el.querySelector('.ip-reset-guide-container')) {
398
  replaceErrorContent(el);
399
  }
400
  }
401
  });
402
+ }, 150);
403
  });
404
  </script>
405
  """
 
422
  color-scheme: light !important;
423
  }
424
 
425
+ /* --- IP Reset Guide CSS --- */
426
  :root {
427
  --guide-bg: rgba(255, 255, 255, 0.98);
428
  --guide-border: rgba(102, 126, 234, 0.2);
 
488
  .summary-title { font-weight: 600; color: #2f5a33; font-size: 0.95rem; }
489
  .summary-text { color: #2f5a33; font-size: 0.85rem; line-height: 1.6; }
490
 
491
+ /* Tutorial Button */
492
  .video-button-container { text-align: center; margin: 25px 0 15px 0; width: 100%; }
493
  .elegant-video-button {
494
  display: inline-flex !important;
 
499
  color: var(--guide-accent) !important;
500
  border: 1px solid #e2e8f0 !important;
501
  text-decoration: none;
502
+ border-radius: 50px !important;
503
  font-weight: 600 !important;
504
  font-size: 0.9rem !important;
505
  cursor: pointer !important;
 
517
  }
518
  .elegant-video-button-icon { width: 18px; height: 18px; margin-left: 8px; fill: currentColor; }
519
 
520
+ /* Action Buttons */
521
  .guide-actions {
522
  display: flex !important;
523
  gap: 12px !important;
 
707
  footer { display: none !important; }
708
  .flagging { display: none !important; }
709
 
710
+ /* Force toast transparency */
711
  .toast-body {
712
  direction: rtl !important;
713
  text-align: right !important;
 
777
  value="تبدیل عکس به انیمه"
778
  )
779
 
780
+ with gr.Accordion("تنظیمات پیشرفته", open=False, visible=True):
781
+ aspect_ratio_selection = gr.Dropdown(
782
+ label="ابعاد تصویر خروجی",
783
+ choices=ASPECT_RATIOS_LIST,
784
+ value="خودکار (پیش‌فرض)",
785
+ interactive=True
786
+ )
787
+
788
+ with gr.Row(visible=False) as custom_dims_row:
789
+ custom_width = gr.Slider(
790
+ label="عرض دلخواه (Width)",
791
+ minimum=256, maximum=2048, step=8, value=1024
792
+ )
793
+ custom_height = gr.Slider(
794
+ label="ارتفاع دلخواه (Height)",
795
+ minimum=256, maximum=2048, step=8, value=1024
796
+ )
797
+
798
+ seed = gr.Slider(label="دانه تصادفی (Seed)", minimum=0, maximum=MAX_SEED, step=1, value=0)
799
+ randomize_seed = gr.Checkbox(label="استفاده از Seed تصادفی", value=True)
800
+ guidance_scale = gr.Slider(label="میزان وفاداری به متن (Guidance Scale)", minimum=1.0, maximum=10.0, step=0.1, value=1.0)
801
+ steps = gr.Slider(label="تعداد مراحل پردازش (Steps)", minimum=1, maximum=50, step=1, value=4)
802
+
803
+ # اصلاح تابع نمایش ردیف اسلایدرها
804
+ def toggle_row(choice):
805
+ if choice == "شخصی‌سازی (Custom)":
806
+ return gr.update(visible=True)
807
+ return gr.update(visible=False)
808
+
809
+ aspect_ratio_selection.change(
810
+ fn=toggle_row,
811
+ inputs=aspect_ratio_selection,
812
+ outputs=custom_dims_row
813
+ )
814
+
815
+ gr.Examples(
816
+ examples=[
817
+ ["examples/1.jpg", "تبدیل به انیمه کن.", "تبدیل عکس به انیمه"],
818
+ ["examples/5.jpg", "سایه‌ها را حذف کن و نورپردازی نرم به تصویر بده.", "اصلاح نور و سایه"],
819
+ ["examples/4.jpg", "از فیلتر ساعت طلایی با پخش نور ملایم استفاده کن.", "نورپردازی مجدد (Relight)"],
820
+ ["examples/2.jpeg", "دوربین را ۴۵ درجه به سمت چپ بچرخان.", "تغییر زاویه دید"],
821
+ ["examples/7.jpg", "منبع نور را از سمت راست عقب قرار بده.", "نورپردازی چند زاویه‌ای"],
822
+ ["examples/10.jpeg", "کیفیت تصویر را افزایش بده (Upscale).", "افزایش کیفیت (Upscale)"],
823
+ ["examples/7.jpg", "منبع نور را از پایین بتابان.", "نورپردازی چند زاویه‌ای"],
824
+ ["examples/2.jpeg", "زاویه دوربین را به نمای بالا گوشه راست تغییر بده.", "تغییر زاویه دید"],
825
+ ["examples/9.jpg", "دوربین کمی به جلو حرکت می‌کند در حالی که نور خورشید از میان ابرها می‌تابد و درخششی نرم اطراف شبح شخصیت در مه ایجاد می‌کند. سبک سینمایی واقعی.", "صحنه بعدی (سینمایی)"],
826
+ ["examples/8.jpg", "جزئیات پوست سوژه را برجسته‌تر و طبیعی‌تر کن.", "روتوش پوست"],
827
+ ["examples/6.jpg", "دوربین را به نمای پایین به بالا تغییر بده.", "تغییر زاویه دید"],
828
+ ],
829
+ inputs=[input_image, prompt, lora_adapter],
830
+ outputs=[output_image, seed, status_box],
831
+ fn=infer_example,
832
+ cache_examples=False,
833
+ label="نمونه‌ها (برای تست کلیک کنید)"
834
+ )
835
+
836
+ run_button.click(
837
+ fn=infer,
838
+ inputs=[input_image, prompt, lora_adapter, seed, randomize_seed, guidance_scale, steps, aspect_ratio_selection, custom_width, custom_height],
839
+ outputs=[output_image, seed, status_box],
840
+ api_name="predict"
841
+ )
842
+
843
+ download_button.click(
844
+ fn=None,
845
+ inputs=[output_image],
846
+ outputs=None,
847
+ js=js_download_func
848
+ )
849
+
850
+ if __name__ == "__main__":
851
+ demo.queue(max_size=30).launch(show_error=True)