Update app.py
Browse files
app.py
CHANGED
|
@@ -98,7 +98,7 @@ HEAD_HTML = """
|
|
| 98 |
.gradio-tabs > div[role="tablist"] > button:hover { background-color: var(--content-background-color) !important; color: var(--primary-color) !important; }
|
| 99 |
.gradio-tabs > div[role="tablist"] > button.selected { color: var(--primary-color) !important; border-bottom: 3px solid var(--primary-color) !important; background-color: var(--content-background-color) !important; }
|
| 100 |
.tabitem { background-color: transparent !important; border: none !important; padding: 0 !important; }
|
| 101 |
-
.gradio-row.panel, .gradio-accordion { background-color: var(--content-background-color) !important; border: 1px solid var(--border-color) !important; border-radius: var(--border-radius) !important; padding: 24px !important; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
|
| 102 |
.gradio-accordion { margin-top: 1rem; }
|
| 103 |
.gradio-button.primary { background: linear-gradient(90deg, var(--primary-color), #00c6ff) !important; color: #ffffff !important; font-weight: 600 !important; font-size: 1.1em !important; border-radius: 8px !important; border: none !important; padding: 12px 24px !important; transition: all 0.3s ease; box-shadow: var(--shadow-light); }
|
| 104 |
.gradio-button.primary:hover { transform: translateY(-2px); box-shadow: var(--shadow-strong); }
|
|
@@ -122,6 +122,7 @@ HEAD_HTML = """
|
|
| 122 |
#chatbot-display .message { border-radius: 18px !important; padding: 12px 18px !important; box-shadow: none !important; max-width: 80%; }
|
| 123 |
#chatbot-display .user { background-color: var(--primary-color) !important; color: white !important; align-self: flex-end; border-bottom-right-radius: 5px !important; }
|
| 124 |
#chatbot-display .bot { background-color: var(--content-background-color) !important; border: 1px solid var(--border-color) !important; align-self: flex-start; border-bottom-left-radius: 5px !important; }
|
|
|
|
| 125 |
#chat-history-sidebar .gradio-radio > div { display: flex; flex-direction: column; gap: 8px; }
|
| 126 |
#chat-history-sidebar .gradio-radio label { width: 100%; text-align: left; padding: 10px; border: 1px solid var(--border-color); border-radius: 8px; transition: all 0.2s ease; }
|
| 127 |
#chat-history-sidebar .gradio-radio input:checked + label { border-color: var(--primary-color); background-color: rgba(0, 170, 255, 0.1); color: var(--primary-color); font-weight: 600; }
|
|
@@ -182,7 +183,7 @@ if Swin2SRForImageSuperResolution:
|
|
| 182 |
upscaler_processor = Swin2SRImageProcessor.from_pretrained("caidas/swin2sr-realworld-sr-x4-64-bsrgan-psnr")
|
| 183 |
print("β
Model AI Upscaler berhasil dimuat.")
|
| 184 |
except Exception as e:
|
| 185 |
-
print(f"β Gagal memuat model Upscaler: {e}. Fitur upscale akan
|
| 186 |
|
| 187 |
# --- KELAS UNTUK CHATBOT GEMINI ---
|
| 188 |
|
|
@@ -215,13 +216,15 @@ class GeminiChat:
|
|
| 215 |
genai.configure(api_key=selected_key)
|
| 216 |
model = genai.GenerativeModel('gemini-2.5-flash')
|
| 217 |
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
|
|
|
|
|
|
| 222 |
|
| 223 |
full_prompt = message
|
| 224 |
-
if system_prompt and not history:
|
| 225 |
full_prompt = f"{system_prompt}\n\nUser query: {message}"
|
| 226 |
|
| 227 |
response = chat_session.send_message(full_prompt)
|
|
@@ -296,7 +299,7 @@ def update_visitor_monitor(time_filter: str):
|
|
| 296 |
column_names = ["Timestamp", "IP Address", "User Agent"]
|
| 297 |
df = pd.read_csv(VISITOR_LOG_FILE, header=None, names=column_names)
|
| 298 |
|
| 299 |
-
if df.iloc[0]['Timestamp'] == 'Timestamp':
|
| 300 |
df = df.iloc[1:].reset_index(drop=True)
|
| 301 |
|
| 302 |
if df.empty: return "## π 0", pd.DataFrame({"Timestamp": [], "Total Pengunjung": []})
|
|
@@ -511,17 +514,14 @@ def handle_user_message(user_message, chat_id, all_chats_history):
|
|
| 511 |
if not chat_id or chat_id not in all_chats_history:
|
| 512 |
all_chats_history, chat_id, current_history, _ = add_new_chat({})
|
| 513 |
|
| 514 |
-
# Tambah pesan pengguna ke riwayat
|
| 515 |
current_history = all_chats_history[chat_id]['history']
|
| 516 |
|
| 517 |
-
# Hapus pesan sambutan awal jika ini pesan pertama
|
| 518 |
if len(current_history) == 1 and current_history[0][0] is None:
|
| 519 |
current_history = []
|
| 520 |
|
| 521 |
current_history.append((user_message, None))
|
| 522 |
all_chats_history[chat_id]['history'] = current_history
|
| 523 |
|
| 524 |
-
# Update judul jika ini pesan pertama
|
| 525 |
if len(current_history) == 1:
|
| 526 |
new_title = user_message[:30] + '...' if len(user_message) > 30 else user_message
|
| 527 |
all_chats_history[chat_id]['title'] = new_title
|
|
@@ -530,8 +530,7 @@ def handle_user_message(user_message, chat_id, all_chats_history):
|
|
| 530 |
|
| 531 |
yield all_chats_history, current_history, gr.update(choices=history_titles, value=all_chats_history[chat_id]['title']), gr.update(value=""), gr.update(visible=False)
|
| 532 |
|
| 533 |
-
|
| 534 |
-
bot_response = gemini_bot.chat(user_message, current_history)
|
| 535 |
current_history[-1] = (user_message, bot_response)
|
| 536 |
all_chats_history[chat_id]['history'] = current_history
|
| 537 |
|
|
@@ -540,7 +539,6 @@ def handle_user_message(user_message, chat_id, all_chats_history):
|
|
| 540 |
def switch_chat(selected_title, all_chats_history):
|
| 541 |
if not selected_title: return None, [], gr.update(visible=False)
|
| 542 |
|
| 543 |
-
# Cari ID berdasarkan judul
|
| 544 |
selected_id = None
|
| 545 |
for chat_id, info in all_chats_history.items():
|
| 546 |
if info['title'] == selected_title:
|
|
@@ -558,7 +556,6 @@ with gr.Blocks(theme=gr.themes.Base(), head=HEAD_HTML) as demo:
|
|
| 558 |
gr.Markdown("# π RenXploit's Creative AI Suite π", elem_id="main-title")
|
| 559 |
gr.Markdown("Sebuah platform lengkap untuk kreativitas Anda, ditenagai oleh AI.", elem_id="main-subtitle")
|
| 560 |
|
| 561 |
-
# State untuk menyimpan semua data sesi
|
| 562 |
chat_history_state = gr.State({})
|
| 563 |
current_chat_id_state = gr.State(None)
|
| 564 |
|
|
@@ -589,8 +586,10 @@ with gr.Blocks(theme=gr.themes.Base(), head=HEAD_HTML) as demo:
|
|
| 589 |
with gr.Column(scale=1, min_width=250) as sidebar:
|
| 590 |
gr.Markdown("### ποΈ Riwayat Chat")
|
| 591 |
new_chat_btn = gr.Button("β Obrolan Baru", variant="primary")
|
| 592 |
-
|
|
|
|
| 593 |
chat_history_list = gr.Radio(label="Pilih Obrolan", choices=[], interactive=True)
|
|
|
|
| 594 |
with gr.Row(visible=False) as chat_action_buttons:
|
| 595 |
share_chat_btn = gr.Button("π Bagikan Chat")
|
| 596 |
share_chat_output = gr.Textbox(label="Salin Konten Chat", lines=10, interactive=True, show_copy_button=True, visible=False)
|
|
@@ -606,7 +605,7 @@ with gr.Blocks(theme=gr.themes.Base(), head=HEAD_HTML) as demo:
|
|
| 606 |
user_chat_input = gr.Textbox(show_label=False, placeholder="Ketik pesan Anda di sini...", scale=5)
|
| 607 |
send_chat_btn = gr.Button("Kirim", variant="secondary", scale=1)
|
| 608 |
|
| 609 |
-
# --- TAB
|
| 610 |
with gr.TabItem("β¨ Prompt Enhancer", id=2):
|
| 611 |
with gr.Row(variant='panel'):
|
| 612 |
with gr.Column():
|
|
@@ -616,7 +615,6 @@ with gr.Blocks(theme=gr.themes.Base(), head=HEAD_HTML) as demo:
|
|
| 616 |
enhanced_prompt_output = gr.Textbox(label="Prompt yang Disempurnakan", lines=5, interactive=True, show_copy_button=True)
|
| 617 |
send_to_gen_btn = gr.Button("β‘οΈ Kirim & Pindah ke Generator")
|
| 618 |
|
| 619 |
-
# --- TAB 4: AI IMAGE UPSCALER ---
|
| 620 |
with gr.TabItem("π AI Image Upscaler", id=3):
|
| 621 |
with gr.Row(variant='panel', equal_height=False):
|
| 622 |
with gr.Column():
|
|
@@ -629,7 +627,6 @@ with gr.Blocks(theme=gr.themes.Base(), head=HEAD_HTML) as demo:
|
|
| 629 |
upscaled_image_output = gr.Image(label="Gambar Hasil Upscale", interactive=False, show_download_button=True)
|
| 630 |
upscale_status_text = gr.Markdown("Status: Menunggu gambar...")
|
| 631 |
|
| 632 |
-
# --- TAB 5 (BARU): GALERI & RIWAYAT (dengan Share) ---
|
| 633 |
with gr.TabItem("πΌοΈ Galeri & Riwayat", id=4) as history_tab:
|
| 634 |
with gr.Row(variant='panel'):
|
| 635 |
with gr.Column(scale=2):
|
|
@@ -646,7 +643,6 @@ with gr.Blocks(theme=gr.themes.Base(), head=HEAD_HTML) as demo:
|
|
| 646 |
share_history_btn = gr.Button("π Bagikan Detail")
|
| 647 |
share_history_output = gr.Textbox(label="URL & Detail untuk Dibagikan", lines=8, interactive=True, show_copy_button=True, visible=False)
|
| 648 |
|
| 649 |
-
# --- TAB 6 (BARU): IMAGE EDITOR ---
|
| 650 |
with gr.TabItem("οΏ½οΏ½οΏ½ Image Editor", id=5):
|
| 651 |
with gr.Row(variant='panel'):
|
| 652 |
with gr.Column(scale=1):
|
|
@@ -663,7 +659,6 @@ with gr.Blocks(theme=gr.themes.Base(), head=HEAD_HTML) as demo:
|
|
| 663 |
gr.Markdown("### **Hasil Editing**")
|
| 664 |
editor_output_image = gr.Image(label="Hasil Akhir", interactive=False, show_download_button=True)
|
| 665 |
|
| 666 |
-
# --- TAB 7: VISITOR MONITOR ---
|
| 667 |
with gr.TabItem("π Visitor Monitor", id=6):
|
| 668 |
with gr.Row(variant='panel'):
|
| 669 |
with gr.Column():
|
|
@@ -675,7 +670,6 @@ with gr.Blocks(theme=gr.themes.Base(), head=HEAD_HTML) as demo:
|
|
| 675 |
refresh_btn = gr.Button("π Segarkan Manual", variant="secondary")
|
| 676 |
visitor_plot = gr.LinePlot(x="Timestamp", y="Total Pengunjung", title="Grafik Pertumbuhan Pengunjung", tooltip=['Timestamp', 'Total Pengunjung'], height=500, interactive=True)
|
| 677 |
|
| 678 |
-
# --- TAB 8: SYSTEM & SETTINGS ---
|
| 679 |
with gr.TabItem("βοΈ System & Settings", id=7):
|
| 680 |
with gr.Row(variant='panel'):
|
| 681 |
with gr.Column():
|
|
@@ -689,14 +683,13 @@ with gr.Blocks(theme=gr.themes.Base(), head=HEAD_HTML) as demo:
|
|
| 689 |
value="FP16 (Cepat, Kualitas Baik)" if device == "cuda" else "FP32 (Lambat, Kualitas Terbaik)",
|
| 690 |
label="Presisi Model Generator", interactive=False, info="Terkunci. Ditentukan saat aplikasi dimulai.")
|
| 691 |
|
| 692 |
-
# --- TAB-TAB STATIS ---
|
| 693 |
with gr.TabItem("π‘ Panduan Prompting", id=8):
|
| 694 |
with gr.Row(variant='panel'): gr.Markdown("""## Cara Menjadi "Art Director" yang Hebat untuk AI...\n (Konten panduan Anda di sini)""")
|
| 695 |
with gr.TabItem("π Blog & Updates", id=9):
|
| 696 |
with gr.Row(variant='panel'): gr.Markdown("""### Perkembangan Terbaru dari RenXploit's AI Suite
|
| 697 |
-
v2.
|
| 698 |
-
v2.
|
| 699 |
-
v2.
|
| 700 |
Rencana Berikutnya: Menjajaki model generator gambar yang berbeda dan fitur Inpainting/Outpainting.""")
|
| 701 |
with gr.TabItem("βΉοΈ About & Support", id=10):
|
| 702 |
with gr.Row(variant='panel'):
|
|
@@ -704,15 +697,13 @@ Rencana Berikutnya: Menjajaki model generator gambar yang berbeda dan fitur Inpa
|
|
| 704 |
gr.Markdown("### Tentang Proyek dan Dukungan")
|
| 705 |
with gr.Accordion("Tentang RenXploit's Creative AI Suite", open=True):
|
| 706 |
gr.Markdown("""
|
| 707 |
-
RenXploit's Creative AI Suite adalah proyek pribadi
|
| 708 |
-
|
| 709 |
-
|
| 710 |
-
Jika Anda memiliki masukan, menemukan bug, atau ingin berdiskusi, jangan ragu untuk menghubungi saya melalui website portofolio di: ngoprek.xyz/contact
|
| 711 |
""")
|
| 712 |
with gr.Accordion("Laporkan Masalah atau Beri Masukan"):
|
| 713 |
report_name = gr.Textbox(label="Nama Anda")
|
| 714 |
report_email = gr.Textbox(label="Email Anda (Opsional)")
|
| 715 |
-
report_message = gr.Textbox(label="Pesan Anda", lines=5, placeholder="Jelaskan masalah
|
| 716 |
report_btn = gr.Button("Kirim Laporan", variant="primary")
|
| 717 |
report_status = gr.Markdown(visible=False)
|
| 718 |
|
|
@@ -720,15 +711,12 @@ Rencana Berikutnya: Menjajaki model generator gambar yang berbeda dan fitur Inpa
|
|
| 720 |
|
| 721 |
# --- PENANGANAN EVENT (EVENT HANDLERS) ---
|
| 722 |
|
| 723 |
-
# 0. Event Utama App
|
| 724 |
demo.load(log_visitor, inputs=None, outputs=None)
|
| 725 |
demo.load(fn=add_new_chat, inputs=[chat_history_state], outputs=[chat_history_state, current_chat_id_state, chatbot_display, chat_history_list])
|
| 726 |
|
| 727 |
-
# 1. Event Image Generator
|
| 728 |
random_seed_btn.click(lambda: -1, outputs=seed_input)
|
| 729 |
generate_btn.click(fn=genie_wrapper, inputs=[prompt_input, negative_prompt_input, steps_slider, seed_input, num_images_slider], outputs=[output_gallery, loader_html, generate_btn, info_box])
|
| 730 |
|
| 731 |
-
# 2. Event Chatbot (UPGRADED)
|
| 732 |
new_chat_btn.click(fn=add_new_chat, inputs=[chat_history_state], outputs=[chat_history_state, current_chat_id_state, chatbot_display, chat_history_list])
|
| 733 |
|
| 734 |
send_chat_btn.click(
|
|
@@ -752,12 +740,10 @@ Rencana Berikutnya: Menjajaki model generator gambar yang berbeda dan fitur Inpa
|
|
| 752 |
outputs=[share_chat_output]
|
| 753 |
)
|
| 754 |
|
| 755 |
-
# 3. Event Fitur Lainnya
|
| 756 |
enhance_btn.click(fn=enhance_prompt, inputs=[simple_prompt_input], outputs=[enhanced_prompt_output])
|
| 757 |
send_to_gen_btn.click(fn=lambda prompt: (prompt, gr.Tabs(selected=0)), inputs=[enhanced_prompt_output], outputs=[prompt_input, tabs])
|
| 758 |
upscale_btn.click(fn=upscale_image, inputs=[image_to_upscale_input, clarity_slider], outputs=[upscaled_image_output, upscale_status_text])
|
| 759 |
|
| 760 |
-
# 4. Event untuk Galeri, Editor & Share
|
| 761 |
history_tab.select(fn=load_history, inputs=None, outputs=[history_gallery, history_df_state, history_details_md])
|
| 762 |
refresh_history_btn.click(fn=load_history, inputs=None, outputs=[history_gallery, history_df_state, history_details_md])
|
| 763 |
history_gallery.select(fn=show_history_details, inputs=[history_df_state], outputs=[history_details_md, history_action_buttons, share_history_output])
|
|
@@ -771,7 +757,6 @@ Rencana Berikutnya: Menjajaki model generator gambar yang berbeda dan fitur Inpa
|
|
| 771 |
filter_radio.change(fn=apply_image_edits, inputs=editor_inputs, outputs=editor_output_image)
|
| 772 |
editor_input_image.change(fn=apply_image_edits, inputs=editor_inputs, outputs=editor_output_image)
|
| 773 |
|
| 774 |
-
# 5. Event Monitor
|
| 775 |
demo.load(fn=update_visitor_monitor, inputs=[time_filter_radio], outputs=[visitor_count_display, visitor_plot])
|
| 776 |
refresh_btn.click(fn=update_visitor_monitor, inputs=[time_filter_radio], outputs=[visitor_count_display, visitor_plot])
|
| 777 |
time_filter_radio.change(fn=update_visitor_monitor, inputs=[time_filter_radio], outputs=[visitor_count_display, visitor_plot])
|
|
@@ -779,10 +764,8 @@ Rencana Berikutnya: Menjajaki model generator gambar yang berbeda dan fitur Inpa
|
|
| 779 |
system_info_trigger_btn.click(fn=update_system_info, inputs=None, outputs=system_info_md)
|
| 780 |
demo.load(fn=update_system_info, inputs=None, outputs=system_info_md)
|
| 781 |
|
| 782 |
-
# 6. Event Support
|
| 783 |
report_btn.click(fn=submit_report, inputs=[report_name, report_email, report_message], outputs=[report_status])
|
| 784 |
|
| 785 |
-
|
| 786 |
# --- Menjalankan Aplikasi ---
|
| 787 |
|
| 788 |
if __name__ == "__main__":
|
|
|
|
| 98 |
.gradio-tabs > div[role="tablist"] > button:hover { background-color: var(--content-background-color) !important; color: var(--primary-color) !important; }
|
| 99 |
.gradio-tabs > div[role="tablist"] > button.selected { color: var(--primary-color) !important; border-bottom: 3px solid var(--primary-color) !important; background-color: var(--content-background-color) !important; }
|
| 100 |
.tabitem { background-color: transparent !important; border: none !important; padding: 0 !important; }
|
| 101 |
+
.gradio-row.panel, .gradio-accordion, .gradio-group { background-color: var(--content-background-color) !important; border: 1px solid var(--border-color) !important; border-radius: var(--border-radius) !important; padding: 24px !important; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
|
| 102 |
.gradio-accordion { margin-top: 1rem; }
|
| 103 |
.gradio-button.primary { background: linear-gradient(90deg, var(--primary-color), #00c6ff) !important; color: #ffffff !important; font-weight: 600 !important; font-size: 1.1em !important; border-radius: 8px !important; border: none !important; padding: 12px 24px !important; transition: all 0.3s ease; box-shadow: var(--shadow-light); }
|
| 104 |
.gradio-button.primary:hover { transform: translateY(-2px); box-shadow: var(--shadow-strong); }
|
|
|
|
| 122 |
#chatbot-display .message { border-radius: 18px !important; padding: 12px 18px !important; box-shadow: none !important; max-width: 80%; }
|
| 123 |
#chatbot-display .user { background-color: var(--primary-color) !important; color: white !important; align-self: flex-end; border-bottom-right-radius: 5px !important; }
|
| 124 |
#chatbot-display .bot { background-color: var(--content-background-color) !important; border: 1px solid var(--border-color) !important; align-self: flex-start; border-bottom-left-radius: 5px !important; }
|
| 125 |
+
#chat-history-sidebar { background-color: transparent !important; border: none !important; padding: 0 !important; box-shadow: none !important; } /* Styling for gr.Group */
|
| 126 |
#chat-history-sidebar .gradio-radio > div { display: flex; flex-direction: column; gap: 8px; }
|
| 127 |
#chat-history-sidebar .gradio-radio label { width: 100%; text-align: left; padding: 10px; border: 1px solid var(--border-color); border-radius: 8px; transition: all 0.2s ease; }
|
| 128 |
#chat-history-sidebar .gradio-radio input:checked + label { border-color: var(--primary-color); background-color: rgba(0, 170, 255, 0.1); color: var(--primary-color); font-weight: 600; }
|
|
|
|
| 183 |
upscaler_processor = Swin2SRImageProcessor.from_pretrained("caidas/swin2sr-realworld-sr-x4-64-bsrgan-psnr")
|
| 184 |
print("β
Model AI Upscaler berhasil dimuat.")
|
| 185 |
except Exception as e:
|
| 186 |
+
print(f"β Gagal memuat model Upscaler: {e}. Fitur upscale akan dinaktifkan.")
|
| 187 |
|
| 188 |
# --- KELAS UNTUK CHATBOT GEMINI ---
|
| 189 |
|
|
|
|
| 216 |
genai.configure(api_key=selected_key)
|
| 217 |
model = genai.GenerativeModel('gemini-2.5-flash')
|
| 218 |
|
| 219 |
+
chat_history_for_api = []
|
| 220 |
+
for user_msg, model_msg in history:
|
| 221 |
+
if user_msg: chat_history_for_api.append({"role": "user", "parts": [user_msg]})
|
| 222 |
+
if model_msg: chat_history_for_api.append({"role": "model", "parts": [model_msg]})
|
| 223 |
+
|
| 224 |
+
chat_session = model.start_chat(history=chat_history_for_api)
|
| 225 |
|
| 226 |
full_prompt = message
|
| 227 |
+
if system_prompt and not history:
|
| 228 |
full_prompt = f"{system_prompt}\n\nUser query: {message}"
|
| 229 |
|
| 230 |
response = chat_session.send_message(full_prompt)
|
|
|
|
| 299 |
column_names = ["Timestamp", "IP Address", "User Agent"]
|
| 300 |
df = pd.read_csv(VISITOR_LOG_FILE, header=None, names=column_names)
|
| 301 |
|
| 302 |
+
if not df.empty and df.iloc[0]['Timestamp'] == 'Timestamp':
|
| 303 |
df = df.iloc[1:].reset_index(drop=True)
|
| 304 |
|
| 305 |
if df.empty: return "## π 0", pd.DataFrame({"Timestamp": [], "Total Pengunjung": []})
|
|
|
|
| 514 |
if not chat_id or chat_id not in all_chats_history:
|
| 515 |
all_chats_history, chat_id, current_history, _ = add_new_chat({})
|
| 516 |
|
|
|
|
| 517 |
current_history = all_chats_history[chat_id]['history']
|
| 518 |
|
|
|
|
| 519 |
if len(current_history) == 1 and current_history[0][0] is None:
|
| 520 |
current_history = []
|
| 521 |
|
| 522 |
current_history.append((user_message, None))
|
| 523 |
all_chats_history[chat_id]['history'] = current_history
|
| 524 |
|
|
|
|
| 525 |
if len(current_history) == 1:
|
| 526 |
new_title = user_message[:30] + '...' if len(user_message) > 30 else user_message
|
| 527 |
all_chats_history[chat_id]['title'] = new_title
|
|
|
|
| 530 |
|
| 531 |
yield all_chats_history, current_history, gr.update(choices=history_titles, value=all_chats_history[chat_id]['title']), gr.update(value=""), gr.update(visible=False)
|
| 532 |
|
| 533 |
+
bot_response = gemini_bot.chat(user_message, [h for h in current_history if h[0] is not None])
|
|
|
|
| 534 |
current_history[-1] = (user_message, bot_response)
|
| 535 |
all_chats_history[chat_id]['history'] = current_history
|
| 536 |
|
|
|
|
| 539 |
def switch_chat(selected_title, all_chats_history):
|
| 540 |
if not selected_title: return None, [], gr.update(visible=False)
|
| 541 |
|
|
|
|
| 542 |
selected_id = None
|
| 543 |
for chat_id, info in all_chats_history.items():
|
| 544 |
if info['title'] == selected_title:
|
|
|
|
| 556 |
gr.Markdown("# π RenXploit's Creative AI Suite π", elem_id="main-title")
|
| 557 |
gr.Markdown("Sebuah platform lengkap untuk kreativitas Anda, ditenagai oleh AI.", elem_id="main-subtitle")
|
| 558 |
|
|
|
|
| 559 |
chat_history_state = gr.State({})
|
| 560 |
current_chat_id_state = gr.State(None)
|
| 561 |
|
|
|
|
| 586 |
with gr.Column(scale=1, min_width=250) as sidebar:
|
| 587 |
gr.Markdown("### ποΈ Riwayat Chat")
|
| 588 |
new_chat_btn = gr.Button("β Obrolan Baru", variant="primary")
|
| 589 |
+
# === PERBAIKAN DI SINI: MENGGUNAKAN gr.Group BUKAN gr.Box ===
|
| 590 |
+
with gr.Group(elem_id="chat-history-sidebar"):
|
| 591 |
chat_history_list = gr.Radio(label="Pilih Obrolan", choices=[], interactive=True)
|
| 592 |
+
# ==========================================================
|
| 593 |
with gr.Row(visible=False) as chat_action_buttons:
|
| 594 |
share_chat_btn = gr.Button("π Bagikan Chat")
|
| 595 |
share_chat_output = gr.Textbox(label="Salin Konten Chat", lines=10, interactive=True, show_copy_button=True, visible=False)
|
|
|
|
| 605 |
user_chat_input = gr.Textbox(show_label=False, placeholder="Ketik pesan Anda di sini...", scale=5)
|
| 606 |
send_chat_btn = gr.Button("Kirim", variant="secondary", scale=1)
|
| 607 |
|
| 608 |
+
# --- TAB-TAB LAINNYA (TETAP SAMA) ---
|
| 609 |
with gr.TabItem("β¨ Prompt Enhancer", id=2):
|
| 610 |
with gr.Row(variant='panel'):
|
| 611 |
with gr.Column():
|
|
|
|
| 615 |
enhanced_prompt_output = gr.Textbox(label="Prompt yang Disempurnakan", lines=5, interactive=True, show_copy_button=True)
|
| 616 |
send_to_gen_btn = gr.Button("β‘οΈ Kirim & Pindah ke Generator")
|
| 617 |
|
|
|
|
| 618 |
with gr.TabItem("π AI Image Upscaler", id=3):
|
| 619 |
with gr.Row(variant='panel', equal_height=False):
|
| 620 |
with gr.Column():
|
|
|
|
| 627 |
upscaled_image_output = gr.Image(label="Gambar Hasil Upscale", interactive=False, show_download_button=True)
|
| 628 |
upscale_status_text = gr.Markdown("Status: Menunggu gambar...")
|
| 629 |
|
|
|
|
| 630 |
with gr.TabItem("πΌοΈ Galeri & Riwayat", id=4) as history_tab:
|
| 631 |
with gr.Row(variant='panel'):
|
| 632 |
with gr.Column(scale=2):
|
|
|
|
| 643 |
share_history_btn = gr.Button("π Bagikan Detail")
|
| 644 |
share_history_output = gr.Textbox(label="URL & Detail untuk Dibagikan", lines=8, interactive=True, show_copy_button=True, visible=False)
|
| 645 |
|
|
|
|
| 646 |
with gr.TabItem("οΏ½οΏ½οΏ½ Image Editor", id=5):
|
| 647 |
with gr.Row(variant='panel'):
|
| 648 |
with gr.Column(scale=1):
|
|
|
|
| 659 |
gr.Markdown("### **Hasil Editing**")
|
| 660 |
editor_output_image = gr.Image(label="Hasil Akhir", interactive=False, show_download_button=True)
|
| 661 |
|
|
|
|
| 662 |
with gr.TabItem("π Visitor Monitor", id=6):
|
| 663 |
with gr.Row(variant='panel'):
|
| 664 |
with gr.Column():
|
|
|
|
| 670 |
refresh_btn = gr.Button("π Segarkan Manual", variant="secondary")
|
| 671 |
visitor_plot = gr.LinePlot(x="Timestamp", y="Total Pengunjung", title="Grafik Pertumbuhan Pengunjung", tooltip=['Timestamp', 'Total Pengunjung'], height=500, interactive=True)
|
| 672 |
|
|
|
|
| 673 |
with gr.TabItem("βοΈ System & Settings", id=7):
|
| 674 |
with gr.Row(variant='panel'):
|
| 675 |
with gr.Column():
|
|
|
|
| 683 |
value="FP16 (Cepat, Kualitas Baik)" if device == "cuda" else "FP32 (Lambat, Kualitas Terbaik)",
|
| 684 |
label="Presisi Model Generator", interactive=False, info="Terkunci. Ditentukan saat aplikasi dimulai.")
|
| 685 |
|
|
|
|
| 686 |
with gr.TabItem("π‘ Panduan Prompting", id=8):
|
| 687 |
with gr.Row(variant='panel'): gr.Markdown("""## Cara Menjadi "Art Director" yang Hebat untuk AI...\n (Konten panduan Anda di sini)""")
|
| 688 |
with gr.TabItem("π Blog & Updates", id=9):
|
| 689 |
with gr.Row(variant='panel'): gr.Markdown("""### Perkembangan Terbaru dari RenXploit's AI Suite
|
| 690 |
+
v2.8 (Perbaikan): Mengganti komponen `gr.Box` dengan `gr.Group` untuk kompatibilitas dengan versi Gradio yang lebih lama.
|
| 691 |
+
v2.7: Perombakan total UI Chatbot menjadi lebih profesional dengan fitur riwayat percakapan, new chat, dan share chat. Menambahkan fitur share detail gambar dari galeri.
|
| 692 |
+
v2.6: Perbaikan final untuk bug KeyError: 'Timestamp' pada Visitor Monitor.
|
| 693 |
Rencana Berikutnya: Menjajaki model generator gambar yang berbeda dan fitur Inpainting/Outpainting.""")
|
| 694 |
with gr.TabItem("βΉοΈ About & Support", id=10):
|
| 695 |
with gr.Row(variant='panel'):
|
|
|
|
| 697 |
gr.Markdown("### Tentang Proyek dan Dukungan")
|
| 698 |
with gr.Accordion("Tentang RenXploit's Creative AI Suite", open=True):
|
| 699 |
gr.Markdown("""
|
| 700 |
+
RenXploit's Creative AI Suite adalah proyek pribadi untuk mengeksplorasi AI generatif.
|
| 701 |
+
Hubungi saya melalui: ngoprek.xyz/contact
|
|
|
|
|
|
|
| 702 |
""")
|
| 703 |
with gr.Accordion("Laporkan Masalah atau Beri Masukan"):
|
| 704 |
report_name = gr.Textbox(label="Nama Anda")
|
| 705 |
report_email = gr.Textbox(label="Email Anda (Opsional)")
|
| 706 |
+
report_message = gr.Textbox(label="Pesan Anda", lines=5, placeholder="Jelaskan masalah atau ide Anda...")
|
| 707 |
report_btn = gr.Button("Kirim Laporan", variant="primary")
|
| 708 |
report_status = gr.Markdown(visible=False)
|
| 709 |
|
|
|
|
| 711 |
|
| 712 |
# --- PENANGANAN EVENT (EVENT HANDLERS) ---
|
| 713 |
|
|
|
|
| 714 |
demo.load(log_visitor, inputs=None, outputs=None)
|
| 715 |
demo.load(fn=add_new_chat, inputs=[chat_history_state], outputs=[chat_history_state, current_chat_id_state, chatbot_display, chat_history_list])
|
| 716 |
|
|
|
|
| 717 |
random_seed_btn.click(lambda: -1, outputs=seed_input)
|
| 718 |
generate_btn.click(fn=genie_wrapper, inputs=[prompt_input, negative_prompt_input, steps_slider, seed_input, num_images_slider], outputs=[output_gallery, loader_html, generate_btn, info_box])
|
| 719 |
|
|
|
|
| 720 |
new_chat_btn.click(fn=add_new_chat, inputs=[chat_history_state], outputs=[chat_history_state, current_chat_id_state, chatbot_display, chat_history_list])
|
| 721 |
|
| 722 |
send_chat_btn.click(
|
|
|
|
| 740 |
outputs=[share_chat_output]
|
| 741 |
)
|
| 742 |
|
|
|
|
| 743 |
enhance_btn.click(fn=enhance_prompt, inputs=[simple_prompt_input], outputs=[enhanced_prompt_output])
|
| 744 |
send_to_gen_btn.click(fn=lambda prompt: (prompt, gr.Tabs(selected=0)), inputs=[enhanced_prompt_output], outputs=[prompt_input, tabs])
|
| 745 |
upscale_btn.click(fn=upscale_image, inputs=[image_to_upscale_input, clarity_slider], outputs=[upscaled_image_output, upscale_status_text])
|
| 746 |
|
|
|
|
| 747 |
history_tab.select(fn=load_history, inputs=None, outputs=[history_gallery, history_df_state, history_details_md])
|
| 748 |
refresh_history_btn.click(fn=load_history, inputs=None, outputs=[history_gallery, history_df_state, history_details_md])
|
| 749 |
history_gallery.select(fn=show_history_details, inputs=[history_df_state], outputs=[history_details_md, history_action_buttons, share_history_output])
|
|
|
|
| 757 |
filter_radio.change(fn=apply_image_edits, inputs=editor_inputs, outputs=editor_output_image)
|
| 758 |
editor_input_image.change(fn=apply_image_edits, inputs=editor_inputs, outputs=editor_output_image)
|
| 759 |
|
|
|
|
| 760 |
demo.load(fn=update_visitor_monitor, inputs=[time_filter_radio], outputs=[visitor_count_display, visitor_plot])
|
| 761 |
refresh_btn.click(fn=update_visitor_monitor, inputs=[time_filter_radio], outputs=[visitor_count_display, visitor_plot])
|
| 762 |
time_filter_radio.change(fn=update_visitor_monitor, inputs=[time_filter_radio], outputs=[visitor_count_display, visitor_plot])
|
|
|
|
| 764 |
system_info_trigger_btn.click(fn=update_system_info, inputs=None, outputs=system_info_md)
|
| 765 |
demo.load(fn=update_system_info, inputs=None, outputs=system_info_md)
|
| 766 |
|
|
|
|
| 767 |
report_btn.click(fn=submit_report, inputs=[report_name, report_email, report_message], outputs=[report_status])
|
| 768 |
|
|
|
|
| 769 |
# --- Menjalankan Aplikasi ---
|
| 770 |
|
| 771 |
if __name__ == "__main__":
|