File size: 4,893 Bytes
4a6179c 02970af c4bf66f 4a6179c c4bf66f 4a6179c 1786f57 73fc0d7 02970af 73fc0d7 c4bf66f 1786f57 73fc0d7 1786f57 4a6179c 73fc0d7 c4bf66f 4a6179c 73fc0d7 4a6179c 21ff015 4a6179c 21ff015 73fc0d7 4a6179c 1786f57 73fc0d7 c4bf66f 73fc0d7 1786f57 73fc0d7 c4bf66f 73fc0d7 21ff015 73fc0d7 |
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 136 137 138 139 140 |
import asyncio
import re
from pathlib import Path
import streamlit as st
import pandas as pd
import plotly.express as px
from fpdf import FPDF
from streamlit_agraph import agraph
from mcp.orchestrator import orchestrate_search, answer_ai_question
from mcp.knowledge_graph import build_agraph
from mcp.graph_metrics import build_nx, get_top_hubs, get_density
from mcp.protocols import draft_protocol
# Streamlit configuration
st.set_page_config(page_title="MedGenesis AI", layout="wide")
# Initialize session state
if "res" not in st.session_state:
st.session_state.res = None
# Header UI
st.title("🧬 MedGenesis AI")
llm = st.radio("LLM engine", ["openai", "gemini"], horizontal=True)
query = st.text_input("Enter biomedical question")
# PDF generation helper
def _make_pdf(papers):
pdf = FPDF()
pdf.add_page()
pdf.set_font("Helvetica", size=12)
pdf.cell(0, 10, "MedGenesis AI – Results", ln=True, align="C")
pdf.ln(5)
for i, p in enumerate(papers, 1):
pdf.set_font("Helvetica", "B", 11)
pdf.multi_cell(0, 7, f"{i}. {p.get('title','')}")
pdf.set_font("Helvetica", size=9)
body = f"""{p.get('authors','')}
{p.get('summary','')}
{p.get('link','')}"""
pdf.multi_cell(0, 6, body)
pdf.ln(3)
return pdf.output(dest="S").encode("latin-1", errors="replace")
# Trigger search
if st.button("Run Search 🚀") and query.strip():
with st.spinner("Gathering data…"):
st.session_state.res = asyncio.run(orchestrate_search(query, llm))
# Retrieve results
res = st.session_state.res
# If no results yet, prompt user
if not res:
st.info("Enter a question and press **Run Search 🚀** to begin.")
else:
# Create tabs
tabs = st.tabs(["Results", "Graph", "Clusters", "Variants", "Trials", "Metrics", "Visuals", "Protocols"])
title_tab, graph_tab, clust_tab, var_tab, trial_tab, met_tab, vis_tab, proto_tab = tabs
# Results Tab
with title_tab:
for i, p in enumerate(res["papers"], 1):
st.markdown(f"**{i}. [{p['title']}]({p['link']})**")
st.write(p["summary"])
c1, c2 = st.columns(2)
c1.download_button("CSV", pd.DataFrame(res["papers"]).to_csv(index=False),
"papers.csv", "text/csv")
c2.download_button("PDF", _make_pdf(res["papers"]),
"papers.pdf", "application/pdf")
st.subheader("AI summary")
st.info(res["ai_summary"])
# Graph Tab
with graph_tab:
nodes, edges, cfg = build_agraph(res["papers"], res["umls"], res.get("drug_safety", []), res.get("umls_relations", []))
hl = st.text_input("Highlight node:", key="hl")
if hl:
pat = re.compile(re.escape(hl), re.I)
for n in nodes:
n.color = "#f1c40f" if pat.search(n.label) else n.color
agraph(nodes, edges, cfg)
# Clusters Tab
with clust_tab:
clusters = res.get("clusters", [])
if clusters:
df = pd.DataFrame({
"title": [p['title'] for p in res['papers']],
"cluster": clusters
})
st.write("### Paper Clusters")
for c in sorted(set(clusters)):
st.write(f"**Cluster {c}**")
for t in df[df['cluster'] == c]['title']:
st.write(f"- {t}")
else:
st.info("No clusters to show.")
# Variants Tab
with var_tab:
variants = res.get("variants", [])
if variants:
st.json(variants)
else:
st.warning("No variants found. Try a well-known gene like 'TP53'.")
# Trials Tab
with trial_tab:
trials = res.get("clinical_trials", [])
if trials:
st.json(trials)
else:
st.warning("No trials found. Try a disease name or specific drug.")
# Metrics Tab
with met_tab:
G = build_nx([n.__dict__ for n in nodes], [e.__dict__ for e in edges])
st.metric("Density", f"{get_density(G):.3f}")
st.markdown("**Top hubs**")
for nid, sc in get_top_hubs(G):
label = next((n.label for n in nodes if n.id == nid), nid)
st.write(f"- {label}: {sc:.3f}")
# Visuals Tab
with vis_tab:
years = [p.get("published", "")[:4] for p in res["papers"] if p.get("published")]
if years:
st.plotly_chart(px.histogram(pd.DataFrame({'year': years}), x='year', nbins=10, title="Publication Year"))
# Protocols Tab
with proto_tab:
hyp = st.text_input("Enter hypothesis for protocol:", key="proto_q")
if st.button("Draft Protocol") and hyp.strip():
with st.spinner("Generating protocol…"):
doc = asyncio.run(draft_protocol(hyp, context=res["ai_summary"], llm=llm))
st.subheader("Experimental Protocol")
st.write(doc)
|