Spaces:
Sleeping
Sleeping
Update app.py
Browse files
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 |
-
|
434 |
-
|
435 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
436 |
with gr.Row():
|
437 |
-
|
438 |
-
with gr.
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
with gr.
|
472 |
-
gr.
|
473 |
-
|
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("
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
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():
|
|
|
499 |
potential_rules = edited_rules_text.split("\n\n---\n\n")
|
500 |
-
if len(potential_rules) == 1 and "\n" in edited_rules_text:
|
501 |
-
|
502 |
-
|
|
|
|
|
|
|
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():
|
|
|
506 |
success, status_msg = add_rule_entry(rule_text.strip())
|
507 |
-
if success:
|
508 |
-
|
509 |
-
|
510 |
-
|
|
|
|
|
|
|
511 |
return f"Editor Save: Added: {added}, Skipped (duplicates): {skipped}, Errors/Invalid: {errors}."
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
-
|
520 |
-
|
521 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
522 |
initialize_memory_system()
|
523 |
logger.info("App loaded. Memory system initialized.")
|
524 |
-
backend_status =
|
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
|
537 |
-
|
|
|
|
|
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.")
|