MCP_Res / app.py
mgbam's picture
Update app.py
5417053 verified
raw
history blame
5.75 kB
# 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()