mgbam commited on
Commit
fcc9342
Β·
verified Β·
1 Parent(s): 76418d6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +26 -16
app.py CHANGED
@@ -1,12 +1,14 @@
1
  #!/usr/bin/env python3
2
  """
3
- MedGenesis AI – Streamlit UI (v3, June 2025)
4
 
5
  β€’ Dual-LLM selector (OpenAI | Gemini)
6
- β€’ Tabs: Results | Genes | Trials | Variants | Graph | Metrics | Visuals
 
7
  β€’ Robust PDF export (all Unicode β†’ Latin-1 safe)
8
- β€’ Null-safe handling of any RuntimeError / HTTPStatusError objects that
9
- slip through the async pipeline.
 
10
  """
11
 
12
  from __future__ import annotations
@@ -16,7 +18,7 @@ from pathlib import Path
16
  import streamlit as st
17
  import pandas as pd
18
  import plotly.express as px
19
- from streamlit_agraph import agraph
20
  from fpdf import FPDF
21
 
22
  from mcp.orchestrator import orchestrate_search, answer_ai_question
@@ -65,7 +67,7 @@ def _workspace_sidebar():
65
  with st.expander(f"{i}. {item['query']}"):
66
  st.write(item["result"]["ai_summary"])
67
 
68
- # ── Main UI ─────────────────────────────────────────────────────────
69
  def render_ui() -> None:
70
  st.set_page_config("MedGenesis AI", layout="wide")
71
 
@@ -112,7 +114,7 @@ def render_ui() -> None:
112
  st.info("Enter a question and press **Run Search πŸš€**")
113
  return
114
 
115
- # Guarantee all expected keys exist
116
  for k in (
117
  "papers", "umls", "drug_safety", "genes", "mesh_defs",
118
  "gene_disease", "clinical_trials", "variants"
@@ -125,7 +127,7 @@ def render_ui() -> None:
125
  "Graph", "Metrics", "Visuals"
126
  ])
127
 
128
- # ---- Results ----------------------------------------------------
129
  with tabs[0]:
130
  st.subheader("Literature")
131
  for i, p in enumerate(res["papers"], 1):
@@ -158,7 +160,7 @@ def render_ui() -> None:
158
  st.subheader("AI summary")
159
  st.info(res["ai_summary"])
160
 
161
- # ---- Genes ------------------------------------------------------
162
  with tabs[1]:
163
  st.header("Gene / Variant signals")
164
  clean = [g for g in res["genes"] if isinstance(g, dict)]
@@ -179,7 +181,7 @@ def render_ui() -> None:
179
  if d:
180
  st.write("-", d)
181
 
182
- # ---- Trials -----------------------------------------------------
183
  with tabs[2]:
184
  st.header("Clinical trials")
185
  if not res["clinical_trials"]:
@@ -189,7 +191,7 @@ def render_ui() -> None:
189
  st.markdown(f"**{t['nctId']}** – {t['briefTitle']}")
190
  st.write(f"Phase {t.get('phase')} | Status {t.get('status')}")
191
 
192
- # ---- Variants ---------------------------------------------------
193
  with tabs[3]:
194
  st.header("Cancer variants (cBioPortal)")
195
  if not res["variants"]:
@@ -197,7 +199,7 @@ def render_ui() -> None:
197
  else:
198
  st.json(res["variants"][:50])
199
 
200
- # ---- Graph ------------------------------------------------------
201
  with tabs[4]:
