File size: 55,005 Bytes
3e595a5
 
 
 
c2d68af
3e595a5
 
 
 
 
 
 
 
 
 
 
95243ee
3e595a5
 
7828fde
 
3e595a5
 
 
 
 
 
 
 
 
95243ee
 
 
3e595a5
 
 
 
c2d68af
3e595a5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c2d68af
3e595a5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c2d68af
3e595a5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95243ee
62f919c
c2d68af
 
 
 
 
 
 
 
 
 
 
 
95243ee
 
 
c2d68af
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3e595a5
 
 
 
 
 
 
 
95243ee
 
 
 
 
3e595a5
95243ee
 
3e595a5
 
 
 
 
 
95243ee
3e595a5
 
 
 
 
 
 
 
95243ee
3e595a5
95243ee
 
c2d68af
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3e595a5
 
c2d68af
3e595a5
 
 
 
 
c2d68af
3e595a5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62f919c
3e595a5
 
 
 
 
 
 
 
 
 
 
 
 
62f919c
3e595a5
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-29T20:09:11.440091Z",
     "iopub.status.busy": "2025-01-29T20:09:11.439766Z",
     "iopub.status.idle": "2025-01-29T20:09:11.751153Z",
     "shell.execute_reply": "2025-01-29T20:09:11.750263Z",
     "shell.execute_reply.started": "2025-01-29T20:09:11.440060Z"
    },
    "id": "xaiioUQni_ga",
    "trusted": true
   },
   "outputs": [],
   "source": [
    "from modules.data_class import DataState\n",
    "from modules.tools import data_node\n",
    "from modules.nodes import chatbot_with_tools, human_node, maybe_exit_human_node, maybe_route_to_tools\n",
    "\n",
    "from langgraph.graph import StateGraph, START, END\n",
    "\n",
    "from IPython.display import Image, display\n",
    "from pprint import pprint\n",
    "from typing import Literal\n",
    "\n",
    "from langgraph.prebuilt import ToolNode\n",
    "\n",
    "from collections.abc import Iterable\n",
    "from IPython.display import display, clear_output\n",
    "import sys"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-29T20:09:11.906458Z",
     "iopub.status.busy": "2025-01-29T20:09:11.905241Z",
     "iopub.status.idle": "2025-01-29T20:09:11.994921Z",
     "shell.execute_reply": "2025-01-29T20:09:11.993761Z",
     "shell.execute_reply.started": "2025-01-29T20:09:11.906419Z"
    },
    "id": "9rqkQzlZxrzp",
    "trusted": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "graph_builder = StateGraph(DataState)\n",
    "\n",
    "# Nodes\n",
    "graph_builder.add_node(\"chatbot_healthassistant\", chatbot_with_tools)\n",
    "graph_builder.add_node(\"patient\", human_node)\n",
    "graph_builder.add_node(\"documenting\", data_node)\n",
    "\n",
    "# Chatbot -> {ordering, tools, human, END}\n",
    "graph_builder.add_conditional_edges(\"chatbot_healthassistant\", maybe_route_to_tools)\n",
    "# Human -> {chatbot, END}\n",
    "graph_builder.add_conditional_edges(\"patient\", maybe_exit_human_node)\n",
    "# TestCase_Paintrek\n",
    "# Tools (both kinds) always route back to chat afterwards.\n",
    "graph_builder.add_edge(\"documenting\", \"chatbot_healthassistant\")\n",
    "\n",
    "graph_builder.add_edge(START, \"chatbot_healthassistant\")\n",
    "graph_with_order_tools = graph_builder.compile()\n",
    "\n",
    "Image(graph_with_order_tools.get_graph().draw_mermaid_png())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-29T20:09:38.185616Z",
     "iopub.status.busy": "2025-01-29T20:09:38.185131Z",
     "iopub.status.idle": "2025-01-29T20:10:08.474591Z",
     "shell.execute_reply": "2025-01-29T20:10:08.472926Z",
     "shell.execute_reply.started": "2025-01-29T20:09:38.185577Z"
    },
    "id": "NCRSgaBUfIHF",
    "trusted": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Executing the chatbot graph...\n",
      "Model: Welcome to the Paintrek world. I am a health assistant, an interactive clinical recording system. I will ask you questions about your pain and related symptoms and record your responses.  I will then store this information securely. At any time, you can type `q` to quit.\n",
      "Model: First, I need to collect some basic information for identification.  Could you please provide your full name, date of birth, gender, and contact number?  Also, please provide the name and contact information for an emergency contact.\n",
      "Model: Thank you. Now, can you describe your main symptom and how long you've been experiencing it?\n",
      "Model: Could you tell me more about the headache? Where is the pain located?  Is it on the left, right, or both sides? On a scale of 0 to 10, with 0 being no pain and 10 being the worst pain imaginable, how intense is the pain?  What are the characteristics of the pain (e.g., sharp, dull, throbbing)? When did it start? Does the pain radiate to any other areas? What, if anything, triggers the headache? Are there any other symptoms associated with the headache (e.g., nausea, vomiting, visual disturbances)?\n",
      "Model: Let's move on to your medical history. Do you have any existing medical conditions?  When were they first diagnosed? Have you ever had any surgeries? If so, when?  Are you currently taking any medications? Do you have any allergies?\n",
      "Model: Now, let's discuss your family medical history. Are there any significant medical conditions that run in your family?\n",
      "Model: To get a more complete picture, could you share some information about your lifestyle? What is your occupation? Do you smoke, drink alcohol, or use drugs?  Could you describe your living situation and support system?\n",
      "Model: We're almost done.  Let's do a quick system review.  Have you experienced any recent weight changes? Have you had any fever, chills, or night sweats? How is your sleep?  How are your gastrointestinal and urinary functions?\n",
      "Model: Finally, let's talk about your pain management. What pain medications are you currently using? Have you consulted any specialists for your pain? Have you tried any alternative therapies? How effective has your pain management been so far?\n",
      "Model: To conclude, could you please describe how this headache impacts your quality of life, any limitations on your activities, and your current mood?  Also, what are your treatment goals and expectations? Are there any alternative treatments you'd consider?\n",
      "Model: Before we finalize this record, could you please confirm that all the information we've gathered is accurate?\n",
      "Saving the data!\n",
      "{'ID': {'name': 'Frank', 'DOB': '1986-01-01', 'gender': 'male', 'contact': '12345', 'emergency_contact': 'Zoe, 67890'}, 'symptom': {'main_symptom': 'Headache', 'symptom_length': '2 days'}, 'pain': {'pain_location': 'Right head', 'pain_side': 'Right', 'pain_intensity': 2.0, 'pain_description': 'Sharp', 'start_time': '2 days ago', 'radiation': False, 'triggers': 'Cold', 'symptom': 'No other symptoms'}, 'medical_hist': {'medical_condition': 'Sinus', 'first_time': '2001-01-01', 'surgery_history': 'None', 'medication': 'Ibprofin', 'allergy': 'None'}, 'family_hist': {'family_history': 'Mother had lung cancer at 45'}, 'social_hist': {'occupation': 'Data scientist', 'smoke': False, 'alcohol': False, 'drug': False, 'support_system': 'Unknown', 'living_condition': 'Unknown'}, 'review_system': {'weight_change': 'None', 'fever': False, 'chill': False, 'night_sweats': False, 'sleep': 'Well', 'gastrointestinal': 'Normal', 'urinary': 'Normal'}, 'pain_manage': {'pain_medication': 'No', 'specialist': False, 'other_therapy': 'No', 'effectiveness': 'Unknown'}, 'functional': {'life_quality': 'Good', 'limit_activity': 'None', 'mood': 'Okay'}, 'plan': {'goal': 'Fix headache', 'expectation': 'Fix headache', 'alternative_treatment': 'None'}}\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'messages': [AIMessage(content='Welcome to the Paintrek world. I am a health assistant, an interactive clinical recording system. I will ask you questions about your pain and related symptoms and record your responses.  I will then store this information securely. At any time, you can type `q` to quit.', additional_kwargs={}, response_metadata={}, id='9d9f4dc0-206c-474f-8322-458b7aeec747'),\n",
       "  HumanMessage(content=\"Let's start\", additional_kwargs={}, response_metadata={}, id='c5cbbc6e-1cd8-4924-84ad-19636037a42b'),\n",
       "  AIMessage(content='First, I need to collect some basic information for identification.  Could you please provide your full name, date of birth, gender, and contact number?  Also, please provide the name and contact information for an emergency contact.', additional_kwargs={}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': []}, id='run-625a1eff-7e43-46a9-b824-0ca7de7959a5-0', usage_metadata={'input_tokens': 1526, 'output_tokens': 47, 'total_tokens': 1573, 'input_token_details': {'cache_read': 0}}),\n",
       "  HumanMessage(content='I am Frank, DOB 1986-01-01, male, phone number is 12345, emergency name is Zoe, number is 67890.', additional_kwargs={}, response_metadata={}, id='efaee7ea-596d-4152-8872-5eb8633f76a5'),\n",
       "  AIMessage(content='', additional_kwargs={'function_call': {'name': 'patient_id', 'arguments': '{\"contact\": \"12345\", \"DOB\": \"1986-01-01\", \"gender\": \"male\", \"emergency_contact\": \"Zoe, 67890\", \"name\": \"Frank\"}'}}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': []}, id='run-3c5557d4-313e-482e-8901-d7ecd490a9f0-0', tool_calls=[{'name': 'patient_id', 'args': {'contact': '12345', 'DOB': '1986-01-01', 'gender': 'male', 'emergency_contact': 'Zoe, 67890', 'name': 'Frank'}, 'id': 'bb2eb4b7-ff42-4584-aa0b-f6bca017bd51', 'type': 'tool_call'}], usage_metadata={'input_tokens': 1615, 'output_tokens': 35, 'total_tokens': 1650, 'input_token_details': {'cache_read': 0}}),\n",
       "  ToolMessage(content='ID\\nsymptom\\npain\\nmedical_hist\\nfamily_hist\\nsocial_hist\\nreview_system\\npain_manage\\nfunctional\\nplan', name='patient_id', id='25805edd-4bea-4d24-864f-e23cb87306cf', tool_call_id='bb2eb4b7-ff42-4584-aa0b-f6bca017bd51'),\n",
       "  AIMessage(content=\"Thank you. Now, can you describe your main symptom and how long you've been experiencing it?\", additional_kwargs={}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': []}, id='run-f7885dbe-c5e7-48c3-9e85-e111c07625dc-0', usage_metadata={'input_tokens': 1684, 'output_tokens': 22, 'total_tokens': 1706, 'input_token_details': {'cache_read': 0}}),\n",
       "  HumanMessage(content='I had a headache, and it started two days ago.', additional_kwargs={}, response_metadata={}, id='aa33a92d-255f-483a-93e1-ef552dc5b109'),\n",
       "  AIMessage(content='', additional_kwargs={'function_call': {'name': 'symptom', 'arguments': '{\"symptom_length\": \"2 days\", \"main_symptom\": \"Headache\"}'}}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': []}, id='run-e2451cbe-be34-4d38-b8d4-5fd8797ee910-0', tool_calls=[{'name': 'symptom', 'args': {'symptom_length': '2 days', 'main_symptom': 'Headache'}, 'id': 'bfdd9836-6f09-4d36-8308-c5571241e899', 'type': 'tool_call'}], usage_metadata={'input_tokens': 1717, 'output_tokens': 14, 'total_tokens': 1731, 'input_token_details': {'cache_read': 0}}),\n",
       "  ToolMessage(content='ID\\nsymptom\\npain\\nmedical_hist\\nfamily_hist\\nsocial_hist\\nreview_system\\npain_manage\\nfunctional\\nplan', name='symptom', id='ed5418d4-6e70-46fd-ad59-3eb26e72d84d', tool_call_id='bfdd9836-6f09-4d36-8308-c5571241e899'),\n",
       "  AIMessage(content='Could you tell me more about the headache? Where is the pain located?  Is it on the left, right, or both sides? On a scale of 0 to 10, with 0 being no pain and 10 being the worst pain imaginable, how intense is the pain?  What are the characteristics of the pain (e.g., sharp, dull, throbbing)? When did it start? Does the pain radiate to any other areas? What, if anything, triggers the headache? Are there any other symptoms associated with the headache (e.g., nausea, vomiting, visual disturbances)?', additional_kwargs={}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': []}, id='run-2fe7272d-2b5a-4fa0-81e2-837f3fcd95d0-0', usage_metadata={'input_tokens': 1764, 'output_tokens': 125, 'total_tokens': 1889, 'input_token_details': {'cache_read': 0}}),\n",
       "  HumanMessage(content='My pain is located on the right head, and the scale is 2, the pain is sharp, the pain started 2 days ago, and the pain is not radiating. Cold will trigger the pain, and no other symptoms. ', additional_kwargs={}, response_metadata={}, id='2e0970d1-76f8-46e1-b9e5-f6c6da1f2a65'),\n",
       "  AIMessage(content='', additional_kwargs={'function_call': {'name': 'pain', 'arguments': '{\"pain_location\": \"Right head\", \"radiation\": false, \"start_time\": \"2 days ago\", \"symptom\": \"No other symptoms\", \"pain_side\": \"Right\", \"pain_intensity\": 2.0, \"pain_description\": \"Sharp\", \"triggers\": \"Cold\"}'}}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': []}, id='run-ccea4875-140d-4d67-8257-972f59fef2d6-0', tool_calls=[{'name': 'pain', 'args': {'pain_location': 'Right head', 'radiation': False, 'start_time': '2 days ago', 'symptom': 'No other symptoms', 'pain_side': 'Right', 'pain_intensity': 2.0, 'pain_description': 'Sharp', 'triggers': 'Cold'}, 'id': 'c00f1773-566e-4caa-b920-6316efd45ef6', 'type': 'tool_call'}], usage_metadata={'input_tokens': 1936, 'output_tokens': 31, 'total_tokens': 1967, 'input_token_details': {'cache_read': 0}}),\n",
       "  ToolMessage(content='ID\\nsymptom\\npain\\nmedical_hist\\nfamily_hist\\nsocial_hist\\nreview_system\\npain_manage\\nfunctional\\nplan', name='pain', id='1f2dbda4-bcad-41a6-b415-d034211f2836', tool_call_id='c00f1773-566e-4caa-b920-6316efd45ef6'),\n",
       "  AIMessage(content=\"Let's move on to your medical history. Do you have any existing medical conditions?  When were they first diagnosed? Have you ever had any surgeries? If so, when?  Are you currently taking any medications? Do you have any allergies?\", additional_kwargs={}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': []}, id='run-1584fcb0-bea9-47b1-88ec-7a2acacd22e0-0', usage_metadata={'input_tokens': 1999, 'output_tokens': 52, 'total_tokens': 2051, 'input_token_details': {'cache_read': 0}}),\n",
       "  HumanMessage(content='I had sinus, diagnosed in 2001-01-01, I did not have any surgery. I am taking ibprofin, no allergies.', additional_kwargs={}, response_metadata={}, id='f59997a9-b21b-4506-9a76-bd11f8d45570'),\n",
       "  AIMessage(content='', additional_kwargs={'function_call': {'name': 'medical_hist', 'arguments': '{\"medical_condition\": \"Sinus\", \"first_time\": \"2001-01-01\", \"allergy\": \"None\", \"surgery_history\": \"None\", \"medication\": \"Ibprofin\"}'}}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': []}, id='run-b577e889-c382-4b92-bb64-436a179d42f3-0', tool_calls=[{'name': 'medical_hist', 'args': {'medical_condition': 'Sinus', 'first_time': '2001-01-01', 'allergy': 'None', 'surgery_history': 'None', 'medication': 'Ibprofin'}, 'id': '909c6e8c-1f8b-4dfa-8419-444ef8e1c3ba', 'type': 'tool_call'}], usage_metadata={'input_tokens': 2085, 'output_tokens': 32, 'total_tokens': 2117, 'input_token_details': {'cache_read': 0}}),\n",
       "  ToolMessage(content='ID\\nsymptom\\npain\\nmedical_hist\\nfamily_hist\\nsocial_hist\\nreview_system\\npain_manage\\nfunctional\\nplan', name='medical_hist', id='d3a4d6fe-c438-491d-9491-ba863db704db', tool_call_id='909c6e8c-1f8b-4dfa-8419-444ef8e1c3ba'),\n",
       "  AIMessage(content=\"Now, let's discuss your family medical history. Are there any significant medical conditions that run in your family?\", additional_kwargs={}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': []}, id='run-a39755e6-5a91-4af1-8519-bf5505f87420-0', usage_metadata={'input_tokens': 2151, 'output_tokens': 24, 'total_tokens': 2175, 'input_token_details': {'cache_read': 0}}),\n",
       "  HumanMessage(content='My mom had a lung cancer at 45.', additional_kwargs={}, response_metadata={}, id='5e7229d4-75c1-4af0-86ee-0bf6b0cf79b8'),\n",
       "  AIMessage(content='', additional_kwargs={'function_call': {'name': 'family_hist', 'arguments': '{\"family_history\": \"Mother had lung cancer at 45\"}'}}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': []}, id='run-649911e3-2e04-411f-9748-6118b678c995-0', tool_calls=[{'name': 'family_hist', 'args': {'family_history': 'Mother had lung cancer at 45'}, 'id': '00538952-3a24-43af-bd00-d8be94a23c0d', 'type': 'tool_call'}], usage_metadata={'input_tokens': 2185, 'output_tokens': 14, 'total_tokens': 2199, 'input_token_details': {'cache_read': 0}}),\n",
       "  ToolMessage(content='ID\\nsymptom\\npain\\nmedical_hist\\nfamily_hist\\nsocial_hist\\nreview_system\\npain_manage\\nfunctional\\nplan', name='family_hist', id='185e4a86-c4f7-467c-9cc4-694e90f14fd5', tool_call_id='00538952-3a24-43af-bd00-d8be94a23c0d'),\n",
       "  AIMessage(content='To get a more complete picture, could you share some information about your lifestyle? What is your occupation? Do you smoke, drink alcohol, or use drugs?  Could you describe your living situation and support system?', additional_kwargs={}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': []}, id='run-b7feb925-e20f-4f26-8e6a-d6d0b6d6f535-0', usage_metadata={'input_tokens': 2233, 'output_tokens': 44, 'total_tokens': 2277, 'input_token_details': {'cache_read': 0}}),\n",
       "  HumanMessage(content=\"I am a data scientist, I am a viggie. I don't use tobbaco or alcohol. My stress level is midium. \", additional_kwargs={}, response_metadata={}, id='9729418d-ccaf-499e-b113-102bda1ffb44'),\n",
       "  AIMessage(content='', additional_kwargs={'function_call': {'name': 'social_hist', 'arguments': '{\"occupation\": \"Data scientist\", \"alcohol\": false, \"support_system\": \"Unknown\", \"living_condition\": \"Unknown\", \"smoke\": false, \"drug\": false}'}}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': []}, id='run-4cd83ff3-1c6c-4a25-b6ce-324f643a9983-0', tool_calls=[{'name': 'social_hist', 'args': {'occupation': 'Data scientist', 'alcohol': False, 'support_system': 'Unknown', 'living_condition': 'Unknown', 'smoke': False, 'drug': False}, 'id': '9e7e59cd-1f82-4509-90fa-0f04e2ae3247', 'type': 'tool_call'}], usage_metadata={'input_tokens': 2307, 'output_tokens': 17, 'total_tokens': 2324, 'input_token_details': {'cache_read': 0}}),\n",
       "  ToolMessage(content='ID\\nsymptom\\npain\\nmedical_hist\\nfamily_hist\\nsocial_hist\\nreview_system\\npain_manage\\nfunctional\\nplan', name='social_hist', id='b5fb4fb9-7a92-4e9b-ae60-f712789d0763', tool_call_id='9e7e59cd-1f82-4509-90fa-0f04e2ae3247'),\n",
       "  AIMessage(content=\"We're almost done.  Let's do a quick system review.  Have you experienced any recent weight changes? Have you had any fever, chills, or night sweats? How is your sleep?  How are your gastrointestinal and urinary functions?\", additional_kwargs={}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': []}, id='run-ad5ad812-ff0f-4df5-8b24-ff8477b846ea-0', usage_metadata={'input_tokens': 2358, 'output_tokens': 53, 'total_tokens': 2411, 'input_token_details': {'cache_read': 0}}),\n",
       "  HumanMessage(content='I sleep well, and no other symptoms.', additional_kwargs={}, response_metadata={}, id='fdae21fe-3b98-4481-8b84-9a37278dbe2e'),\n",
       "  AIMessage(content='', additional_kwargs={'function_call': {'name': 'review_system', 'arguments': '{\"night_sweats\": false, \"urinary\": \"Normal\", \"fever\": false, \"chill\": false, \"weight_change\": \"None\", \"gastrointestinal\": \"Normal\", \"sleep\": \"Well\"}'}}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': []}, id='run-5fee7657-9fa1-49e7-8eae-6692fb4c091f-0', tool_calls=[{'name': 'review_system', 'args': {'night_sweats': False, 'urinary': 'Normal', 'fever': False, 'chill': False, 'weight_change': 'None', 'gastrointestinal': 'Normal', 'sleep': 'Well'}, 'id': '8eb97099-d605-4f5f-b68f-09b42c1b57a3', 'type': 'tool_call'}], usage_metadata={'input_tokens': 2419, 'output_tokens': 22, 'total_tokens': 2441, 'input_token_details': {'cache_read': 0}}),\n",
       "  ToolMessage(content='ID\\nsymptom\\npain\\nmedical_hist\\nfamily_hist\\nsocial_hist\\nreview_system\\npain_manage\\nfunctional\\nplan', name='review_system', id='79d367c4-9f55-4bf4-8e57-61a181f04c50', tool_call_id='8eb97099-d605-4f5f-b68f-09b42c1b57a3'),\n",
       "  AIMessage(content=\"Finally, let's talk about your pain management. What pain medications are you currently using? Have you consulted any specialists for your pain? Have you tried any alternative therapies? How effective has your pain management been so far?\", additional_kwargs={}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': []}, id='run-b04ae18f-4886-4f4e-bac0-249fa25a9104-0', usage_metadata={'input_tokens': 2475, 'output_tokens': 46, 'total_tokens': 2521, 'input_token_details': {'cache_read': 0}}),\n",
       "  HumanMessage(content=\"No, I am not taking any other medication, and I haven't tried any alternative therapies. \", additional_kwargs={}, response_metadata={}, id='2f7663f0-bf45-4a88-8166-87296401b484'),\n",
       "  AIMessage(content='', additional_kwargs={'function_call': {'name': 'pain_manage', 'arguments': '{\"other_therapy\": \"No\", \"effectiveness\": \"Unknown\", \"specialist\": false, \"pain_medication\": \"No\"}'}}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': []}, id='run-957a0591-60ca-432f-8d58-96b6e320d3f8-0', tool_calls=[{'name': 'pain_manage', 'args': {'other_therapy': 'No', 'effectiveness': 'Unknown', 'specialist': False, 'pain_medication': 'No'}, 'id': '8e3b6362-259c-4761-8afd-8dafdf089d64', 'type': 'tool_call'}], usage_metadata={'input_tokens': 2541, 'output_tokens': 14, 'total_tokens': 2555, 'input_token_details': {'cache_read': 0}}),\n",
       "  ToolMessage(content='ID\\nsymptom\\npain\\nmedical_hist\\nfamily_hist\\nsocial_hist\\nreview_system\\npain_manage\\nfunctional\\nplan', name='pain_manage', id='05176215-7b75-44b0-bf4b-781415e99c92', tool_call_id='8e3b6362-259c-4761-8afd-8dafdf089d64'),\n",
       "  AIMessage(content=\"To conclude, could you please describe how this headache impacts your quality of life, any limitations on your activities, and your current mood?  Also, what are your treatment goals and expectations? Are there any alternative treatments you'd consider?\", additional_kwargs={}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': []}, id='run-180eb319-b8ab-4839-9e4a-0dfddc1db7a5-0', usage_metadata={'input_tokens': 2589, 'output_tokens': 49, 'total_tokens': 2638, 'input_token_details': {'cache_read': 0}}),\n",
       "  HumanMessage(content='I am okay on my mood, and my quality of life is also good. I want to fix my headache.', additional_kwargs={}, response_metadata={}, id='8d9d0595-b4c8-4363-8a12-9d25d622df40'),\n",
       "  AIMessage(content='', additional_kwargs={'function_call': {'name': 'plan', 'arguments': '{\"alternative_treatment\": \"None\", \"goal\": \"Fix headache\", \"expectation\": \"Fix headache\"}'}}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': []}, id='run-b8aa1b09-e8ca-4b28-975b-b9c236fec8cf-0', tool_calls=[{'name': 'functional', 'args': {'limit_activity': 'None', 'life_quality': 'Good', 'mood': 'Okay'}, 'id': 'a4e3932e-f8f4-4f04-b197-f8a121bc9a83', 'type': 'tool_call'}, {'name': 'plan', 'args': {'alternative_treatment': 'None', 'goal': 'Fix headache', 'expectation': 'Fix headache'}, 'id': '6b547d21-4aa1-4446-bd88-513e89f40a00', 'type': 'tool_call'}], usage_metadata={'input_tokens': 2660, 'output_tokens': 23, 'total_tokens': 2683, 'input_token_details': {'cache_read': 0}}),\n",
       "  ToolMessage(content='ID\\nsymptom\\npain\\nmedical_hist\\nfamily_hist\\nsocial_hist\\nreview_system\\npain_manage\\nfunctional\\nplan', name='functional', id='ac6a0abc-75f5-4166-be1d-0b0380b4be42', tool_call_id='a4e3932e-f8f4-4f04-b197-f8a121bc9a83'),\n",
       "  ToolMessage(content='ID\\nsymptom\\npain\\nmedical_hist\\nfamily_hist\\nsocial_hist\\nreview_system\\npain_manage\\nfunctional\\nplan', name='plan', id='36e5190d-6e92-408e-81cc-a4e4002db458', tool_call_id='6b547d21-4aa1-4446-bd88-513e89f40a00'),\n",
       "  AIMessage(content=\"Before we finalize this record, could you please confirm that all the information we've gathered is accurate?\", additional_kwargs={}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': []}, id='run-418aedcc-36df-4162-88fa-502fe88c92de-0', usage_metadata={'input_tokens': 2746, 'output_tokens': 22, 'total_tokens': 2768, 'input_token_details': {'cache_read': 0}}),\n",
       "  HumanMessage(content='I am okay on my mood, and my quality of life is also good. I want to fix my headache.', additional_kwargs={}, response_metadata={}, id='284f6024-d70b-4465-a9cf-359d9302bc55'),\n",
       "  AIMessage(content='Okay, I will save your information now.', additional_kwargs={'function_call': {'name': 'save_data', 'arguments': '{}'}}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': []}, id='run-50382a72-be29-45cb-b883-fa7242e1c717-0', tool_calls=[{'name': 'save_data', 'args': {}, 'id': '4da5513e-f8e6-4b08-a9ff-70e63825b9df', 'type': 'tool_call'}], usage_metadata={'input_tokens': 2790, 'output_tokens': 13, 'total_tokens': 2803, 'input_token_details': {'cache_read': 0}}),\n",
       "  ToolMessage(content='4', name='save_data', id='b332e4a1-52dc-4739-9abc-1d8ff8d973d2', tool_call_id='4da5513e-f8e6-4b08-a9ff-70e63825b9df'),\n",
       "  AIMessage(content='Thank you for providing all the necessary information. Your medical record has been successfully saved.  Please let me know if you have any further questions or need additional assistance.  Have a good day.', additional_kwargs={}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': []}, id='run-63007311-b94d-49c4-8ed1-0c23a32af250-0', usage_metadata={'input_tokens': 2797, 'output_tokens': 40, 'total_tokens': 2837, 'input_token_details': {'cache_read': 0}})],\n",
       " 'data': {'ID': {'name': 'Frank',\n",
       "   'DOB': '1986-01-01',\n",
       "   'gender': 'male',\n",
       "   'contact': '12345',\n",
       "   'emergency_contact': 'Zoe, 67890'},\n",
       "  'symptom': {'main_symptom': 'Headache', 'symptom_length': '2 days'},\n",
       "  'pain': {'pain_location': 'Right head',\n",
       "   'pain_side': 'Right',\n",
       "   'pain_intensity': 2.0,\n",
       "   'pain_description': 'Sharp',\n",
       "   'start_time': '2 days ago',\n",
       "   'radiation': False,\n",
       "   'triggers': 'Cold',\n",
       "   'symptom': 'No other symptoms'},\n",
       "  'medical_hist': {'medical_condition': 'Sinus',\n",
       "   'first_time': '2001-01-01',\n",
       "   'surgery_history': 'None',\n",
       "   'medication': 'Ibprofin',\n",
       "   'allergy': 'None'},\n",
       "  'family_hist': {'family_history': 'Mother had lung cancer at 45'},\n",
       "  'social_hist': {'occupation': 'Data scientist',\n",
       "   'smoke': False,\n",
       "   'alcohol': False,\n",
       "   'drug': False,\n",
       "   'support_system': 'Unknown',\n",
       "   'living_condition': 'Unknown'},\n",
       "  'review_system': {'weight_change': 'None',\n",
       "   'fever': False,\n",
       "   'chill': False,\n",
       "   'night_sweats': False,\n",
       "   'sleep': 'Well',\n",
       "   'gastrointestinal': 'Normal',\n",
       "   'urinary': 'Normal'},\n",
       "  'pain_manage': {'pain_medication': 'No',\n",
       "   'specialist': False,\n",
       "   'other_therapy': 'No',\n",
       "   'effectiveness': 'Unknown'},\n",
       "  'functional': {'life_quality': 'Good',\n",
       "   'limit_activity': 'None',\n",
       "   'mood': 'Okay'},\n",
       "  'plan': {'goal': 'Fix headache',\n",
       "   'expectation': 'Fix headache',\n",
       "   'alternative_treatment': 'None'}},\n",
       " 'finished': True}"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# The default recursion limit for traversing nodes is 25 - setting it higher\n",
    "# means you can try a more complex order with multiple steps and round-trips.\n",
    "config = {\"recursion_limit\": 500}\n",
    "\n",
    "# Uncomment this line to execute the graph:\n",
    "# Clear output before running new states\n",
    "clear_output(wait=True)\n",
    "\n",
    "# Ensure messages print immediately\n",
    "print(\"Executing the chatbot graph...\", flush=True)\n",
    "state = graph_with_order_tools.invoke({\"messages\": []}, config)\n",
    "display(state)  # Ensures state is shown in Jupyter\n",
    "sys.stdout.flush()\n",
    "\n",
    "# pprint(state)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "trusted": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'ID': {'name': 'Frank',\n",
       "  'DOB': '1986-01-01',\n",
       "  'gender': 'male',\n",
       "  'contact': '12345',\n",
       "  'emergency_contact': 'Zoe, 67890'},\n",
       " 'symptom': {'main_symptom': 'Headache', 'symptom_length': '2 days'},\n",
       " 'pain': {'pain_location': 'Right head',\n",
       "  'pain_side': 'Right',\n",
       "  'pain_intensity': 2.0,\n",
       "  'pain_description': 'Sharp',\n",
       "  'start_time': '2 days ago',\n",
       "  'radiation': False,\n",
       "  'triggers': 'Cold',\n",
       "  'symptom': 'No other symptoms'},\n",
       " 'medical_hist': {'medical_condition': 'Sinus',\n",
       "  'first_time': '2001-01-01',\n",
       "  'surgery_history': 'None',\n",
       "  'medication': 'Ibprofin',\n",
       "  'allergy': 'None'},\n",
       " 'family_hist': {'family_history': 'Mother had lung cancer at 45'},\n",
       " 'social_hist': {'occupation': 'Data scientist',\n",
       "  'smoke': False,\n",
       "  'alcohol': False,\n",
       "  'drug': False,\n",
       "  'support_system': 'Unknown',\n",
       "  'living_condition': 'Unknown'},\n",
       " 'review_system': {'weight_change': 'None',\n",
       "  'fever': False,\n",
       "  'chill': False,\n",
       "  'night_sweats': False,\n",
       "  'sleep': 'Well',\n",
       "  'gastrointestinal': 'Normal',\n",
       "  'urinary': 'Normal'},\n",
       " 'pain_manage': {'pain_medication': 'No',\n",
       "  'specialist': False,\n",
       "  'other_therapy': 'No',\n",
       "  'effectiveness': 'Unknown'},\n",
       " 'functional': {'life_quality': 'Good',\n",
       "  'limit_activity': 'None',\n",
       "  'mood': 'Okay'},\n",
       " 'plan': {'goal': 'Fix headache',\n",
       "  'expectation': 'Fix headache',\n",
       "  'alternative_treatment': 'None'}}"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "state[\"data\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "colab": {
   "name": "day-3-building-an-agent-with-langgraph.ipynb",
   "toc_visible": true
  },
  "kaggle": {
   "accelerator": "none",
   "dataSources": [],
   "dockerImageVersionId": 30786,
   "isGpuEnabled": false,
   "isInternetEnabled": true,
   "language": "python",
   "sourceType": "notebook"
  },
  "kernelspec": {
   "display_name": "paintrek",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}