Update app.py
Browse files
app.py
CHANGED
|
@@ -320,47 +320,50 @@ def process_generation(original_prompt, aspect_ratio, resolution, request: gr.Re
|
|
| 320 |
"""이미지 생성 처리 - HF OAuth 사용"""
|
| 321 |
# 로그인 확인
|
| 322 |
if not request.username:
|
| 323 |
-
yield "❌ 로그인이 필요합니다.
|
| 324 |
return
|
| 325 |
|
| 326 |
# 유저 정보 가져오기/생성
|
| 327 |
user = get_or_create_user(request.username)
|
|
|
|
| 328 |
|
| 329 |
if not user["is_active"]:
|
| 330 |
-
yield "❌ 비활성화된 계정입니다.", None, None, None, "
|
| 331 |
return
|
| 332 |
|
| 333 |
# 사용량 확인
|
| 334 |
allowed, current, limit = check_usage_limit(user["id"], user["daily_limit"])
|
| 335 |
if not allowed:
|
| 336 |
-
yield f"❌ 일일 한도({limit}회) 초과", None, None, None, f"{current}/{limit}"
|
| 337 |
return
|
| 338 |
|
| 339 |
fw_key = FIREWORKS_API_KEY
|
| 340 |
fl_key = FAL_KEY
|
| 341 |
|
| 342 |
if not fw_key or not fl_key:
|
| 343 |
-
yield "❌ API 키가 설정되지 않았습니다.", None, None, None, f"{current}/{limit}"
|
| 344 |
return
|
| 345 |
|
| 346 |
-
|
|
|
|
|
|
|
| 347 |
|
| 348 |
enhanced = enhance_prompt(original_prompt, fw_key)
|
| 349 |
if enhanced.startswith("❌"):
|
| 350 |
-
yield enhanced, None, None, None, f"{current}/{limit}"
|
| 351 |
return
|
| 352 |
|
| 353 |
-
yield "✅ 프롬프트 증강 완료\n⚡ 원본 이미지 생성 중...", enhanced, None, None, f"{current}/{limit}"
|
| 354 |
original_image = generate_image(original_prompt, fl_key, aspect_ratio, resolution)
|
| 355 |
|
| 356 |
-
yield "✅ 원본 이미지 완료\n⚡ 증강 이미지 생성 중...", enhanced, original_image, None, f"{current}/{limit}"
|
| 357 |
enhanced_image = generate_image(enhanced, fl_key, aspect_ratio, resolution)
|
| 358 |
|
| 359 |
# 사용량 증가 및 저장
|
| 360 |
new_count = increment_usage(user["id"])
|
| 361 |
save_generation(user["id"], original_prompt, enhanced, enhanced_image or original_image, "success" if enhanced_image else "partial")
|
| 362 |
|
| 363 |
-
yield f"✅ 완료! 사용량: {new_count}/{limit}", enhanced, original_image, enhanced_image, f"{new_count}/{limit}"
|
| 364 |
|
| 365 |
# ============================================
|
| 366 |
# CSS - 밝은 프로페셔널 테마
|
|
@@ -564,6 +567,63 @@ a.hf-login-btn:hover {
|
|
| 564 |
box-shadow: 0 6px 16px rgba(255, 157, 0, 0.4);
|
| 565 |
}
|
| 566 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 567 |
.hf-login-btn svg {
|
| 568 |
width: 20px;
|
| 569 |
height: 20px;
|
|
@@ -633,47 +693,6 @@ examples = [
|
|
| 633 |
["바다 위 일몰과 작은 돛단배"],
|
| 634 |
]
|
| 635 |
|
| 636 |
-
def get_header_html(request: gr.Request):
|
| 637 |
-
"""헤더 HTML 생성 - 로그인 상태에 따라 다른 버튼 표시"""
|
| 638 |
-
if request.username:
|
| 639 |
-
user = get_or_create_user(request.username)
|
| 640 |
-
usage = get_daily_usage(user["id"])
|
| 641 |
-
admin_icon = '<span class="admin-crown">👑</span>' if user["is_admin"] else ''
|
| 642 |
-
|
| 643 |
-
return f'''
|
| 644 |
-
<div class="header-container">
|
| 645 |
-
<div class="header-left">
|
| 646 |
-
<h1 class="cyber-title" style="margin:0; font-size:2rem;">🚀 PROMPT ENHANCER</h1>
|
| 647 |
-
<p style="color: #4b5563; font-size: 0.95rem; margin: 4px 0 0 0;">AI-Powered Image Generation</p>
|
| 648 |
-
</div>
|
| 649 |
-
<div class="header-right">
|
| 650 |
-
<span class="usage-badge">📊 오늘 사용량: <strong>{usage}/{user["daily_limit"]}</strong></span>
|
| 651 |
-
<div class="user-badge">
|
| 652 |
-
{admin_icon}
|
| 653 |
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg>
|
| 654 |
-
{request.username}
|
| 655 |
-
</div>
|
| 656 |
-
</div>
|
| 657 |
-
</div>
|
| 658 |
-
'''
|
| 659 |
-
else:
|
| 660 |
-
return '''
|
| 661 |
-
<div class="header-container">
|
| 662 |
-
<div class="header-left">
|
| 663 |
-
<h1 class="cyber-title" style="margin:0; font-size:2rem;">🚀 PROMPT ENHANCER</h1>
|
| 664 |
-
<p style="color: #4b5563; font-size: 0.95rem; margin: 4px 0 0 0;">AI-Powered Image Generation</p>
|
| 665 |
-
</div>
|
| 666 |
-
<div class="header-right">
|
| 667 |
-
<a href="/login/huggingface" class="hf-login-btn">
|
| 668 |
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120" fill="currentColor">
|
| 669 |
-
<path d="M37.5 45c-5.5 0-10 4.5-10 10s4.5 10 10 10 10-4.5 10-10-4.5-10-10-10zm45 0c-5.5 0-10 4.5-10 10s4.5 10 10 10 10-4.5 10-10-4.5-10-10-10zM60 85c-11 0-20-6.3-20-14h40c0 7.7-9 14-20 14z"/>
|
| 670 |
-
</svg>
|
| 671 |
-
HuggingFace로 로그인
|
| 672 |
-
</a>
|
| 673 |
-
</div>
|
| 674 |
-
</div>
|
| 675 |
-
'''
|
| 676 |
-
|
| 677 |
def get_user_info(request: gr.Request):
|
| 678 |
"""현재 로그인한 유저 정보 반환"""
|
| 679 |
if not request.username:
|
|
@@ -766,13 +785,23 @@ def admin_change_limit(user_id, new_limit, request: gr.Request):
|
|
| 766 |
# Gradio 앱 빌드
|
| 767 |
with gr.Blocks(title="AI PROMPT ENHANCER", css=CUSTOM_CSS) as demo:
|
| 768 |
|
| 769 |
-
#
|
| 770 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 771 |
|
| 772 |
-
# 유저 정보 표시
|
| 773 |
-
|
| 774 |
-
user_info_display = gr.Markdown("")
|
| 775 |
-
usage_display = gr.Markdown("")
|
| 776 |
|
| 777 |
with gr.Tabs() as tabs:
|
| 778 |
# Tab 1: 이미지 생성
|
|
@@ -823,15 +852,30 @@ with gr.Blocks(title="AI PROMPT ENHANCER", css=CUSTOM_CSS) as demo:
|
|
| 823 |
|
| 824 |
# ========== 이벤트 핸들러 ==========
|
| 825 |
|
| 826 |
-
# 페이지 로드 시
|
| 827 |
-
|
| 828 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 829 |
|
| 830 |
# 이미지 생성
|
| 831 |
generate_btn.click(
|
| 832 |
process_generation,
|
| 833 |
[prompt_input, aspect_ratio, resolution],
|
| 834 |
-
[status_text, enhanced_output, original_image_output, enhanced_image_output,
|
| 835 |
)
|
| 836 |
|
| 837 |
# 내 계정 탭
|
|
|
|
| 320 |
"""이미지 생성 처리 - HF OAuth 사용"""
|
| 321 |
# 로그인 확인
|
| 322 |
if not request.username:
|
| 323 |
+
yield "❌ 로그인이 필요합니다. 상단에서 HuggingFace로 로그인해주세요.", None, None, None, "🔐 로그인이 필요합니다"
|
| 324 |
return
|
| 325 |
|
| 326 |
# 유저 정보 가져오기/생성
|
| 327 |
user = get_or_create_user(request.username)
|
| 328 |
+
admin_badge = " 👑 관리자" if user["is_admin"] else ""
|
| 329 |
|
| 330 |
if not user["is_active"]:
|
| 331 |
+
yield "❌ 비활성화된 계정입니다.", None, None, None, f"**👋 {request.username}**{admin_badge} | ❌ 비활성화"
|
| 332 |
return
|
| 333 |
|
| 334 |
# 사용량 확인
|
| 335 |
allowed, current, limit = check_usage_limit(user["id"], user["daily_limit"])
|
| 336 |
if not allowed:
|
| 337 |
+
yield f"❌ 일일 한도({limit}회) 초과", None, None, None, f"**👋 {request.username}**{admin_badge} | 사용량: {current}/{limit} ❌ 초과"
|
| 338 |
return
|
| 339 |
|
| 340 |
fw_key = FIREWORKS_API_KEY
|
| 341 |
fl_key = FAL_KEY
|
| 342 |
|
| 343 |
if not fw_key or not fl_key:
|
| 344 |
+
yield "❌ API 키가 설정되지 않았습니다.", None, None, None, f"**👋 {request.username}**{admin_badge} | 사용량: {current}/{limit}"
|
| 345 |
return
|
| 346 |
|
| 347 |
+
status_base = f"**👋 {request.username}**{admin_badge}"
|
| 348 |
+
|
| 349 |
+
yield f"⚡ 프롬프트 증강 중...", None, None, None, f"{status_base} | 사용량: {current}/{limit}"
|
| 350 |
|
| 351 |
enhanced = enhance_prompt(original_prompt, fw_key)
|
| 352 |
if enhanced.startswith("❌"):
|
| 353 |
+
yield enhanced, None, None, None, f"{status_base} | 사용량: {current}/{limit}"
|
| 354 |
return
|
| 355 |
|
| 356 |
+
yield "✅ 프롬프트 증강 완료\n⚡ 원본 이미지 생성 중...", enhanced, None, None, f"{status_base} | 사용량: {current}/{limit}"
|
| 357 |
original_image = generate_image(original_prompt, fl_key, aspect_ratio, resolution)
|
| 358 |
|
| 359 |
+
yield "✅ 원본 이미지 완료\n⚡ 증강 이미지 생성 중...", enhanced, original_image, None, f"{status_base} | 사용량: {current}/{limit}"
|
| 360 |
enhanced_image = generate_image(enhanced, fl_key, aspect_ratio, resolution)
|
| 361 |
|
| 362 |
# 사용량 증가 및 저장
|
| 363 |
new_count = increment_usage(user["id"])
|
| 364 |
save_generation(user["id"], original_prompt, enhanced, enhanced_image or original_image, "success" if enhanced_image else "partial")
|
| 365 |
|
| 366 |
+
yield f"✅ 완료! 사용량: {new_count}/{limit}", enhanced, original_image, enhanced_image, f"{status_base} | 사용량: {new_count}/{limit}"
|
| 367 |
|
| 368 |
# ============================================
|
| 369 |
# CSS - 밝은 프로페셔널 테마
|
|
|
|
| 567 |
box-shadow: 0 6px 16px rgba(255, 157, 0, 0.4);
|
| 568 |
}
|
| 569 |
|
| 570 |
+
/* Gradio LoginButton 스타일 오버라이드 */
|
| 571 |
+
.hf-login-btn button,
|
| 572 |
+
button.hf-login-btn,
|
| 573 |
+
.hf-login-btn > button {
|
| 574 |
+
background: linear-gradient(135deg, #ff9d00 0%, #ffb347 100%) !important;
|
| 575 |
+
color: #000 !important;
|
| 576 |
+
font-weight: 600 !important;
|
| 577 |
+
font-size: 0.9rem !important;
|
| 578 |
+
padding: 10px 20px !important;
|
| 579 |
+
border-radius: 25px !important;
|
| 580 |
+
border: none !important;
|
| 581 |
+
cursor: pointer !important;
|
| 582 |
+
box-shadow: 0 4px 12px rgba(255, 157, 0, 0.3) !important;
|
| 583 |
+
transition: all 0.2s ease !important;
|
| 584 |
+
}
|
| 585 |
+
|
| 586 |
+
.hf-login-btn button:hover {
|
| 587 |
+
transform: translateY(-2px) !important;
|
| 588 |
+
box-shadow: 0 6px 16px rgba(255, 157, 0, 0.4) !important;
|
| 589 |
+
}
|
| 590 |
+
|
| 591 |
+
/* 로그아웃 버튼 */
|
| 592 |
+
.logout-btn button,
|
| 593 |
+
button.logout-btn {
|
| 594 |
+
background: #f3f4f6 !important;
|
| 595 |
+
color: #4b5563 !important;
|
| 596 |
+
font-weight: 500 !important;
|
| 597 |
+
font-size: 0.85rem !important;
|
| 598 |
+
padding: 8px 16px !important;
|
| 599 |
+
border-radius: 20px !important;
|
| 600 |
+
border: 1px solid #e5e7eb !important;
|
| 601 |
+
}
|
| 602 |
+
|
| 603 |
+
.logout-btn button:hover {
|
| 604 |
+
background: #e5e7eb !important;
|
| 605 |
+
}
|
| 606 |
+
|
| 607 |
+
/* 사용량 정보 */
|
| 608 |
+
.usage-info {
|
| 609 |
+
display: flex;
|
| 610 |
+
align-items: center;
|
| 611 |
+
padding: 8px 16px;
|
| 612 |
+
background: #f0f9ff;
|
| 613 |
+
border-radius: 20px;
|
| 614 |
+
font-size: 0.9rem;
|
| 615 |
+
}
|
| 616 |
+
|
| 617 |
+
/* 헤더 Row */
|
| 618 |
+
.header-row {
|
| 619 |
+
background: linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%);
|
| 620 |
+
border-radius: 16px;
|
| 621 |
+
padding: 10px 20px;
|
| 622 |
+
margin-bottom: 20px;
|
| 623 |
+
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
| 624 |
+
align-items: center;
|
| 625 |
+
}
|
| 626 |
+
|
| 627 |
.hf-login-btn svg {
|
| 628 |
width: 20px;
|
| 629 |
height: 20px;
|
|
|
|
| 693 |
["바다 위 일몰과 작은 돛단배"],
|
| 694 |
]
|
| 695 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 696 |
def get_user_info(request: gr.Request):
|
| 697 |
"""현재 로그인한 유저 정보 반환"""
|
| 698 |
if not request.username:
|
|
|
|
| 785 |
# Gradio 앱 빌드
|
| 786 |
with gr.Blocks(title="AI PROMPT ENHANCER", css=CUSTOM_CSS) as demo:
|
| 787 |
|
| 788 |
+
# 헤더 영역
|
| 789 |
+
with gr.Row(elem_classes=["header-row"]):
|
| 790 |
+
with gr.Column(scale=3):
|
| 791 |
+
gr.HTML('''
|
| 792 |
+
<div style="padding: 20px 0;">
|
| 793 |
+
<h1 class="cyber-title" style="margin:0; font-size:2rem;">🚀 PROMPT ENHANCER</h1>
|
| 794 |
+
<p style="color: #4b5563; font-size: 0.95rem; margin: 4px 0 0 0;">AI-Powered Image Generation</p>
|
| 795 |
+
</div>
|
| 796 |
+
''')
|
| 797 |
+
with gr.Column(scale=1):
|
| 798 |
+
with gr.Row():
|
| 799 |
+
usage_info = gr.Markdown("", elem_classes=["usage-info"])
|
| 800 |
+
login_btn = gr.LoginButton(value="🤗 HuggingFace 로그인", size="sm", elem_classes=["hf-login-btn"])
|
| 801 |
+
logout_btn = gr.LogoutButton(value="로그아웃", size="sm", elem_classes=["logout-btn"])
|
| 802 |
|
| 803 |
+
# 유저 정보 표시
|
| 804 |
+
user_status = gr.Markdown("")
|
|
|
|
|
|
|
| 805 |
|
| 806 |
with gr.Tabs() as tabs:
|
| 807 |
# Tab 1: 이미지 생성
|
|
|
|
| 852 |
|
| 853 |
# ========== 이벤트 핸들러 ==========
|
| 854 |
|
| 855 |
+
# 페이지 로드 시 유저 상태 표시
|
| 856 |
+
def show_user_status(request: gr.Request):
|
| 857 |
+
if request.username:
|
| 858 |
+
user = get_or_create_user(request.username)
|
| 859 |
+
usage = get_daily_usage(user["id"])
|
| 860 |
+
admin_badge = " 👑 관리자" if user["is_admin"] else ""
|
| 861 |
+
return f"**👋 {request.username}**{admin_badge} | 사용량: {usage}/{user['daily_limit']}"
|
| 862 |
+
return "🔐 로그인이 필요합니다"
|
| 863 |
+
|
| 864 |
+
def show_usage_info(request: gr.Request):
|
| 865 |
+
if request.username:
|
| 866 |
+
user = get_or_create_user(request.username)
|
| 867 |
+
usage = get_daily_usage(user["id"])
|
| 868 |
+
return f"📊 **{usage}/{user['daily_limit']}**"
|
| 869 |
+
return ""
|
| 870 |
+
|
| 871 |
+
demo.load(show_user_status, None, [user_status])
|
| 872 |
+
demo.load(show_usage_info, None, [usage_info])
|
| 873 |
|
| 874 |
# 이미지 생성
|
| 875 |
generate_btn.click(
|
| 876 |
process_generation,
|
| 877 |
[prompt_input, aspect_ratio, resolution],
|
| 878 |
+
[status_text, enhanced_output, original_image_output, enhanced_image_output, user_status]
|
| 879 |
)
|
| 880 |
|
| 881 |
# 내 계정 탭
|