File size: 5,957 Bytes
4a6179c c4bf66f 4a6179c c4bf66f 4a6179c 1786f57 4a6179c 1786f57 c4bf66f 1786f57 4a6179c c4bf66f 4a6179c 1786f57 4a6179c c4bf66f 1786f57 c4bf66f 4a6179c c4bf66f 4a6179c c4bf66f 1786f57 4a6179c c4bf66f 4a6179c c4bf66f 4a6179c c4bf66f 4a6179c c4bf66f 4a6179c c4bf66f 4a6179c c4bf66f 4a6179c c4bf66f 4a6179c c4bf66f 4a6179c c4bf66f 4a6179c c4bf66f 4a6179c |
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 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# ββ app.py βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
import asyncio
import re
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 setup ββββββββββββββββββββββββββββββββββββββββββββββββββββ
st.set_page_config(layout="wide", page_title="MedGenesis AI")
if "res" not in st.session_state:
st.session_state.res = None
st.title("𧬠MedGenesis AI")
llm = st.radio("LLM engine", ["openai", "gemini"], horizontal=True)
query = st.text_input("Enter biomedical question")
# PDF 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")
# Run search
if st.button("Run Search π") and query:
with st.spinner("Gathering dataβ¦"):
st.session_state.res = asyncio.run(orchestrate_search(query, llm))
res = st.session_state.res
if not res:
st.info("Enter a query and press Run Search")
st.stop()
# Tabs
tabs = st.tabs(["Results", "Graph", "Clusters", "Variants", "Trials", "Metrics", "Visuals", "Protocols"])
# ββ Results tab
with tabs[0]:
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 tabs[1]:
nodes, edges, cfg = build_agraph(
res["papers"], res["umls"], res["drug_safety"], res["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 tabs[2]:
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 tabs[3]:
if res.get("variants"):
st.json(res["variants"])
else:
st.warning("No variants found. Try 'TP53' or 'BRCA1'.")
# ββ Trials tab
with tabs[4]:
if res.get("clinical_trials"):
st.json(res["clinical_trials"])
else:
st.warning("No trials found. Try a disease or drug.")
# ββ Metrics tab
with tabs[5]:
nodes_dicts = [n.__dict__ for n in nodes]
edges_dicts = [e.__dict__ for e in edges]
G = build_nx(nodes_dicts, edges_dicts)
st.metric("Density", f"{get_density(G):.3f}")
st.markdown("**Top hubs**")
for nid, sc in get_top_hubs(G):
lbl = next((n.label for n in nodes if n.id == nid), nid)
st.write(f"- {lbl}: {sc:.3f}")
# ββ Visuals tab
with tabs[6]:
years = [p.get("published","")[:4] for p in res["papers"] if p.get("published")]
if years:
st.plotly_chart(px.histogram(years, nbins=10, title="Publication Year"))
# ββ Protocols tab
with tabs[7]:
proto_q = st.text_input("Enter hypothesis for protocol:", key="proto_q")
if st.button("Draft Protocol") and proto_q.strip():
with st.spinner("Generating protocolβ¦"):
proto = asyncio.run(draft_protocol(
proto_q, context=res['ai_summary'], llm=llm
))
st.subheader("Experimental Protocol")
st.write(proto)
βββββββββββββββββββββββββββββββββββββββββββββββββββ
# In import section:
from mcp.embeddings import embed_texts, cluster_embeddings
from mcp.protocols import draft_protocol
# After creating tabs = st.tabs([...,'Clusters','Protocols']):
with tabs[-2]: # second last tab = Clusters
if res.get('clusters'):
df = pd.DataFrame({
'title': [p['title'] for p in res['papers']],
'cluster': res['clusters']
})
st.write("### Paper Clusters")
for c in sorted(set(res['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.")
with tabs[-1]: # last tab = Protocols
proto_q = st.text_input("Enter hypothesis for protocol:", key="proto_q")
if st.button("Draft Protocol") and proto_q.strip():
with st.spinner("Generating protocolβ¦"):
proto = asyncio.run(draft_protocol(
proto_q, context=res['ai_summary'], llm=llm))
st.subheader("Experimental Protocol")
st.write(proto)
|