yasserrmd commited on
Commit
188b27c
Β·
verified Β·
1 Parent(s): 2e924a6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +261 -104
app.py CHANGED
@@ -1,20 +1,23 @@
1
  import gradio as gr
 
2
  import torch
3
- from transformers import AutoTokenizer, AutoModelForCausalLM, TextIteratorStreamer
4
  from threading import Thread
5
  import re
 
 
6
  from typing import Iterator, List, Tuple
7
  import spaces
 
 
 
8
 
9
- # --- Model Configuration ---
10
- # Using the recommended base model for this setup.
11
- # The original model name seems to be a fine-tuned version, but the tokenizer should come from the base.
12
  MODEL_NAME = "yasserrmd/SinaReason-Magistral-2509"
13
- TOKENIZER_NAME = "mistralai/Magistral-7B-v0.3" # Use the base model's tokenizer for compatibility
14
  DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
15
 
16
- # --- Medical System Prompt ---
17
- # As recommended by the model card.
18
  MEDICAL_SYSTEM_PROMPT = """
19
  You are SinaReason, a medical reasoning assistant for educational and clinical support.
20
  Your goal is to carefully reason through clinical problems for a professional audience (clinicians, students).
@@ -30,74 +33,104 @@ Your thinking process must follow the template below:[THINK]Your thoughts or/and
30
 
31
  class SinaReasonMedicalChat:
32
  def __init__(self):
33
- """Initializes the tokenizer and model."""
34
  self.tokenizer = None
35
  self.model = None
36
  self.load_model()
37
-
38
  def load_model(self):
39
- """Load the SinaReason medical model and tokenizer."""
40
  try:
41
- print(f"Loading tokenizer from: {TOKENIZER_NAME}")
42
- self.tokenizer = AutoTokenizer.from_pretrained(TOKENIZER_NAME)
43
-
44
- # Add padding token if it's missing
 
 
 
45
  if self.tokenizer.pad_token is None:
46
  self.tokenizer.pad_token = self.tokenizer.eos_token
47
-
48
- print(f"Loading medical model: {MODEL_NAME}")
49
- self.model = AutoModelForCausalLM.from_pretrained(
50
  MODEL_NAME,
51
- torch_dtype=torch.bfloat16, # Use bfloat16 for better performance on modern GPUs
52
- device_map="auto"
53
  )
54
- print("SinaReason medical model loaded successfully!")
55
 
 
 
 
56
  except Exception as e:
57
  print(f"Error loading model: {e}")
58
  raise e
59
-
60
  def extract_thinking_and_response(self, text: str) -> Tuple[str, str]:
61
- """Extracts thinking process and the clinical response from the full text."""
62
- think_pattern = r'\[THINK\](.*?)\[/THINK\]'
63
- match = re.search(think_pattern, text, re.DOTALL)
64
-
 
 
 
 
65
  if match:
66
  thinking = match.group(1).strip()
67
- # Remove the entire thinking block to get the response
68
- response = re.sub(think_pattern, "", text, flags=re.DOTALL).strip()
69
- return thinking, response
70
- else:
71
- # If the thinking block is not yet complete or present, treat the whole text as thinking
72
- return text, ""
73
 
74
  @spaces.GPU(duration=120)
75
  def medical_chat_stream(self, message: str, history: List[List[str]], max_tokens: int = 1024,
76
- temperature: float = 0.7, top_p: float = 0.95) -> Iterator[Tuple[str, List[List[str]]]]:
77
- """Streams medical reasoning responses, smoothly updating the thinking and summary sections."""
78
- self.model.eval()
79
  if not message.strip():
80
  return
81
 
 
 
 
82
  # Apply the chat template with the medical system prompt
83
  messages = [
84
- {"role": "system", "content": MEDICAL_SYSTEM_PROMPT},
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  ]
86
 
87
  # Add conversation history
88
  for user_msg, assistant_msg in history:
89
- # We need to extract the raw model output from the formatted HTML
90
- raw_assistant_msg = re.sub(r'<.*?>', '', assistant_msg).replace("🧠 **Medical Reasoning Process**", "").replace("---", "").replace("🩺 **Clinical Summary**", "").strip()
91
  messages.append({"role": "user", "content": user_msg})
92
- messages.append({"role": "assistant", "content": raw_assistant_msg})
93
 
 
94
  messages.append({"role": "user", "content": message})
95
 
96
- # Apply chat template and tokenize
97
- prompt = self.tokenizer.apply_chat_template(messages, tokenize=False)
98
- inputs = self.tokenizer(text=prompt, return_tensors="pt").to(DEVICE)
 
 
99
 
100
- # Setup streamer for handling the model's output token by token
 
 
 
 
 
 
101
  streamer = TextIteratorStreamer(
102
  self.tokenizer,
103
  timeout=30.0,
@@ -105,7 +138,7 @@ class SinaReasonMedicalChat:
105
  skip_special_tokens=True
106
  )
107
 
108
- # Generation parameters for medical reasoning
109
  generation_kwargs = {
110
  **inputs,
111
  "max_new_tokens": max_tokens,
@@ -117,64 +150,121 @@ class SinaReasonMedicalChat:
117
  "repetition_penalty": 1.1
118
  }
119
 
120
- # Run model generation in a separate thread to avoid blocking the UI
121
- thread = Thread(target=self.model.generate, kwargs=generation_kwargs)
 
 
122
  thread.start()
123
 
124
- # Stream the response back to the UI
125
  partial_response = ""
 
 
 
126
  for new_token in streamer:
127
  partial_response += new_token
128
- thinking_content, clinical_content = self.extract_thinking_and_response(partial_response)
129
-
130
- # Create a single, consistently formatted HTML block that updates smoothly
131
- formatted_display = f"""🧠 **Medical Reasoning Process**
132
- <details open>
133
- <summary>πŸ” Click to view detailed thinking process</summary>
134
- <p style="white-space: pre-wrap;">*{thinking_content}*</p>
135
- </details>
136
- <hr>
137
- 🩺 **Clinical Summary**
138
- <p style="white-space: pre-wrap;">{clinical_content}</p>
139
- """
140
- # Update the history and yield the change to the Gradio interface
141
- new_history = history + [[message, formatted_display]]
142
- yield "", new_history
143
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
 
145
- # --- Gradio Interface ---
146
 
147
  # Initialize the medical chat model
148
  medical_chat_model = SinaReasonMedicalChat()
149
 
150
  def respond(message, history, max_tokens, temperature, top_p):
151
- """Gradio response function wrapper."""
152
- yield from medical_chat_model.medical_chat_stream(message, history, max_tokens, temperature, top_p)
 
153
 
154
- # Custom CSS for a professional medical interface
155
  css = """