202
  nodes, edges, cfg = build_agraph(
203
  res["papers"], res["umls"], res["drug_safety"]
@@ -209,11 +211,19 @@ def render_ui() -> None:
209
  n.color = "#f1c40f" if pat.search(n.label) else "#d3d3d3"
210
  agraph(nodes, edges, cfg)
211
 
212
- # ---- Metrics ----------------------------------------------------
213
  with tabs[5]:
 
 
 
 
 
 
 
 
214
  G = build_nx(
215
  [n.__dict__ for n in nodes],
216
- [e.__dict__ for e in edges],
217
  )
218
  st.metric("Density", f"{get_density(G):.3f}")
219
  st.markdown("**Top hubs**")
@@ -221,14 +231,14 @@ def render_ui() -> None:
221
  lab = next((n.label for n in nodes if n.id == nid), nid)
222
  st.write(f"- {lab} {sc:.3f}")
223
 
224
- # ---- Visuals ----------------------------------------------------
225
  with tabs[6]:
226
  years = [p.get("published", "")[:4] for p in res["papers"] if p.get("published")]
227
  if years:
228
  st.plotly_chart(px.histogram(years, nbins=12,
229
  title="Publication Year"))
230
 
231
- # ---- Follow-up QA ----------------------------------------------
232
  st.markdown("---")
233
  st.text_input("Ask follow-up question:", key="followup_input")
234
 
 
1
  #!/usr/bin/env python3
2
  """
3
+ MedGenesis AI – Streamlit UI (v3.1 β€’ June 2025)
4
 
5
  β€’ Dual-LLM selector (OpenAI | Gemini)
6
+ β€’ Tabs:
7
+ Results | Genes | Trials | Variants | Graph | Metrics | Visuals
8
  β€’ Robust PDF export (all Unicode β†’ Latin-1 safe)
9
+ β€’ Null-safe handling of RuntimeError / HTTPStatusError placeholders
10
+ β€’ Metrics tab now converts Edge objects β†’ {'source', 'target'} safely,
11
+ preventing the KeyError you just saw.
12
  """
13
 
14
  from __future__ import annotations
 
18
  import streamlit as st
19
  import pandas as pd
20
  import plotly.express as px
21
+ from streamlit_agraph import agraph, Node, Edge
22
  from fpdf import FPDF
23
 
24
  from mcp.orchestrator import orchestrate_search, answer_ai_question
 
67
  with st.expander(f"{i}. {item['query']}"):
68
  st.write(item["result"]["ai_summary"])
69
 
70
+ # ── Main UI ──────────────────────────────────────────────────────────
71
  def render_ui() -> None:
72
  st.set_page_config("MedGenesis AI", layout="wide")
73
 
 
114
  st.info("Enter a question and press **Run Search πŸš€**")
115
  return
116
 
117
+ # Guarantee keys
118
  for k in (
119
  "papers", "umls", "drug_safety", "genes", "mesh_defs",
120
  "gene_disease", "clinical_trials", "variants"
 
127
  "Graph", "Metrics", "Visuals"
128
  ])
129
 
130
+ # Results tab -----------------------------------------------------
131
  with tabs[0]:
132
  st.subheader("Literature")
133
  for i, p in enumerate(res["papers"], 1):
 
160
  st.subheader("AI summary")
161
  st.info(res["ai_summary"])
162
 
163
+ # Genes tab -------------------------------------------------------
164
  with tabs[1]:
165
  st.header("Gene / Variant signals")
166
  clean = [g for g in res["genes"] if isinstance(g, dict)]
 
181
  if d:
182
  st.write("-", d)
183
 
184
+ # Trials tab ------------------------------------------------------
185
  with tabs[2]:
186
  st.header("Clinical trials")
187
  if not res["clinical_trials"]:
 
191
  st.markdown(f"**{t['nctId']}** – {t['briefTitle']}")
192
  st.write(f"Phase {t.get('phase')} | Status {t.get('status')}")
193
 
194
+ # Variants tab ----------------------------------------------------
195
  with tabs[3]:
196
  st.header("Cancer variants (cBioPortal)")
197
  if not res["variants"]:
 
199
  else:
200
  st.json(res["variants"][:50])
201
 
202
+ # Graph tab -------------------------------------------------------
203
  with tabs[4]:
204
  nodes, edges, cfg = build_agraph(
205
  res["papers"], res["umls"], res["drug_safety"]
 
211
  n.color = "#f1c40f" if pat.search(n.label) else "#d3d3d3"
212
  agraph(nodes, edges, cfg)
213
 
214
+ # Metrics tab -----------------------------------------------------
215
  with tabs[5]:
216
+ # Convert Edge objects β†’ dicts with guaranteed 'source'/'target'
217
+ edge_dicts = [
218
+ {"source": getattr(e, "source", getattr(e, "from", "")),
219
+ "target": getattr(e, "target", getattr(e, "to", ""))}
220
+ for e in edges if isinstance(e, Edge)
221
+ if getattr(e, "source", getattr(e, "from", None))
222
+ and getattr(e, "target", getattr(e, "to", None))
223
+ ]
224
  G = build_nx(
225
  [n.__dict__ for n in nodes],
226
+ edge_dicts,
227
  )
228
  st.metric("Density", f"{get_density(G):.3f}")
229
  st.markdown("**Top hubs**")
 
231
  lab = next((n.label for n in nodes if n.id == nid), nid)
232
  st.write(f"- {lab} {sc:.3f}")
233
 
234
+ # Visuals tab -----------------------------------------------------
235
  with tabs[6]:
236
  years = [p.get("published", "")[:4] for p in res["papers"] if p.get("published")]
237
  if years:
238
  st.plotly_chart(px.histogram(years, nbins=12,
239
  title="Publication Year"))
240
 
241
+ # Follow-up QA ----------------------------------------------------
242
  st.markdown("---")
243
  st.text_input("Ask follow-up question:", key="followup_input")
244