mgbam commited on
Commit
94febc8
Β·
verified Β·
1 Parent(s): a392df0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +76 -139
app.py CHANGED
@@ -4,35 +4,29 @@ import os
4
  import streamlit as st
5
  from fastapi import FastAPI
6
  from fastapi.middleware.cors import CORSMiddleware
7
- from mcp.orchestrator import orchestrate_search, answer_ai_question
8
- from mcp.schemas import UnifiedSearchInput, UnifiedSearchResult
9
- from mcp.workspace import get_workspace, save_query
10
- from mcp.knowledge_graph import build_knowledge_graph
11
  from pathlib import Path
12
  import pandas as pd
13
  from fpdf import FPDF
14
- import asyncio
15
  import plotly.express as px
16
  import streamlit.components.v1 as components
17
 
18
- ROOT_DIR = Path(__file__).resolve().parent
19
- LOGO_PATH = ROOT_DIR / "assets" / "logo.png"
 
 
20
 
21
- # --- FASTAPI BACKEND ---
 
 
22
 
 
23
  api = FastAPI(
24
  title="MedGenesis MCP Server",
25
  version="2.0.0",
26
- description="MedGenesis AI unifies PubMed, ArXiv, OpenFDA, UMLS, and GPT-4o into a single biomedical intelligence platform."
27
- )
28
-
29
- api.add_middleware(
30
- CORSMiddleware,
31
- allow_origins=["*"],
32
- allow_credentials=True,
33
- allow_methods=["*"],
34
- allow_headers=["*"],
35
  )
 
36
 
37
  @api.post("/unified_search", response_model=UnifiedSearchResult)
38
  async def unified_search_endpoint(data: UnifiedSearchInput):
@@ -42,174 +36,117 @@ async def unified_search_endpoint(data: UnifiedSearchInput):
42
  async def ask_ai_endpoint(question: str, context: str = ""):
43
  return await answer_ai_question(question, context)
44
 
45
- # --- PDF Export Utility ---
46
-
47
  def generate_pdf(papers):
48
- pdf = FPDF()
49
- pdf.add_page()
50
- pdf.set_font("Arial", size=12)
51
- pdf.cell(200, 10, txt="MedGenesis AI - Search Results", ln=True, align='C')
52
  pdf.ln(10)
53
- for i, paper in enumerate(papers, 1):
54
- pdf.set_font("Arial", style="B", size=12)
55
- pdf.multi_cell(0, 10, f"{i}. {paper['title']}")
56
- pdf.set_font("Arial", style="", size=10)
57
- pdf.multi_cell(0, 8, f"Authors: {paper['authors']}\nLink: {paper['link']}\nSummary: {paper['summary']}\n")
58
  pdf.ln(2)
59
- pdf_out = pdf.output(dest='S').encode('latin-1')
60
- return pdf_out
61
-
62
- # --- STREAMLIT UI ---
63
 
 
64
  def render_ui():
65
  st.set_page_config(page_title="MedGenesis AI", layout="wide")
66
 
67
- # --- SIDEBAR WORKSPACE ---
68
  with st.sidebar:
69
- st.header("πŸ—‚οΈ Your Workspace")
70
- saved_queries = get_workspace()
71
- if saved_queries:
72
- for i, item in enumerate(saved_queries, 1):
73
  with st.expander(f"{i}. {item['query']}"):
74
  st.write("**AI Summary:**", item["result"]["ai_summary"])
75
- st.write("**First Paper:**", item["result"]["papers"][0]["title"] if item["result"]["papers"] else "None")
76
  df = pd.DataFrame(item["result"]["papers"])
77
- st.download_button(
78
- label="πŸ“₯ Download as CSV",
79
- data=df.to_csv(index=False),
80
- file_name=f"workspace_query_{i}.csv",
81
- mime="text/csv",
82
- )
83
  else:
84
- st.info("Run a search and save it here!")
85
 
86
- # --- MAIN APP HEADER ---
87
  col1, col2 = st.columns([0.15, 0.85])
88
  with col1:
89
- if LOGO_PATH.exists():
90
- st.image(str(LOGO_PATH), width=100)
91
- else:
92
- st.markdown("🧬")
93
  with col2:
94
- st.markdown("""
95
- ## 🧬 **MedGenesis AI** – Biomedical Research Reimagined
96
- *Unified Intelligence from PubMed, ArXiv, OpenFDA, UMLS, and GPT-4o*
97
- """)
98
- st.caption("Created by Oluwafemi Idiakhoa | Hugging Face Spaces")
99
 
