ErNewdev0 commited on
Commit
41766c3
·
verified ·
1 Parent(s): dbb50ea

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +196 -348
app.py CHANGED
@@ -304,8 +304,10 @@ class RepoAnalyzer:
304
 
305
  def create_ui():
306
  analyzer = RepoAnalyzer()
 
307
 
308
  with gr.Blocks(title="Open Repo AI", theme=gr.themes.Soft()) as app:
 
309
  gr.Markdown("""
310
  <style>
311
  .container { max-width: 100% !important; padding: 1rem; }
@@ -313,6 +315,38 @@ def create_ui():
313
  .file-list { margin: 10px 0; padding: 10px; border: 1px solid #ddd; border-radius: 4px; }
314
  .file-item { display: flex; justify-content: space-between; padding: 5px 0; }
315
  .file-remove { color: red; cursor: pointer; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
316
  @media (max-width: 768px) {
317
  .gr-form { flex-direction: column !important; }
318
  .gr-group { margin: 0.5rem 0 !important; }
@@ -320,14 +354,17 @@ def create_ui():
320
  </style>
321
  """)
322
 
 
323
  with gr.Row(elem_classes="container"):
324
  gr.Markdown(f"""
325
  # AI Github Repository Chat
326
 
327
- 📅 {datetime.now().strftime("%Y-%m-%d %H:%M:%S")} UTC
 
328
  """)
329
 
330
- with gr.Tabs() as tabs: # Main tabs container
 
331
  # Configuration Tab
332
  with gr.Tab("🛠️ Konfigurasi"):
