dyadd commited on
Commit
09354cb
·
verified ·
1 Parent(s): 62055c0

Upload folder using huggingface_hub

Browse files
nbs/01_clinical_tutor.ipynb CHANGED
@@ -145,8 +145,8 @@
145
  " self.learning_context = LearningContext(context_path)\n",
146
  " \n",
147
  " # Track current discussion\n",
148
- " self.current_discussion: List[Dict] = []\n",
149
- " \n",
150
  " logger.info(\"Clinical tutor initialized\")\n",
151
  "\n",
152
  " async def _get_completion(\n",
@@ -496,6 +496,7 @@
496
  "outputs": [],
497
  "source": [
498
  "#| hide\n",
 
499
  "class ClinicalTutor:\n",
500
  " \"\"\"\n",
501
  " Adaptive clinical teaching module that provides context-aware feedback.\n",
 
145
  " self.learning_context = LearningContext(context_path)\n",
146
  " \n",
147
  " # Track current discussion\n",
148
+ " self.current_discussion: List[Dict[str, str]] = []\n",
149
+ " \n",
150
  " logger.info(\"Clinical tutor initialized\")\n",
151
  "\n",
152
  " async def _get_completion(\n",
 
496
  "outputs": [],
497
  "source": [
498
  "#| hide\n",
499
+ "# old\n",
500
  "class ClinicalTutor:\n",
501
  " \"\"\"\n",
502
  " Adaptive clinical teaching module that provides context-aware feedback.\n",
nbs/02_learning_interface.ipynb CHANGED
@@ -92,61 +92,79 @@
92
  "def create_css() -> str:\n",
93
  " \"\"\"Create custom CSS for interface styling.\"\"\"\n",
94
  " return \"\"\"\n",
 
95
  " .gradio-container {\n",
96
  " background-color: #0f172a !important;\n",
 
 
97
  " }\n",
98
  " \n",
99
- " .discussion-status {\n",
100
- " color: #94a3b8;\n",
101
- " font-size: 0.9em;\n",
102
- " margin-bottom: 1rem;\n",
103
- " }\n",
104
- " \n",
105
  " .chat-window {\n",
106
  " background-color: #1e293b !important;\n",
107
  " border: 1px solid #334155 !important;\n",
108
  " border-radius: 0.5rem !important;\n",
 
 
109
  " }\n",
110
  " \n",
111
  " .chat-message {\n",
112
  " background-color: #1e293b !important;\n",
113
  " border: 1px solid #334155 !important;\n",
114
  " border-radius: 0.5rem !important;\n",
115
- " padding: 1rem !important;\n",
116
  " margin: 0.5rem 0 !important;\n",
 
117
  " }\n",
118
  " \n",
119
  " .user-message {\n",
120
  " background-color: #2563eb !important;\n",
121
  " }\n",
122
  " \n",
 
123
  " textarea, select {\n",
124
  " background-color: #1e293b !important;\n",
125
  " border: 1px solid #334155 !important;\n",
126
  " color: #f1f5f9 !important;\n",
 
 
127
  " }\n",
128
  " \n",
129
  " button {\n",
130
  " background-color: #2563eb !important;\n",
131
  " color: white !important;\n",
 
 
 
132
  " }\n",
133
  " \n",
134
  " button:hover {\n",
135
  " background-color: #1d4ed8 !important;\n",
136
  " }\n",
137
  " \n",
138
- " .tab-nav {\n",
139
- " border-bottom: 1px solid #334155 !important;\n",
140
- " }\n",
141
- " \n",
142
- " .tab-nav button {\n",
143
- " background-color: transparent !important;\n",
144
- " color: #94a3b8 !important;\n",
145
- " }\n",
146
- " \n",
147
- " .tab-nav button.selected {\n",
148
- " color: #f1f5f9 !important;\n",
149
- " border-bottom: 2px solid #2563eb !important;\n",
 
 
 
 
 
 
 
 
 
 
 
150
  " }\n",
151
  " \"\"\""
152
  ]
@@ -209,7 +227,17 @@
209
  " history: List[Dict[str, str]],\n",
210
  " state: Dict[str, Any]\n",
211
  " ) -> AsyncGenerator[Tuple[List[Dict[str, str]], str, Dict[str, Any]], None]:\n",
212
- " \"\"\"Process chat messages with streaming and proper message format.\"\"\"\n",
 
 
 
 
 
 
 
 
 
 
213
  " try:\n",
214
  " if not message.strip():\n",
215
  " yield history, \"\", state\n",
@@ -219,6 +247,7 @@
219
  " if not state.get(\"discussion_active\"):\n",
220
  " state[\"discussion_active\"] = True\n",
221
  " state[\"discussion_start\"] = datetime.now().isoformat()\n",
 
222
  " \n",
223
  " # Initialize history if needed\n",
224
  " if history is None:\n",
@@ -239,14 +268,35 @@
239
  " # Update display\n",
240
  " yield history, \"\", state\n",
241
  " \n",
 
 
 
 
 
 
 
 
 
 
 
 
242
  " # Process response with streaming\n",
243
  " current_response = \"\"\n",
244
- " async for token in self.tutor.discuss_case(message):\n",
245
  " current_response += token\n",
246
  " history[-1][\"content\"] = current_response\n",
247
  " yield history, \"\", state\n",
248
  " \n",
 
249
  " state[\"last_message\"] = datetime.now().isoformat()\n",
 
 
 
 
 
 
 
 
250
  " yield history, \"\", state\n",
251
  " \n",
252
  " except Exception as e:\n",
@@ -315,11 +365,12 @@
315
  " return self._update_displays(state)\n",
316
  "\n",
317
  " def end_discussion(self, state: Dict[str, Any]) -> List:\n",
318
- " \"\"\"End current discussion.\"\"\"\n",
319
  " self.tutor.end_discussion()\n",
320
  " state[\"discussion_active\"] = False\n",
321
  " state[\"discussion_start\"] = None\n",
322
  " state[\"last_message\"] = None\n",
 
323
  " return self._update_displays(state)\n",
324
  "\n",
325
  " def _update_displays(self, state: Dict[str, Any]) -> List:\n",
@@ -489,6 +540,7 @@
489
  "\n",
490
  " def clear_discussion() -> Tuple[List, str, Dict]:\n",
491
  " \"\"\"Clear chat history.\"\"\"\n",
 
492
  " return [], \"\", {\n",
493
  " \"discussion_active\": False,\n",
494
  " \"suggested_goals\": [],\n",
 
92
  "def create_css() -> str:\n",
93
  " \"\"\"Create custom CSS for interface styling.\"\"\"\n",
94
  " return \"\"\"\n",
95
+ " /* Base styles */\n",
96
  " .gradio-container {\n",
97
  " background-color: #0f172a !important;\n",
98
+ " max-width: 100% !important;\n",
99
+ " padding: 1rem !important;\n",
100
  " }\n",
101
  " \n",
102
+ " /* Mobile-first approach */\n",
 
 
 
 
 
103
  " .chat-window {\n",
104
  " background-color: #1e293b !important;\n",
105
  " border: 1px solid #334155 !important;\n",
106
  " border-radius: 0.5rem !important;\n",
107
+ " height: calc(100vh - 300px) !important; /* Responsive height */\n",
108
+ " min-height: 300px !important;\n",
109
  " }\n",
110
  " \n",
111
  " .chat-message {\n",
112
  " background-color: #1e293b !important;\n",
113
  " border: 1px solid #334155 !important;\n",
114
  " border-radius: 0.5rem !important;\n",
115
+ " padding: 0.75rem !important;\n",
116
  " margin: 0.5rem 0 !important;\n",
117
+ " font-size: 0.95rem !important;\n",
118
  " }\n",
119
  " \n",
120
  " .user-message {\n",
121
  " background-color: #2563eb !important;\n",
122
  " }\n",
123
  " \n",
124
+ " /* Form elements */\n",
125
  " textarea, select {\n",
126
  " background-color: #1e293b !important;\n",
127
  " border: 1px solid #334155 !important;\n",
128
  " color: #f1f5f9 !important;\n",
129
+ " font-size: 1rem !important;\n",
130
+ " padding: 0.75rem !important;\n",
131
  " }\n",
132
  " \n",
133
  " button {\n",
134
  " background-color: #2563eb !important;\n",
135
  " color: white !important;\n",
136
+ " padding: 0.75rem 1rem !important;\n",
137
+ " font-size: 1rem !important;\n",
138
+ " min-height: 44px !important; /* Touch target size */\n",
139
  " }\n",
140
  " \n",
141
  " button:hover {\n",
142
  " background-color: #1d4ed8 !important;\n",
143
  " }\n",
144
  " \n",
145
+ " /* Mobile optimizations */\n",
146
+ " @media (max-width: 768px) {\n",
147
+ " .gradio-container {\n",
148
+ " padding: 0.5rem !important;\n",
149
+ " }\n",
150
+ " \n",
151
+ " .chat-window {\n",
152
+ " height: calc(100vh - 250px) !important;\n",
153
+ " }\n",
154
+ " \n",
155
+ " .chat-message {\n",
156
+ " padding: 0.5rem !important;\n",
157
+ " font-size: 0.9rem !important;\n",
158
+ " }\n",
159
+ " \n",
160
+ " textarea {\n",
161
+ " min-height: 100px !important;\n",
162
+ " }\n",
163
+ " \n",
164
+ " button {\n",
165
+ " width: 100% !important;\n",
166
+ " margin: 0.25rem 0 !important;\n",
167
+ " }\n",
168
  " }\n",
169
  " \"\"\""
170
  ]
 
