victoria-latynina commited on
Commit
56e185e
·
verified ·
1 Parent(s): 1ec0f3e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +247 -56
app.py CHANGED
@@ -1,64 +1,255 @@
 
 
 
 
 
 
1
  import gradio as gr
2
- from huggingface_hub import InferenceClient
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
- """
5
- For more information on `huggingface_hub` Inference API support, please check the docs: https://huggingface.co/docs/huggingface_hub/v0.22.2/en/guides/inference
6
- """
7
- client = InferenceClient("HuggingFaceH4/zephyr-7b-beta")
8
 
 
 
 
 
9
 
10
- def respond(
11
- message,
12
- history: list[tuple[str, str]],
13
- system_message,
14
- max_tokens,
15
- temperature,
16
- top_p,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  ):
18
- messages = [{"role": "system", "content": system_message}]
19
-
20
- for val in history:
21
- if val[0]:
22
- messages.append({"role": "user", "content": val[0]})
23
- if val[1]:
24
- messages.append({"role": "assistant", "content": val[1]})
25
-
26
- messages.append({"role": "user", "content": message})
27
-
28
- response = ""
29
-
30
- for message in client.chat_completion(
31
- messages,
32
- max_tokens=max_tokens,
33
- stream=True,
34
- temperature=temperature,
35
- top_p=top_p,
36
- ):
37
- token = message.choices[0].delta.content
38
-
39
- response += token
40
- yield response
41
-
42
-
43
- """
44
- For information on how to customize the ChatInterface, peruse the gradio docs: https://www.gradio.app/docs/chatinterface
45
- """
46
- demo = gr.ChatInterface(
47
- respond,
48
- additional_inputs=[
49
- gr.Textbox(value="You are a friendly Chatbot.", label="System message"),
50
- gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
51
- gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
52
- gr.Slider(
53
- minimum=0.1,
54
- maximum=1.0,
55
- value=0.95,
56
- step=0.05,
57
- label="Top-p (nucleus sampling)",
58
- ),
59
- ],
60
- )
 
 
 
 
 
61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
  if __name__ == "__main__":
64
- demo.launch()
 
 
1
+ import os
2
+ import uuid
3
+ import json
4
+ import asyncio
5
+ from dotenv import load_dotenv
6
+
7
  import gradio as gr
8
+ from mcp.server.fastmcp import FastMCP, Context
9
+
10
+ # ---------------------------------------------------------------------------
11
+ # Environment & MCP initialisation
12
+ # ---------------------------------------------------------------------------
13
+ load_dotenv()
14
+
15
+ mcp = FastMCP(
16
+ name="healthcare-mcp",
17
+ version="1.0.0",
18
+ description="Healthcare MCP server for medical information access (Gradio edition)"
19
+ )
20
+
21
+ # ---------------------------------------------------------------------------
22
+ # Internal tools & services
23
+ # ---------------------------------------------------------------------------
24
+ from src.tools.fda_tool import FDATool
25
+ from src.tools.pubmed_tool import PubMedTool
26
+ from src.tools.healthfinder_tool import HealthFinderTool
27
+ from src.tools.clinical_trials_tool import ClinicalTrialsTool
28
+ from src.tools.medical_terminology_tool import MedicalTerminologyTool
29
+ from src.services.usage_service import UsageService
30
+
31
+ fda_tool = FDATool()
32
+ pubmed_tool = PubMedTool()
33
+ healthfinder_tool = HealthFinderTool()
34
+ clinical_trials_tool = ClinicalTrialsTool()
35
+ medical_terminology_tool = MedicalTerminologyTool()
36
+
37
+ usage_service = UsageService(db_path="healthcare_usage.db")
38
 
39
+ # Unique session – ensures all usage is grouped for the current interface user
40
+ session_id = str(uuid.uuid4())
 
 
41
 
42
+ # ---------------------------------------------------------------------------
43
+ # FastMCP tool definitions – these can be reached programmatically by MCP
44
+ # clients (and are also reused by the Gradio UI wrappers below).
45
+ # ---------------------------------------------------------------------------
46
 
47
+ @mcp.tool()
48
+ async def fda_drug_lookup(ctx: Context, drug_name: str, search_type: str = "general"):
49
+ """Look up drug information from the FDA database."""
50
+ usage_service.record_usage(session_id, "fda_drug_lookup")
51
+ return await fda_tool.lookup_drug(drug_name, search_type)
52
+
53
+
54
+ @mcp.tool()
55
+ async def pubmed_search(ctx: Context, query: str, max_results: int = 5, date_range: str = ""):
56
+ """Search for medical literature in the PubMed database."""
57
+ usage_service.record_usage(session_id, "pubmed_search")
58
+ return await pubmed_tool.search_literature(query, max_results, date_range)
59
+
60
+
61
+ @mcp.tool()
62
+ async def health_topics(ctx: Context, topic: str, language: str = "en"):
63
+ """Retrieve evidence‑based information for a specific health topic."""
64
+ usage_service.record_usage(session_id, "health_topics")
65
+ return await healthfinder_tool.get_health_topics(topic, language)
66
+
67
+
68
+ @mcp.tool()
69
+ async def clinical_trials_search(
70
+ ctx: Context,
71
+ condition: str,
72
+ status: str = "recruiting",
73
+ max_results: int = 10,
74
  ):