333
  provider = gr.Radio(
@@ -359,7 +396,6 @@ def create_ui():
359
  with gr.Column(scale=1):
360
  gr.Markdown(GEMINI_API_HELP)
361
 
362
- # Model selection
363
  with gr.Row():
364
  model_dropdown = gr.Dropdown(
365
  label="Model AI",
@@ -371,6 +407,7 @@ def create_ui():
371
  # Repository Analysis Tab
372
  with gr.Tab("📊 Analisis Repository"):
373
  with gr.Group():
 
374
  with gr.Row():
375
  repo_url = gr.Textbox(
376
  label="URL Repository GitHub",
@@ -394,369 +431,180 @@ def create_ui():
394
  elem_classes="mobile-full",
395
  )
396
 
397
- clone_button = gr.Button(
398
- "🔄 Clone Repository", variant="primary", elem_classes="mobile-full"
399
- )
400
-
401
- clone_status = gr.Markdown(
402
- value="", label="Status Repository", elem_classes="mobile-full"
403
- )
404
-
405
- with gr.Tab("💡 Examples"):
406
 
407
- def generate_examples(selected_files):
408
- if not selected_files:
409
- return "Pilih file terlebih dahulu di tab Analisis Repository untuk mendapatkan contoh pertanyaan yang relevan."
410
 
411
- examples = "<div class='example-list'>"
 
 
 
 
 
 
 
 
 
 
 
 
412
 
413
- # General examples for any file
414
- examples += """
415
- <h3>Contoh Pertanyaan Umum:</h3>
416
- <ul>
417
- """
418
 
419
- file_names = ", ".join(
420
- [f"<code>{f}</code>" for f in selected_files]
421
- )
422
- examples += f"""
423
- <li><strong>Analisis Kode:</strong> "Jelaskan logika dan fungsi utama dari {file_names}"</li>
424
- <li><strong>Deteksi Bug:</strong> "Apakah ada potensi bug atau masalah keamanan di file-file ini?"</li>
425
- <li><strong>Best Practices:</strong> "Bagaimana cara mengoptimalkan kode di {file_names}?"</li>
426
- """
427
-
428
- # Specific examples based on file types
429
- for file in selected_files:
430
- ext = file.split(".")[-1].lower() if "." in file else ""
431
- examples += f"<h4>Contoh untuk {file}:</h4><ul>"
432
-
433
- if ext in ["py", "js", "java", "cpp", "c", "go"]:
434
- examples += f"""
435
- <li>"Jelaskan fungsi-fungsi utama di {file}"</li>
436
- <li>"Bagaimana cara mengoptimalkan performa di {file}?"</li>
437
- <li>"Buat unit test untuk fungsi-fungsi di {file}"</li>
438
- """
439
- elif ext in ["html", "css"]:
440
- examples += f"""
441
- <li>"Analisis struktur dan layout dari {file}"</li>
442
- <li>"Bagaimana cara membuat {file} lebih responsif?"</li>
443
- <li>"Optimasi untuk mobile view di {file}"</li>
444
- """
445
- elif ext == "md":
446
- examples += f"""
447
- <li>"Ringkas isi dokumentasi dari {file}"</li>
448
- <li>"Buat tabel konten untuk {file}"</li>
449
- <li>"Perbaiki formatting di {file}"</li>
450
- """
451
- elif ext in ["json", "yaml", "yml"]:
452
- examples += f"""
453
- <li>"Validasi struktur data di {file}"</li>
454
- <li>"Jelaskan konfigurasi di {file}"</li>
455
- <li>"Optimasi format di {file}"</li>
456
- """
457
- elif ext == "dockerfile":
458
- examples += f"""
459
- <li>"Analisis keamanan dari {file}"</li>
460
- <li>"Optimasi multi-stage build di {file}"</li>
461
- <li>"Best practices untuk {file}"</li>
462
- """
463
- else:
464
- examples += f"""
465
- <li>"Analisis isi dari {file}"</li>
466
- <li>"Jelaskan struktur dan tujuan {file}"</li>
467
- <li>"Saran perbaikan untuk {file}"</li>
468
- """
469
- examples += "</ul>"
470
-
471
- examples += """
472
- <h3>Tips Bertanya:</h3>
473
- <ul>
474
- <li>Gunakan pertanyaan yang spesifik dan fokus pada bagian tertentu</li>
475
- <li>Sebutkan nama file jika bertanya tentang file tertentu</li>
476
- <li>Jelaskan konteks atau masalah yang ingin diselesaikan</li>
477
- </ul>
478
- """
479
-
480
- examples += "</div>"
481
-
482
- # Add some CSS styling
483
- examples = f"""
484
- <style>
485
- .example-list {{
486
- padding: 20px;
487
- background: #f8f9fa;
488
- border-radius: 8px;
489
- border: 1px solid #e9ecef;
490
- }}
491
- .example-list h3 {{
492
- color: #2c3e50;
493
- margin-top: 20px;
494
- margin-bottom: 10px;
495
- }}
496
- .example-list h4 {{
497
- color: #34495e;
498
- margin-top: 15px;
499
- margin-bottom: 5px;
500
- }}
501
- .example-list ul {{
502
- margin-bottom: 15px;
503
- }}
504
- .example-list li {{
505
- margin: 8px 0;
506
- line-height: 1.5;
507
- }}
508
- .example-list code {{
509
- background: #e9ecef;
510
- padding: 2px 5px;
511
- border-radius: 4px;
512
- font-family: monospace;
513
- }}
514
- .example-list strong {{
515
- color: #2c3e50;
516
- }}
517
- </style>
518
- {examples}
519
- """
520
-
521
- return examples
522
-
523
- # Example output area
524
  example_output = gr.HTML(
525
  value="Pilih file di tab Analisis Repository untuk melihat contoh pertanyaan.",
526
  label="Contoh Pertanyaan",
527
  )
528
 
529
- # Update examples when switching to this tab
530
- def on_tab_select(selected_files):
531
- if selected_files:
532
- return generate_examples(selected_files)
533
- return "Pilih file terlebih dahulu di tab Analisis Repository untuk mendapatkan contoh pertanyaan yang relevan."
534
-
535
- tabs.select(
536
- fn=on_tab_select,
537
- inputs=[file_selector],
538
- outputs=[example_output],
539
- api_name=False,
540
- )
541
-
542
- # Also update when file selection changes
543
- file_selector.change(
544
- fn=generate_examples,
545
- inputs=[file_selector],
546
- outputs=[example_output],
547
- )
548
- # File Selection with improved handling
549
- with gr.Group():
550
- gr.Markdown("### 📎 File yang Dipilih")
551
-
552
- with gr.Row():
553
- file_selector = gr.Dropdown(
554
- label="Pilih File dari Repository",
555
- choices=[],
556
- multiselect=True,
557
- value=[],
558
- allow_custom_value=True, # Allow custom values
559
- max_choices=None, # Allow multiple selections
560
- elem_classes="mobile-full",
561
- )
562
-
563
- file_list = gr.HTML(
564
- value="<div class='file-list'>Belum ada file yang dipilih</div>",
565
- label="Daftar File Terpilih",
566
- )
567
-
568
- # Event Handlers
569
- def handle_clone(repo_url, github_token, branch):
570
- if not repo_url:
571
- return (
572
- "⚠️ URL repository diperlukan!",
573
- gr.Dropdown(choices=[]),
574
- "<div class='file-list'>Belum ada file yang dipilih</div>",
575
- )
576
-
577
- success, message = analyzer.clone_repository(
578
- repo_url, github_token, branch
579
- )
580
-
581
- if success:
582
- # Get list of files and sort them
583
- files = sorted(list(analyzer.repo_content.keys()))
584
- # Update dropdown with new choices
585
- return (
586
- message,
587
- gr.Dropdown(choices=files, value=[]),
588
- "<div class='file-list'>Belum ada file yang dipilih</div>",
589
- )
590
-
591
- return (
592
- message,
593
- gr.Dropdown(choices=[]),
594
- "<div class='file-list'>Belum ada file yang dipilih</div>",
595
- )
596
-
597
- def update_file_list(selected):
598
- if not selected:
599
- return (
600
- "<div class='file-list'>Belum ada file yang dipilih</div>"
601
- )
602
 
603
- html = "<div class='file-list'>"
604
- for file in selected:
605
- html += f"<div class='file-item'><span>{file}</span></div>"
606
- html += "</div>"
607
- return html
608
-
609
- # Connect clone button
610
- clone_button.click(
611
- fn=handle_clone,
612
- inputs=[repo_url, github_token, branch],
613
- outputs=[clone_status, file_selector, file_list],
614
  )
 
 
615
 
616
- # Update file list when selection changes
617
- file_selector.change(
618
- fn=update_file_list, inputs=[file_selector], outputs=[file_list]
 
 
 
 
619
  )
620
 
621
- # Chat Interface
622
- with gr.Group():
623
- chat_history = gr.Chatbot(
624
- label="📝 Riwayat Chat",
625
- height=500,
626
- show_label=True,
627
- type="messages",
628
- elem_classes="mobile-full",
629
- )
630
-
631
- with gr.Row():
632
- chat_input = gr.Textbox(
633
- label="💭 Tanyakan tentang Repository",
634
- placeholder="Ketik pertanyaan Anda di sini...",
635
- lines=3,
636
- elem_classes="mobile-full",
637
- )
638
- send_button = gr.Button("📤 Kirim", variant="primary")
639
-
640
- loading_indicator = gr.HTML(
641
- '<div id="loading" style="display:none">Memproses permintaan...</div>'
642
- )
643
 
644
- async def handle_chat(
 
 
645
  message,
646
- history,
647
- provider_choice,
648
- model_name,
649
- xai_key,
650
- gemini_key,
651
- selected_files,
652
- ):
653
- if not analyzer.current_repo:
654
- new_message = {
655
- "role": "assistant",
656
- "content": "⚠️ Mohon clone repository terlebih dahulu sebelum mengajukan pertanyaan.",
657
- }
658
- history = history or []
659
- history.append({"role": "user", "content": message})
660
- history.append(new_message)
661
- yield history
662
- return
663
-
664
- history = history or []
665
- history.append({"role": "user", "content": message})
666
- history.append({"role": "assistant", "content": ""})
667
-
668
- try:
669
- # Add context about selected files to the prompt
670
- file_context = ""
671
- if selected_files:
672
- file_context = "\n\nFile yang dipilih:\n"
673
- for file in selected_files:
674
- content = analyzer.repo_content.get(file, "")
675
- if content: # Only include files that exist
676
- file_context += f"\n{file}:\n```\n{content}\n```\n"
677
-
678
- enhanced_message = f"{message}\n{file_context}"
679
-
680
- full_response = ""
681
- if provider_choice == AIProvider.XAI:
682
- async for chunk in analyzer.stream_xai_response(
683
- enhanced_message, xai_key, model_name
684
- ):
685
- full_response += chunk
686
- # Add delay between chunks for readability
687
- await asyncio.sleep(0.05)
688
- history[-1]["content"] = full_response
689
- yield history
690
-
691
- elif provider_choice == AIProvider.GEMINI:
692
- async for chunk in analyzer.stream_gemini_response(
693
- enhanced_message, gemini_key or DEFAULT_GEMINI_KEY
694
- ):
695
- full_response += chunk
696
- # Add delay between chunks for readability
697
- await asyncio.sleep(0.05)
698
- history[-1]["content"] = full_response
699
- yield history
700
-
701
- else: # OLLAMA
702
- response = analyze_with_ollama(model_name, enhanced_message)
703
- # Simulate streaming for OLLAMA with delay
704
- words = response.split()
705
- for i in range(len(words)):
706
- full_response = " ".join(words[: i + 1])
707
- await asyncio.sleep(0.05)
708
- history[-1]["content"] = full_response
709
- yield history
710
-
711
- except Exception as e:
712
- history[-1]["content"] = f"⚠️ Error: {str(e)}"
713
- yield history
714
-
715
- # Update chat interface definition
716
- chat_history = gr.Chatbot(
717
- label="📝 Riwayat Chat",
718
- height=500,
719
- show_label=True,
720
- type="messages", # Make sure this is set
721
- elem_classes="mobile-full",
722
  )
723
 
724
- def clear_chat_history():
725
- return []
726
-
727
- clear_button = gr.Button("🧹 Bersihkan Chat", variant="secondary")
728
- clear_button.click(fn=clear_chat_history, outputs=[chat_history])
729
-
730
- # Connect chat events with file selection
731
- send_event = send_button.click(
732
- fn=handle_chat,
733
- inputs=[
734
- chat_input,
735
- chat_history,
736
- provider,
737
- model_dropdown,
738
- xai_key,
739
- gemini_key,
740
- file_selector,
741
- ],
742
- outputs=chat_history,
743
- show_progress=True,
744
- ).then(fn=lambda: gr.update(value=""), outputs=chat_input)
745
-
746
- input_event = chat_input.submit(
747
- fn=handle_chat,
748
- inputs=[
749
- chat_input,
750
- chat_history,
751
- provider,
752
- model_dropdown,
753
- xai_key,
754
- gemini_key,
755
- file_selector,
756
- ],
757
- outputs=chat_history,
758
- show_progress=True,
759
- ).then(fn=lambda: gr.update(value=""), outputs=chat_input)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
760
 
761
  return app
762
 
 
304
 
305
  def create_ui():
306
  analyzer = RepoAnalyzer()
307
+ current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
308
 
309
  with gr.Blocks(title="Open Repo AI", theme=gr.themes.Soft()) as app:
310
+ # CSS Styling
311
  gr.Markdown("""
312
  <style>
313
  .container { max-width: 100% !important; padding: 1rem; }
 
315
  .file-list { margin: 10px 0; padding: 10px; border: 1px solid #ddd; border-radius: 4px; }
316
  .file-item { display: flex; justify-content: space-between; padding: 5px 0; }
317
  .file-remove { color: red; cursor: pointer; }
318
+ .example-list {
319
+ padding: 20px;
320
+ background: #f8f9fa;
321
+ border-radius: 8px;
322
+ border: 1px solid #e9ecef;
323
+ }
324
+ .example-list h3 {
325
+ color: #2c3e50;
326
+ margin-top: 20px;
327
+ margin-bottom: 10px;
328
+ }
329
+ .example-list h4 {
330
+ color: #34495e;
331
+ margin-top: 15px;
332
+ margin-bottom: 5px;
333
+ }
334
+ .example-list ul {
335
+ margin-bottom: 15px;
336
+ }
337
+ .example-list li {
338
+ margin: 8px 0;
339
+ line-height: 1.5;
340
+ }
341
+ .example-list code {
342
+ background: #e9ecef;
343
+ padding: 2px 5px;
344
+ border-radius: 4px;
345
+ font-family: monospace;
346
+ }
347
+ .example-list strong {
348
+ color: #2c3e50;
349
+ }
350
  @media (max-width: 768px) {
351
  .gr-form { flex-direction: column !important; }
352
  .gr-group { margin: 0.5rem 0 !important; }
 
354
  </style>
355
  """)
356
 
357
+ # Header
358
  with gr.Row(elem_classes="container"):
359
  gr.Markdown(f"""
360
  # AI Github Repository Chat
361
 
362
+ 📅 Current Date and Time (UTC): {current_time}
363
+ 👤 User: {CURRENT_USER}
364
  """)
365
 
366
+ # Main Tabs Container
367
+ with gr.Tabs() as tabs:
368
  # Configuration Tab
369
  with gr.Tab("🛠️ Konfigurasi"):
370
  provider = gr.Radio(
 
396
  with gr.Column(scale=1):
397
  gr.Markdown(GEMINI_API_HELP)
398
 
 
399
  with gr.Row():
400
  model_dropdown = gr.Dropdown(
401
  label="Model AI",
 
407
  # Repository Analysis Tab
408
  with gr.Tab("📊 Analisis Repository"):
409
  with gr.Group():
410
+ # Repository URL and Token inputs
411
  with gr.Row():
412
  repo_url = gr.Textbox(
413
  label="URL Repository GitHub",
 
431
  elem_classes="mobile-full",
432
  )
433
 
434
+ # Clone Button and Status
435
+ clone_button = gr.Button(
436
+ "🔄 Clone Repository",
437
+ variant="primary",
438
+ elem_classes="mobile-full",
439
+ )
 
 
 
440
 
441
+ clone_status = gr.Markdown(
442
+ value="", label="Status Repository", elem_classes="mobile-full"
443
+ )
444
 
445
+ # File Selection
446
+ with gr.Group():
447
+ gr.Markdown("### 📎 File yang Dipilih")
448
+ with gr.Row():
449
+ file_selector = gr.Dropdown(
450
+ label="Pilih File dari Repository",
451
+ choices=[],
452
+ multiselect=True,
453
+ value=[],
454
+ allow_custom_value=True,
455
+ max_choices=None,
456
+ elem_classes="mobile-full",
457
+ )
458
 
459
+ file_list = gr.HTML(
460
+ value="<div class='file-list'>Belum ada file yang dipilih</div>",
461
+ label="Daftar File Terpilih",
462
+ )
 
463
 
464
+ # Examples Tab
465
+ with gr.Tab("💡 Examples"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
466
  example_output = gr.HTML(
467
  value="Pilih file di tab Analisis Repository untuk melihat contoh pertanyaan.",
468
  label="Contoh Pertanyaan",
469
  )
470
 
471
+ # Chat Interface (outside tabs)
472
+ with gr.Group():
473
+ chat_history = gr.Chatbot(
474
+ label="📝 Riwayat Chat",
475
+ height=500,
476
+ show_label=True,
477
+ type="messages",
478
+ elem_classes="mobile-full",
479
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
480
 
481
+ with gr.Row():
482
+ chat_input = gr.Textbox(
483
+ label="💭 Tanyakan tentang Repository",
484
+ placeholder="Ketik pertanyaan Anda di sini...",
485
+ lines=3,
486
+ elem_classes="mobile-full",
 
 
 
 
 
487
  )
488
+ send_button = gr.Button("📤 Kirim", variant="primary")
489
+ clear_button = gr.Button("🧹 Bersihkan", variant="secondary")
490
 
491
+ # Event Handlers
492
+ def handle_clone(repo_url, github_token, branch):
493
+ if not repo_url:
494
+ return (
495
+ "⚠️ URL repository diperlukan!",
496
+ gr.Dropdown(choices=[]),
497
+ "<div class='file-list'>Belum ada file yang dipilih</div>",
498
  )
499
 
500
+ success, message = analyzer.clone_repository(repo_url, github_token, branch)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
501
 
502
+ if success:
503
+ files = sorted(list(analyzer.repo_content.keys()))
504
+ return (
505
  message,
506
+ gr.Dropdown(choices=files, value=[]),
507
+ "<div class='file-list'>Belum ada file yang dipilih</div>",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
508
  )
509
 
510
+ return (
511
+ message,
512
+ gr.Dropdown(choices=[]),
513
+ "<div class='file-list'>Belum ada file yang dipilih</div>",
514
+ )
515
+
516
+ def update_file_list(selected):
517
+ if not selected:
518
+ return "<div class='file-list'>Belum ada file yang dipilih</div>"
519
+
520
+ html = "<div class='file-list'>"
521
+ for file in selected:
522
+ html += f"<div class='file-item'><span>{file}</span></div>"
523
+ html += "</div>"
524
+ return html
525
+
526
+ def generate_examples(selected_files):
527
+ if not selected_files:
528
+ return "Pilih file terlebih dahulu di tab Analisis Repository untuk mendapatkan contoh pertanyaan yang relevan."
529
+
530
+ examples = "<div class='example-list'>"
531
+
532
+ # Add example generation logic here (as shown in previous example)
533
+ # ...
534
+
535
+ examples += "</div>"
536
+ return examples
537
+
538
+ def clear_chat_history():
539
+ return []
540
+
541
+ def update_model_list(provider_choice):
542
+ if provider_choice == AIProvider.XAI:
543
+ return gr.Dropdown(choices=XAI_MODELS, value="grok-2-latest")
544
+ elif provider_choice == AIProvider.GEMINI:
545
+ return gr.Dropdown(choices=GEMINI_MODELS, value="gemini-1.5-mini")
546
+ else: # OLLAMA
547
+ return gr.Dropdown(choices=OLLAMA_MODELS, value="llama2")
548
+
549
+ # Connect Events
550
+ provider.change(
551
+ fn=update_model_list, inputs=[provider], outputs=[model_dropdown]
552
+ )
553
+
554
+ clone_button.click(
555
+ fn=handle_clone,
556
+ inputs=[repo_url, github_token, branch],
557
+ outputs=[clone_status, file_selector, file_list],
558
+ )
559
+
560
+ file_selector.change(
561
+ fn=update_file_list, inputs=[file_selector], outputs=[file_list]
562
+ )
563
+
564
+ # Example tab updates
565
+ tabs.select(
566
+ fn=generate_examples,
567
+ inputs=[file_selector],
568
+ outputs=[example_output],
569
+ api_name=False,
570
+ )
571
+
572
+ file_selector.change(
573
+ fn=generate_examples, inputs=[file_selector], outputs=[example_output]
574
+ )
575
+
576
+ # Chat events
577
+ clear_button.click(fn=clear_chat_history, outputs=[chat_history])
578
+
579
+ send_button.click(
580
+ fn=handle_chat,
581
+ inputs=[
582
+ chat_input,
583
+ chat_history,
584
+ provider,
585
+ model_dropdown,
586
+ xai_key,
587
+ gemini_key,
588
+ file_selector,
589
+ ],
590
+ outputs=chat_history,
591
+ show_progress=True,
592
+ ).then(fn=lambda: gr.update(value=""), outputs=chat_input)
593
+
594
+ chat_input.submit(
595
+ fn=handle_chat,
596
+ inputs=[
597
+ chat_input,
598
+ chat_history,
599
+ provider,
600
+ model_dropdown,
601
+ xai_key,
602
+ gemini_key,
603
+ file_selector,
604
+ ],
605
+ outputs=chat_history,
606
+ show_progress=True,
607
+ ).then(fn=lambda: gr.update(value=""), outputs=chat_input)
608
 
609
  return app
610