227
  " history: List[Dict[str, str]],\n",
228
  " state: Dict[str, Any]\n",
229
  " ) -> AsyncGenerator[Tuple[List[Dict[str, str]], str, Dict[str, Any]], None]:\n",
230
+ " \"\"\"\n",
231
+ " Process chat messages with streaming and proper history management.\n",
232
+ " \n",
233
+ " Args:\n",
234
+ " message: User input message\n",
235
+ " history: Chat history list of message dictionaries\n",
236
+ " state: Current interface state\n",
237
+ " \n",
238
+ " Yields:\n",
239
+ " tuple: (updated history, cleared message input, updated state)\n",
240
+ " \"\"\"\n",
241
  " try:\n",
242
  " if not message.strip():\n",
243
  " yield history, \"\", state\n",
 
247
  " if not state.get(\"discussion_active\"):\n",
248
  " state[\"discussion_active\"] = True\n",
249
  " state[\"discussion_start\"] = datetime.now().isoformat()\n",
250
+ " self.tutor.current_discussion = [] # Reset tutor's discussion history\n",
251
  " \n",
252
  " # Initialize history if needed\n",
253
  " if history is None:\n",
 
268
  " # Update display\n",
269
  " yield history, \"\", state\n",
270
  " \n",
271
+ " # Build messages array for LLM including full history\n",
272
+ " messages = [{\n",
273
+ " \"role\": \"system\",\n",
274
+ " \"content\": self.tutor._build_discussion_prompt()\n",
275
+ " }]\n",
276
+ " \n",
277
+ " # Add previous messages from tutor's discussion history\n",
278
+ " messages.extend(self.tutor.current_discussion)\n",
279
+ " \n",
280
+ " # Add current message\n",
281
+ " messages.append({\"role\": \"user\", \"content\": message})\n",
282
+ " \n",
283
  " # Process response with streaming\n",