156
- .medical-chatbot { min-height: 700px; }
157
- .warning-box { background-color: #fff3cd; border: 1px solid #ffeeba; border-radius: 8px; padding: 15px; margin: 15px 0; color: #856404; }
158
- .footer-text { text-align: center; color: #666; font-size: 0.9em; margin-top: 20px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
  """
160
 
 
161
  with gr.Blocks(css=css, title="SinaReason Medical Reasoning", theme=gr.themes.Soft()) as demo:
162
- gr.Markdown("# 🩺 SinaReason Medical Reasoning Assistant")
163
- gr.Markdown("**Advanced Clinical Reasoning Model** - Inspired by Ibn Sina (Avicenna)")
164
-
 
 
 
 
 
 
165
  with gr.Row():
166
  gr.HTML("""
167
  <div class="warning-box">
168
  <h4>⚠️ Important Medical Disclaimer</h4>
169
  <p><strong>This is a research and educational tool for medical professionals, researchers, and students.</strong></p>
170
  <ul>
171
- <li>🚫 <strong>NOT for patient diagnosis or treatment.</strong> All information must be verified by qualified professionals.</li>
172
- <li>πŸ‘¨β€βš•οΈ <strong>Intended for professional use only.</strong></li>
173
- <li>πŸ“š <strong>For educational purposes</strong> to understand clinical reasoning patterns.</li>
 
174
  </ul>
175
  </div>
176
  """)
177
-
178
  with gr.Row():
179
  with gr.Column(scale=4):
180
  chatbot = gr.Chatbot(
@@ -182,54 +272,121 @@ with gr.Blocks(css=css, title="SinaReason Medical Reasoning", theme=gr.themes.So
182
  show_copy_button=True,
183
  bubble_full_width=False,
184
  elem_classes=["medical-chatbot"],
185
- avatar_images=(None, "https://img.icons8.com/fluency/96/doctor-male.png")
186
  )
 
187
  msg = gr.Textbox(
188
- placeholder="Describe a clinical scenario for medical reasoning analysis...",
189
  lines=3,
 
190
  show_label=False,
191
  container=False
192
  )
 
 
 
 
 
 
193
  with gr.Column(scale=1, min_width=250):
194
  gr.Markdown("### βš™οΈ Model Parameters")
195
- max_tokens = gr.Slider(minimum=256, maximum=4096, value=2048, step=128, label="Max Tokens")
196
- temperature = gr.Slider(minimum=0.1, maximum=1.0, value=0.7, step=0.05, label="Temperature")
197
- top_p = gr.Slider(minimum=0.8, maximum=1.0, value=0.95, step=0.01, label="Top-p")
198
- gr.Markdown("---")
199
- submit_btn = gr.Button("πŸ” Analyze Case", variant="primary")
200
- retry_btn = gr.Button("πŸ”„ Retry")
201
- clear_btn = gr.Button("πŸ—‘οΈ Clear")
202
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
  gr.Examples(
204
  examples=[
205
  "Patient: 72-year-old with history of hypertension presents with confusion, right-sided weakness, and slurred speech. What is the likely cause and immediate steps?",
206
  "Patient: 45-year-old with sudden onset severe headache described as 'the worst ever'. What should be ruled out and how?",
207
  "Patient: 60-year-old with long-standing diabetes has numbness and tingling in both feet. What is the most likely diagnosis and first-line management?",
 
 
 
208
  ],
209
  inputs=[msg],
210
- label="πŸ“‹ Clinical Case Examples"
211
  )
212
-
 
213
  gr.HTML("""
214
  <div class="footer-text">
215
- <p><strong>Model:</strong> yasserrmd/SinaReason-Magistral-2509</p>
 
 
 
216
  </div>
217
  """)
218
 
219
- # Event Handlers
220
- def clear_chat():
221
- return [], ""
222
-
223
- def retry_last(history):
224
- if not history:
225
- return [], ""
226
- last_user_msg = history[-1][0]
227
- return history[:-1], last_user_msg
228
-
229
- submit_btn.click(respond, [msg, chatbot, max_tokens, temperature, top_p], [msg, chatbot])
230
- msg.submit(respond, [msg, chatbot, max_tokens, temperature, top_p], [msg, chatbot])
231
- clear_btn.click(clear_chat, None, [chatbot, msg])
232
- retry_btn.click(retry_last, [chatbot], [chatbot, msg])
233
-
234
  if __name__ == "__main__":
235
- demo.launch(debug=True, show_error=True)
 
 
 
 
1
  import gradio as gr
2
+ import gradio as gr
3
  import torch
4
+ from transformers import AutoTokenizer, Mistral3ForConditionalGeneration, TextIteratorStreamer
5
  from threading import Thread
6
  import re
7
+ import time
8
+ import os
9
  from typing import Iterator, List, Tuple
10
  import spaces
11
+ import threading
12
+
13
+
14
 
15
+ # Model configuration
 
 
16
  MODEL_NAME = "yasserrmd/SinaReason-Magistral-2509"
17
+ #MODEL_NAME = "yasserrmd/SinaReason-Magistral-2509-bnb-4bit"
18
  DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
19
 
20
+ # Medical system prompt as recommended by the model card
 
21
  MEDICAL_SYSTEM_PROMPT = """
22
  You are SinaReason, a medical reasoning assistant for educational and clinical support.
23
  Your goal is to carefully reason through clinical problems for a professional audience (clinicians, students).
 
33
 
34
  class SinaReasonMedicalChat:
35
  def __init__(self):
 
36
  self.tokenizer = None
37
  self.model = None
38
  self.load_model()
39
+
40
  def load_model(self):
41
+ """Load the SinaReason medical model and tokenizer"""
42
  try:
43
+ print(f"Loading medical model: {MODEL_NAME}")
44
+ self.tokenizer = AutoTokenizer.from_pretrained(
45
+ "mistralai/Magistral-Small-2509",
46
+ tokenizer_type="mistral"
47
+ )
48
+
49
+ # Add padding token if not present
50
  if self.tokenizer.pad_token is None:
51
  self.tokenizer.pad_token = self.tokenizer.eos_token
52
+
53
+ self.model = Mistral3ForConditionalGeneration.from_pretrained(
 
54
  MODEL_NAME,
55
+ dtype="auto"
 
56
  )
57
+
58
 
59
+
60
+ print("SinaReason medical model loaded successfully!")
61
+
62
  except Exception as e:
63
  print(f"Error loading model: {e}")
64
  raise e
65
+
66
  def extract_thinking_and_response(self, text: str) -> Tuple[str, str]:
67
+ """Extract thinking process from <think>...</think> tags and clinical response"""
68
+ # Look for the specific [THINK]...[/THINK] pattern used by SinaReason
69
+ think_pattern = r'[THINK](.*?)[/THINK]'
70
+
71
+ thinking = ""
72
+ response = text
73
+
74
+ match = re.search(think_pattern, text, re.DOTALL | re.IGNORECASE)
75
  if match:
76
  thinking = match.group(1).strip()
77
+ response = re.sub(think_pattern, "", text, flags=re.DOTALL | re.IGNORECASE).strip()
78
+
79
+ return thinking, response
 
 
 
80
 
81
  @spaces.GPU(duration=120)
82
  def medical_chat_stream(self, message: str, history: List[List[str]], max_tokens: int = 1024,
83
+ temperature: float = 0.7, top_p: float = 0.95) -> Iterator[Tuple[str, List[List[str]]]]:
84
+ """Stream medical reasoning responses with thinking display without threading."""
85
+ self.model.to(DEVICE).eval()
86
  if not message.strip():
87
  return
88
 
89
+ index_begin_think = MEDICAL_SYSTEM_PROMPT.find("[THINK]")
90
+ index_end_think = MEDICAL_SYSTEM_PROMPT.find("[/THINK]")
91
+
92
  # Apply the chat template with the medical system prompt
93
  messages = [
94
+ {
95
+ "role": "system",
96
+ "content": [
97
+ {"type": "text", "text": MEDICAL_SYSTEM_PROMPT[:index_begin_think]},
98
+ {
99
+ "type": "thinking",
100
+ "thinking": MEDICAL_SYSTEM_PROMPT[
101
+ index_begin_think + len("[THINK]") : index_end_think
102
+ ],
103
+ "closed": True,
104
+ },
105
+ {
106
+ "type": "text",
107
+ "text": MEDICAL_SYSTEM_PROMPT[index_end_think + len("[/THINK]") :],
108
+ },
109
+ ],
110
+ }
111
  ]
112
 
113
  # Add conversation history
114
  for user_msg, assistant_msg in history:
 
 
115
  messages.append({"role": "user", "content": user_msg})
116
+ messages.append({"role": "assistant", "content": assistant_msg})
117
 
118
+ # Add current message
119
  messages.append({"role": "user", "content": message})
120
 
121
+ # Apply chat template
122
+ prompt = self.tokenizer.apply_chat_template(
123
+ messages,
124
+ tokenize=False
125
+ )
126
 
127
+ # Tokenize input and move to the same device as the model
128
+ inputs = self.tokenizer(
129
+ text=prompt,
130
+ return_tensors="pt"
131
+ ).to(DEVICE)
132
+
133
+ # Setup streamer
134
  streamer = TextIteratorStreamer(
135
  self.tokenizer,
136
  timeout=30.0,
 
138
  skip_special_tokens=True
139
  )
140
 
141
+ # Generation parameters optimized for medical reasoning
142
  generation_kwargs = {
143
  **inputs,
144
  "max_new_tokens": max_tokens,
 
150
  "repetition_penalty": 1.1
151
  }
152
 
153
+ # Start generation directly.
154
+ # This will return immediately and the streamer will be populated in the background.
155
+ #self.model.generate(**generation_kwargs)
156
+ thread = threading.Thread(target=self.model.generate, kwargs=generation_kwargs)
157
  thread.start()
158
 
159
+ # Stream the response
160
  partial_response = ""
161
+ current_thinking = ""
162
+ current_response = ""
163
+
164
  for new_token in streamer:
165
  partial_response += new_token
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
 
167
+ print(partial_response)
168
+ # Extract thinking and response
169
+ #thinking, response = self.extract_thinking_and_response(partial_response)
170
+ thinking, response =None, partial_response
171
+ # Show thinking phase while it's being generated
172
+ if thinking and thinking != current_thinking:
173
+ current_thinking = thinking
174
+ display_text = f"🧠 **Medical Reasoning in Progress...**\n\n<details>\n<summary>πŸ” Click to see thinking process</summary>\n\n*{current_thinking}*\n\n</details>"
175
+ new_history = history + [[message, display_text]]
176
+ yield "", new_history
177
+ time.sleep(0.1) # Smooth streaming
178
+
179
+ # Show clinical response as it's generated
180
+ if response and response != current_response:
181
+ current_response = response
182
+
183
+ final_display = f"""🧠 **Medical Reasoning Process**
184
+ <details>
185
+ <summary>πŸ” Click to view detailed thinking process</summary>
186
+ *{current_thinking}*
187
+ </details>
188
+ ---
189
+ 🩺 **Clinical Summary**
190
+ {current_response}"""
191
+
192
+ new_history = history + [[message, final_display]]
193
+ yield "", new_history
194
 
 
195
 
196
  # Initialize the medical chat model
197
  medical_chat_model = SinaReasonMedicalChat()
198
 
199
  def respond(message, history, max_tokens, temperature, top_p):
200
+ """Gradio response function for medical reasoning"""
201
+ for response in medical_chat_model.medical_chat_stream(message, history, max_tokens, temperature, top_p):
202
+ yield response
203
 
204
+ # Custom CSS for medical interface
205
  css = """
206
+ .medical-chatbot {
207
+ min-height: 700px;
208
+ border: 2px solid #e3f2fd;
209
+ border-radius: 10px;
210
+ }
211
+ .thinking-section {
212
+ background: linear-gradient(135deg, #f8f9ff 0%, #e8f4f8 100%);
213
+ border-left: 4px solid #2196f3;
214
+ padding: 15px;
215
+ margin: 10px 0;
216
+ border-radius: 8px;
217
+ font-family: 'Monaco', monospace;
218
+ font-size: 0.9em;
219
+ }
220
+ .clinical-response {
221
+ background: linear-gradient(135deg, #fff8f0 0%, #fef7ed 100%);
222
+ border-left: 4px solid #ff9800;
223
+ padding: 15px;
224
+ margin: 10px 0;
225
+ border-radius: 8px;
226
+ }
227
+ .warning-box {
228
+ background: #fff3cd;
229
+ border: 1px solid #ffeaa7;
230
+ border-radius: 8px;
231
+ padding: 15px;
232
+ margin: 15px 0;
233
+ color: #856404;
234
+ }
235
+ .footer-text {
236
+ text-align: center;
237
+ color: #666;
238
+ font-size: 0.9em;
239
+ margin-top: 20px;
240
+ }
241
  """
242
 
243
+ # Create medical Gradio interface
244
  with gr.Blocks(css=css, title="SinaReason Medical Reasoning", theme=gr.themes.Soft()) as demo:
245
+ gr.Markdown("""
246
+ # 🩺 SinaReason Medical Reasoning Assistant
247
+
248
+ **Advanced Clinical Reasoning Model** - Inspired by Ibn Sina (Avicenna)
249
+
250
+ This model provides transparent chain-of-thought medical reasoning for **educational and clinical support purposes**.
251
+ """)
252
+
253
+ # Medical disclaimer
254
  with gr.Row():
255
  gr.HTML("""
256
  <div class="warning-box">
257
  <h4>⚠️ Important Medical Disclaimer</h4>
258
  <p><strong>This is a research and educational tool for medical professionals, researchers, and students.</strong></p>
259
  <ul>
260
+ <li>🚫 <strong>NOT a medical device</strong> - Not for patient diagnosis or treatment</li>
261
+ <li>πŸ‘¨β€βš•οΈ <strong>Professional use only</strong> - Intended for clinicians and medical students</li>
262
+ <li>πŸ” <strong>Verify all outputs</strong> - Always confirm with qualified medical professionals</li>
263
+ <li>πŸ“š <strong>Educational purpose</strong> - For learning clinical reasoning patterns</li>
264
  </ul>
265
  </div>
266
  """)
267
+
268
  with gr.Row():
269
  with gr.Column(scale=4):
270
  chatbot = gr.Chatbot(
 
272
  show_copy_button=True,
273
  bubble_full_width=False,
274
  elem_classes=["medical-chatbot"],
275
+ avatar_images=(None, "🩺")
276
  )
277
+
278
  msg = gr.Textbox(
279
+ placeholder="Describe a clinical scenario or case for medical reasoning analysis...",
280
  lines=3,
281
+ max_lines=8,
282
  show_label=False,
283
  container=False
284
  )
285
+
286
+ with gr.Row():
287
+ submit_btn = gr.Button("πŸ” Analyze Case", variant="primary", size="sm")
288
+ clear_btn = gr.Button("πŸ—‘οΈ Clear", variant="secondary", size="sm")
289
+ retry_btn = gr.Button("πŸ”„ Retry", variant="secondary", size="sm")
290
+
291
  with gr.Column(scale=1, min_width=250):
292
  gr.Markdown("### βš™οΈ Model Parameters")
293
+
294
+ max_tokens = gr.Slider(
295
+ minimum=256,
296
+ maximum=2048,
297
+ value=1024,
298
+ step=64,
299
+ label="Max Tokens",
300
+ info="Maximum response length"
301
+ )
302
+
303
+ temperature = gr.Slider(
304
+ minimum=0.1,
305
+ maximum=1.0,
306
+ value=0.7,
307
+ step=0.05,
308
+ label="Temperature",
309
+ info="Reasoning creativity (0.7 recommended)"
310
+ )
311
+
312
+ top_p = gr.Slider(
313
+ minimum=0.8,
314
+ maximum=1.0,
315
+ value=0.95,
316
+ step=0.01,
317
+ label="Top-p",
318
+ info="Focus precision (0.95 recommended)"
319
+ )
320
+
321
+ gr.Markdown("""
322
+ ### 🎯 Usage Guidelines:
323
+
324
+ **Best for:**
325
+ - Clinical case analysis
326
+ - Differential diagnosis reasoning
327
+ - Medical education scenarios
328
+ - Professional consultation support
329
+
330
+ **Features:**
331
+ - Transparent `<think>` process
332
+ - Step-by-step clinical reasoning
333
+ - Evidence-based conclusions
334
+ - Professional medical language
335
+ """)
336
+
337
+ # Event handlers
338
+ def clear_chat():
339
+ return [], ""
340
+
341
+ def retry_last(history):
342
+ if history:
343
+ last_user_msg = history[-1][0]
344
+ return history[:-1], last_user_msg
345
+ return history, ""
346
+
347
+ # Button events
348
+ submit_btn.click(
349
+ respond,
350
+ inputs=[msg, chatbot, max_tokens, temperature, top_p],
351
+ outputs=[msg, chatbot]
352
+ )
353
+
354
+ msg.submit(
355
+ respond,
356
+ inputs=[msg, chatbot, max_tokens, temperature, top_p],
357
+ outputs=[msg, chatbot]
358
+ )
359
+
360
+ clear_btn.click(clear_chat, outputs=[chatbot, msg])
361
+ retry_btn.click(retry_last, inputs=[chatbot], outputs=[chatbot, msg])
362
+
363
+ # Medical case examples
364
  gr.Examples(
365
  examples=[
366
  "Patient: 72-year-old with history of hypertension presents with confusion, right-sided weakness, and slurred speech. What is the likely cause and immediate steps?",
367
  "Patient: 45-year-old with sudden onset severe headache described as 'the worst ever'. What should be ruled out and how?",
368
  "Patient: 60-year-old with long-standing diabetes has numbness and tingling in both feet. What is the most likely diagnosis and first-line management?",
369
+ "Patient: 30-year-old with polyuria, polydipsia, and weight loss. What investigation confirms the diagnosis?",
370
+ "Patient: 55-year-old with progressive shortness of breath, orthopnea, and ankle swelling. What condition and investigation are likely?",
371
+ "Patient: 25-year-old presents with high fever, sore throat, swollen neck, and drooling. What life-threatening condition must be excluded?"
372
  ],
373
  inputs=[msg],
374
+ label="πŸ“‹ Clinical Case Examples (Try these scenarios):"
375
  )
376
+
377
+ # Footer
378
  gr.HTML("""
379
  <div class="footer-text">
380
+ <p><strong>Model:</strong> yasserrmd/SinaReason-Magistral-2509 (24B parameters)</p>
381
+ <p><strong>Base:</strong> Magistral-Small-2509 | <strong>Inspired by:</strong> Ibn Sina (Avicenna)</p>
382
+ <p><strong>Dataset:</strong> FreedomIntelligence/medical-o1-reasoning-SFT</p>
383
+ <p>πŸš€ <strong>Optimized for:</strong> Hugging Face Zero GPU Spaces</p>
384
  </div>
385
  """)
386
 
387
+ # Launch configuration for HF Spaces
 
 
 
 
 
 
 
 
 
 
 
 
 
 
388
  if __name__ == "__main__":
389
+ demo.launch(
390
+ debug=True,
391
+ show_error=True
392
+ )