75
+ """Search for clinical trials by condition and status."""
76
+ usage_service.record_usage(session_id, "clinical_trials_search")
77
+ return await clinical_trials_tool.search_trials(condition, status, max_results)
78
+
79
+
80
+ @mcp.tool()
81
+ async def lookup_icd_code(
82
+ ctx: Context,
83
+ code: str | None = None,
84
+ description: str | None = None,
85
+ max_results: int = 10,
86
+ ):
87
+ """Look up ICD‑10 codes by code or text description."""
88
+ usage_service.record_usage(session_id, "lookup_icd_code")
89
+ return await medical_terminology_tool.lookup_icd_code(code, description, max_results)
90
+
91
+
92
+ @mcp.tool()
93
+ async def get_usage_stats(ctx: Context):
94
+ """Return per‑session usage statistics."""
95
+ return usage_service.get_monthly_usage(session_id)
96
+
97
+
98
+ @mcp.tool()
99
+ async def get_all_usage_stats(ctx: Context):
100
+ """Return aggregate usage statistics across all sessions."""
101
+ return usage_service.get_usage_stats()
102
+
103
+
104
+ # ---------------------------------------------------------------------------
105
+ # Helper – convert coroutine results to nicely‑formatted JSON for UI display
106
+ # ---------------------------------------------------------------------------
107
+
108
+ def pretty_json(data):
109
+ try:
110
+ return json.dumps(data, indent=2, ensure_ascii=False)
111
+ except TypeError:
112
+ # Fallback if the object isn’t serialisable
113
+ return str(data)
114
+
115
+
116
+ # ---------------------------------------------------------------------------
117
+ # Gradio UI definitions
118
+ # ---------------------------------------------------------------------------
119
+
120
+ # Notes on async handling:
121
+ # – Blocks.launch supports async handlers directly; we expose async functions
122
+ # that call the underlying tool methods.
123
 