100
  st.markdown("---")
101
-
102
- # Unified Semantic Search
103
- st.subheader("πŸ” Unified Semantic Search")
104
- query = st.text_input("Enter your biomedical research question:", placeholder="e.g. New treatments for glioblastoma using CRISPR")
105
 
106
  results = None
107
  if st.button("Run Search πŸš€"):
108
- with st.spinner("Thinking... Gathering and analyzing data across 5 systems..."):
109
  results = asyncio.run(orchestrate_search(query))
110
- st.success("Search complete! πŸŽ‰")
111
 
112
  if results:
113
  tabs = st.tabs(["πŸ“ Results", "πŸ—ΊοΈ Knowledge Graph", "πŸ“Š Visualizations"])
114
 
115
- # --- TAB 1: Results ---
116
  with tabs[0]:
117
- for i, paper in enumerate(results["papers"], 1):
118
- st.markdown(f"**{i}. [{paper['title']}]({paper['link']})** \n*{paper['authors']}* ({paper['source']})")
119
- st.markdown(f"<div style='font-size: 0.9em; color: gray'>{paper['summary']}</div>", unsafe_allow_html=True)
120
-
121
- # Save to workspace (user-initiated, for clarity)
122
- if st.button("Save this search to Workspace"):
123
- save_query(query, results)
124
- st.success("Saved to your workspace!")
125
-
126
- # Export as CSV
127
- if results["papers"]:
128
- df = pd.DataFrame(results["papers"])
129
- csv = df.to_csv(index=False)
130
- st.download_button(
131
- label="πŸ“₯ Download results as CSV",
132
- data=csv,
133
- file_name="medgenesis_results.csv",
134
- mime="text/csv",
135
- )
136
-
137
- # Export as PDF
138
- if results["papers"]:
139
- pdf_bytes = generate_pdf(results["papers"])
140
- st.download_button(
141
- label="πŸ“„ Download results as PDF",
142
- data=pdf_bytes,
143
- file_name="medgenesis_results.pdf",
144
- mime="application/pdf",
145
- )
146
-
147
- # UMLS Concepts
148
- st.markdown("### 🧠 Biomedical Concept Enrichment (UMLS)")
149
- for concept in results["umls"]:
150
- if concept["cui"]:
151
- st.markdown(f"πŸ”Ή **{concept['name']}** (CUI: `{concept['cui']}`): {concept['definition'] or 'No definition available'}")
152
-
153
- # Drug Safety
154
- st.markdown("### πŸ’Š Drug Safety Insights (OpenFDA)")
155
- for drug_report in results["drug_safety"]:
156
- if drug_report:
157
- st.json(drug_report)
158
-
159
- # AI Summary
160
- st.markdown("### πŸ€– AI-Powered Summary")
161
- st.info(results["ai_summary"])
162
 
163
- # Suggested Reading
164
- st.markdown("### πŸ“– Suggested Links")
165
- for link in results["suggested_reading"]:
166
- st.write(f"- {link}")
167
 
168
- # --- TAB 2: Knowledge Graph ---
 
 
 
 
 
 
 
 
 
 
 
 
169
  with tabs[1]:
170
- st.markdown("#### Explore Connections")
171
  try:
172
- kg_html_path = build_knowledge_graph(results["papers"], results["umls"], results["drug_safety"])
173
- with open(kg_html_path, 'r', encoding='utf-8') as f:
174
- kg_html = f.read()
175
- components.html(kg_html, height=600)
176
  except Exception as e:
177
- st.warning("⚠️ Knowledge graph visualization is unavailable. "
178
- "Please ensure 'pyvis' and 'jinja2' are installed. "
179
- f"Error: {e}")
180
 
181
- # --- TAB 3: Visualizations ---
182
  with tabs[2]:
183
  pub_years = [p["published"] for p in results["papers"] if p.get("published")]
184
  if pub_years:
185
  fig = px.histogram(pub_years, nbins=10, title="Publication Year Distribution")
186
  st.plotly_chart(fig)
187
- # Placeholder for more charts
188
 
189
- # Follow-up AI Q&A
190
  st.markdown("---")