284
  " current_response = \"\"\n",
285
+ " async for token in self.tutor._get_completion_stream(messages):\n",
286
  " current_response += token\n",
287
  " history[-1][\"content\"] = current_response\n",
288
  " yield history, \"\", state\n",
289
  " \n",
290
+ " # Update state and discussion history\n",
291
  " state[\"last_message\"] = datetime.now().isoformat()\n",
292
+ " \n",
293
+ " # Update tutor's discussion history\n",
294
+ " self.tutor.current_discussion = history[:-1] # Don't include empty assistant message\n",
295
+ " self.tutor.current_discussion.append({\n",
296
+ " \"role\": \"assistant\",\n",
297
+ " \"content\": current_response\n",
298
+ " })\n",
299
+ " \n",
300
  " yield history, \"\", state\n",
301
  " \n",
302
  " except Exception as e:\n",
 
365
  " return self._update_displays(state)\n",
366
  "\n",
367
  " def end_discussion(self, state: Dict[str, Any]) -> List:\n",
368
+ " \"\"\"End current discussion and analyze results.\"\"\"\n",
369
  " self.tutor.end_discussion()\n",
370
  " state[\"discussion_active\"] = False\n",
371
  " state[\"discussion_start\"] = None\n",
372
  " state[\"last_message\"] = None\n",
373
+ " self.tutor.current_discussion = [] # Clear discussion history\n",
374
  " return self._update_displays(state)\n",
375
  "\n",
376
  " def _update_displays(self, state: Dict[str, Any]) -> List:\n",
 
540
  "\n",
541
  " def clear_discussion() -> Tuple[List, str, Dict]:\n",
542
  " \"\"\"Clear chat history.\"\"\"\n",
543
+ " self.tutor.current_discussion = [] # Clear tutor's discussion history\n",
544
  " return [], \"\", {\n",
545
  " \"discussion_active\": False,\n",
546
  " \"suggested_goals\": [],\n",
wardbuddy/clinical_tutor.py CHANGED
@@ -65,8 +65,8 @@ class ClinicalTutor:
65
  self.learning_context = LearningContext(context_path)
66
 
67
  # Track current discussion
68
- self.current_discussion: List[Dict] = []
69
-
70
  logger.info("Clinical tutor initialized")
71
 
