File size: 5,748 Bytes
3987ef0
978c4cf
3987ef0
 
94febc8
517de74
9efa522
 
31dadea
a9e8fde
517de74
94febc8
 
 
 
5417053
978c4cf
94febc8
 
42d374e
9efa522
40a1d7a
 
 
94febc8
9efa522
94febc8
40a1d7a
 
94febc8
 
9efa522
94febc8
42d374e
3987ef0
517de74
978c4cf
5417053
31dadea
94febc8
5417053
 
 
 
 
 
 
 
 
 
 
 
42d374e
 
94febc8
 
42d374e
94febc8
 
42d374e
 
5417053
42d374e
9efa522
42d374e
5417053
517de74
5417053
42d374e
9efa522
c1cd51c
 
5417053
c1cd51c
5417053
94febc8
5417053
94febc8
 
5417053
 
94febc8
5417053
94febc8
5417053
94febc8
 
 
5417053
 
94febc8
 
5417053
94febc8
 
5417053
c1cd51c
5417053
 
cc1d6cf
94febc8
5417053
 
a9e8fde
5417053
 
 
a9e8fde
 
94febc8
cc1d6cf
5417053
c1cd51c
5417053
c1cd51c
5417053
 
 
 
978c4cf
5417053
3987ef0
5417053
 
3987ef0
5417053
 
 
42d374e
 
5417053
978c4cf
3987ef0
40a1d7a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# app.py

import os
import streamlit as st
import asyncio
from pathlib import Path
import pandas as pd
from fpdf import FPDF
import plotly.express as px
import re

from mcp.orchestrator import orchestrate_search, answer_ai_question
from mcp.schemas import UnifiedSearchInput, UnifiedSearchResult
from mcp.workspace import get_workspace, save_query
from mcp.knowledge_graph import build_agraph
from streamlit_agraph import agraph

ROOT = Path(__file__).parent
LOGO = ROOT / "assets" / "logo.png"

def generate_pdf(papers):
    pdf = FPDF()
    pdf.add_page()
    pdf.set_font("Arial", size=12)
    pdf.cell(200, 10, "MedGenesis AI - Search Results", ln=True, align="C")
    pdf.ln(10)
    for i, p in enumerate(papers, 1):
        pdf.set_font("Arial", "B", 12)
        pdf.multi_cell(0, 10, f"{i}. {p['title']}")
        pdf.set_font("Arial", "", 10)
        pdf.multi_cell(0, 8, f"Authors: {p['authors']}\nLink: {p['link']}\nSummary: {p['summary']}\n")
        pdf.ln(2)
    return pdf.output(dest="S").encode("latin-1")

def render_ui():
    st.set_page_config(page_title="MedGenesis AI", layout="wide")

    # Workspace in sidebar
    with st.sidebar:
        st.header("πŸ—‚οΈ Workspace")
        ws = get_workspace()
        if ws:
            for i, item in enumerate(ws, 1):
                with st.expander(f"{i}. {item['query']}"):
                    st.write("**AI Summary:**", item["result"]["ai_summary"])
                    st.write("**Top Paper:**", item["result"]["papers"][0]["title"] if item["result"]["papers"] else "None")
                    df = pd.DataFrame(item["result"]["papers"])
                    st.download_button("πŸ“₯ CSV", df.to_csv(index=False), f"query_{i}.csv", "text/csv")
        else:
            st.info("Run & save searches here.")

    # Header and logo
    col1, col2 = st.columns([0.15, 0.85])
    with col1:
        if LOGO.exists():
            st.image(str(LOGO), width=100)
    with col2:
        st.markdown("## 🧬 MedGenesis AI\n*Unified Intelligence from PubMed, ArXiv, OpenFDA, UMLS, GPT‑4o*")
        st.caption("Built by Oluwafemi Idiakhoa β€’ Hugging Face Spaces")

    st.markdown("---")
    query = st.text_input("πŸ” Enter biomedical research question:", placeholder="e.g. CRISPR treatments for glioblastoma")

    results = None
    if st.button("Run Search πŸš€"):
        with st.spinner("Gathering and analyzing data..."):
            results = asyncio.run(orchestrate_search(query))
            st.success("βœ… Search complete")

    if results:
        tabs = st.tabs(["πŸ“ Results", "πŸ—ΊοΈ Knowledge Graph", "πŸ“Š Visualizations"])

        # Tab 1: Results
        with tabs[0]:
            st.header("πŸ“š Most Relevant Papers")
            for i, p in enumerate(results["papers"], 1):
                st.markdown(f"**{i}. [{p['title']}]({p['link']})**  \n*{p['authors']}* ({p['source']})")
                st.markdown(f"<div style='color:gray'>{p['summary']}</div>", unsafe_allow_html=True)
            if st.button("Save to Workspace"):
                save_query(query, results)
                st.success("Saved to workspace!")
            df = pd.DataFrame(results["papers"])
            st.download_button("πŸ“₯ Download CSV", df.to_csv(index=False), "results.csv", "text/csv")
            pdf = generate_pdf(results["papers"])
            st.download_button("πŸ“„ Download PDF", pdf, "results.pdf", "application/pdf")
            st.subheader("🧠 UMLS Concepts")
            for c in results["umls"]:
                if c.get("cui"):
                    st.markdown(f"- **{c['name']}** (CUI: `{c['cui']}`): {c.get('definition','No definition')}")
            st.subheader("πŸ’Š Drug Safety (OpenFDA)")
            for d in results["drug_safety"]:
                st.json(d)
            st.subheader("πŸ€– AI-Powered Summary")
            st.info(results["ai_summary"])

        # Tab 2: Knowledge Graph (with Node Search Highlight)
        with tabs[1]:
            st.header("πŸ—ΊοΈ Knowledge Graph Explorer")
            search_term = st.text_input("πŸ”Ž Highlight nodes containing:", value="")
            try:
                nodes, edges, config = build_agraph(results["papers"], results["umls"], results["drug_safety"])
                if search_term.strip():
                    pattern = re.compile(re.escape(search_term), re.IGNORECASE)
                    for node in nodes:
                        if pattern.search(node.label) or (hasattr(node, "tooltip") and pattern.search(getattr(node, "tooltip", ""))):
                            node.color = "#f1c40f"
                            node.size = max(node.size, 30)
                        else:
                            node.color = "#ddd"
                agraph(nodes=nodes, edges=edges, config=config)
            except Exception as e:
                st.warning("Knowledge graph unavailable: " + str(e))

        # Tab 3: Visualizations
        with tabs[2]:
            pub_years = [p["published"] for p in results["papers"] if p.get("published")]
            if pub_years:
                fig = px.histogram(pub_years, nbins=10, title="Publication Year Distribution")
                st.plotly_chart(fig)

    # Follow-up AI Q&A
    st.markdown("---")
    st.subheader("πŸ’¬ Ask a Follow-up Question")
    follow_up = st.text_input("Based on above:", placeholder="e.g. What's the most promising therapy?")
    if st.button("Ask AI"):
        with st.spinner("Analyzing..."):
            ai_ans = asyncio.run(answer_ai_question(follow_up, context=query))
            st.write(ai_ans.get("answer", ai_ans))

    st.markdown("---")
    st.caption("✨ Built by Oluwafemi Idiakhoa β€’ Powered by FastAPI, Streamlit, OpenAI, UMLS, OpenFDA, NCBI")

if __name__ == "__main__":
    render_ui()