191
- st.subheader("πŸ’¬ Ask AI a Follow-up Question")
192
- follow_up = st.text_input("What do you want to ask based on the above?", placeholder="e.g. What's the most promising therapy?")
193
  if st.button("Ask AI"):
194
- with st.spinner("Analyzing and responding..."):
195
- ai_answer = asyncio.run(answer_ai_question(follow_up, context=query))
196
- st.success("AI's Response:")
197
- st.write(ai_answer["answer"])
198
 
199
- # Footer
200
  st.markdown("---")
201
- st.markdown(
202
- "<div style='text-align: center; font-size: 0.9em;'>"
203
- "✨ Built with ❀️ by <strong>Oluwafemi Idiakhoa</strong> β€’ Powered by FastAPI, Streamlit, Hugging Face, OpenAI, UMLS, OpenFDA, and NCBI</div>",
204
- unsafe_allow_html=True
205
- )
206
-
207
- # --- MAIN ENTRY ---
208
 
 
209
  if __name__ == "__main__":
210
  import sys
211
  if "runserver" in sys.argv:
212
- import uvicorn
213
- uvicorn.run(api, host="0.0.0.0", port=7860)
214
  else:
215
  render_ui()
 
4
  import streamlit as st
5
  from fastapi import FastAPI
6
  from fastapi.middleware.cors import CORSMiddleware
7
+ import asyncio
 
 
 
8
  from pathlib import Path
9
  import pandas as pd
10
  from fpdf import FPDF
 
11
  import plotly.express as px
12
  import streamlit.components.v1 as components
13
 
14
+ from mcp.orchestrator import orchestrate_search, answer_ai_question
15
+ from mcp.schemas import UnifiedSearchInput, UnifiedSearchResult
16
+ from mcp.workspace import get_workspace, save_query
17
+ from mcp.knowledge_graph import build_agraph
18
 
19
+ # Paths
20
+ ROOT = Path(__file__).parent
21
+ LOGO = ROOT / "assets" / "logo.png"
22
 
23
+ # FastAPI setup
24
  api = FastAPI(
25
  title="MedGenesis MCP Server",
26
  version="2.0.0",
27
+ description="MedGenesis AI – Unified Intelligence from PubMed, ArXiv, OpenFDA, UMLS, GPT-4o"
 
 
 
 
 
 
 
 
28
  )
29
+ api.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"])
30
 
31
  @api.post("/unified_search", response_model=UnifiedSearchResult)
32
  async def unified_search_endpoint(data: UnifiedSearchInput):
 
36
  async def ask_ai_endpoint(question: str, context: str = ""):
37
  return await answer_ai_question(question, context)
38
 
39
+ # PDF Export
 
40
  def generate_pdf(papers):
41
+ pdf = FPDF(); pdf.add_page(); pdf.set_font("Arial", size=12)
42
+ pdf.cell(200, 10, "MedGenesis AI - Search Results", ln=True, align="C")
 
 
43
  pdf.ln(10)
44
+ for i, p in enumerate(papers, 1):
45
+ pdf.set_font("Arial", "B", 12); pdf.multi_cell(0, 10, f"{i}. {p['title']}")
46
+ pdf.set_font("Arial", "", 10)
47
+ pdf.multi_cell(0, 8, f"Authors: {p['authors']}\nLink: {p['link']}\nSummary: {p['summary']}\n")
 
48
  pdf.ln(2)
49
+ return pdf.output(dest="S").encode("latin-1")
 
 
 
50
 
51
+ # UI
52
  def render_ui():
53
  st.set_page_config(page_title="MedGenesis AI", layout="wide")
54
 
55
+ # Sidebar workspace
56
  with st.sidebar:
57
+ st.header("πŸ—‚οΈ Workspace")
58
+ ws = get_workspace()
59
+ if ws:
60
+ for i, item in enumerate(ws, 1):
61
  with st.expander(f"{i}. {item['query']}"):
62
  st.write("**AI Summary:**", item["result"]["ai_summary"])
63
+ st.write("**Top Paper:**", item["result"]["papers"][0]["title"] if item["result"]["papers"] else "None")
64
  df = pd.DataFrame(item["result"]["papers"])
65
+ st.download_button("πŸ“₯ CSV", df.to_csv(index=False), f"query_{i}.csv", "text/csv")
 
 
 
 
 
66
  else:
67
+ st.info("Run & save searches here.")
68
 
69
+ # Header
70
  col1, col2 = st.columns([0.15, 0.85])