72
  async def _get_completion(
 
65
  self.learning_context = LearningContext(context_path)
66
 
67
  # Track current discussion
68
+ self.current_discussion: List[Dict[str, str]] = []
69
+
70
  logger.info("Clinical tutor initialized")
71
 
72
  async def _get_completion(
wardbuddy/learning_interface.py CHANGED
@@ -23,61 +23,79 @@ logger = setup_logger(__name__)
23
  def create_css() -> str:
24
  """Create custom CSS for interface styling."""
25
  return """
 
26
  .gradio-container {
27
  background-color: #0f172a !important;
 
 
28
  }
29
 
30
- .discussion-status {
31
- color: #94a3b8;
32
- font-size: 0.9em;
33
- margin-bottom: 1rem;
34
- }
35
-
36
  .chat-window {
37
  background-color: #1e293b !important;
38
  border: 1px solid #334155 !important;
39
  border-radius: 0.5rem !important;
 
 
40
  }
41
 
42
  .chat-message {
43
  background-color: #1e293b !important;
44
  border: 1px solid #334155 !important;
45
  border-radius: 0.5rem !important;
46
- padding: 1rem !important;
47
  margin: 0.5rem 0 !important;
 
48
  }
49
 
50
  .user-message {
51
  background-color: #2563eb !important;
52
  }
53
 
 
54
  textarea, select {
55
  background-color: #1e293b !important;
56
  border: 1px solid #334155 !important;
57
  color: #f1f5f9 !important;
 
 
58
  }
59
 
60
  button {
61
  background-color: #2563eb !important;
62
  color: white !important;
 
 
 
63
  }
64
 
65
  button:hover {
66
  background-color: #1d4ed8 !important;
67
  }
68
 
69
- .tab-nav {
70
- border-bottom: 1px solid #334155 !important;
71
- }
72
-
73
- .tab-nav button {
74
- background-color: transparent !important;
75
- color: #94a3b8 !important;
76
- }
77
-
78
- .tab-nav button.selected {
79
- color: #f1f5f9 !important;
80
- border-bottom: 2px solid #2563eb !important;
 
 
 
 
 
 
 
 
 
 
 
81
  }
82
  """
83
 
@@ -120,7 +138,17 @@ class LearningInterface:
120
  history: List[Dict[str, str]],
121
  state: Dict[str, Any]
122
  ) -> AsyncGenerator[Tuple[List[Dict[str, str]], str, Dict[str, Any]], None]:
123
- """Process chat messages with streaming and proper message format."""
 
 
 
 
 
 
 
 
 
 
124
  try:
125
  if not message.strip():
126
  yield history, "", state
@@ -130,6 +158,7 @@ class LearningInterface:
130
  if not state.get("discussion_active"):
131
  state["discussion_active"] = True
132
  state["discussion_start"] = datetime.now().isoformat()
 
133
 
134
  # Initialize history if needed
135
  if history is None:
@@ -150,14 +179,35 @@ class LearningInterface:
150
  # Update display
151
  yield history, "", state
152
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  # Process response with streaming
154
  current_response = ""
155
- async for token in self.tutor.discuss_case(message):
156
  current_response += token
157
  history[-1]["content"] = current_response
158
  yield history, "", state
159
 
 
160
  state["last_message"] = datetime.now().isoformat()
 
 
 
 
 
 
 
 
161
  yield history, "", state
162
 
163
  except Exception as e:
@@ -226,11 +276,12 @@ class LearningInterface:
226
  return self._update_displays(state)
227
 
228
  def end_discussion(self, state: Dict[str, Any]) -> List:
229
- """End current discussion."""
230
  self.tutor.end_discussion()
231
  state["discussion_active"] = False
232
  state["discussion_start"] = None
233
  state["last_message"] = None
 
234
  return self._update_displays(state)
235
 
236
  def _update_displays(self, state: Dict[str, Any]) -> List:
@@ -400,6 +451,7 @@ class LearningInterface:
400
 
401
  def clear_discussion() -> Tuple[List, str, Dict]:
402
  """Clear chat history."""
 
403
  return [], "", {
404
  "discussion_active": False,
405
  "suggested_goals": [],
 
23
  def create_css() -> str:
24
  """Create custom CSS for interface styling."""
25
  return """
26
+ /* Base styles */
27
  .gradio-container {
28
  background-color: #0f172a !important;
29
+ max-width: 100% !important;
30
+ padding: 1rem !important;
31
  }
32
 
33
+ /* Mobile-first approach */
 
 
 
 
 
34
  .chat-window {
35
  background-color: #1e293b !important;
36
  border: 1px solid #334155 !important;
37
  border-radius: 0.5rem !important;
38
+ height: calc(100vh - 300px) !important; /* Responsive height */
39
+ min-height: 300px !important;
40
  }
41
 
42
  .chat-message {
43
  background-color: #1e293b !important;
44
  border: 1px solid #334155 !important;
45
  border-radius: 0.5rem !important;
46
+ padding: 0.75rem !important;
47
  margin: 0.5rem 0 !important;
48
+ font-size: 0.95rem !important;
49
  }
50
 
51
  .user-message {
52
  background-color: #2563eb !important;
53
  }
54
 
55
+ /* Form elements */
56
  textarea, select {
57
  background-color: #1e293b !important;
58
  border: 1px solid #334155 !important;
59
  color: #f1f5f9 !important;
60
+ font-size: 1rem !important;
61
+ padding: 0.75rem !important;
62
  }
63
 
64
  button {
65
  background-color: #2563eb !important;
66
  color: white !important;
67
+ padding: 0.75rem 1rem !important;
68
+ font-size: 1rem !important;
69
+ min-height: 44px !important; /* Touch target size */
70
  }
71
 
72
  button:hover {
73
  background-color: #1d4ed8 !important;
74
  }
75
 
76
+ /* Mobile optimizations */
77
+ @media (max-width: 768px) {
78
+ .gradio-container {
79
+ padding: 0.5rem !important;
80
+ }
81
+
82
+ .chat-window {
83
+ height: calc(100vh - 250px) !important;
84
+ }
85
+
86
+ .chat-message {
87
+ padding: 0.5rem !important;
88
+ font-size: 0.9rem !important;
89
+ }
90
+
91
+ textarea {
92
+ min-height: 100px !important;
93
+ }
94
+
95
+ button {
96
+ width: 100% !important;
97
+ margin: 0.25rem 0 !important;
98
+ }
99
  }
100
  """
101
 
 
138
  history: List[Dict[str, str]],
139
  state: Dict[str, Any]
140
  ) -> AsyncGenerator[Tuple[List[Dict[str, str]], str, Dict[str, Any]], None]:
141
+ """
142
+ Process chat messages with streaming and proper history management.
143
+
144
+ Args:
145
+ message: User input message
146
+ history: Chat history list of message dictionaries
147
+ state: Current interface state
148
+
149
+ Yields:
150
+ tuple: (updated history, cleared message input, updated state)
151
+ """
152
  try:
153
  if not message.strip():
154
  yield history, "", state
 
158
  if not state.get("discussion_active"):
159
  state["discussion_active"] = True
160
  state["discussion_start"] = datetime.now().isoformat()
161
+ self.tutor.current_discussion = [] # Reset tutor's discussion history
162
 
163
  # Initialize history if needed
164
  if history is None:
 
179
  # Update display
180
  yield history, "", state
181
 
182
+ # Build messages array for LLM including full history
183
+ messages = [{
184
+ "role": "system",
185
+ "content": self.tutor._build_discussion_prompt()
186
+ }]
187
+
188
+ # Add previous messages from tutor's discussion history
189
+ messages.extend(self.tutor.current_discussion)
190
+
191
+ # Add current message
192
+ messages.append({"role": "user", "content": message})
193
+
194
  # Process response with streaming
195
  current_response = ""
196
+ async for token in self.tutor._get_completion_stream(messages):
197
  current_response += token
198
  history[-1]["content"] = current_response
199
  yield history, "", state
200
 
201
+ # Update state and discussion history
202
  state["last_message"] = datetime.now().isoformat()
203
+
204
+ # Update tutor's discussion history
205
+ self.tutor.current_discussion = history[:-1] # Don't include empty assistant message
206
+ self.tutor.current_discussion.append({
207
+ "role": "assistant",
208
+ "content": current_response
209
+ })
210
+
211
  yield history, "", state
212
 
213
  except Exception as e:
 
276
  return self._update_displays(state)
277
 
278
  def end_discussion(self, state: Dict[str, Any]) -> List:
279
+ """End current discussion and analyze results."""
280
  self.tutor.end_discussion()
281
  state["discussion_active"] = False
282
  state["discussion_start"] = None
283
  state["last_message"] = None
284
+ self.tutor.current_discussion = [] # Clear discussion history
285
  return self._update_displays(state)
286
 
287
  def _update_displays(self, state: Dict[str, Any]) -> List:
 
451
 
452
  def clear_discussion() -> Tuple[List, str, Dict]:
453
  """Clear chat history."""
454
+ self.tutor.current_discussion = [] # Clear tutor's discussion history
455
  return [], "", {
456
  "discussion_active": False,
457
  "suggested_goals": [],