Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -20,23 +20,59 @@ def qa_bot(user_question, history, min_year, max_year, specialty):
|
|
20 |
return history, history
|
21 |
|
22 |
css = """
|
|
|
|
|
|
|
|
|
|
|
23 |
body {
|
24 |
background: #f5f7fa !important;
|
25 |
font-family: 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif !important;
|
26 |
color: #212529 !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
}
|
28 |
#main-card {
|
29 |
background: #fff !important;
|
30 |
-
border-radius:
|
31 |
box-shadow: 0 4px 24px rgba(60, 80, 120, 0.07), 0 1.5px 4px rgba(60, 80, 120, 0.05);
|
32 |
padding: 32px 32px 24px 32px;
|
33 |
-
|
34 |
-
|
35 |
-
|
|
|
|
|
36 |
}
|
37 |
#chatbot {
|
38 |
background: #f9fbfd !important;
|
39 |
-
border-radius:
|
40 |
box-shadow: 0 2px 8px rgba(60, 80, 120, 0.06);
|
41 |
margin-bottom: 18px !important;
|
42 |
border: 1px solid #e3e7ef !important;
|
@@ -93,18 +129,99 @@ body {
|
|
93 |
background: linear-gradient(90deg, #174ea6 0%, #0ea5e9 100%) !important;
|
94 |
color: #fff !important;
|
95 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
"""
|
97 |
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
|
|
|
|
|
106 |
|
107 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
specialty_options = [
|
109 |
"Rheumatology", "Psychiatry", "Pulmonology & Respiratory Medicine", "Nephrology", "Public Health & Epidemiology",
|
110 |
"Medical Research & Methodology", "Pharmacy & Pharmacology", "Hematology", "Oncology", "Medical Ethics & Law",
|
@@ -119,29 +236,32 @@ with gr.Blocks(theme=gr.themes.Monochrome(), css=css) as demo:
|
|
119 |
"Preventive Medicine", "Genetics", "Nursing", "Allied Health Professions", "Plastic & Reconstructive Surgery", "Others",
|
120 |
"Toxicology", "General Medicine"
|
121 |
]
|
122 |
-
# Replace dropdown with slider for year selection
|
123 |
specialty_dropdown = gr.Dropdown(choices=specialty_options, value="General Medicine", label="Specialty", scale=2, elem_id="specialty-dropdown")
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
|
|
|
|
|
|
|
|
145 |
if __name__ == "__main__":
|
146 |
demo.launch()
|
147 |
|
|
|
20 |
return history, history
|
21 |
|
22 |
css = """
|
23 |
+
html, body, #root, .gradio-container {
|
24 |
+
margin: 0 !important;
|
25 |
+
padding: 0 !important;
|
26 |
+
}
|
27 |
+
|
28 |
body {
|
29 |
background: #f5f7fa !important;
|
30 |
font-family: 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif !important;
|
31 |
color: #212529 !important;
|
32 |
+
margin: 0;
|
33 |
+
padding: 0;
|
34 |
+
}
|
35 |
+
#main-row {
|
36 |
+
display: flex;
|
37 |
+
flex-direction: row;
|
38 |
+
width: 100vw;
|
39 |
+
min-height: 100vh;
|
40 |
+
box-sizing: border-box;
|
41 |
+
gap: 0;
|
42 |
+
}
|
43 |
+
#readme-col {
|
44 |
+
flex: 1 1 0;
|
45 |
+
background: #f5f7fa;
|
46 |
+
padding: 0 0 0 0;
|
47 |
+
border-right: 1px solid #e3e7ef;
|
48 |
+
height: 108vh;
|
49 |
+
overflow-y: auto;
|
50 |
+
box-sizing: border-box;
|
51 |
+
}
|
52 |
+
#readme-markdown {
|
53 |
+
border-radius: 5px;
|
54 |
+
box-shadow: 0 4px 24px rgba(60, 80, 120, 0.07), 0 1.5px 4px rgba(60, 80, 120, 0.05);
|
55 |
+
padding: 32px 32px 24px 32px;
|
56 |
+
margin: 0;
|
57 |
+
border: none;
|
58 |
+
overflow-y: auto;
|
59 |
+
box-sizing: border-box;
|
60 |
+
flex: 1;
|
61 |
}
|
62 |
#main-card {
|
63 |
background: #fff !important;
|
64 |
+
border-radius: 5px;
|
65 |
box-shadow: 0 4px 24px rgba(60, 80, 120, 0.07), 0 1.5px 4px rgba(60, 80, 120, 0.05);
|
66 |
padding: 32px 32px 24px 32px;
|
67 |
+
margin: 0;
|
68 |
+
border: none;
|
69 |
+
overflow-y: auto;
|
70 |
+
box-sizing: border-box;
|
71 |
+
flex: 1;
|
72 |
}
|
73 |
#chatbot {
|
74 |
background: #f9fbfd !important;
|
75 |
+
border-radius: 5px !important;
|
76 |
box-shadow: 0 2px 8px rgba(60, 80, 120, 0.06);
|
77 |
margin-bottom: 18px !important;
|
78 |
border: 1px solid #e3e7ef !important;
|
|
|
129 |
background: linear-gradient(90deg, #174ea6 0%, #0ea5e9 100%) !important;
|
130 |
color: #fff !important;
|
131 |
}
|
132 |
+
@media (max-width: 900px) {
|
133 |
+
#main-row {
|
134 |
+
flex-direction: column;
|
135 |
+
width: 100vw;
|
136 |
+
}
|
137 |
+
#readme-col, #main-card {
|
138 |
+
min-width: 0 !important;
|
139 |
+
max-width: 100vw !important;
|
140 |
+
border-radius: 0 !important;
|
141 |
+
height: auto !important;
|
142 |
+
}
|
143 |
+
#readme-markdown {
|
144 |
+
padding: 24px 12px 16px 12px;
|
145 |
+
}
|
146 |
+
}
|
147 |
+
@media (max-width: 600px) {
|
148 |
+
#main-row {
|
149 |
+
flex-direction: column;
|
150 |
+
width: 100vw;
|
151 |
+
}
|
152 |
+
#readme-col, #main-card {
|
153 |
+
min-width: 0 !important;
|
154 |
+
max-width: 100vw !important;
|
155 |
+
border-radius: 0 !important;
|
156 |
+
height: auto !important;
|
157 |
+
}
|
158 |
+
#readme-markdown {
|
159 |
+
padding: 14px 6px 10px 6px;
|
160 |
+
font-size: 0.98rem;
|
161 |
+
}
|
162 |
+
#main-card {
|
163 |
+
padding: 16px 6px 10px 6px !important;
|
164 |
+
}
|
165 |
+
}
|
166 |
"""
|
167 |
|
168 |
+
readme_content = """
|
169 |
+
# Medical QA Chatbot
|
170 |
+
|
171 |
+
This is a Chain-of-Thought powered medical chatbot that:
|
172 |
+
|
173 |
+
- Retrieves answers from a Qdrant Cloud vector DB
|
174 |
+
- Uses Stanford DSPy to reason step-by-step
|
175 |
+
- Supports filtering by year and specialty
|
176 |
+
- Uses dense + ColBERT multivectors for retrieval
|
177 |
+
|
178 |
+
---
|
179 |
+
|
180 |
+
## How to Use
|
181 |
+
|
182 |
+
- Add your `OPENAI_API_KEY` to `.env`
|
183 |
+
- Add your `QDRANT_API_KEY` to `.env`
|
184 |
+
- Add your `QDRANT_CLOUD_URL` to `.env`
|
185 |
+
- Make sure `qdrant-client` points to your
|
186 |
+
Qdrant Cloud instance in `rag_dspy.py`
|
187 |
+
- Run `python app.py`
|
188 |
+
|
189 |
+
## Sample Questions
|
190 |
|
191 |
+
### General Medical Knowledge
|
192 |
+
- What are the most common symptoms of lupus?
|
193 |
|
194 |
+
- How is type 2 diabetes usually managed in adults?
|
195 |
+
|
196 |
+
- What is the difference between viral and bacterial pneumonia?
|
197 |
+
|
198 |
+
### Treatment & Medication
|
199 |
+
- What are the first-line medications for treating hypertension?
|
200 |
+
|
201 |
+
- How does metformin work to lower blood sugar?
|
202 |
+
|
203 |
+
### Diagnosis & Tests
|
204 |
+
- What diagnostic tests are used to detect rheumatoid arthritis?
|
205 |
+
|
206 |
+
- When is a colonoscopy recommended for cancer screening?
|
207 |
+
|
208 |
+
### Hospital & Patient Care
|
209 |
+
- What are the psychosocial challenges faced by cancer patients?
|
210 |
+
|
211 |
+
- How do hospitals manage patients with multidrug-resistant infections?
|
212 |
+
|
213 |
+
### Clinical Guidelines / Rare Topics
|
214 |
+
- What is the recommended treatment for acute myocardial infarction in elderly patients?
|
215 |
+
"""
|
216 |
+
def suggestion_click(q, history, min_year, max_year, specialty):
|
217 |
+
return qa_bot(q, history, min_year, max_year, specialty)
|
218 |
+
|
219 |
+
with gr.Blocks(theme=gr.themes.Monochrome(), css=css) as demo:
|
220 |
+
|
221 |
+
with gr.Row(elem_id="main-row"):
|
222 |
+
with gr.Column(elem_id="main-card"):
|
223 |
+
chatbot = gr.Chatbot(label="", elem_id="chatbot", type="messages", height=300)
|
224 |
+
state = gr.State([])
|
225 |
specialty_options = [
|
226 |
"Rheumatology", "Psychiatry", "Pulmonology & Respiratory Medicine", "Nephrology", "Public Health & Epidemiology",
|
227 |
"Medical Research & Methodology", "Pharmacy & Pharmacology", "Hematology", "Oncology", "Medical Ethics & Law",
|
|
|
236 |
"Preventive Medicine", "Genetics", "Nursing", "Allied Health Professions", "Plastic & Reconstructive Surgery", "Others",
|
237 |
"Toxicology", "General Medicine"
|
238 |
]
|
|
|
239 |
specialty_dropdown = gr.Dropdown(choices=specialty_options, value="General Medicine", label="Specialty", scale=2, elem_id="specialty-dropdown")
|
240 |
+
with gr.Row():
|
241 |
+
min_year_slider = gr.Slider(minimum=1793, maximum=2021, value=1990, step=1, label="Min Year", scale=2, elem_id="min-year-slider")
|
242 |
+
max_year_slider = gr.Slider(minimum=1793, maximum=2021, value=2021, step=1, label="Max Year", scale=2, elem_id="max-year-slider")
|
243 |
+
|
244 |
+
with gr.Row():
|
245 |
+
user_input = gr.Textbox(placeholder="Type a medical question...", show_label=False, lines=1, scale=8, elem_id="user-input")
|
246 |
+
submit_btn = gr.Button(value="➤", scale=1, elem_id="submit-btn")
|
247 |
+
|
248 |
+
with gr.Row():
|
249 |
+
suggestion_buttons = []
|
250 |
+
for i, q in enumerate(sample_questions):
|
251 |
+
btn = gr.Button(q, elem_id=f"suggestion-{i}", elem_classes=["suggestion-btn"])
|
252 |
+
suggestion_buttons.append(btn)
|
253 |
+
|
254 |
+
submit_btn.click(qa_bot, inputs=[user_input, state, min_year_slider, max_year_slider, specialty_dropdown], outputs=[chatbot, state])
|
255 |
+
user_input.submit(qa_bot, inputs=[user_input, state, min_year_slider, max_year_slider, specialty_dropdown], outputs=[chatbot, state])
|
256 |
+
for btn, q in zip(suggestion_buttons, sample_questions):
|
257 |
+
btn.click(suggestion_click, inputs=[gr.State(q), state, min_year_slider, max_year_slider, specialty_dropdown], outputs=[chatbot, state])
|
258 |
+
|
259 |
+
with gr.Column(elem_id="readme-col"):
|
260 |
+
gr.Markdown(readme_content, elem_id="readme-markdown")
|
261 |
+
|
262 |
+
|
263 |
+
|
264 |
+
|
265 |
if __name__ == "__main__":
|
266 |
demo.launch()
|
267 |
|