124
+ async def fda_drug_lookup_gr(drug_name, search_type):
125
+ usage_service.record_usage(session_id, "fda_drug_lookup")
126
+ res = await fda_tool.lookup_drug(drug_name, search_type)
127
+ return pretty_json(res)
128
+
129
+
130
+ async def pubmed_search_gr(query, max_results, date_range):
131
+ usage_service.record_usage(session_id, "pubmed_search")
132
+ res = await pubmed_tool.search_literature(query, int(max_results), str(date_range or ""))
133
+ return pretty_json(res)
134
+
135
+
136
+ async def health_topics_gr(topic, language):
137
+ usage_service.record_usage(session_id, "health_topics")
138
+ res = await healthfinder_tool.get_health_topics(topic, language)
139
+ return pretty_json(res)
140
+
141
+
142
+ async def clinical_trials_search_gr(condition, status, max_results):
143
+ usage_service.record_usage(session_id, "clinical_trials_search")
144
+ res = await clinical_trials_tool.search_trials(condition, status, int(max_results))
145
+ return pretty_json(res)
146
+
147
+
148
+ async def lookup_icd_code_gr(code, description, max_results):
149
+ usage_service.record_usage(session_id, "lookup_icd_code")
150
+ code = code or None
151
+ description = description or None
152
+ res = await medical_terminology_tool.lookup_icd_code(code, description, int(max_results))
153
+ return pretty_json(res)
154
+
155
+
156
+ # Usage statistics are synchronous; no external IO
157
+
158
+ def get_usage_stats_gr():
159
+ return pretty_json(usage_service.get_monthly_usage(session_id))
160
+
161
+
162
+ def get_all_usage_stats_gr():
163
+ return pretty_json(usage_service.get_usage_stats())
164
+
165
+
166
+ # ---------------------------------------------------------------------------
167
+ # Build the Gradio Blocks interface
168
+ # ---------------------------------------------------------------------------
169
+
170
+ with gr.Blocks(title="Healthcare MCP Explorer") as demo:
171
+ gr.Markdown("""# 🩺 Healthcare MCP Dashboard\nInteractively query FDA, PubMed, HealthFinder, Clinical‑Trials, and ICD‑10 data — all from one screen.""")
172
+
173
+ # ---------------- Drug lookup ----------------
174
+ with gr.Group():
175
+ gr.Markdown("## 💊 FDA Drug Lookup")
176
+ with gr.Row():
177
+ drug_name_tb = gr.Textbox(label="Drug name", placeholder="e.g. atorvastatin")
178
+ search_type_dd = gr.Dropdown(
179
+ label="Search type",
180
+ choices=["general", "label", "adverse_events"],
181
+ value="general",
182
+ )
183
+ fda_button = gr.Button("Search")
184
+ fda_output = gr.Textbox(label="Result", lines=12)
185
+
186
+ # ---------------- PubMed search -------------
187
+ with gr.Group():
188
+ gr.Markdown("## 🔍 PubMed Literature Search")
189
+ query_tb = gr.Textbox(label="Query", placeholder="e.g. type 2 diabetes glycemic control")
190
+ with gr.Row():
191
+ max_results_slider = gr.Slider(1, 20, value=5, step=1, label="Max articles")
192
+ date_range_tb = gr.Textbox(label="Published within last N years (optional)")
193
+ pubmed_button = gr.Button("Search PubMed")
194
+ pubmed_output = gr.Textbox(label="Result", lines=12)
195
+
196
+ # ---------------- Health topics -------------
197
+ with gr.Group():
198
+ gr.Markdown("## 📚 HealthFinder Topics")
199
+ topic_tb = gr.Textbox(label="Health topic", placeholder="e.g. hypertension")
200
+ language_dd = gr.Dropdown(label="Language", choices=["en", "es"], value="en")
201
+ hf_button = gr.Button("Get Topic Info")
202
+ hf_output = gr.Textbox(label="Result", lines=12)
203
+
204
+ # ---------------- Clinical trials -----------
205
+ with gr.Group():
206
+ gr.Markdown("## 🧪 Clinical‑Trials.gov Search")
207
+ condition_tb = gr.Textbox(label="Condition", placeholder="e.g. melanoma")
208
+ with gr.Row():
209
+ status_dd = gr.Dropdown(
210
+ label="Status",
211
+ choices=["recruiting", "completed", "active", "not_recruiting", "all"],
212
+ value="recruiting",
213
+ )
214
+ ct_max_slider = gr.Slider(1, 50, value=10, step=1, label="Max results")
215
+ ct_button = gr.Button("Search Trials")
216
+ ct_output = gr.Textbox(label="Result", lines=12)
217
+
218
+ # ---------------- ICD‑10 lookup -------------
219
+ with gr.Group():
220
+ gr.Markdown("## 🏷️ ICD‑10 Lookup")
221
+ code_tb = gr.Textbox(label="ICD‑10 Code (optional)")
222
+ description_tb = gr.Textbox(label="Description (optional)")
223
+ with gr.Row():
224
+ icd_max_slider = gr.Slider(1, 50, value=10, step=1, label="Max results")
225
+ icd_button = gr.Button("Lookup ICD‑10")
226
+ icd_output = gr.Textbox(label="Result", lines=12)
227
+
228
+ # ---------------- Usage stats ---------------
229
+ with gr.Group():
230
+ gr.Markdown("## 📈 Usage Statistics")
231
+ with gr.Row():
232
+ session_button = gr.Button("Current Session")
233
+ all_button = gr.Button("All‑time Usage")
234
+ session_output = gr.Textbox(label="Session Usage", lines=6)
235
+ all_output = gr.Textbox(label="All Usage", lines=6)
236
+
237
+ # -------------------------------------------------------------------
238
+ # Wire‑up callbacks
239
+ # -------------------------------------------------------------------
240
+ fda_button.click(fda_drug_lookup_gr, inputs=[drug_name_tb, search_type_dd], outputs=fda_output)
241
+ pubmed_button.click(pubmed_search_gr, inputs=[query_tb, max_results_slider, date_range_tb], outputs=pubmed_output)
242
+ hf_button.click(health_topics_gr, inputs=[topic_tb, language_dd], outputs=hf_output)
243
+ ct_button.click(clinical_trials_search_gr, inputs=[condition_tb, status_dd, ct_max_slider], outputs=ct_output)
244
+ icd_button.click(lookup_icd_code_gr, inputs=[code_tb, description_tb, icd_max_slider], outputs=icd_output)
245
+
246
+ session_button.click(get_usage_stats_gr, outputs=session_output)
247
+ all_button.click(get_all_usage_stats_gr, outputs=all_output)
248
+
249
+ # ---------------------------------------------------------------------------
250
+ # Entrypoint – run Gradio and MCP in one process
251
+ # ---------------------------------------------------------------------------
252
 
253
  if __name__ == "__main__":
254
+ demo.launch(mcp_server=True, show_error=True)
255
+