mgbam commited on
Commit
c17cf5b
Β·
verified Β·
1 Parent(s): defde16

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +33 -38
app.py CHANGED
@@ -10,9 +10,6 @@ Tabs:
10
  Results | Genes | Trials | Variants | Graph | Metrics | Visuals
11
  """
12
 
13
- ##############################################################################
14
- # Std-lib / third-party
15
- ##############################################################################
16
  import os
17
  import pathlib
18
  import asyncio
@@ -24,18 +21,13 @@ import plotly.express as px
24
  from fpdf import FPDF
25
  from streamlit_agraph import agraph
26
 
27
- ##############################################################################
28
- # Internal helpers
29
- ##############################################################################
30
  from mcp.orchestrator import orchestrate_search, answer_ai_question
31
  from mcp.workspace import get_workspace, save_query
32
  from mcp.knowledge_graph import build_agraph
33
  from mcp.graph_metrics import build_nx, get_top_hubs, get_density
34
  from mcp.alerts import check_alerts
35
 
36
- # ---------------------------------------------------------------------------
37
- # Streamlit telemetry directory β†’ /tmp
38
- # ---------------------------------------------------------------------------
39
  os.environ.update({
40
  "STREAMLIT_DATA_DIR": "/tmp/.streamlit",
41
  "XDG_STATE_HOME" : "/tmp",
@@ -46,9 +38,6 @@ pathlib.Path("/tmp/.streamlit").mkdir(parents=True, exist_ok=True)
46
  ROOT = Path(__file__).parent
47
  LOGO = ROOT / "assets" / "logo.png"
48
 
49
- ##############################################################################
50
- # Utility helpers
51
- ##############################################################################
52
 
53
  def _latin1_safe(txt: str) -> str:
54
  """Coerce UTF-8 β†’ Latin-1 with replacement (for FPDF)."""
@@ -66,7 +55,12 @@ def _pdf(papers: list[dict]) -> bytes:
66
  pdf.set_font("Helvetica", "B", 11)
67
  pdf.multi_cell(0, 7, _latin1_safe(f"{i}. {p.get('title','')}"))
68
  pdf.set_font("Helvetica", "", 9)
69
- body = f"{p.get('authors','')}\n{p.get('summary','')}\n{p.get('link','')}\n"
 
 
 
 
 
70
  pdf.multi_cell(0, 6, _latin1_safe(body))
71
  pdf.ln(1)
72
  return pdf.output(dest="S").encode("latin-1", "replace")
@@ -83,9 +77,6 @@ def _workspace_sidebar():
83
  with st.expander(f"{i}. {item['query']}"):
84
  st.write(item['result']['ai_summary'])
85
 
86
- ##############################################################################
87
- # Main UI renderer
88
- ##############################################################################
89
 
90
  def render_ui():
91
  st.set_page_config("MedGenesis AI", layout="wide")
@@ -176,10 +167,9 @@ def render_ui():
176
  st.subheader("AI summary")
177
  st.info(res['ai_summary'])
178
 
179
- # --- Genes tab
180
  with tabs[1]:
181
  st.header("Gene / Variant signals")
182
- # Filter out non-dict entries (e.g., errors)
183
  valid_genes = [g for g in res['genes'] if isinstance(g, dict)]
184
  if valid_genes:
185
  for g in valid_genes:
@@ -188,14 +178,12 @@ def render_ui():
188
  else:
189
  st.info("No gene signals returned.")
190
 
191
- # MeSH definitions (skip errors/non-strings)
192
  mesh_list = [d for d in res['mesh_defs'] if isinstance(d, str) and d]
193
  if mesh_list:
194
  st.markdown("### MeSH definitions")
195
  for d in mesh_list:
196
  st.write(f"- {d}")
197
 
198
- # DisGeNET links (skip non-dict entries)
199
  gene_disease = [d for d in res['gene_disease'] if isinstance(d, dict)]
200
  if gene_disease:
201
  st.markdown("### DisGeNET links")
@@ -207,8 +195,12 @@ def render_ui():
207
  trials = res['clinical_trials']
208
  if not trials:
209
  st.info("No trials returned (rate-limited or none found).")
210
- for t in trials:
211
- st.markdown(f"**{t.get('nctId','')}** – {t.get('briefTitle','')} Phase {t.get('phase','?')} | Status {t.get('status','?')}")
 
 
 
 
212
 
213
  # --- Variants tab
214
  with tabs[3]:
@@ -239,25 +231,28 @@ def render_ui():
239
  if years:
240
  st.plotly_chart(px.histogram(years, nbins=12, title="Publication Year"))
241
 
242
- # Follow-up QA
243
  st.markdown("---")
244
- st.text_input("Ask follow-up question:", key="followup_input")
245
-
246
- def _on_ask():
247
- q = st.session_state.followup_input
248
- if not q.strip():
249
- st.warning("Please type a question first.")
250
- return
251
- with st.spinner("Querying LLM …"):
252
- ans = asyncio.run(answer_ai_question(q, context=st.session_state.last_query, llm=st.session_state.last_llm))
253
- st.session_state.followup_response = ans['answer']
254
-
255
- st.button("Ask AI", on_click=_on_ask)
 
 
 
 
 
256
  if st.session_state.followup_response:
257
  st.write(st.session_state.followup_response)
258
 
259
- ##############################################################################
260
- # Entrypoint
261
- ##############################################################################
262
  if __name__ == "__main__":
263
  render_ui()
 
10
  Results | Genes | Trials | Variants | Graph | Metrics | Visuals
11
  """
