Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
|
@@ -200,7 +200,10 @@ DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
|
|
| 200 |
DTYPE = torch.float16 if DEVICE == "cuda" else torch.float32
|
| 201 |
print("DEVICE:", DEVICE, "DTYPE:", DTYPE, flush=True)
|
| 202 |
|
| 203 |
-
tensor_transfrom = transforms.Compose([
|
|
|
|
|
|
|
|
|
|
| 204 |
|
| 205 |
unet = UNet2DConditionModel.from_pretrained(base_path, subfolder="unet", torch_dtype=DTYPE)
|
| 206 |
unet.requires_grad_(False)
|
|
@@ -309,7 +312,6 @@ def start_tryon(
|
|
| 309 |
if device == "cuda":
|
| 310 |
autocast_ctx = torch.cuda.amp.autocast()
|
| 311 |
else:
|
| 312 |
-
|
| 313 |
class _NoCtx:
|
| 314 |
def __enter__(self):
|
| 315 |
return None
|
|
@@ -393,6 +395,7 @@ button[aria-label="Settings"] {display:none !important;}
|
|
| 393 |
border-radius: 12px;
|
| 394 |
padding: 10px 12px;
|
| 395 |
font-size: 14px;
|
|
|
|
| 396 |
}
|
| 397 |
|
| 398 |
.feedback-idle {
|
|
@@ -402,6 +405,7 @@ button[aria-label="Settings"] {display:none !important;}
|
|
| 402 |
border-radius: 12px;
|
| 403 |
padding: 10px 12px;
|
| 404 |
font-size: 14px;
|
|
|
|
| 405 |
}
|
| 406 |
"""
|
| 407 |
|
|
@@ -441,7 +445,7 @@ def on_gallery_select(files_list: List[str], evt: gr.SelectData):
|
|
| 441 |
|
| 442 |
|
| 443 |
# =========================
|
| 444 |
-
# Feedback
|
| 445 |
# =========================
|
| 446 |
FEEDBACK_DIR = "./feedback"
|
| 447 |
FEEDBACK_PATH = os.path.join(FEEDBACK_DIR, "feedback.jsonl")
|
|
@@ -486,6 +490,7 @@ def _upload_repo_feedback(api: HfApi, token: str, text: str) -> None:
|
|
| 486 |
|
| 487 |
os.makedirs(FEEDBACK_DIR, exist_ok=True)
|
| 488 |
tmp_path = os.path.join(FEEDBACK_DIR, "_feedback_upload.jsonl")
|
|
|
|
| 489 |
with open(tmp_path, "w", encoding="utf-8") as f:
|
| 490 |
f.write(text)
|
| 491 |
|
|
@@ -499,19 +504,7 @@ def _upload_repo_feedback(api: HfApi, token: str, text: str) -> None:
|
|
| 499 |
)
|
| 500 |
|
| 501 |
|
| 502 |
-
def
|
| 503 |
-
os.makedirs(FEEDBACK_DIR, exist_ok=True)
|
| 504 |
-
|
| 505 |
-
clean_comment = (comment or "").strip()
|
| 506 |
-
if len(clean_comment) > 1500:
|
| 507 |
-
clean_comment = clean_comment[:1500]
|
| 508 |
-
|
| 509 |
-
record = {
|
| 510 |
-
"timestamp": datetime.utcnow().isoformat(),
|
| 511 |
-
"like": bool(is_like),
|
| 512 |
-
"garment": garment_name or "",
|
| 513 |
-
"comment": clean_comment,
|
| 514 |
-
}
|
| 515 |
line = json.dumps(record, ensure_ascii=False) + "\n"
|
| 516 |
|
| 517 |
try:
|
|
@@ -525,11 +518,11 @@ def save_feedback(is_like: bool, garment_name: str, comment: str):
|
|
| 525 |
token = (os.getenv("HF_TOKEN", "").strip() or os.getenv("HUGGINGFACEHUB_API_TOKEN", "").strip())
|
| 526 |
if not token:
|
| 527 |
print("Feedback repo sync skipped: HF_TOKEN not set", flush=True)
|
| 528 |
-
return
|
| 529 |
|
| 530 |
if not FEEDBACK_REPO_ID:
|
| 531 |
print("Feedback repo sync skipped: FEEDBACK_REPO_ID not set", flush=True)
|
| 532 |
-
return
|
| 533 |
|
| 534 |
api = HfApi()
|
| 535 |
repo_text = _download_repo_feedback(api, token)
|
|
@@ -538,63 +531,132 @@ def save_feedback(is_like: bool, garment_name: str, comment: str):
|
|
| 538 |
except Exception as e:
|
| 539 |
print("Feedback repo sync failed:", repr(e), flush=True)
|
| 540 |
|
| 541 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 542 |
|
| 543 |
|
| 544 |
-
def
|
| 545 |
return """
|
| 546 |
<div class="feedback-idle">
|
| 547 |
-
|
| 548 |
</div>
|
| 549 |
"""
|
| 550 |
|
| 551 |
|
| 552 |
-
def
|
| 553 |
-
comment_text = " и комментарий" if has_comment else ""
|
| 554 |
return f"""
|
| 555 |
<div class="feedback-ok">
|
| 556 |
-
✅
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 557 |
</div>
|
| 558 |
"""
|
| 559 |
|
| 560 |
|
| 561 |
-
|
| 562 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 563 |
|
| 564 |
if not garment_name:
|
| 565 |
return (
|
| 566 |
"⚠️ Сначала выполните примерку и выберите одежду",
|
| 567 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 568 |
gr.update(value=comment),
|
| 569 |
)
|
| 570 |
|
| 571 |
try:
|
| 572 |
-
|
| 573 |
return (
|
| 574 |
-
|
| 575 |
-
|
| 576 |
gr.update(value=""),
|
| 577 |
)
|
| 578 |
except Exception as e:
|
| 579 |
return (
|
| 580 |
-
f"❌ Ошибка
|
| 581 |
-
|
| 582 |
-
<div class="feedback-idle">
|
| 583 |
-
Не удалось сохранить отзыв. Попробуйте ещё раз.
|
| 584 |
-
</div>
|
| 585 |
-
""",
|
| 586 |
gr.update(value=comment),
|
| 587 |
)
|
| 588 |
|
| 589 |
|
| 590 |
-
|
| 591 |
-
|
| 592 |
-
|
| 593 |
-
|
| 594 |
-
def submit_dislike_feedback(garment_name: str, comment: str):
|
| 595 |
-
return submit_feedback_ui(False, garment_name, comment)
|
| 596 |
-
|
| 597 |
-
|
| 598 |
def tryon_ui(person_pil, selected_filename):
|
| 599 |
for msg in [
|
| 600 |
"🧵 Анализируем посадку ткани…",
|
|
@@ -609,7 +671,8 @@ def tryon_ui(person_pil, selected_filename):
|
|
| 609 |
msg,
|
| 610 |
gr.update(visible=False),
|
| 611 |
gr.update(value=""),
|
| 612 |
-
gr.update(value=
|
|
|
|
| 613 |
)
|
| 614 |
time.sleep(2.3)
|
| 615 |
|
|
@@ -620,7 +683,8 @@ def tryon_ui(person_pil, selected_filename):
|
|
| 620 |
msg,
|
| 621 |
gr.update(visible=False),
|
| 622 |
gr.update(value=""),
|
| 623 |
-
gr.update(value=
|
|
|
|
| 624 |
)
|
| 625 |
return
|
| 626 |
|
|
@@ -630,7 +694,8 @@ def tryon_ui(person_pil, selected_filename):
|
|
| 630 |
"❌ Загрузите фото человека",
|
| 631 |
gr.update(visible=False),
|
| 632 |
gr.update(value=""),
|
| 633 |
-
gr.update(value=
|
|
|
|
| 634 |
)
|
| 635 |
return
|
| 636 |
|
|
@@ -640,7 +705,8 @@ def tryon_ui(person_pil, selected_filename):
|
|
| 640 |
"❌ Выберите одежду (клик по превью)",
|
| 641 |
gr.update(visible=False),
|
| 642 |
gr.update(value=""),
|
| 643 |
-
gr.update(value=
|
|
|
|
| 644 |
)
|
| 645 |
return
|
| 646 |
|
|
@@ -651,7 +717,8 @@ def tryon_ui(person_pil, selected_filename):
|
|
| 651 |
"❌ Не удалось загрузить выбранную одежду",
|
| 652 |
gr.update(visible=False),
|
| 653 |
gr.update(value=""),
|
| 654 |
-
gr.update(value=
|
|
|
|
| 655 |
)
|
| 656 |
return
|
| 657 |
|
|
@@ -659,10 +726,11 @@ def tryon_ui(person_pil, selected_filename):
|
|
| 659 |
out_img = start_tryon(human_pil=person_pil, garm_img=garm)
|
| 660 |
yield (
|
| 661 |
out_img,
|
| 662 |
-
"✅ Готово — оцените результат
|
| 663 |
gr.update(visible=True),
|
| 664 |
gr.update(value=""),
|
| 665 |
-
gr.update(value=
|
|
|
|
| 666 |
)
|
| 667 |
except Exception as e:
|
| 668 |
yield (
|
|
@@ -670,11 +738,14 @@ def tryon_ui(person_pil, selected_filename):
|
|
| 670 |
f"❌ Ошибка: {type(e).__name__}: {str(e)[:220]}",
|
| 671 |
gr.update(visible=False),
|
| 672 |
gr.update(value=""),
|
| 673 |
-
gr.update(value=
|
|
|
|
| 674 |
)
|
| 675 |
|
| 676 |
|
| 677 |
-
#
|
|
|
|
|
|
|
| 678 |
ensure_garments_available()
|
| 679 |
_default_gender = "Женская"
|
| 680 |
_initial_files = list_garments(gender=_default_gender)
|
|
@@ -734,18 +805,23 @@ with gr.Blocks(title="Virtual Try-On Rendez-vous", css=CUSTOM_CSS) as demo:
|
|
| 734 |
with gr.Column(visible=False) as feedback_box:
|
| 735 |
gr.HTML('<div class="feedback-box">')
|
| 736 |
|
|
|
|
| 737 |
with gr.Row():
|
| 738 |
like_btn = gr.Button("👍 Нравится")
|
| 739 |
dislike_btn = gr.Button("👎 Не нравится")
|
|
|
|
| 740 |
|
|
|
|
| 741 |
feedback_comment = gr.Textbox(
|
| 742 |
-
label="
|
| 743 |
placeholder="Напишите, что понравилось или что стоит улучшить...",
|
| 744 |
lines=3,
|
| 745 |
-
max_lines=
|
|
|
|
| 746 |
)
|
|
|
|
|
|
|
| 747 |
|
| 748 |
-
feedback_notice = gr.HTML(_feedback_idle_html())
|
| 749 |
gr.HTML("</div>")
|
| 750 |
|
| 751 |
gender.change(
|
|
@@ -763,21 +839,28 @@ with gr.Blocks(title="Virtual Try-On Rendez-vous", css=CUSTOM_CSS) as demo:
|
|
| 763 |
run.click(
|
| 764 |
fn=tryon_ui,
|
| 765 |
inputs=[person, selected_garment_state],
|
| 766 |
-
outputs=[out, status, feedback_box, feedback_comment,
|
| 767 |
concurrency_limit=1,
|
| 768 |
)
|
| 769 |
|
| 770 |
like_btn.click(
|
| 771 |
fn=submit_like_feedback,
|
| 772 |
-
inputs=[selected_garment_state
|
| 773 |
-
outputs=[status,
|
| 774 |
concurrency_limit=1,
|
| 775 |
)
|
| 776 |
|
| 777 |
dislike_btn.click(
|
| 778 |
fn=submit_dislike_feedback,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 779 |
inputs=[selected_garment_state, feedback_comment],
|
| 780 |
-
outputs=[status,
|
| 781 |
concurrency_limit=1,
|
| 782 |
)
|
| 783 |
|
|
|
|
| 200 |
DTYPE = torch.float16 if DEVICE == "cuda" else torch.float32
|
| 201 |
print("DEVICE:", DEVICE, "DTYPE:", DTYPE, flush=True)
|
| 202 |
|
| 203 |
+
tensor_transfrom = transforms.Compose([
|
| 204 |
+
transforms.ToTensor(),
|
| 205 |
+
transforms.Normalize([0.5], [0.5]),
|
| 206 |
+
])
|
| 207 |
|
| 208 |
unet = UNet2DConditionModel.from_pretrained(base_path, subfolder="unet", torch_dtype=DTYPE)
|
| 209 |
unet.requires_grad_(False)
|
|
|
|
| 312 |
if device == "cuda":
|
| 313 |
autocast_ctx = torch.cuda.amp.autocast()
|
| 314 |
else:
|
|
|
|
| 315 |
class _NoCtx:
|
| 316 |
def __enter__(self):
|
| 317 |
return None
|
|
|
|
| 395 |
border-radius: 12px;
|
| 396 |
padding: 10px 12px;
|
| 397 |
font-size: 14px;
|
| 398 |
+
margin-top: 8px;
|
| 399 |
}
|
| 400 |
|
| 401 |
.feedback-idle {
|
|
|
|
| 405 |
border-radius: 12px;
|
| 406 |
padding: 10px 12px;
|
| 407 |
font-size: 14px;
|
| 408 |
+
margin-top: 8px;
|
| 409 |
}
|
| 410 |
"""
|
| 411 |
|
|
|
|
| 445 |
|
| 446 |
|
| 447 |
# =========================
|
| 448 |
+
# Feedback storage
|
| 449 |
# =========================
|
| 450 |
FEEDBACK_DIR = "./feedback"
|
| 451 |
FEEDBACK_PATH = os.path.join(FEEDBACK_DIR, "feedback.jsonl")
|
|
|
|
| 490 |
|
| 491 |
os.makedirs(FEEDBACK_DIR, exist_ok=True)
|
| 492 |
tmp_path = os.path.join(FEEDBACK_DIR, "_feedback_upload.jsonl")
|
| 493 |
+
|
| 494 |
with open(tmp_path, "w", encoding="utf-8") as f:
|
| 495 |
f.write(text)
|
| 496 |
|
|
|
|
| 504 |
)
|
| 505 |
|
| 506 |
|
| 507 |
+
def _append_feedback_record(record: dict) -> None:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 508 |
line = json.dumps(record, ensure_ascii=False) + "\n"
|
| 509 |
|
| 510 |
try:
|
|
|
|
| 518 |
token = (os.getenv("HF_TOKEN", "").strip() or os.getenv("HUGGINGFACEHUB_API_TOKEN", "").strip())
|
| 519 |
if not token:
|
| 520 |
print("Feedback repo sync skipped: HF_TOKEN not set", flush=True)
|
| 521 |
+
return
|
| 522 |
|
| 523 |
if not FEEDBACK_REPO_ID:
|
| 524 |
print("Feedback repo sync skipped: FEEDBACK_REPO_ID not set", flush=True)
|
| 525 |
+
return
|
| 526 |
|
| 527 |
api = HfApi()
|
| 528 |
repo_text = _download_repo_feedback(api, token)
|
|
|
|
| 531 |
except Exception as e:
|
| 532 |
print("Feedback repo sync failed:", repr(e), flush=True)
|
| 533 |
|
| 534 |
+
|
| 535 |
+
def save_rating_feedback(is_like: bool, garment_name: str) -> None:
|
| 536 |
+
record = {
|
| 537 |
+
"timestamp": datetime.utcnow().isoformat(),
|
| 538 |
+
"event": "rating",
|
| 539 |
+
"like": bool(is_like),
|
| 540 |
+
"garment": garment_name or "",
|
| 541 |
+
}
|
| 542 |
+
_append_feedback_record(record)
|
| 543 |
+
|
| 544 |
+
|
| 545 |
+
def save_comment_feedback(garment_name: str, comment: str) -> None:
|
| 546 |
+
clean_comment = (comment or "").strip()
|
| 547 |
+
if len(clean_comment) > 1500:
|
| 548 |
+
clean_comment = clean_comment[:1500]
|
| 549 |
+
|
| 550 |
+
record = {
|
| 551 |
+
"timestamp": datetime.utcnow().isoformat(),
|
| 552 |
+
"event": "comment",
|
| 553 |
+
"garment": garment_name or "",
|
| 554 |
+
"comment": clean_comment,
|
| 555 |
+
}
|
| 556 |
+
_append_feedback_record(record)
|
| 557 |
+
|
| 558 |
+
|
| 559 |
+
# =========================
|
| 560 |
+
# Feedback UI helpers
|
| 561 |
+
# =========================
|
| 562 |
+
def _rating_notice_idle_html():
|
| 563 |
+
return """
|
| 564 |
+
<div class="feedback-idle">
|
| 565 |
+
Оцените результат: нажмите лайк или дизлайк.
|
| 566 |
+
</div>
|
| 567 |
+
"""
|
| 568 |
|
| 569 |
|
| 570 |
+
def _comment_notice_idle_html():
|
| 571 |
return """
|
| 572 |
<div class="feedback-idle">
|
| 573 |
+
При желании напишите комментарий и нажмите кнопку отправки.
|
| 574 |
</div>
|
| 575 |
"""
|
| 576 |
|
| 577 |
|
| 578 |
+
def _rating_notice_ok_html(action_text: str):
|
|
|
|
| 579 |
return f"""
|
| 580 |
<div class="feedback-ok">
|
| 581 |
+
✅ Ваша оценка <b>{action_text}</b> сохранена.
|
| 582 |
+
</div>
|
| 583 |
+
"""
|
| 584 |
+
|
| 585 |
+
|
| 586 |
+
def _comment_notice_ok_html():
|
| 587 |
+
return """
|
| 588 |
+
<div class="feedback-ok">
|
| 589 |
+
✅ Комментарий отправлен. Спасибо за обратную связь.
|
| 590 |
</div>
|
| 591 |
"""
|
| 592 |
|
| 593 |
|
| 594 |
+
# =========================
|
| 595 |
+
# Feedback actions
|
| 596 |
+
# =========================
|
| 597 |
+
def submit_like_feedback(garment_name: str):
|
| 598 |
+
if not garment_name:
|
| 599 |
+
return "⚠️ Сначала выполните примерку и выберите одежду", _rating_notice_idle_html()
|
| 600 |
+
|
| 601 |
+
try:
|
| 602 |
+
save_rating_feedback(True, garment_name)
|
| 603 |
+
return "✅ Оценка сохранена: «Нравится»", _rating_notice_ok_html("«Нравится»")
|
| 604 |
+
except Exception as e:
|
| 605 |
+
return (
|
| 606 |
+
f"❌ Ошибка сохранения оценки: {type(e).__name__}: {str(e)[:200]}",
|
| 607 |
+
_rating_notice_idle_html(),
|
| 608 |
+
)
|
| 609 |
+
|
| 610 |
+
|
| 611 |
+
def submit_dislike_feedback(garment_name: str):
|
| 612 |
+
if not garment_name:
|
| 613 |
+
return "⚠️ Сначала выполните примерку и выберите одежду", _rating_notice_idle_html()
|
| 614 |
+
|
| 615 |
+
try:
|
| 616 |
+
save_rating_feedback(False, garment_name)
|
| 617 |
+
return "✅ Оценка сохранена: «Не нравится»", _rating_notice_ok_html("«Не нравится»")
|
| 618 |
+
except Exception as e:
|
| 619 |
+
return (
|
| 620 |
+
f"❌ Ошибка сохранения оценки: {type(e).__name__}: {str(e)[:200]}",
|
| 621 |
+
_rating_notice_idle_html(),
|
| 622 |
+
)
|
| 623 |
+
|
| 624 |
+
|
| 625 |
+
def submit_comment_feedback(garment_name: str, comment: str):
|
| 626 |
+
clean_comment = (comment or "").strip()
|
| 627 |
|
| 628 |
if not garment_name:
|
| 629 |
return (
|
| 630 |
"⚠️ Сначала выполните примерку и выберите одежду",
|
| 631 |
+
_comment_notice_idle_html(),
|
| 632 |
+
gr.update(value=comment),
|
| 633 |
+
)
|
| 634 |
+
|
| 635 |
+
if not clean_comment:
|
| 636 |
+
return (
|
| 637 |
+
"⚠️ Напишите комментарий перед отправкой",
|
| 638 |
+
_comment_notice_idle_html(),
|
| 639 |
gr.update(value=comment),
|
| 640 |
)
|
| 641 |
|
| 642 |
try:
|
| 643 |
+
save_comment_feedback(garment_name, clean_comment)
|
| 644 |
return (
|
| 645 |
+
"✅ Комментарий отправлен",
|
| 646 |
+
_comment_notice_ok_html(),
|
| 647 |
gr.update(value=""),
|
| 648 |
)
|
| 649 |
except Exception as e:
|
| 650 |
return (
|
| 651 |
+
f"❌ Ошибка отправки комментария: {type(e).__name__}: {str(e)[:200]}",
|
| 652 |
+
_comment_notice_idle_html(),
|
|
|
|
|
|
|
|
|
|
|
|
|
| 653 |
gr.update(value=comment),
|
| 654 |
)
|
| 655 |
|
| 656 |
|
| 657 |
+
# =========================
|
| 658 |
+
# Try-on UI
|
| 659 |
+
# =========================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 660 |
def tryon_ui(person_pil, selected_filename):
|
| 661 |
for msg in [
|
| 662 |
"🧵 Анализируем посадку ткани…",
|
|
|
|
| 671 |
msg,
|
| 672 |
gr.update(visible=False),
|
| 673 |
gr.update(value=""),
|
| 674 |
+
gr.update(value=_rating_notice_idle_html()),
|
| 675 |
+
gr.update(value=_comment_notice_idle_html()),
|
| 676 |
)
|
| 677 |
time.sleep(2.3)
|
| 678 |
|
|
|
|
| 683 |
msg,
|
| 684 |
gr.update(visible=False),
|
| 685 |
gr.update(value=""),
|
| 686 |
+
gr.update(value=_rating_notice_idle_html()),
|
| 687 |
+
gr.update(value=_comment_notice_idle_html()),
|
| 688 |
)
|
| 689 |
return
|
| 690 |
|
|
|
|
| 694 |
"❌ Загрузите фото человека",
|
| 695 |
gr.update(visible=False),
|
| 696 |
gr.update(value=""),
|
| 697 |
+
gr.update(value=_rating_notice_idle_html()),
|
| 698 |
+
gr.update(value=_comment_notice_idle_html()),
|
| 699 |
)
|
| 700 |
return
|
| 701 |
|
|
|
|
| 705 |
"❌ Выберите одежду (клик по превью)",
|
| 706 |
gr.update(visible=False),
|
| 707 |
gr.update(value=""),
|
| 708 |
+
gr.update(value=_rating_notice_idle_html()),
|
| 709 |
+
gr.update(value=_comment_notice_idle_html()),
|
| 710 |
)
|
| 711 |
return
|
| 712 |
|
|
|
|
| 717 |
"❌ Не удалось загрузить выбранную одежду",
|
| 718 |
gr.update(visible=False),
|
| 719 |
gr.update(value=""),
|
| 720 |
+
gr.update(value=_rating_notice_idle_html()),
|
| 721 |
+
gr.update(value=_comment_notice_idle_html()),
|
| 722 |
)
|
| 723 |
return
|
| 724 |
|
|
|
|
| 726 |
out_img = start_tryon(human_pil=person_pil, garm_img=garm)
|
| 727 |
yield (
|
| 728 |
out_img,
|
| 729 |
+
"✅ Готово — оцените результат и при желании оставьте комментарий",
|
| 730 |
gr.update(visible=True),
|
| 731 |
gr.update(value=""),
|
| 732 |
+
gr.update(value=_rating_notice_idle_html()),
|
| 733 |
+
gr.update(value=_comment_notice_idle_html()),
|
| 734 |
)
|
| 735 |
except Exception as e:
|
| 736 |
yield (
|
|
|
|
| 738 |
f"❌ Ошибка: {type(e).__name__}: {str(e)[:220]}",
|
| 739 |
gr.update(visible=False),
|
| 740 |
gr.update(value=""),
|
| 741 |
+
gr.update(value=_rating_notice_idle_html()),
|
| 742 |
+
gr.update(value=_comment_notice_idle_html()),
|
| 743 |
)
|
| 744 |
|
| 745 |
|
| 746 |
+
# =========================
|
| 747 |
+
# Boot
|
| 748 |
+
# =========================
|
| 749 |
ensure_garments_available()
|
| 750 |
_default_gender = "Женская"
|
| 751 |
_initial_files = list_garments(gender=_default_gender)
|
|
|
|
| 805 |
with gr.Column(visible=False) as feedback_box:
|
| 806 |
gr.HTML('<div class="feedback-box">')
|
| 807 |
|
| 808 |
+
gr.Markdown("### Оценка результата")
|
| 809 |
with gr.Row():
|
| 810 |
like_btn = gr.Button("👍 Нравится")
|
| 811 |
dislike_btn = gr.Button("👎 Не нравится")
|
| 812 |
+
rating_notice = gr.HTML(_rating_notice_idle_html())
|
| 813 |
|
| 814 |
+
gr.Markdown("### Комментарий")
|
| 815 |
feedback_comment = gr.Textbox(
|
| 816 |
+
label="",
|
| 817 |
placeholder="Напишите, что понравилось или что стоит улучшить...",
|
| 818 |
lines=3,
|
| 819 |
+
max_lines=6,
|
| 820 |
+
show_label=False,
|
| 821 |
)
|
| 822 |
+
submit_comment_btn = gr.Button("Отправить комментарий")
|
| 823 |
+
comment_notice = gr.HTML(_comment_notice_idle_html())
|
| 824 |
|
|
|
|
| 825 |
gr.HTML("</div>")
|
| 826 |
|
| 827 |
gender.change(
|
|
|
|
| 839 |
run.click(
|
| 840 |
fn=tryon_ui,
|
| 841 |
inputs=[person, selected_garment_state],
|
| 842 |
+
outputs=[out, status, feedback_box, feedback_comment, rating_notice, comment_notice],
|
| 843 |
concurrency_limit=1,
|
| 844 |
)
|
| 845 |
|
| 846 |
like_btn.click(
|
| 847 |
fn=submit_like_feedback,
|
| 848 |
+
inputs=[selected_garment_state],
|
| 849 |
+
outputs=[status, rating_notice],
|
| 850 |
concurrency_limit=1,
|
| 851 |
)
|
| 852 |
|
| 853 |
dislike_btn.click(
|
| 854 |
fn=submit_dislike_feedback,
|
| 855 |
+
inputs=[selected_garment_state],
|
| 856 |
+
outputs=[status, rating_notice],
|
| 857 |
+
concurrency_limit=1,
|
| 858 |
+
)
|
| 859 |
+
|
| 860 |
+
submit_comment_btn.click(
|
| 861 |
+
fn=submit_comment_feedback,
|
| 862 |
inputs=[selected_garment_state, feedback_comment],
|
| 863 |
+
outputs=[status, comment_notice, feedback_comment],
|
| 864 |
concurrency_limit=1,
|
| 865 |
)
|
| 866 |
|