71
  with col1:
72
+ if LOGO.exists():
73
+ st.image(str(LOGO), width=100)
 
 
74
  with col2:
75
+ st.markdown("## οΏ½οΏ½ MedGenesis AI\n*Unified Intelligence from PubMed, ArXiv, OpenFDA, UMLS, GPT‑4o*")
76
+ st.caption("Built by Oluwafemi Idiakhoa β€’ Hugging Face Spaces")
 
 
 
77
 
78
  st.markdown("---")
79
+ query = st.text_input("πŸ” Enter biomedical research question:", placeholder="e.g. Glioblastoma CRISPR treatments")
 
 
 
80
 
81
  results = None
82
  if st.button("Run Search πŸš€"):
83
+ with st.spinner("Fetching & synthesizing..."):
84
  results = asyncio.run(orchestrate_search(query))
85
+ st.success("βœ… Search complete")
86
 
87
  if results:
88
  tabs = st.tabs(["πŸ“ Results", "πŸ—ΊοΈ Knowledge Graph", "πŸ“Š Visualizations"])
89
 
90
+ # Tab 1: Results
91
  with tabs[0]:
92
+ st.header("πŸ“š Top Papers")
93
+ for i, p in enumerate(results["papers"], 1):
94
+ st.markdown(f"**{i}. [{p['title']}]({p['link']})** \n*{p['authors']}* ({p['source']})")
95
+ st.markdown(f"<div style='color:gray'>{p['summary']}</div>", unsafe_allow_html=True)
96
+
97
+ if st.button("Save to Workspace"):
98
+ save_query(query, results); st.success("Saved!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
 
100
+ df = pd.DataFrame(results["papers"])
101
+ st.download_button("πŸ“₯ Download CSV", df.to_csv(index=False), "results.csv", "text/csv")
102
+ pdf = generate_pdf(results["papers"])
103
+ st.download_button("πŸ“„ Download PDF", pdf, "results.pdf", "application/pdf")
104
 
105
+ st.subheader("🧠 UMLS Concepts")
106
+ for c in results["umls"]:
107
+ if c.get("cui"):
108
+ st.markdown(f"- **{c['name']}** (CUI: `{c['cui']}`): {c.get('definition','No definition')}")
109
+
110
+ st.subheader("πŸ’Š Drug Safety (OpenFDA)")
111
+ for d in results["drug_safety"]:
112
+ st.json(d)
113
+
114
+ st.subheader("πŸ€– AI Summary")
115
+ st.info(results["ai_summary"])
116
+
117
+ # Tab 2: Knowledge Graph
118
  with tabs[1]:
119
+ st.header("πŸ—ΊοΈ Knowledge Graph Explorer")
120
  try:
121
+ nodes, edges, config = build_agraph(results["papers"], results["umls"], results["drug_safety"])
122
+ from streamlit_agraph import agraph
123
+ agraph(nodes=nodes, edges=edges, config=config)
 
124
  except Exception as e:
125
+ st.warning("Knowledge graph unavailable: " + str(e))
 
 
126
 
127
+ # Tab 3: Visualizations
128
  with tabs[2]:
129
  pub_years = [p["published"] for p in results["papers"] if p.get("published")]
130
  if pub_years:
131
  fig = px.histogram(pub_years, nbins=10, title="Publication Year Distribution")
132
  st.plotly_chart(fig)
 
133
 
134
+ # Follow-up Q&A
135
  st.markdown("---")
136
+ st.subheader("πŸ’¬ Ask Follow-up AI Question")
137
+ follow_up = st.text_input("Based on above:", placeholder="e.g. Most promising therapy?")
138
  if st.button("Ask AI"):
139
+ with st.spinner("Thinking..."):
140
+ ai_ans = asyncio.run(answer_ai_question(follow_up, context=query))
141
+ st.write(ai_ans.get("answer", ai_ans))
 
142
 
 
143
  st.markdown("---")
144
+ st.caption("✨ Built by Oluwafemi Idiakhoa β€’ Powered by FastAPI, Streamlit, OpenAI, UMLS, OpenFDA, NCBI")
 
 
 
 
 
 
145
 
146
+ # Entry
147
  if __name__ == "__main__":
148
  import sys
149
  if "runserver" in sys.argv:
150
+ import uvicorn; uvicorn.run(api, host="0.0.0.0", port=7860)
 
151
  else:
152
  render_ui()