12
 
 
 
 
13
  import os
14
  import pathlib
15
  import asyncio
 
21
  from fpdf import FPDF
22
  from streamlit_agraph import agraph
23
 
 
 
 
24
  from mcp.orchestrator import orchestrate_search, answer_ai_question
25
  from mcp.workspace import get_workspace, save_query
26
  from mcp.knowledge_graph import build_agraph
27
  from mcp.graph_metrics import build_nx, get_top_hubs, get_density
28
  from mcp.alerts import check_alerts
29
 
30
+ # Streamlit telemetry directory β†’ /tmp
 
 
31
  os.environ.update({
32
  "STREAMLIT_DATA_DIR": "/tmp/.streamlit",
33
  "XDG_STATE_HOME" : "/tmp",
 
38
  ROOT = Path(__file__).parent
39
  LOGO = ROOT / "assets" / "logo.png"
40
 
 
 
 
41
 
42
  def _latin1_safe(txt: str) -> str:
43
  """Coerce UTF-8 β†’ Latin-1 with replacement (for FPDF)."""
 
55
  pdf.set_font("Helvetica", "B", 11)
56
  pdf.multi_cell(0, 7, _latin1_safe(f"{i}. {p.get('title','')}"))
57
  pdf.set_font("Helvetica", "", 9)
58
+ # fixed string literal with explicit newlines
59
+ body = (
60
+ f"{p.get('authors','')}\n"
61
+ f"{p.get('summary','')}\n"
62
+ f"{p.get('link','')}\n"
63
+ )
64
  pdf.multi_cell(0, 6, _latin1_safe(body))
65
  pdf.ln(1)
66
  return pdf.output(dest="S").encode("latin-1", "replace")
 
77
  with st.expander(f"{i}. {item['query']}"):
78
  st.write(item['result']['ai_summary'])
79
 
 
 
 
80
 
81
  def render_ui():
82
  st.set_page_config("MedGenesis AI", layout="wide")
 
167
  st.subheader("AI summary")
168
  st.info(res['ai_summary'])
169
 
170
+ # --- Genes tab
171
  with tabs[1]:
172
  st.header("Gene / Variant signals")
 
173
  valid_genes = [g for g in res['genes'] if isinstance(g, dict)]
174
  if valid_genes:
175
  for g in valid_genes:
 
178
  else:
179
  st.info("No gene signals returned.")
180
 
 
181
  mesh_list = [d for d in res['mesh_defs'] if isinstance(d, str) and d]
182
  if mesh_list:
183
  st.markdown("### MeSH definitions")
184
  for d in mesh_list:
185
  st.write(f"- {d}")
186
 
 
187
  gene_disease = [d for d in res['gene_disease'] if isinstance(d, dict)]
188
  if gene_disease:
189
  st.markdown("### DisGeNET links")
 
195
  trials = res['clinical_trials']
196
  if not trials:
197
  st.info("No trials returned (rate-limited or none found).")
198
+ else:
199
+ for t in trials:
200
+ st.markdown(
201
+ f"**{t.get('nctId','')}** – {t.get('briefTitle','')} "
202
+ f"Phase {t.get('phase','?')} | Status {t.get('status','?')}"
203
+ )
204
 
205
  # --- Variants tab
206
  with tabs[3]:
 
231
  if years:
232
  st.plotly_chart(px.histogram(years, nbins=12, title="Publication Year"))
233
 
234
+ # Follow-up QA (outside any tab)
235
  st.markdown("---")
236
+ input_col, button_col = st.columns([4, 1])
237
+ with input_col:
238
+ followup = st.text_input("Ask follow-up question:", key="followup_input")
239
+ with button_col:
240
+ if st.button("Ask AI"):
241
+ if followup.strip():
242
+ with st.spinner("Querying LLM …"):
243
+ ans = asyncio.run(
244
+ answer_ai_question(
245
+ question=followup,
246
+ context=st.session_state.last_query,
247
+ llm=st.session_state.last_llm,
248
+ )
249
+ )
250
+ st.session_state.followup_response = ans.get('answer', '')
251
+ else:
252
+ st.warning("Please type a question first.")
253
  if st.session_state.followup_response:
254
  st.write(st.session_state.followup_response)
255
 
256
+
 
 
257
  if __name__ == "__main__":
258
  render_ui()