panda992 commited on
Commit
c52edc4
Β·
1 Parent(s): 8c0905e
Files changed (2) hide show
  1. README.md +54 -29
  2. app.py +88 -31
README.md CHANGED
@@ -1,8 +1,8 @@
1
  ---
2
- title: "GHAPA: Intelligent Health AI Assistant"
3
- emoji: "🧠⚑"
4
- colorFrom: "blue"
5
- colorTo: "green"
6
  sdk: "gradio"
7
  app_file: "app.py"
8
  pinned: false
@@ -10,36 +10,61 @@ secrets:
10
  - MODAL_BACKEND_URL
11
  ---
12
 
13
- # 🧠 GHAPA: Global Health AI Prompt Assistant (Powered by Modal ⚑)
14
 
15
- **GHAPA** is a multilingual biomedical assistant that provides trusted, citable health information across global languages. It combines real-time hybrid search with domain-specific LLM reasoning in a modular Retrieval-Augmented Generation (RAG) pipeline.
16
 
17
- ## 🌍 Key Features
18
 
19
- - 🌐 **Multilingual Q&A**: Accepts questions in **English**, **Hindi**, **Spanish**, and **French**, with automatic language detection and translation.
20
- - πŸ” **Hybrid Search**: Retrieves biomedical data from **PubMed** and general health insights via **DuckDuckGo**, ensuring broader yet reliable context.
21
- - πŸ“š **Citable Results**: Every answer includes a direct **source link** and **context snippet**.
22
- - 🧠 **Biomedical Reasoning**: Uses **PMC-LLaMA**, a large language model fine-tuned on medical literature, for precise and grounded answers.
23
- - βš™οΈ **Serverless Backend**: All heavy processing runs on scalable GPU backends via [Modal](https://modal.com), decoupled from the lightweight Gradio UI.
24
- - πŸ’‘ **Minimal UI**: Clean, responsive interface built using [Gradio](https://www.gradio.app), hosted on [Hugging Face Spaces](https://huggingface.co/spaces).
 
 
 
 
 
 
25
 
26
  ---
27
 
28
- ## πŸ›  Architecture Overview
 
 
29
 
30
  ```plaintext
31
- User Input (any language)
32
- ↓
33
- Language Detection & Translation
34
- ↓
35
- Hybrid Search (PubMed + DuckDuckGo)
36
- ↓
37
- Unified Ranking (SentenceTransformer)
38
- ↓
39
- Prompt Construction with Top Contexts
40
- ↓
41
- PMC-LLaMA Generative Reasoning Engine
42
- ↓
43
- Back-Translation & Markdown Output
44
- ↓
45
- Final Answer + Cited Sources
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: "MediAgent AI: Your Trusted AI Health & Drug Navigator"
3
+ emoji: "🧬"
4
+ colorFrom: "indigo"
5
+ colorTo: "purple"
6
  sdk: "gradio"
7
  app_file: "app.py"
8
  pinned: false
 
10
  - MODAL_BACKEND_URL
11
  ---
12
 
13
+ # 🧬 MediAgent AI: Your Trusted AI Health & Drug Navigator
14
 
15
+ **MediAgent AI** is a sophisticated, multilingual health assistant designed to provide reliable, sourced, and easy-to-understand answers to a wide range of medical questions. It leverages a powerful agentic framework to reason, select tools, and synthesize information from trusted sources.
16
 
17
+ This application is built with a decoupled architecture: a modern Gradio UI hosted on Hugging Face Spaces and a powerful, serverless GPU backend running on [Modal](https://modal.com).
18
 
19
+ ## πŸš€ Key Features
20
+
21
+ - πŸ’¬ **Multilingual Support**: Automatically detects and responds in **English**, **Hindi**, **Spanish**, and **French**.
22
+ - πŸ› οΈ **Agentic Tool Use**: Instead of a simple search, MediAgent AI actively chooses the best tool for your question from its specialized toolkit:
23
+ - `search_pubmed`: For technical and clinical research.
24
+ - `search_web`: For general health and symptom information.
25
+ - `check_drug_interactions`: To check for interactions between multiple drugs via the openFDA API.
26
+ - `check_drug_side_effects`: To find adverse reactions for a specific drug via the openFDA API.
27
+ - πŸ›‘οΈ **Advanced Safety Layers**: Features a critical pre-check system that identifies queries related to **physical medical emergencies** or **mental health crises** and provides immediate, appropriate guidance instead of attempting an answer.
28
+ - 🧠 **Agentic Reasoning Engine**: Powered by **Mistral-7B-Instruct-v0.2** and a **LlamaIndex ReAct Agent**, allowing the model to think, act, and observe in a loop to arrive at a well-reasoned conclusion.
29
+ - πŸ“š **Sourced & Explained Answers**: All information is presented with citations (links to PubMed/web sources or notes from the FDA database) and complex medical terms are automatically explained in simple language.
30
+ - ✨ **Modern & User-Friendly UI**: A clean, responsive interface built with [Gradio](https://www.gradio.app) that includes example prompts and a one-click "Copy to Clipboard" button for convenience.
31
 
32
  ---
33
 
34
+ ## πŸ› οΈ Architecture Overview
35
+
36
+ MediAgent AI uses an advanced agentic architecture, which is more dynamic than a standard RAG pipeline.
37
 
38
  ```plaintext
39
+ User Input (any language)
40
+ β”‚
41
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
42
+ β”‚ Gradio UI on HF Spaces β”‚
43
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
44
+ β”‚ (API Call to Modal)
45
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β†“β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
46
+ β”‚ Modal Serverless Backend β”‚
47
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
48
+ β”‚
49
+ 1. πŸ›‘οΈ Critical Safety Pre-Check
50
+ (Is it a medical or mental health emergency?)
51
+ β”‚
52
+ 2. 🌐 Language Detection & Translation to English
53
+ β”‚
54
+ 3. πŸ€– LlamaIndex ReAct Agent (Mistral-7B)
55
+ (Agentic Loop Begins)
56
+ a. πŸ€” Thought: "Which tool should I use based on the user's query?"
57
+ b. 🎬 Action: Selects and executes a tool (e.g., check_drug_interactions)
58
+ c. πŸ‘€ Observation: Receives data back from the tool (e.g., FDA results)
59
+ (Loop continues until the agent has enough information)
60
+ β”‚
61
+ 4. πŸ“ Final Answer Synthesis
62
+ (Agent composes a complete answer, explaining complex terms)
63
+ β”‚
64
+ 5. 🌐 Back-Translation to Original Language
65
+ β”‚
66
+ 6. πŸ“€ Formatted Markdown Response
67
+ β”‚
68
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β†“β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
69
+ β”‚ Final Answer Displayed in UI β”‚
70
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
app.py CHANGED
@@ -7,21 +7,19 @@ import uuid
7
  MODAL_BACKEND_URL = os.getenv("MODAL_BACKEND_URL")
8
 
9
  # --- Session ID ---
10
- SESSION_ID = str(uuid.uuid4()) # Generate a persistent session ID
11
 
12
  # --- Backend Communication ---
13
  def call_modal_backend(user_input):
 
14
  if not MODAL_BACKEND_URL:
15
  return {
16
- "final_markdown": "### ❗ Configuration Error\n**Reason**: `MODAL_BACKEND_URL` is not set.",
17
- "detected_lang": "Unknown"
18
  }
19
 
20
  headers = {"Content-Type": "application/json"}
21
- data = {
22
- "user_input": user_input,
23
- "session_id": SESSION_ID,
24
- }
25
 
26
  try:
27
  response = requests.post(MODAL_BACKEND_URL, headers=headers, json=data, timeout=300)
@@ -33,52 +31,99 @@ def call_modal_backend(user_input):
33
  "detected_lang": "Error"
34
  }
35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  # --- Gradio UI Definition ---
37
- with gr.Blocks(theme=gr.themes.Soft(), css="footer {display: none !important;}") as demo:
 
 
38
  gr.Markdown("""
39
- # 🧠 GHAPA: Global Health AI Prompt Assistant
40
- _Ask trusted health questions in **English**, **Hindi**, **Spanish**, or **French**._
41
  """)
42
 
43
- with gr.Row():
 
44
  inp = gr.Textbox(
45
- label="❓ Enter your health question",
46
- placeholder="e.g., What are the symptoms of dengue?",
47
- scale=4
 
48
  )
49
- btn = gr.Button("πŸ” Submit", variant="primary", scale=1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
 
51
- lang_detected = gr.Markdown("🌐 Language detected: _waiting..._", visible=False)
52
- output = gr.Markdown(label="βœ… Answer & Explanation")
53
  backend_result = gr.State()
54
 
 
55
  def start_processing(user_input):
56
  if not user_input.strip():
57
  return {
58
- inp: gr.update(),
59
- btn: gr.update(),
60
- output: "Please enter a question before submitting.",
61
  lang_detected: gr.update(visible=False),
 
62
  }
63
  return {
64
  inp: gr.update(interactive=False),
65
- btn: gr.update(interactive=False, value="⏳ Processing..."),
66
  output: "",
67
- lang_detected: gr.update(visible=True, value="🌐 Detecting language and processing..."),
 
68
  }
69
 
70
  def finish_processing(response_json):
 
 
 
 
 
71
  return {
72
- inp: gr.update(interactive=True),
73
- btn: gr.update(interactive=True, value="πŸ” Submit"),
74
- output: response_json.get("final_markdown", "Error: No response from backend."),
75
- lang_detected: gr.update(visible=True, value=f"🌐 Language detected: **{response_json.get('detected_lang', 'Unknown')}**"),
 
76
  }
77
-
78
- btn.click(
 
79
  fn=start_processing,
80
  inputs=[inp],
81
- outputs=[inp, btn, output, lang_detected]
82
  ).then(
83
  fn=call_modal_backend,
84
  inputs=[inp],
@@ -86,8 +131,20 @@ with gr.Blocks(theme=gr.themes.Soft(), css="footer {display: none !important;}")
86
  ).then(
87
  fn=finish_processing,
88
  inputs=[backend_result],
89
- outputs=[inp, btn, output, lang_detected]
 
 
 
 
 
 
 
 
 
 
 
 
90
  )
91
 
92
  if __name__ == "__main__":
93
- demo.launch()
 
7
  MODAL_BACKEND_URL = os.getenv("MODAL_BACKEND_URL")
8
 
9
  # --- Session ID ---
10
+ SESSION_ID = str(uuid.uuid4())
11
 
12
  # --- Backend Communication ---
13
  def call_modal_backend(user_input):
14
+ """Sends the user's question to the Modal backend and returns the response."""
15
  if not MODAL_BACKEND_URL:
16
  return {
17
+ "final_markdown": "### ❗ Configuration Error\n**Reason**: `MODAL_BACKEND_URL` environment variable is not set.",
18
+ "detected_lang": "Error"
19
  }
20
 
21
  headers = {"Content-Type": "application/json"}
22
+ data = {"user_input": user_input, "session_id": SESSION_ID}
 
 
 
23
 
24
  try:
25
  response = requests.post(MODAL_BACKEND_URL, headers=headers, json=data, timeout=300)
 
31
  "detected_lang": "Error"
32
  }
33
 
34
+ # --- UI Styling ---
35
+ CUSTOM_CSS = """
36
+ body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
37
+ .gradio-container { max-width: 800px !important; margin: auto; padding-top: 2rem; }
38
+ .output-area {
39
+ background-color: #f9f9f9;
40
+ padding: 1.5rem;
41
+ border-radius: 0.5rem;
42
+ border: 1px solid #e0e0e0;
43
+ box-shadow: 0 1px 3px rgba(0,0,0,0.05);
44
+ }
45
+ footer { display: none !important; }
46
+ #user-input textarea { font-size: 1rem; line-height: 1.5; }
47
+ """
48
+
49
  # --- Gradio UI Definition ---
50
+ # UPDATED: Title and header to reflect the new name "MediAgent AI"
51
+ with gr.Blocks(theme=gr.themes.Soft(), css=CUSTOM_CSS, title="MediAgent AI") as demo:
52
+ # --- Header ---
53
  gr.Markdown("""
54
+ # 🧬 MediAgent AI
55
+ _Your Trusted AI Health & Drug Navigator_
56
  """)
57
 
58
+ # --- Input Section ---
59
+ with gr.Group():
60
  inp = gr.Textbox(
61
+ label="❓ Ask any health question (e.g., about symptoms, drugs, or diseases)",
62
+ placeholder="e.g., What are the symptoms of dengue? or Do aspirin and warfarin interact?",
63
+ lines=3,
64
+ elem_id="user-input"
65
  )
66
+ with gr.Row():
67
+ btn = gr.Button("πŸ” Get Answer", variant="primary", scale=2)
68
+ clear_btn = gr.ClearButton(value="Clear", scale=1)
69
+
70
+ gr.Examples(
71
+ examples=[
72
+ ["What are symptoms of malaria?"],
73
+ ["Do aspirin and warfarin interact?"],
74
+ ["ΒΏCuΓ‘les son los efectos secundarios del ibuprofeno?"],
75
+ ["COVID-19 ΰ€•ΰ₯‡ ΰ€²ΰ€•ΰ₯ΰ€·ΰ€£ ΰ€•ΰ₯ΰ€―ΰ€Ύ ΰ€Ήΰ₯ˆΰ€‚?"],
76
+ ],
77
+ inputs=inp,
78
+ label="Example Questions"
79
+ )
80
+
81
+ # --- Output Section ---
82
+ lang_detected = gr.Label(value="", visible=False)
83
+
84
+ with gr.Column(elem_classes=["output-area"]):
85
+ output = gr.Markdown(label="βœ… Answer & Explanation")
86
+
87
+ copy_btn = gr.Button("πŸ“‹ Copy Answer to Clipboard", visible=False)
88
 
89
+ # --- Backend State ---
 
90
  backend_result = gr.State()
91
 
92
+ # --- UI Logic Functions ---
93
  def start_processing(user_input):
94
  if not user_input.strip():
95
  return {
96
+ output: gr.Markdown("Please enter a question before submitting."),
 
 
97
  lang_detected: gr.update(visible=False),
98
+ copy_btn: gr.update(visible=False),
99
  }
100
  return {
101
  inp: gr.update(interactive=False),
102
+ btn: gr.update(interactive=False, value="⏳ Thinking..."),
103
  output: "",
104
+ lang_detected: gr.update(visible=True, value="🌐 Analyzing your question..."),
105
+ copy_btn: gr.update(visible=False),
106
  }
107
 
108
  def finish_processing(response_json):
109
+ final_markdown = response_json.get("final_markdown", "Error: No response from backend.")
110
+ detected_lang = response_json.get('detected_lang', 'Unknown')
111
+
112
+ show_copy = "error" not in detected_lang.lower() and "error" not in final_markdown.lower()
113
+
114
  return {
115
+ inp: gr.update(interactive=True, value=""),
116
+ btn: gr.update(interactive=True, value="πŸ” Get Answer"),
117
+ output: final_markdown,
118
+ lang_detected: gr.update(visible=True, value=f"🌐 Language detected: **{detected_lang}**"),
119
+ copy_btn: gr.update(visible=show_copy),
120
  }
121
+
122
+ # --- Event Listeners ---
123
+ event_chain = btn.click(
124
  fn=start_processing,
125
  inputs=[inp],
126
+ outputs=[inp, btn, output, lang_detected, copy_btn]
127
  ).then(
128
  fn=call_modal_backend,
129
  inputs=[inp],
 
131
  ).then(
132
  fn=finish_processing,
133
  inputs=[backend_result],
134
+ outputs=[inp, btn, output, lang_detected, copy_btn]
135
+ )
136
+
137
+ clear_btn.add([inp, output, lang_detected, copy_btn])
138
+
139
+ copy_btn.click(
140
+ fn=None,
141
+ inputs=[output],
142
+ outputs=None,
143
+ _js="""(text) => {
144
+ navigator.clipboard.writeText(text);
145
+ alert('Answer copied to clipboard!');
146
+ }"""
147
  )
148
 
149
  if __name__ == "__main__":
150
+ demo.launch()