broadfield-dev commited on
Commit
26b14aa
Β·
verified Β·
1 Parent(s): 805a95e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +241 -81
app.py CHANGED
@@ -430,111 +430,271 @@ body { background: linear-gradient(to bottom right, #2c3e50, #34495e); color: #e
430
  .app-title-area { padding: 0.5rem 0; text-align: center;} /* Area for title and subtitle */
431
  """
432
 
433
- with gr.Blocks(title="AI Research Agent v5.8") as demo:
434
-
435
- gr.HTML("<h1> πŸ€– AI Research Agent </h1>")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
436
  with gr.Row():
437
- with gr.Column(scale=3): agent_stat_tb = gr.Textbox(label="Agent Status", interactive=False, lines=1, value="Initializing systems...")
438
- with gr.Column(scale=1): memory_backend_info_tb = gr.Textbox(label="Memory Backend", value=f"{MEMORY_STORAGE_BACKEND}", interactive=False)
439
- sqlite_path_display = gr.Textbox(label="SQLite Path", value=f"{MEMORY_SQLITE_PATH}", interactive=False, scale=2) # Use visible
440
- hf_repos_display = gr.Textbox(label="HF Repos", value=f"M: {MEMORY_HF_MEM_REPO}, R: {MEMORY_HF_RULES_REPO}", interactive=False, scale=2) # Use visible
441
-
442
- avail_provs = get_available_providers()
443
- def_prov = avail_provs[0] if avail_provs else None
444
- def_models = get_model_display_names_for_provider(def_prov) if def_prov else []
445
- def_model_disp = get_default_model_display_name_for_provider(def_prov) if def_prov else None
446
- with gr.Sidebar(): # Using Gradio's explicit Sidebar component
447
- gr.Markdown("## βš™οΈ Configuration")
448
- with gr.Group():
449
- gr.Markdown("### AI Model Settings")
450
- api_key_tb = gr.Textbox(label="AI Provider API Key (Override)", type="password", placeholder="Uses .env if blank")
451
- prov_sel_dd = gr.Dropdown(label="AI Provider", choices=avail_provs, value=def_prov, interactive=True)
452
- model_sel_dd = gr.Dropdown(label="AI Model", choices=def_models, value=def_model_disp, interactive=True)
453
- with gr.Group():
454
- gr.Markdown("### System Prompt")
455
- sys_prompt_tb = gr.Textbox(label="System Prompt Base", lines=10, value=DEFAULT_SYSTEM_PROMPT, interactive=True)
456
- if MEMORY_STORAGE_BACKEND == "RAM":
457
- save_faiss_sidebar_btn = gr.Button("Save FAISS Indices", variant="secondary")
458
-
459
- with gr.Tabs():
460
- with gr.TabItem("πŸ’¬ AI Chat & Research Output"):
461
- gr.Markdown("### AI Chat Interface") # Using H3 for section titles within tabs
462
- main_chat_disp = gr.Chatbot(label="AI Research Chat", height=500, bubble_full_width=False, avatar_images=(None, "https://raw.githubusercontent.com/huggingface/brand-assets/main/hf-logo-with-title.png"), show_copy_button=True, render_markdown=True, sanitize_html=True)
463
- with gr.Row():
464
- user_msg_tb = gr.Textbox(show_label=False, placeholder="Ask your research question...", scale=7, lines=1, max_lines=5, autofocus=True)
465
- send_btn = gr.Button("Send", variant="primary", scale=1, min_width=100)
466
- with gr.Accordion("πŸ“ Full Response / Details", open=False):
467
- fmt_report_tb = gr.Textbox(label="Full AI Response", lines=10, interactive=True, show_copy_button=True)
468
- dl_report_btn = gr.DownloadButton("Download Report", interactive=False, visible=False)
469
- detect_out_md = gr.Markdown()
470
-
471
- with gr.TabItem("🧠 Knowledge Base Management"):
472
- gr.Markdown("### Manage Stored Knowledge")
473
- with gr.Row():
474
- with gr.Column():
475
- with gr.Group():
476
- gr.Markdown("#### πŸ“œ Rules (Insights)")
477
- rules_disp_ta = gr.TextArea(label="View/Edit Rules", lines=15, interactive=True, placeholder="Load rules or type new ones...")
478
- with gr.Row(): view_rules_btn = gr.Button("πŸ”„ Load"); save_edited_rules_btn = gr.Button("πŸ’Ύ Save Edits", variant="primary")
479
- upload_rules_fobj = gr.File(label="Upload Rules File", file_types=[".txt", ".jsonl"])
480
- rules_stat_tb = gr.Textbox(label="Rules Status", interactive=False, lines=2)
481
- clear_rules_btn = gr.Button("⚠️ Clear All Rules", variant="stop")
482
- with gr.Column():
483
  with gr.Group():
484
- gr.Markdown("#### πŸ“š Memories")
485
- mems_disp_json = gr.JSON(label="View Memories")
486
- view_mems_btn = gr.Button("πŸ”„ Load Memories")
487
- upload_mems_fobj = gr.File(label="Upload Memories File", file_types=[".jsonl"])
488
- mems_stat_tb = gr.Textbox(label="Memories Status", interactive=False, lines=2)
489
- clear_mems_btn = gr.Button("⚠️ Clear All Memories", variant="stop")
490
-
491
- def dyn_upd_model_dd(sel_prov_dyn:str): models_dyn, def_model_dyn = get_model_display_names_for_provider(sel_prov_dyn), get_default_model_display_name_for_provider(sel_prov_dyn); return gr.Dropdown(choices=models_dyn, value=def_model_dyn, interactive=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
492
  prov_sel_dd.change(fn=dyn_upd_model_dd, inputs=prov_sel_dd, outputs=model_sel_dd)
 
493
  chat_ins = [user_msg_tb, main_chat_disp, prov_sel_dd, model_sel_dd, api_key_tb, sys_prompt_tb]
494
  chat_outs = [user_msg_tb, main_chat_disp, agent_stat_tb, detect_out_md, fmt_report_tb, dl_report_btn]
495
- send_btn.click(fn=handle_gradio_chat_submit, inputs=chat_ins, outputs=chat_outs); user_msg_tb.submit(fn=handle_gradio_chat_submit, inputs=chat_ins, outputs=chat_outs)
 
 
496
  view_rules_btn.click(fn=ui_view_rules_action_fn, outputs=rules_disp_ta)
 
497
  def save_edited_rules_action_fn(edited_rules_text: str, progress=gr.Progress()):
498
- if not edited_rules_text.strip(): return "No rules text to save."
 
499
  potential_rules = edited_rules_text.split("\n\n---\n\n")
500
- if len(potential_rules) == 1 and "\n" in edited_rules_text: potential_rules = [r.strip() for r in edited_rules_text.splitlines() if r.strip()]
501
- if not potential_rules: return "No rules found to process from editor."
502
- added, skipped, errors = 0,0,0; total = len(potential_rules)
 
 
 
503
  progress(0, desc=f"Saving {total} rules from editor...")
504
  for idx, rule_text in enumerate(potential_rules):
505
- if not rule_text.strip(): continue
 
506
  success, status_msg = add_rule_entry(rule_text.strip())
507
- if success: added +=1
508
- elif status_msg == "duplicate": skipped +=1
509
- else: errors +=1
510
- progress((idx+1)/total)
 
 
 
511
  return f"Editor Save: Added: {added}, Skipped (duplicates): {skipped}, Errors/Invalid: {errors}."
512
- save_edited_rules_btn.click(fn=save_edited_rules_action_fn, inputs=[rules_disp_ta], outputs=[rules_stat_tb], show_progress="full").then(fn=ui_view_rules_action_fn, outputs=rules_disp_ta)
513
- upload_rules_fobj.upload(fn=ui_upload_rules_action_fn, inputs=[upload_rules_fobj], outputs=[rules_stat_tb], show_progress="full").then(fn=ui_view_rules_action_fn, outputs=rules_disp_ta)
514
- clear_rules_btn.click(fn=lambda: "All rules cleared." if clear_all_rules_data_backend() else "Error clearing rules.", outputs=rules_stat_tb).then(fn=ui_view_rules_action_fn, outputs=rules_disp_ta)
515
- if MEMORY_STORAGE_BACKEND == "RAM" and 'save_faiss_sidebar_btn' in locals() and save_faiss_sidebar_btn is not None:
516
- def save_faiss_action_with_feedback_sidebar_fn(): save_faiss_indices_to_disk(); gr.Info("Attempted to save FAISS indices to disk.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
517
  save_faiss_sidebar_btn.click(fn=save_faiss_action_with_feedback_sidebar_fn, inputs=None, outputs=None)
 
518
  view_mems_btn.click(fn=ui_view_memories_action_fn, outputs=mems_disp_json)
519
- upload_mems_fobj.upload(fn=ui_upload_memories_action_fn, inputs=[upload_mems_fobj], outputs=[mems_stat_tb], show_progress="full").then(fn=ui_view_memories_action_fn, outputs=mems_disp_json)
520
- clear_mems_btn.click(fn=lambda: "All memories cleared." if clear_all_memory_data_backend() else "Error clearing memories.", outputs=mems_stat_tb).then(fn=ui_view_memories_action_fn, outputs=mems_disp_json)
521
- def app_load_fn():
 
 
 
 
 
 
 
 
 
 
 
522
  initialize_memory_system()
523
  logger.info("App loaded. Memory system initialized.")
524
- backend_status = f"AI Systems Initialized. Ready."
525
  rules_on_load = ui_view_rules_action_fn()
526
  mems_on_load = ui_view_memories_action_fn()
527
- # Initial visibility for conditional Textboxes based on backend
528
- vis_sqlite = MEMORY_STORAGE_BACKEND == "SQLITE"
529
- vis_hf = MEMORY_STORAGE_BACKEND == "HF_DATASET"
530
  return backend_status, rules_on_load, mems_on_load
531
 
532
  demo.load(fn=app_load_fn, inputs=None, outputs=[agent_stat_tb, rules_disp_ta, mems_disp_json])
533
 
534
  if __name__ == "__main__":
535
  logger.info(f"Starting Gradio AI Research Mega Agent (v5.8 - UI Style/Layout Update, Memory: {MEMORY_STORAGE_BACKEND})...")
536
- app_port, app_server = int(os.getenv("GRADIO_PORT", 7860)), os.getenv("GRADIO_SERVER_NAME", "127.0.0.1")
537
- app_debug, app_share = os.getenv("GRADIO_DEBUG", "False").lower()=="true", os.getenv("GRADIO_SHARE", "False").lower()=="true"
 
 
538
  logger.info(f"Launching Gradio server: http://{app_server}:{app_port}. Debug: {app_debug}, Share: {app_share}")
539
  demo.queue().launch(server_name=app_server, server_port=app_port, debug=app_debug, share=app_share)
540
  logger.info("Gradio application shut down.")
 
430
  .app-title-area { padding: 0.5rem 0; text-align: center;} /* Area for title and subtitle */
431
  """
432
 
433
+
434
+ with gr.Blocks(
435
+ title="AI Research Agent v5.8",
436
+ theme=gr.themes.Soft(), # Use a clean, modern theme
437
+ css="""
438
+ .gr-button { margin: 5px; }
439
+ .gr-textbox, .gr-text-area, .gr-dropdown { border-radius: 8px; }
440
+ .gr-group { border: 1px solid #e0e0e0; border-radius: 8px; padding: 10px; }
441
+ .gr-row { gap: 10px; }
442
+ .gr-tab { border-radius: 8px; }
443
+ .status-text { font-size: 0.9em; color: #555; }
444
+ """
445
+ ) as demo:
446
+ # Header Section
447
+ gr.Markdown(
448
+ """
449
+ # πŸ€– AI Research Agent
450
+ Your intelligent assistant for research and knowledge management
451
+ """,
452
+ elem_classes=["header"]
453
+ )
454
+
455
+ # Status Bar
456
+ with gr.Row(variant="compact"):
457
+ agent_stat_tb = gr.Textbox(
458
+ label="Agent Status",
459
+ value="Initializing systems...",
460
+ interactive=False,
461
+ elem_classes=["status-text"],
462
+ scale=4
463
+ )
464
+ with gr.Column(scale=1, min_width=150):
465
+ memory_backend_info_tb = gr.Textbox(
466
+ label="Memory Backend",
467
+ value=MEMORY_STORAGE_BACKEND,
468
+ interactive=False,
469
+ elem_classes=["status-text"]
470
+ )
471
+ sqlite_path_display = gr.Textbox(
472
+ label="SQLite Path",
473
+ value=MEMORY_SQLITE_PATH,
474
+ interactive=False,
475
+ visible=MEMORY_STORAGE_BACKEND == "SQLITE",
476
+ elem_classes=["status-text"]
477
+ )
478
+ hf_repos_display = gr.Textbox(
479
+ label="HF Repos",
480
+ value=f"M: {MEMORY_HF_MEM_REPO}, R: {MEMORY_HF_RULES_REPO}",
481
+ interactive=False,
482
+ visible=MEMORY_STORAGE_BACKEND == "HF_DATASET",
483
+ elem_classes=["status-text"]
484
+ )
485
+
486
  with gr.Row():
487
+ # Sidebar (unchanged)
488
+ with gr.Sidebar():
489
+ gr.Markdown("## βš™οΈ Configuration")
490
+ with gr.Group():
491
+ gr.Markdown("### AI Model Settings")
492
+ api_key_tb = gr.Textbox(
493
+ label="AI Provider API Key (Override)",
494
+ type="password",
495
+ placeholder="Uses .env if blank"
496
+ )
497
+ prov_sel_dd = gr.Dropdown(
498
+ label="AI Provider",
499
+ choices=get_available_providers(),
500
+ value=get_available_providers()[0] if get_available_providers() else None,
501
+ interactive=True
502
+ )
503
+ model_sel_dd = gr.Dropdown(
504
+ label="AI Model",
505
+ choices=get_model_display_names_for_provider(get_available_providers()[0]) if get_available_providers() else [],
506
+ value=get_default_model_display_name_for_provider(get_available_providers()[0]) if get_available_providers() else None,
507
+ interactive=True
508
+ )
509
+ with gr.Group():
510
+ gr.Markdown("### System Prompt")
511
+ sys_prompt_tb = gr.Textbox(
512
+ label="System Prompt Base",
513
+ lines=8,
514
+ value=DEFAULT_SYSTEM_PROMPT,
515
+ interactive=True
516
+ )
517
+ if MEMORY_STORAGE_BACKEND == "RAM":
518
+ save_faiss_sidebar_btn = gr.Button("Save FAISS Indices", variant="secondary")
519
+
520
+ # Main Content Area
521
+ with gr.Column(scale=3):
522
+ with gr.Tabs():
523
+ with gr.TabItem("πŸ’¬ Chat & Research"):
 
 
 
 
 
 
 
 
 
524
  with gr.Group():
525
+ gr.Markdown("### AI Chat Interface")
526
+ main_chat_disp = gr.Chatbot(
527
+ label=None,
528
+ height=400,
529
+ bubble_full_width=False,
530
+ avatar_images=(None, "https://raw.githubusercontent.com/huggingface/brand-assets/main/hf-logo-with-title.png"),
531
+ show_copy_button=True,
532
+ render_markdown=True,
533
+ sanitize_html=True
534
+ )
535
+ with gr.Row(variant="compact"):
536
+ user_msg_tb = gr.Textbox(
537
+ show_label=False,
538
+ placeholder="Ask your research question...",
539
+ scale=7,
540
+ lines=1,
541
+ max_lines=3,
542
+ autofocus=True
543
+ )
544
+ send_btn = gr.Button("Send", variant="primary", scale=1, min_width=100)
545
+ with gr.Accordion("πŸ“ Detailed Response", open=False):
546
+ fmt_report_tb = gr.Textbox(
547
+ label="Full AI Response",
548
+ lines=8,
549
+ interactive=True,
550
+ show_copy_button=True
551
+ )
552
+ dl_report_btn = gr.DownloadButton(
553
+ "Download Report",
554
+ interactive=False,
555
+ visible=False
556
+ )
557
+ detect_out_md = gr.Markdown(visible=False)
558
+
559
+ with gr.TabItem("🧠 Knowledge Base"):
560
+ with gr.Row(equal_height=True):
561
+ with gr.Column():
562
+ gr.Markdown("### πŸ“œ Rules Management")
563
+ rules_disp_ta = gr.TextArea(
564
+ label=None,
565
+ lines=10,
566
+ placeholder="View or edit rules...",
567
+ interactive=True
568
+ )
569
+ with gr.Row(variant="compact"):
570
+ view_rules_btn = gr.Button("πŸ”„ Load Rules")
571
+ save_edited_rules_btn = gr.Button("πŸ’Ύ Save Rules", variant="primary")
572
+ clear_rules_btn = gr.Button("πŸ—‘οΈ Clear Rules", variant="stop")
573
+ upload_rules_fobj = gr.File(
574
+ label="Upload Rules",
575
+ file_types=[".txt", ".jsonl"]
576
+ )
577
+ rules_stat_tb = gr.Textbox(
578
+ label="Rules Status",
579
+ interactive=False,
580
+ lines=1,
581
+ elem_classes=["status-text"]
582
+ )
583
+
584
+ with gr.Column():
585
+ gr.Markdown("### πŸ“š Memories Management")
586
+ mems_disp_json = gr.JSON(
587
+ label=None,
588
+ value={"memories": []}
589
+ )
590
+ with gr.Row(variant="compact"):
591
+ view_mems_btn = gr.Button("πŸ”„ Load Memories")
592
+ clear_mems_btn = gr.Button("πŸ—‘οΈ Clear Memories", variant="stop")
593
+ upload_mems_fobj = gr.File(
594
+ label="Upload Memories",
595
+ file_types=[".jsonl"]
596
+ )
597
+ mems_stat_tb = gr.Textbox(
598
+ label="Memories Status",
599
+ interactive=False,
600
+ lines=1,
601
+ elem_classes=["status-text"]
602
+ )
603
+
604
+ # Event Handlers (unchanged logic, cleaned up organization)
605
+ def dyn_upd_model_dd(sel_prov_dyn: str):
606
+ models_dyn = get_model_display_names_for_provider(sel_prov_dyn)
607
+ def_model_dyn = get_default_model_display_name_for_provider(sel_prov_dyn)
608
+ return gr.Dropdown(choices=models_dyn, value=def_model_dyn, interactive=True)
609
+
610
  prov_sel_dd.change(fn=dyn_upd_model_dd, inputs=prov_sel_dd, outputs=model_sel_dd)
611
+
612
  chat_ins = [user_msg_tb, main_chat_disp, prov_sel_dd, model_sel_dd, api_key_tb, sys_prompt_tb]
613
  chat_outs = [user_msg_tb, main_chat_disp, agent_stat_tb, detect_out_md, fmt_report_tb, dl_report_btn]
614
+ send_btn.click(fn=handle_gradio_chat_submit, inputs=chat_ins, outputs=chat_outs)
615
+ user_msg_tb.submit(fn=handle_gradio_chat_submit, inputs=chat_ins, outputs=chat_outs)
616
+
617
  view_rules_btn.click(fn=ui_view_rules_action_fn, outputs=rules_disp_ta)
618
+
619
  def save_edited_rules_action_fn(edited_rules_text: str, progress=gr.Progress()):
620
+ if not edited_rules_text.strip():
621
+ return "No rules text to save."
622
  potential_rules = edited_rules_text.split("\n\n---\n\n")
623
+ if len(potential_rules) == 1 and "\n" in edited_rules_text:
624
+ potential_rules = [r.strip() for r in edited_rules_text.splitlines() if r.strip()]
625
+ if not potential_rules:
626
+ return "No rules found to process from editor."
627
+ added, skipped, errors = 0, 0, 0
628
+ total = len(potential_rules)
629
  progress(0, desc=f"Saving {total} rules from editor...")
630
  for idx, rule_text in enumerate(potential_rules):
631
+ if not rule_text.strip():
632
+ continue
633
  success, status_msg = add_rule_entry(rule_text.strip())
634
+ if success:
635
+ added += 1
636
+ elif status_msg == "duplicate":
637
+ skipped += 1
638
+ else:
639
+ errors += 1
640
+ progress((idx + 1) / total)
641
  return f"Editor Save: Added: {added}, Skipped (duplicates): {skipped}, Errors/Invalid: {errors}."
642
+
643
+ save_edited_rules_btn.click(
644
+ fn=save_edited_rules_action_fn,
645
+ inputs=[rules_disp_ta],
646
+ outputs=[rules_stat_tb],
647
+ show_progress="full"
648
+ ).then(fn=ui_view_rules_action_fn, outputs=rules_disp_ta)
649
+
650
+ upload_rules_fobj.upload(
651
+ fn=ui_upload_rules_action_fn,
652
+ inputs=[upload_rules_fobj],
653
+ outputs=[rules_stat_tb],
654
+ show_progress="full"
655
+ ).then(fn=ui_view_rules_action_fn, outputs=rules_disp_ta)
656
+
657
+ clear_rules_btn.click(
658
+ fn=lambda: "All rules cleared." if clear_all_rules_data_backend() else "Error clearing rules.",
659
+ outputs=rules_stat_tb
660
+ ).then(fn=ui_view_rules_action_fn, outputs=rules_disp_ta)
661
+
662
+ if MEMORY_STORAGE_BACKEND == "RAM" and 'save_faiss_sidebar_btn' in locals():
663
+ def save_faiss_action_with_feedback_sidebar_fn():
664
+ save_faiss_indices_to_disk()
665
+ gr.Info("Attempted to save FAISS indices to disk.")
666
  save_faiss_sidebar_btn.click(fn=save_faiss_action_with_feedback_sidebar_fn, inputs=None, outputs=None)
667
+
668
  view_mems_btn.click(fn=ui_view_memories_action_fn, outputs=mems_disp_json)
669
+
670
+ upload_mems_fobj.upload(
671
+ fn=ui_upload_memories_action_fn,
672
+ inputs=[upload_mems_fobj],
673
+ outputs=[mems_stat_tb],
674
+ show_progress="full"
675
+ ).then(fn=ui_view_memories_action_fn, outputs=mems_disp_json)
676
+
677
+ clear_mems_btn.click(
678
+ fn=lambda: "All memories cleared." if clear_all_memory_data_backend() else "Error clearing memories.",
679
+ outputs=mems_stat_tb
680
+ ).then(fn=ui_view_memories_action_fn, outputs=mems_disp_json)
681
+
682
+ def app_load_fn():
683
  initialize_memory_system()
684
  logger.info("App loaded. Memory system initialized.")
685
+ backend_status = "AI Systems Initialized. Ready."
686
  rules_on_load = ui_view_rules_action_fn()
687
  mems_on_load = ui_view_memories_action_fn()
 
 
 
688
  return backend_status, rules_on_load, mems_on_load
689
 
690
  demo.load(fn=app_load_fn, inputs=None, outputs=[agent_stat_tb, rules_disp_ta, mems_disp_json])
691
 
692
  if __name__ == "__main__":
693
  logger.info(f"Starting Gradio AI Research Mega Agent (v5.8 - UI Style/Layout Update, Memory: {MEMORY_STORAGE_BACKEND})...")
694
+ app_port = int(os.getenv("GRADIO_PORT", 7860))
695
+ app_server = os.getenv("GRADIO_SERVER_NAME", "127.0.0.1")
696
+ app_debug = os.getenv("GRADIO_DEBUG", "False").lower() == "true"
697
+ app_share = os.getenv("GRADIO_SHARE", "False").lower() == "true"
698
  logger.info(f"Launching Gradio server: http://{app_server}:{app_port}. Debug: {app_debug}, Share: {app_share}")
699
  demo.queue().launch(server_name=app_server, server_port=app_port, debug=app_debug, share=app_share)
700
  logger.info("Gradio application shut down.")