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()
|