Pdro-ruiz commited on
Commit
659888a
·
verified ·
1 Parent(s): 623dede

First upload

Browse files
Notebooks/00_synthetic_data.ipynb ADDED
@@ -0,0 +1,430 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {},
6
+ "source": [
7
+ "# Generación de Datos Sintéticos para Wikidoc y MedQA\n",
8
+ "\n",
9
+ "En este notebook se generan datos sintéticos de forma separada para dos bases de datos:\n",
10
+ "- **Wikidoc**: con columnas *instruction*, *input* y *output*.\n",
11
+ "- **MedQA**: con columnas *question*, *answer*, *options*, etc.\n",
12
+ "\n",
13
+ "Se aplicarán técnicas simples de data augmentation, añadiendo frases modificadoras para simular variaciones en los datos.\n",
14
+ "\n",
15
+ "## 1. Importar librerías y cargar datos"
16
+ ]
17
+ },
18
+ {
19
+ "cell_type": "code",
20
+ "execution_count": 1,
21
+ "metadata": {},
22
+ "outputs": [],
23
+ "source": [
24
+ "import pandas as pd\n",
25
+ "import random\n",
26
+ "from pathlib import Path\n",
27
+ "\n",
28
+ "pd.set_option('display.max_columns', None)"
29
+ ]
30
+ },
31
+ {
32
+ "cell_type": "markdown",
33
+ "metadata": {},
34
+ "source": [
35
+ "## 2. Cargar las Bases de Datos"
36
+ ]
37
+ },
38
+ {
39
+ "cell_type": "code",
40
+ "execution_count": 2,
41
+ "metadata": {},
42
+ "outputs": [
43
+ {
44
+ "name": "stdout",
45
+ "output_type": "stream",
46
+ "text": [
47
+ "Wikidoc: (10000, 3)\n",
48
+ "MedQA: (10178, 6)\n"
49
+ ]
50
+ }
51
+ ],
52
+ "source": [
53
+ "# Definir la ruta a los datos (ajusta según tu estructura)\n",
54
+ "raw_path = Path(\"../data/raw\")\n",
55
+ "\n",
56
+ "# Cargar Wikidoc y MedQA\n",
57
+ "wikidoc_file = raw_path / \"medical_meadow_wikidoc.csv\"\n",
58
+ "medqa_file = raw_path / \"medqa.csv\"\n",
59
+ "\n",
60
+ "wikidoc = pd.read_csv(wikidoc_file)\n",
61
+ "medqa = pd.read_csv(medqa_file)\n",
62
+ "\n",
63
+ "print(\"Wikidoc:\", wikidoc.shape)\n",
64
+ "print(\"MedQA:\", medqa.shape)"
65
+ ]
66
+ },
67
+ {
68
+ "cell_type": "markdown",
69
+ "metadata": {},
70
+ "source": [
71
+ "## 3. Generación de Datos Sintéticos para Wikidoc\n",
72
+ "\n",
73
+ "En esta sección se generan datos sintéticos a partir de la base de datos **Wikidoc**.\n",
74
+ "Se tomarán filas aleatorias y se modificará ligeramente el texto en las columnas:\n",
75
+ "- **instruction**\n",
76
+ "- **input**\n",
77
+ "- **output**\n",
78
+ " \n",
79
+ "Se añadirá una frase modificadora para simular variaciones."
80
+ ]
81
+ },
82
+ {
83
+ "cell_type": "code",
84
+ "execution_count": 4,
85
+ "metadata": {},
86
+ "outputs": [
87
+ {
88
+ "data": {
89
+ "text/html": [
90
+ "<div>\n",
91
+ "<style scoped>\n",
92
+ " .dataframe tbody tr th:only-of-type {\n",
93
+ " vertical-align: middle;\n",
94
+ " }\n",
95
+ "\n",
96
+ " .dataframe tbody tr th {\n",
97
+ " vertical-align: top;\n",
98
+ " }\n",
99
+ "\n",
100
+ " .dataframe thead th {\n",
101
+ " text-align: right;\n",
102
+ " }\n",
103
+ "</style>\n",
104
+ "<table border=\"1\" class=\"dataframe\">\n",
105
+ " <thead>\n",
106
+ " <tr style=\"text-align: right;\">\n",
107
+ " <th></th>\n",
108
+ " <th>instruction_sintetica</th>\n",
109
+ " <th>input_sintetico</th>\n",
110
+ " <th>output_sintetico</th>\n",
111
+ " </tr>\n",
112
+ " </thead>\n",
113
+ " <tbody>\n",
114
+ " <tr>\n",
115
+ " <th>0</th>\n",
116
+ " <td>Answer this question truthfully [augmented]</td>\n",
117
+ " <td>Could you explain what Meckel's diverticulum i...</td>\n",
118
+ " <td>There is insufficient evidence to recommend ro...</td>\n",
119
+ " </tr>\n",
120
+ " <tr>\n",
121
+ " <th>1</th>\n",
122
+ " <td>Answer this question truthfully (versión sinté...</td>\n",
123
+ " <td>Could you provide information on AIDS dementia...</td>\n",
124
+ " <td>AIDS (acquired immune deficiency syndrome) is ...</td>\n",
125
+ " </tr>\n",
126
+ " <tr>\n",
127
+ " <th>2</th>\n",
128
+ " <td>Answer this question truthfully (versión sinté...</td>\n",
129
+ " <td>What information is available regarding esopha...</td>\n",
130
+ " <td>Esophageal cancer is not very common in the Un...</td>\n",
131
+ " </tr>\n",
132
+ " <tr>\n",
133
+ " <th>3</th>\n",
134
+ " <td>Answer this question truthfully [datos aumenta...</td>\n",
135
+ " <td>Can you provide an overview of delirium tremen...</td>\n",
136
+ " <td>Screening tools include the Alcohol Use Disord...</td>\n",
137
+ " </tr>\n",
138
+ " <tr>\n",
139
+ " <th>4</th>\n",
140
+ " <td>Answer this question truthfully (modificado si...</td>\n",
141
+ " <td>What information is available about Nocturia? ...</td>\n",
142
+ " <td>http://www.nlm.nih.gov/medlineplus/ency/articl...</td>\n",
143
+ " </tr>\n",
144
+ " </tbody>\n",
145
+ "</table>\n",
146
+ "</div>"
147
+ ],
148
+ "text/plain": [
149
+ " instruction_sintetica \\\n",
150
+ "0 Answer this question truthfully [augmented] \n",
151
+ "1 Answer this question truthfully (versión sinté... \n",
152
+ "2 Answer this question truthfully (versión sinté... \n",
153
+ "3 Answer this question truthfully [datos aumenta... \n",
154
+ "4 Answer this question truthfully (modificado si... \n",
155
+ "\n",
156
+ " input_sintetico \\\n",
157
+ "0 Could you explain what Meckel's diverticulum i... \n",
158
+ "1 Could you provide information on AIDS dementia... \n",
159
+ "2 What information is available regarding esopha... \n",
160
+ "3 Can you provide an overview of delirium tremen... \n",
161
+ "4 What information is available about Nocturia? ... \n",
162
+ "\n",
163
+ " output_sintetico \n",
164
+ "0 There is insufficient evidence to recommend ro... \n",
165
+ "1 AIDS (acquired immune deficiency syndrome) is ... \n",
166
+ "2 Esophageal cancer is not very common in the Un... \n",
167
+ "3 Screening tools include the Alcohol Use Disord... \n",
168
+ "4 http://www.nlm.nih.gov/medlineplus/ency/articl... "
169
+ ]
170
+ },
171
+ "execution_count": 4,
172
+ "metadata": {},
173
+ "output_type": "execute_result"
174
+ }
175
+ ],
176
+ "source": [
177
+ "def generar_datos_sinteticos_wikidoc(df, n=10):\n",
178
+ " \"\"\"\n",
179
+ " Genera datos sintéticos para el dataset Wikidoc.\n",
180
+ " Toma 'n' muestras y modifica ligeramente el texto en las columnas instruction, input y output.\n",
181
+ " \n",
182
+ " Retorna un DataFrame con las columnas modificadas.\n",
183
+ " \"\"\"\n",
184
+ " sampled = df.sample(n, replace=True)\n",
185
+ " modificaciones = [\n",
186
+ " \"(modificado sintéticamente)\",\n",
187
+ " \"[datos aumentados]\",\n",
188
+ " \"(versión sintética)\",\n",
189
+ " \"[augmented]\"\n",
190
+ " ]\n",
191
+ " \n",
192
+ " instrucciones_sinteticas = []\n",
193
+ " entradas_sinteticas = []\n",
194
+ " salidas_sinteticas = []\n",
195
+ " \n",
196
+ " for _, row in sampled.iterrows():\n",
197
+ " mod = random.choice(modificaciones)\n",
198
+ " instruccion = str(row[\"instruction\"]) + \" \" + mod\n",
199
+ " # Si 'input' es nulo, se usa solo la modificación\n",
200
+ " entrada = (str(row[\"input\"]) + \" \" + mod) if pd.notnull(row[\"input\"]) else mod\n",
201
+ " salida = str(row[\"output\"]) + \" \" + mod\n",
202
+ " instrucciones_sinteticas.append(instruccion)\n",
203
+ " entradas_sinteticas.append(entrada)\n",
204
+ " salidas_sinteticas.append(salida)\n",
205
+ " \n",
206
+ " df_sintetico = pd.DataFrame({\n",
207
+ " \"instruction_sintetica\": instrucciones_sinteticas,\n",
208
+ " \"input_sintetico\": entradas_sinteticas,\n",
209
+ " \"output_sintetico\": salidas_sinteticas\n",
210
+ " })\n",
211
+ " \n",
212
+ " return df_sintetico\n",
213
+ "\n",
214
+ "# Generamos 10 filas sintéticas para Wikidoc\n",
215
+ "wikidoc_sintetico = generar_datos_sinteticos_wikidoc(wikidoc, n=10)\n",
216
+ "wikidoc_sintetico.head()\n",
217
+ "\n"
218
+ ]
219
+ },
220
+ {
221
+ "cell_type": "markdown",
222
+ "metadata": {},
223
+ "source": [
224
+ "## 4. Generación de Datos Sintéticos para MedQA\n",
225
+ " \n",
226
+ "En esta sección se generan datos sintéticos a partir de la base de datos **MedQA**.\n",
227
+ "Se modificarán las columnas:\n",
228
+ "- **question**\n",
229
+ "- **answer**\n",
230
+ " \n",
231
+ "Se añadirá una frase modificadora para simular variaciones en la consulta y en la respuesta."
232
+ ]
233
+ },
234
+ {
235
+ "cell_type": "code",
236
+ "execution_count": 5,
237
+ "metadata": {},
238
+ "outputs": [
239
+ {
240
+ "data": {
241
+ "text/html": [
242
+ "<div>\n",
243
+ "<style scoped>\n",
244
+ " .dataframe tbody tr th:only-of-type {\n",
245
+ " vertical-align: middle;\n",
246
+ " }\n",
247
+ "\n",
248
+ " .dataframe tbody tr th {\n",
249
+ " vertical-align: top;\n",
250
+ " }\n",
251
+ "\n",
252
+ " .dataframe thead th {\n",
253
+ " text-align: right;\n",
254
+ " }\n",
255
+ "</style>\n",
256
+ "<table border=\"1\" class=\"dataframe\">\n",
257
+ " <thead>\n",
258
+ " <tr style=\"text-align: right;\">\n",
259
+ " <th></th>\n",
260
+ " <th>question_sintetica</th>\n",
261
+ " <th>answer_sintetica</th>\n",
262
+ " </tr>\n",
263
+ " </thead>\n",
264
+ " <tbody>\n",
265
+ " <tr>\n",
266
+ " <th>0</th>\n",
267
+ " <td>A 55-year-old man with a history of myocardial...</td>\n",
268
+ " <td>Post-traumatic stress disorder [synthetic data]</td>\n",
269
+ " </tr>\n",
270
+ " <tr>\n",
271
+ " <th>1</th>\n",
272
+ " <td>A 50-year-old man is brought to the emergency ...</td>\n",
273
+ " <td>Muffled heart sounds [versión aumentada]</td>\n",
274
+ " </tr>\n",
275
+ " <tr>\n",
276
+ " <th>2</th>\n",
277
+ " <td>A 30-year-old woman presents with generalized ...</td>\n",
278
+ " <td>Ribavirin (datos generados)</td>\n",
279
+ " </tr>\n",
280
+ " <tr>\n",
281
+ " <th>3</th>\n",
282
+ " <td>A 58-year-old man with type 2 diabetes mellitu...</td>\n",
283
+ " <td>Ludwig angina\\n\" [synthetic data]</td>\n",
284
+ " </tr>\n",
285
+ " <tr>\n",
286
+ " <th>4</th>\n",
287
+ " <td>A 55-year-old woman comes to the physician bec...</td>\n",
288
+ " <td>Pulmonary embolism (datos generados)</td>\n",
289
+ " </tr>\n",
290
+ " </tbody>\n",
291
+ "</table>\n",
292
+ "</div>"
293
+ ],
294
+ "text/plain": [
295
+ " question_sintetica \\\n",
296
+ "0 A 55-year-old man with a history of myocardial... \n",
297
+ "1 A 50-year-old man is brought to the emergency ... \n",
298
+ "2 A 30-year-old woman presents with generalized ... \n",
299
+ "3 A 58-year-old man with type 2 diabetes mellitu... \n",
300
+ "4 A 55-year-old woman comes to the physician bec... \n",
301
+ "\n",
302
+ " answer_sintetica \n",
303
+ "0 Post-traumatic stress disorder [synthetic data] \n",
304
+ "1 Muffled heart sounds [versión aumentada] \n",
305
+ "2 Ribavirin (datos generados) \n",
306
+ "3 Ludwig angina\\n\" [synthetic data] \n",
307
+ "4 Pulmonary embolism (datos generados) "
308
+ ]
309
+ },
310
+ "execution_count": 5,
311
+ "metadata": {},
312
+ "output_type": "execute_result"
313
+ }
314
+ ],
315
+ "source": [
316
+ "def generar_datos_sinteticos_medqa(df, n=10):\n",
317
+ " \"\"\"\n",
318
+ " Genera datos sintéticos para el dataset MedQA.\n",
319
+ " Toma 'n' muestras y modifica ligeramente el texto en las columnas question y answer.\n",
320
+ " \n",
321
+ " Retorna un DataFrame con las columnas modificadas.\n",
322
+ " \"\"\"\n",
323
+ " sampled = df.sample(n, replace=True)\n",
324
+ " modificaciones = [\n",
325
+ " \"(consulta sintética)\",\n",
326
+ " \"[versión aumentada]\",\n",
327
+ " \"(datos generados)\",\n",
328
+ " \"[synthetic data]\"\n",
329
+ " ]\n",
330
+ " \n",
331
+ " questions_sinteticas = []\n",
332
+ " answers_sinteticas = []\n",
333
+ " \n",
334
+ " for _, row in sampled.iterrows():\n",
335
+ " mod = random.choice(modificaciones)\n",
336
+ " question = str(row[\"question\"]) + \" \" + mod\n",
337
+ " answer = str(row[\"answer\"]) + \" \" + mod\n",
338
+ " questions_sinteticas.append(question)\n",
339
+ " answers_sinteticas.append(answer)\n",
340
+ " \n",
341
+ " df_sintetico_medqa = pd.DataFrame({\n",
342
+ " \"question_sintetica\": questions_sinteticas,\n",
343
+ " \"answer_sintetica\": answers_sinteticas\n",
344
+ " })\n",
345
+ " \n",
346
+ " return df_sintetico_medqa\n",
347
+ "\n",
348
+ "# Generamos 10 filas sintéticas para MedQA\n",
349
+ "medqa_sintetico = generar_datos_sinteticos_medqa(medqa, n=10)\n",
350
+ "medqa_sintetico.head()"
351
+ ]
352
+ },
353
+ {
354
+ "cell_type": "code",
355
+ "execution_count": 7,
356
+ "metadata": {},
357
+ "outputs": [
358
+ {
359
+ "name": "stdout",
360
+ "output_type": "stream",
361
+ "text": [
362
+ "wikidoc_sintetico: (10000, 3)\n",
363
+ "medqa_sintetico: (10178, 6)\n"
364
+ ]
365
+ }
366
+ ],
367
+ "source": [
368
+ "print(\"wikidoc_sintetico:\", wikidoc.shape)\n",
369
+ "print(\"medqa_sintetico:\", medqa.shape)"
370
+ ]
371
+ },
372
+ {
373
+ "cell_type": "markdown",
374
+ "metadata": {},
375
+ "source": [
376
+ "## 5. Conclusión\n",
377
+ "\n",
378
+ "Se han generado datos sintéticos de forma separada para las bases de datos **Wikidoc** y **MedQA**.\n",
379
+ "Estos datos pueden usarse para realizar pruebas, evaluar la robustez de tus modelos y ampliar el conjunto de entrenamiento."
380
+ ]
381
+ },
382
+ {
383
+ "cell_type": "code",
384
+ "execution_count": 8,
385
+ "metadata": {},
386
+ "outputs": [
387
+ {
388
+ "name": "stdout",
389
+ "output_type": "stream",
390
+ "text": [
391
+ "Número de datos sintéticos generados para Wikidoc: 10\n",
392
+ "Número de datos sintéticos generados para MedQA: 10\n"
393
+ ]
394
+ }
395
+ ],
396
+ "source": [
397
+ "print(\"Número de datos sintéticos generados para Wikidoc:\", wikidoc_sintetico.shape[0])\n",
398
+ "print(\"Número de datos sintéticos generados para MedQA:\", medqa_sintetico.shape[0])\n"
399
+ ]
400
+ },
401
+ {
402
+ "cell_type": "code",
403
+ "execution_count": null,
404
+ "metadata": {},
405
+ "outputs": [],
406
+ "source": []
407
+ }
408
+ ],
409
+ "metadata": {
410
+ "kernelspec": {
411
+ "display_name": "carecompanion",
412
+ "language": "python",
413
+ "name": "python3"
414
+ },
415
+ "language_info": {
416
+ "codemirror_mode": {
417
+ "name": "ipython",
418
+ "version": 3
419
+ },
420
+ "file_extension": ".py",
421
+ "mimetype": "text/x-python",
422
+ "name": "python",
423
+ "nbconvert_exporter": "python",
424
+ "pygments_lexer": "ipython3",
425
+ "version": "3.9.21"
426
+ }
427
+ },
428
+ "nbformat": 4,
429
+ "nbformat_minor": 2
430
+ }
Notebooks/01_triage_tool.ipynb ADDED
@@ -0,0 +1,191 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {},
6
+ "source": [
7
+ "# Herramienta de Triaje - Atención Primaria\n",
8
+ " \n",
9
+ "Esta notebook implementa una herramienta de triaje para la atención primaria, evaluando síntomas, intensidad, duración y antecedentes del paciente. La idea es asignar un puntaje de riesgo y generar una recomendación sobre la necesidad de atención médica urgente o no.\n",
10
+ "\n",
11
+ "## Definición de Funciones\n",
12
+ " \n",
13
+ "En esta sección definimos:\n",
14
+ "- `evaluar_triaje`: Evalúa el puntaje de riesgo según los datos ingresados.\n",
15
+ "- `recomendar_atencion`: Emite una recomendación basada en el puntaje obtenido.\n",
16
+ "- `triaje_primer_tool`: Función principal que integra el proceso."
17
+ ]
18
+ },
19
+ {
20
+ "cell_type": "code",
21
+ "execution_count": 1,
22
+ "metadata": {},
23
+ "outputs": [],
24
+ "source": [
25
+ "import re\n",
26
+ "\n",
27
+ "def evaluar_triaje(sintomas, intensidad, duracion, antecedentes):\n",
28
+ " \"\"\"\n",
29
+ " Evalúa el nivel de riesgo basado en síntomas, intensidad, duración y antecedentes.\n",
30
+ " \n",
31
+ " Parámetros:\n",
32
+ " - sintomas: texto descriptivo de los síntomas.\n",
33
+ " - intensidad: nivel de intensidad (ej. \"leve\", \"moderada\", \"intensa\").\n",
34
+ " - duracion: duración de los síntomas (en horas, como cadena numérica o número).\n",
35
+ " - antecedentes: antecedentes médicos relevantes (texto).\n",
36
+ " \n",
37
+ " Retorna:\n",
38
+ " - score: puntaje numérico que indica el nivel de riesgo.\n",
39
+ " \"\"\"\n",
40
+ " score = 0\n",
41
+ "\n",
42
+ " # Evaluación de síntomas críticos\n",
43
+ " sintomas_criticos = [\"dolor intenso\", \"falta de aire\", \"desmayo\", \"pérdida de conciencia\"]\n",
44
+ " for sintoma in sintomas_criticos:\n",
45
+ " if sintoma in sintomas.lower():\n",
46
+ " score += 5\n",
47
+ "\n",
48
+ " # Evaluación de síntomas moderados\n",
49
+ " sintomas_moderados = [\"fiebre alta\", \"dolor en el pecho\", \"mareos\", \"náusea\"]\n",
50
+ " for sintoma in sintomas_moderados:\n",
51
+ " if sintoma in sintomas.lower():\n",
52
+ " score += 3\n",
53
+ "\n",
54
+ " # Ponderación basada en la intensidad\n",
55
+ " intensidad = intensidad.lower()\n",
56
+ " if intensidad in [\"intensa\", \"alta\"]:\n",
57
+ " score += 3\n",
58
+ " elif intensidad == \"moderada\":\n",
59
+ " score += 2\n",
60
+ " elif intensidad in [\"leve\", \"baja\"]:\n",
61
+ " score += 1\n",
62
+ "\n",
63
+ " # Ponderación según la duración (suponiendo que es en horas)\n",
64
+ " try:\n",
65
+ " duracion = float(duracion)\n",
66
+ " if duracion >= 24:\n",
67
+ " score += 3\n",
68
+ " elif duracion >= 6:\n",
69
+ " score += 2\n",
70
+ " else:\n",
71
+ " score += 1\n",
72
+ " except ValueError:\n",
73
+ " print(\"Error: La duración debe ser un valor numérico.\")\n",
74
+ "\n",
75
+ " # Evaluación de antecedentes médicos relevantes\n",
76
+ " antecedentes_relevantes = [\"cardiopatía\", \"hipertensión\", \"diabetes\"]\n",
77
+ " for item in antecedentes_relevantes:\n",
78
+ " if item in antecedentes.lower():\n",
79
+ " score += 2\n",
80
+ "\n",
81
+ " return score\n"
82
+ ]
83
+ },
84
+ {
85
+ "cell_type": "code",
86
+ "execution_count": 2,
87
+ "metadata": {},
88
+ "outputs": [],
89
+ "source": [
90
+ "def recomendar_atencion(score):\n",
91
+ " \"\"\"\n",
92
+ " Genera una recomendación basada en el puntaje de riesgo obtenido.\n",
93
+ " \n",
94
+ " Retorna:\n",
95
+ " - recomendacion: mensaje de acción a seguir.\n",
96
+ " \"\"\"\n",
97
+ " if score >= 12:\n",
98
+ " return \"Se recomienda atención de emergencia. Llame a los servicios de urgencia.\"\n",
99
+ " elif score >= 7:\n",
100
+ " return \"Se sugiere acudir a consulta médica lo antes posible.\"\n",
101
+ " else:\n",
102
+ " return \"Puede programar una consulta médica de rutina.\"\n"
103
+ ]
104
+ },
105
+ {
106
+ "cell_type": "code",
107
+ "execution_count": 3,
108
+ "metadata": {},
109
+ "outputs": [],
110
+ "source": [
111
+ "\n",
112
+ "def triaje_primer_tool(data):\n",
113
+ " \"\"\"\n",
114
+ " Función principal para la herramienta de triaje.\n",
115
+ " \n",
116
+ " Parámetro:\n",
117
+ " - data: diccionario con las claves 'sintomas', 'intensidad', 'duracion', 'antecedentes'\n",
118
+ " \n",
119
+ " Retorna:\n",
120
+ " - Diccionario con el 'score' obtenido y la 'recomendacion'\n",
121
+ " \"\"\"\n",
122
+ " score = evaluar_triaje(\n",
123
+ " data.get(\"sintomas\", \"\"),\n",
124
+ " data.get(\"intensidad\", \"\"),\n",
125
+ " data.get(\"duracion\", \"0\"),\n",
126
+ " data.get(\"antecedentes\", \"\")\n",
127
+ " )\n",
128
+ " recomendacion = recomendar_atencion(score)\n",
129
+ " return {\n",
130
+ " \"score\": score,\n",
131
+ " \"recomendacion\": recomendacion\n",
132
+ " }"
133
+ ]
134
+ },
135
+ {
136
+ "cell_type": "code",
137
+ "execution_count": null,
138
+ "metadata": {},
139
+ "outputs": [],
140
+ "source": [
141
+ "\n",
142
+ "# %% [markdown]\n",
143
+ "# ## Ejemplo de Uso\n",
144
+ "# \n",
145
+ "# En la siguiente celda se muestra un ejemplo de cómo utilizar la herramienta con datos de entrada simulados.\n",
146
+ "\n",
147
+ "# %%\n",
148
+ "# Ejemplo de datos de entrada\n",
149
+ "ejemplo_data = {\n",
150
+ " \"sintomas\": \"El paciente presenta dolor intenso en el pecho y falta de aire.\",\n",
151
+ " \"intensidad\": \"intensa\",\n",
152
+ " \"duracion\": \"8\", # en horas\n",
153
+ " \"antecedentes\": \"El paciente tiene antecedentes de hipertensión.\"\n",
154
+ "}\n",
155
+ "\n",
156
+ "# Ejecución de la herramienta de triaje\n",
157
+ "resultado = triaje_primer_tool(ejemplo_data)\n",
158
+ "print(\"Puntaje de riesgo:\", resultado[\"score\"])\n",
159
+ "print(\"Recomendación:\", resultado[\"recomendacion\"])\n"
160
+ ]
161
+ },
162
+ {
163
+ "cell_type": "code",
164
+ "execution_count": null,
165
+ "metadata": {},
166
+ "outputs": [],
167
+ "source": []
168
+ }
169
+ ],
170
+ "metadata": {
171
+ "kernelspec": {
172
+ "display_name": "carecompanion",
173
+ "language": "python",
174
+ "name": "python3"
175
+ },
176
+ "language_info": {
177
+ "codemirror_mode": {
178
+ "name": "ipython",
179
+ "version": 3
180
+ },
181
+ "file_extension": ".py",
182
+ "mimetype": "text/x-python",
183
+ "name": "python",
184
+ "nbconvert_exporter": "python",
185
+ "pygments_lexer": "ipython3",
186
+ "version": "3.9.21"
187
+ }
188
+ },
189
+ "nbformat": 4,
190
+ "nbformat_minor": 2
191
+ }
Notebooks/02_asesoramiento.ipynb ADDED
@@ -0,0 +1,466 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {},
6
+ "source": [
7
+ "# 02_data_augmentation.ipynb\n",
8
+ "\n",
9
+ "En este notebook realizamos las siguientes tareas:\n",
10
+ "\n",
11
+ "1. Cargamos y exploramos los datasets `wikidoc` y `medqa`.\n",
12
+ "2. Unificamos o combinamos la información mínima necesaria.\n",
13
+ "3. Generamos datos sintéticos (data augmentation) para enriquecer el conjunto.\n",
14
+ "4. Realizamos pruebas llamando a las herramientas de triaje y asesoramiento.\n",
15
+ "\n",
16
+ "Al final, podemos convertir este notebook a un script `.py` si lo deseamos.\n"
17
+ ]
18
+ },
19
+ {
20
+ "cell_type": "markdown",
21
+ "metadata": {},
22
+ "source": [
23
+ "## 1. Importar librerías y configuraciones\n"
24
+ ]
25
+ },
26
+ {
27
+ "cell_type": "code",
28
+ "execution_count": 1,
29
+ "metadata": {},
30
+ "outputs": [],
31
+ "source": [
32
+ "import pandas as pd\n",
33
+ "import os\n",
34
+ "import random\n",
35
+ "from pathlib import Path\n",
36
+ "\n",
37
+ "# Opcional: configuración para visualizar más columnas\n",
38
+ "pd.set_option('display.max_columns', None)\n"
39
+ ]
40
+ },
41
+ {
42
+ "cell_type": "markdown",
43
+ "metadata": {},
44
+ "source": [
45
+ "## 2. Cargar y explorar datos"
46
+ ]
47
+ },
48
+ {
49
+ "cell_type": "code",
50
+ "execution_count": 3,
51
+ "metadata": {},
52
+ "outputs": [
53
+ {
54
+ "name": "stdout",
55
+ "output_type": "stream",
56
+ "text": [
57
+ "===== wikidoc.info() =====\n",
58
+ "<class 'pandas.core.frame.DataFrame'>\n",
59
+ "RangeIndex: 10000 entries, 0 to 9999\n",
60
+ "Data columns (total 3 columns):\n",
61
+ " # Column Non-Null Count Dtype \n",
62
+ "--- ------ -------------- ----- \n",
63
+ " 0 instruction 10000 non-null object\n",
64
+ " 1 input 9998 non-null object\n",
65
+ " 2 output 10000 non-null object\n",
66
+ "dtypes: object(3)\n",
67
+ "memory usage: 234.5+ KB\n",
68
+ "\n",
69
+ "===== wikidoc.head() =====\n"
70
+ ]
71
+ },
72
+ {
73
+ "data": {
74
+ "text/html": [
75
+ "<div>\n",
76
+ "<style scoped>\n",
77
+ " .dataframe tbody tr th:only-of-type {\n",
78
+ " vertical-align: middle;\n",
79
+ " }\n",
80
+ "\n",
81
+ " .dataframe tbody tr th {\n",
82
+ " vertical-align: top;\n",
83
+ " }\n",
84
+ "\n",
85
+ " .dataframe thead th {\n",
86
+ " text-align: right;\n",
87
+ " }\n",
88
+ "</style>\n",
89
+ "<table border=\"1\" class=\"dataframe\">\n",
90
+ " <thead>\n",
91
+ " <tr style=\"text-align: right;\">\n",
92
+ " <th></th>\n",
93
+ " <th>instruction</th>\n",
94
+ " <th>input</th>\n",
95
+ " <th>output</th>\n",
96
+ " </tr>\n",
97
+ " </thead>\n",
98
+ " <tbody>\n",
99
+ " <tr>\n",
100
+ " <th>0</th>\n",
101
+ " <td>Answer this question truthfully</td>\n",
102
+ " <td>Can you provide an overview of the lung's squa...</td>\n",
103
+ " <td>Squamous cell carcinoma of the lung may be cla...</td>\n",
104
+ " </tr>\n",
105
+ " <tr>\n",
106
+ " <th>1</th>\n",
107
+ " <td>Answer this question truthfully</td>\n",
108
+ " <td>What does \"Clear: cell\" mean?</td>\n",
109
+ " <td>Clear cell tumors are part of the surface epit...</td>\n",
110
+ " </tr>\n",
111
+ " <tr>\n",
112
+ " <th>2</th>\n",
113
+ " <td>Answer this question truthfully</td>\n",
114
+ " <td>Can you provide me with information regarding ...</td>\n",
115
+ " <td>Two Japanese scientists commenced research int...</td>\n",
116
+ " </tr>\n",
117
+ " <tr>\n",
118
+ " <th>3</th>\n",
119
+ " <td>Answer this question truthfully</td>\n",
120
+ " <td>What are the historical background and symptom...</td>\n",
121
+ " <td>Symptoms of vulvovaginitis caused by Candida s...</td>\n",
122
+ " </tr>\n",
123
+ " <tr>\n",
124
+ " <th>4</th>\n",
125
+ " <td>Answer this question truthfully</td>\n",
126
+ " <td>What does the \"Hypotension: Resident Survival ...</td>\n",
127
+ " <td>Hypotension is the term for low blood pressure...</td>\n",
128
+ " </tr>\n",
129
+ " </tbody>\n",
130
+ "</table>\n",
131
+ "</div>"
132
+ ],
133
+ "text/plain": [
134
+ " instruction \\\n",
135
+ "0 Answer this question truthfully \n",
136
+ "1 Answer this question truthfully \n",
137
+ "2 Answer this question truthfully \n",
138
+ "3 Answer this question truthfully \n",
139
+ "4 Answer this question truthfully \n",
140
+ "\n",
141
+ " input \\\n",
142
+ "0 Can you provide an overview of the lung's squa... \n",
143
+ "1 What does \"Clear: cell\" mean? \n",
144
+ "2 Can you provide me with information regarding ... \n",
145
+ "3 What are the historical background and symptom... \n",
146
+ "4 What does the \"Hypotension: Resident Survival ... \n",
147
+ "\n",
148
+ " output \n",
149
+ "0 Squamous cell carcinoma of the lung may be cla... \n",
150
+ "1 Clear cell tumors are part of the surface epit... \n",
151
+ "2 Two Japanese scientists commenced research int... \n",
152
+ "3 Symptoms of vulvovaginitis caused by Candida s... \n",
153
+ "4 Hypotension is the term for low blood pressure... "
154
+ ]
155
+ },
156
+ "metadata": {},
157
+ "output_type": "display_data"
158
+ }
159
+ ],
160
+ "source": [
161
+ "# Ajusta la ruta según tu organización de carpetas\n",
162
+ "raw_path = Path(\"../data/raw\")\n",
163
+ "wikidoc_file = raw_path / \"medical_meadow_wikidoc.csv\"\n",
164
+ "medqa_file = raw_path / \"medqa.csv\"\n",
165
+ "\n",
166
+ "wikidoc = pd.read_csv(wikidoc_file)\n",
167
+ "medqa = pd.read_csv(medqa_file)\n",
168
+ "\n",
169
+ "print(\"===== wikidoc.info() =====\")\n",
170
+ "wikidoc.info()\n",
171
+ "print(\"\\n===== wikidoc.head() =====\")\n",
172
+ "display(wikidoc.head())"
173
+ ]
174
+ },
175
+ {
176
+ "cell_type": "code",
177
+ "execution_count": 4,
178
+ "metadata": {},
179
+ "outputs": [
180
+ {
181
+ "name": "stdout",
182
+ "output_type": "stream",
183
+ "text": [
184
+ "\n",
185
+ "===== medqa.info() =====\n",
186
+ "<class 'pandas.core.frame.DataFrame'>\n",
187
+ "RangeIndex: 10178 entries, 0 to 10177\n",
188
+ "Data columns (total 6 columns):\n",
189
+ " # Column Non-Null Count Dtype \n",
190
+ "--- ------ -------------- ----- \n",
191
+ " 0 question 10178 non-null object\n",
192
+ " 1 answer 10177 non-null object\n",
193
+ " 2 options 10178 non-null object\n",
194
+ " 3 meta_info 10178 non-null object\n",
195
+ " 4 answer_idx 10178 non-null object\n",
196
+ " 5 metamap_phrases 10178 non-null object\n",
197
+ "dtypes: object(6)\n",
198
+ "memory usage: 477.2+ KB\n",
199
+ "\n",
200
+ "===== medqa.head() =====\n"
201
+ ]
202
+ },
203
+ {
204
+ "data": {
205
+ "text/html": [
206
+ "<div>\n",
207
+ "<style scoped>\n",
208
+ " .dataframe tbody tr th:only-of-type {\n",
209
+ " vertical-align: middle;\n",
210
+ " }\n",
211
+ "\n",
212
+ " .dataframe tbody tr th {\n",
213
+ " vertical-align: top;\n",
214
+ " }\n",
215
+ "\n",
216
+ " .dataframe thead th {\n",
217
+ " text-align: right;\n",
218
+ " }\n",
219
+ "</style>\n",
220
+ "<table border=\"1\" class=\"dataframe\">\n",
221
+ " <thead>\n",
222
+ " <tr style=\"text-align: right;\">\n",
223
+ " <th></th>\n",
224
+ " <th>question</th>\n",
225
+ " <th>answer</th>\n",
226
+ " <th>options</th>\n",
227
+ " <th>meta_info</th>\n",
228
+ " <th>answer_idx</th>\n",
229
+ " <th>metamap_phrases</th>\n",
230
+ " </tr>\n",
231
+ " </thead>\n",
232
+ " <tbody>\n",
233
+ " <tr>\n",
234
+ " <th>0</th>\n",
235
+ " <td>A 23-year-old pregnant woman at 22 weeks gesta...</td>\n",
236
+ " <td>Nitrofurantoin</td>\n",
237
+ " <td>{'A': 'Ampicillin', 'B': 'Ceftriaxone', 'C': '...</td>\n",
238
+ " <td>step2&amp;3</td>\n",
239
+ " <td>D</td>\n",
240
+ " <td>['23 year old pregnant woman', 'weeks presents...</td>\n",
241
+ " </tr>\n",
242
+ " <tr>\n",
243
+ " <th>1</th>\n",
244
+ " <td>A 3-month-old baby died suddenly at night whil...</td>\n",
245
+ " <td>Placing the infant in a supine position on a f...</td>\n",
246
+ " <td>{'A': 'Placing the infant in a supine position...</td>\n",
247
+ " <td>step2&amp;3</td>\n",
248
+ " <td>A</td>\n",
249
+ " <td>['3 month old baby died', 'night', 'asleep', '...</td>\n",
250
+ " </tr>\n",
251
+ " <tr>\n",
252
+ " <th>2</th>\n",
253
+ " <td>A mother brings her 3-week-old infant to the p...</td>\n",
254
+ " <td>Abnormal migration of ventral pancreatic bud</td>\n",
255
+ " <td>{'A': 'Abnormal migration of ventral pancreati...</td>\n",
256
+ " <td>step1</td>\n",
257
+ " <td>A</td>\n",
258
+ " <td>['mother', 'week old infant', \"pediatrician's ...</td>\n",
259
+ " </tr>\n",
260
+ " <tr>\n",
261
+ " <th>3</th>\n",
262
+ " <td>A pulmonary autopsy specimen from a 58-year-ol...</td>\n",
263
+ " <td>Thromboembolism</td>\n",
264
+ " <td>{'A': 'Thromboembolism', 'B': 'Pulmonary ische...</td>\n",
265
+ " <td>step1</td>\n",
266
+ " <td>A</td>\n",
267
+ " <td>['pulmonary autopsy specimen', '58 year old wo...</td>\n",
268
+ " </tr>\n",
269
+ " <tr>\n",
270
+ " <th>4</th>\n",
271
+ " <td>A 20-year-old woman presents with menorrhagia ...</td>\n",
272
+ " <td>Von Willebrand disease</td>\n",
273
+ " <td>{'A': 'Hemophilia A', 'B': 'Lupus anticoagulan...</td>\n",
274
+ " <td>step1</td>\n",
275
+ " <td>D</td>\n",
276
+ " <td>['20 year old woman presents', 'menorrhagia', ...</td>\n",
277
+ " </tr>\n",
278
+ " </tbody>\n",
279
+ "</table>\n",
280
+ "</div>"
281
+ ],
282
+ "text/plain": [
283
+ " question \\\n",
284
+ "0 A 23-year-old pregnant woman at 22 weeks gesta... \n",
285
+ "1 A 3-month-old baby died suddenly at night whil... \n",
286
+ "2 A mother brings her 3-week-old infant to the p... \n",
287
+ "3 A pulmonary autopsy specimen from a 58-year-ol... \n",
288
+ "4 A 20-year-old woman presents with menorrhagia ... \n",
289
+ "\n",
290
+ " answer \\\n",
291
+ "0 Nitrofurantoin \n",
292
+ "1 Placing the infant in a supine position on a f... \n",
293
+ "2 Abnormal migration of ventral pancreatic bud \n",
294
+ "3 Thromboembolism \n",
295
+ "4 Von Willebrand disease \n",
296
+ "\n",
297
+ " options meta_info answer_idx \\\n",
298
+ "0 {'A': 'Ampicillin', 'B': 'Ceftriaxone', 'C': '... step2&3 D \n",
299
+ "1 {'A': 'Placing the infant in a supine position... step2&3 A \n",
300
+ "2 {'A': 'Abnormal migration of ventral pancreati... step1 A \n",
301
+ "3 {'A': 'Thromboembolism', 'B': 'Pulmonary ische... step1 A \n",
302
+ "4 {'A': 'Hemophilia A', 'B': 'Lupus anticoagulan... step1 D \n",
303
+ "\n",
304
+ " metamap_phrases \n",
305
+ "0 ['23 year old pregnant woman', 'weeks presents... \n",
306
+ "1 ['3 month old baby died', 'night', 'asleep', '... \n",
307
+ "2 ['mother', 'week old infant', \"pediatrician's ... \n",
308
+ "3 ['pulmonary autopsy specimen', '58 year old wo... \n",
309
+ "4 ['20 year old woman presents', 'menorrhagia', ... "
310
+ ]
311
+ },
312
+ "metadata": {},
313
+ "output_type": "display_data"
314
+ }
315
+ ],
316
+ "source": [
317
+ "\n",
318
+ "print(\"\\n===== medqa.info() =====\")\n",
319
+ "medqa.info()\n",
320
+ "print(\"\\n===== medqa.head() =====\")\n",
321
+ "display(medqa.head())\n"
322
+ ]
323
+ },
324
+ {
325
+ "cell_type": "code",
326
+ "execution_count": 5,
327
+ "metadata": {},
328
+ "outputs": [
329
+ {
330
+ "ename": "SyntaxError",
331
+ "evalue": "invalid syntax (2686254339.py, line 3)",
332
+ "output_type": "error",
333
+ "traceback": [
334
+ "\u001b[1;36m Cell \u001b[1;32mIn[5], line 3\u001b[1;36m\u001b[0m\n\u001b[1;33m Aquí podemos hacer una unificación mínima o simplemente quedarnos con columnas que nos interesen.\u001b[0m\n\u001b[1;37m ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m invalid syntax\n"
335
+ ]
336
+ }
337
+ ],
338
+ "source": [
339
+ "## 3. Unificar o manipular datos\n",
340
+ "\n",
341
+ "Aquí podemos hacer una unificación mínima o simplemente quedarnos con columnas que nos interesen.\n"
342
+ ]
343
+ },
344
+ {
345
+ "cell_type": "code",
346
+ "execution_count": null,
347
+ "metadata": {},
348
+ "outputs": [],
349
+ "source": [
350
+ "# Copias de los dataframes\n",
351
+ "df_wikidoc = wikidoc.copy()\n",
352
+ "df_wikidoc.rename(columns={\"instruction\": \"consulta\", \"output\": \"respuesta\"}, inplace=True)\n",
353
+ "\n",
354
+ "# Un ejemplo: concatenar 'instruction' e 'input'\n",
355
+ "df_wikidoc[\"consulta\"] = df_wikidoc[\"consulta\"].fillna(\"\") + \": \" + df_wikidoc[\"input\"].fillna(\"\")\n",
356
+ "df_wikidoc = df_wikidoc[[\"consulta\", \"respuesta\"]]\n",
357
+ "\n",
358
+ "df_medqa = medqa.copy()\n",
359
+ "df_medqa.rename(columns={\"question\": \"consulta\", \"answer\": \"respuesta\"}, inplace=True)\n",
360
+ "\n",
361
+ "# Unificación mínima\n",
362
+ "df_unificado = pd.concat(\n",
363
+ " [df_wikidoc, df_medqa[[\"consulta\", \"respuesta\"]]],\n",
364
+ " ignore_index=True\n",
365
+ ")\n",
366
+ "\n",
367
+ "# Eliminamos filas con NaN en consulta/respuesta\n",
368
+ "df_unificado.dropna(subset=[\"consulta\", \"respuesta\"], inplace=True)\n",
369
+ "\n",
370
+ "print(\"Tamaño de df_unificado:\", df_unificado.shape)\n",
371
+ "df_unificado.head()\n"
372
+ ]
373
+ },
374
+ {
375
+ "cell_type": "markdown",
376
+ "metadata": {},
377
+ "source": [
378
+ "## 4. Generación de Datos Sintéticos\n",
379
+ "\n",
380
+ "Definimos una función que toma ejemplos del dataframe unificado y genera variaciones.\n"
381
+ ]
382
+ },
383
+ {
384
+ "cell_type": "markdown",
385
+ "metadata": {},
386
+ "source": []
387
+ },
388
+ {
389
+ "cell_type": "code",
390
+ "execution_count": null,
391
+ "metadata": {},
392
+ "outputs": [],
393
+ "source": [
394
+ "def generar_datos_sinteticos(df, n=10):\n",
395
+ " \"\"\"\n",
396
+ " Genera un conjunto de datos sintéticos basados en el dataframe unificado.\n",
397
+ " - Toma filas aleatorias de 'consulta' y 'respuesta'.\n",
398
+ " - Modifica ligeramente el texto para simular nuevas entradas.\n",
399
+ " \n",
400
+ " Retorna un DataFrame con las columnas 'consulta_sintetica' y 'respuesta_sintetica'.\n",
401
+ " \"\"\"\n",
402
+ " sampled_rows = df.sample(n, replace=True)\n",
403
+ "\n",
404
+ " consultas_sinteticas = []\n",
405
+ " respuestas_sinteticas = []\n",
406
+ "\n",
407
+ " modificaciones = [\n",
408
+ " \"(Por favor, detalle más los síntomas)\",\n",
409
+ " \"(Caso leve, pero podría complicarse)\",\n",
410
+ " \"(Consulta para un familiar)\",\n",
411
+ " \"(Síntomas descritos hace 2 días)\",\n",
412
+ " \"(Sugerir revisión médica)\"\n",
413
+ " ]\n",
414
+ "\n",
415
+ " for _, row in sampled_rows.iterrows():\n",
416
+ " consulta_original = row[\"consulta\"]\n",
417
+ " respuesta_original = row[\"respuesta\"]\n",
418
+ "\n",
419
+ " # Elegimos una modificación aleatoria\n",
420
+ " extra = random.choice(modificaciones)\n",
421
+ " nueva_consulta = f\"{consulta_original} {extra}\"\n",
422
+ "\n",
423
+ " nueva_respuesta = (\n",
424
+ " respuesta_original\n",
425
+ " + \"\\nNota: Esta es una versión sintética para pruebas.\"\n",
426
+ " )\n",
427
+ "\n",
428
+ " consultas_sinteticas.append(nueva_consulta)\n",
429
+ " respuestas_sinteticas.append(nueva_respuesta)\n",
430
+ "\n",
431
+ " df_sintetico = pd.DataFrame({\n",
432
+ " \"consulta_sintetica\": consultas_sinteticas,\n",
433
+ " \"respuesta_sintetica\": respuestas_sinteticas\n",
434
+ " })\n",
435
+ "\n",
436
+ " return df_sintetico\n",
437
+ "\n",
438
+ "# Generamos un ejemplo de datos sintéticos\n",
439
+ "df_sintetico = generar_datos_sinteticos(df_unificado, n=15)\n",
440
+ "print(\"Tamaño de df_sintetico:\", df_sintetico.shape)\n",
441
+ "df_sintetico.head(10)\n"
442
+ ]
443
+ }
444
+ ],
445
+ "metadata": {
446
+ "kernelspec": {
447
+ "display_name": "carecompanion",
448
+ "language": "python",
449
+ "name": "python3"
450
+ },
451
+ "language_info": {
452
+ "codemirror_mode": {
453
+ "name": "ipython",
454
+ "version": 3
455
+ },
456
+ "file_extension": ".py",
457
+ "mimetype": "text/x-python",
458
+ "name": "python",
459
+ "nbconvert_exporter": "python",
460
+ "pygments_lexer": "ipython3",
461
+ "version": "3.9.21"
462
+ }
463
+ },
464
+ "nbformat": 4,
465
+ "nbformat_minor": 2
466
+ }
app.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Importar bibliotecas necesarias
2
+ from transformers import pipeline
3
+ import gradio as gr
4
+
5
+ # Cargar el modelo (usamos Mistral como base inicial)
6
+ health_nlp = pipeline("text-generation", model="mistralai/Mixtral-8x7B-Instruct-v0.1")
7
+
8
+ # Función de triaje básico
9
+ def triage_symptoms(symptoms):
10
+ # Prompt claro para el modelo
11
+ prompt = (
12
+ f"Evalúa los siguientes síntomas: {symptoms}. "
13
+ "Sugiere pasos a seguir (por ejemplo, descansar, visitar un médico) "
14
+ "y añade un disclaimer legal indicando que esto no sustituye una consulta médica."
15
+ )
16
+ # Generar respuesta
17
+ response = health_nlp(prompt, max_length=150, num_return_sequences=1)[0]["generated_text"]
18
+ # Asegurar el disclaimer
19
+ disclaimer = "\n\n*Nota: Este es un asistente de IA y no sustituye el consejo de un profesional médico. Consulta a un doctor para un diagnóstico preciso.*"
20
+ return response + disclaimer
21
+
22
+ # Crear la interfaz con Gradio
23
+ interface = gr.Interface(
24
+ fn=triage_symptoms,
25
+ inputs=gr.Textbox(label="Describe tus síntomas", placeholder="Ejemplo: Tengo tos y fiebre desde ayer"),
26
+ outputs=gr.Textbox(label="Sugerencias"),
27
+ title="CareCompanion - Asistente de Triaje Básico",
28
+ description="Ingresa tus síntomas y obtén sugerencias básicas. No reemplaza una consulta médica."
29
+ )
30
+
31
+ # Lanzar la aplicación
32
+ interface.launch()
notas.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ Diseño de la API Interna:
2
+ Diseñar una API que conecte la herramienta de asesoramiento con la de triaje, permitiendo que, al detectar palabras clave de alerta en una consulta, se redirija automáticamente o se active el "modo triaje". Esto implicaría definir endpoints, protocolos de comunicación y validación de datos.
3
+
4
+ Algoritmos de NLP:
5
+ Profundizar en el uso de modelos de lenguaje entrenados en datos médicos para extraer entidades y evaluar la urgencia. Podríamos hablar de técnicas de tokenización, extracción de entidades, y uso de modelos preentrenados (por ejemplo, BioBERT o modelos adaptados) para mejorar la precisión en la detección de síntomas y señales de alarma.
6
+
7
+ Generación de Datos Sintéticos (Data Augmentation):
8
+ Explorar técnicas como back translation, parafraseo o generación de casos con modelos de lenguaje, que permitan ampliar el conjunto de datos. Esto es muy útil para simular variaciones en las consultas, tanto en el asesoramiento como en el triaje, y asegurar que los algoritmos se robustezcan frente a diferentes redacciones o combinaciones de síntomas.
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ transformers
2
+ torch
3
+ gradio
tools/asesoramiento.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ asesoramiento_tool.py
3
+
4
+ Esta herramienta procesa una consulta médica en lenguaje natural y retorna una respuesta orientativa.
5
+ Si se detectan señales de alerta (por ejemplo, "dolor intenso", "falta de aire", etc.), se recomienda al usuario
6
+ realizar una evaluación en la herramienta de atención primaria.
7
+ """
8
+
9
+ def asesorar_consulta(query):
10
+ """
11
+ Procesa una consulta médica en lenguaje natural y retorna una respuesta orientativa.
12
+
13
+ Parámetros:
14
+ - query: cadena de texto con la consulta del usuario.
15
+
16
+ Retorna:
17
+ - dict con:
18
+ - 'respuesta': mensaje de asesoramiento.
19
+ - 'alerta': booleano que indica si se detectaron señales de alerta.
20
+ """
21
+ # Lista de palabras clave que indican señales de alerta
22
+ urgent_keywords = [
23
+ "dolor intenso",
24
+ "falta de aire",
25
+ "desmayo",
26
+ "pérdida de conciencia",
27
+ "urgente"
28
+ ]
29
+
30
+ query_lower = query.lower()
31
+ alerta = any(keyword in query_lower for keyword in urgent_keywords)
32
+
33
+ respuesta = ""
34
+ if alerta:
35
+ respuesta += "Se detectan señales de alerta en su consulta. "
36
+ respuesta += "Le recomendamos realizar una evaluación de triaje en la herramienta de atención primaria.\n\n"
37
+
38
+ # Respuesta orientativa general
39
+ respuesta += "Según la información proporcionada, se sugiere que la condición descrita puede requerir un seguimiento médico. "
40
+ respuesta += "Recuerde que esta respuesta es orientativa y no sustituye una consulta médica profesional. "
41
+ respuesta += "Si los síntomas empeoran o se presentan nuevos síntomas, por favor, consulte a un especialista."
42
+
43
+ return {"respuesta": respuesta, "alerta": alerta}
44
+
45
+ if __name__ == "__main__":
46
+ # Ejemplo de consulta del usuario
47
+ consulta = "Tengo dolor intenso en la cabeza y me siento mareado. ¿Qué debo hacer?"
48
+
49
+ # Uso de la herramienta de asesoramiento
50
+ resultado = asesorar_consulta(consulta)
51
+ print("Respuesta del Asistente:")
52
+ print(resultado["respuesta"])
53
+ print("¿Se detectó alerta?", resultado["alerta"])
tools/triaje_tool.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # %% [markdown]
2
+ # # Herramienta de Triaje - Atención Primaria
3
+ #
4
+ # Esta notebook implementa una herramienta de triaje para la atención primaria, evaluando síntomas, intensidad, duración y antecedentes del paciente. La idea es asignar un puntaje de riesgo y generar una recomendación sobre la necesidad de atención médica urgente o no.
5
+
6
+ # %% [markdown]
7
+ # ## Definición de Funciones
8
+ #
9
+ # En esta sección definimos:
10
+ # - `evaluar_triaje`: Evalúa el puntaje de riesgo según los datos ingresados.
11
+ # - `recomendar_atencion`: Emite una recomendación basada en el puntaje obtenido.
12
+ # - `triaje_primer_tool`: Función principal que integra el proceso.
13
+
14
+ # %%
15
+ import re
16
+
17
+ def evaluar_triaje(sintomas, intensidad, duracion, antecedentes):
18
+ """
19
+ Evalúa el nivel de riesgo basado en síntomas, intensidad, duración y antecedentes.
20
+
21
+ Parámetros:
22
+ - sintomas: texto descriptivo de los síntomas.
23
+ - intensidad: nivel de intensidad (ej. "leve", "moderada", "intensa").
24
+ - duracion: duración de los síntomas (en horas, como cadena numérica o número).
25
+ - antecedentes: antecedentes médicos relevantes (texto).
26
+
27
+ Retorna:
28
+ - score: puntaje numérico que indica el nivel de riesgo.
29
+ """
30
+ score = 0
31
+
32
+ # Evaluación de síntomas críticos
33
+ sintomas_criticos = ["dolor intenso", "falta de aire", "desmayo", "pérdida de conciencia"]
34
+ for sintoma in sintomas_criticos:
35
+ if sintoma in sintomas.lower():
36
+ score += 5
37
+
38
+ # Evaluación de síntomas moderados
39
+ sintomas_moderados = ["fiebre alta", "dolor en el pecho", "mareos", "náusea"]
40
+ for sintoma in sintomas_moderados:
41
+ if sintoma in sintomas.lower():
42
+ score += 3
43
+
44
+ # Ponderación basada en la intensidad
45
+ intensidad = intensidad.lower()
46
+ if intensidad in ["intensa", "alta"]:
47
+ score += 3
48
+ elif intensidad == "moderada":
49
+ score += 2
50
+ elif intensidad in ["leve", "baja"]:
51
+ score += 1
52
+
53
+ # Ponderación según la duración (suponiendo que es en horas)
54
+ try:
55
+ duracion = float(duracion)
56
+ if duracion >= 24:
57
+ score += 3
58
+ elif duracion >= 6:
59
+ score += 2
60
+ else:
61
+ score += 1
62
+ except ValueError:
63
+ print("Error: La duración debe ser un valor numérico.")
64
+
65
+ # Evaluación de antecedentes médicos relevantes
66
+ antecedentes_relevantes = ["cardiopatía", "hipertensión", "diabetes"]
67
+ for item in antecedentes_relevantes:
68
+ if item in antecedentes.lower():
69
+ score += 2
70
+
71
+ return score
72
+
73
+ def recomendar_atencion(score):
74
+ """
75
+ Genera una recomendación basada en el puntaje de riesgo obtenido.
76
+
77
+ Retorna:
78
+ - recomendacion: mensaje de acción a seguir.
79
+ """
80
+ if score >= 12:
81
+ return "Se recomienda atención de emergencia. Llame a los servicios de urgencia."
82
+ elif score >= 7:
83
+ return "Se sugiere acudir a consulta médica lo antes posible."
84
+ else:
85
+ return "Puede programar una consulta médica de rutina."
86
+
87
+ def triaje_primer_tool(data):
88
+ """
89
+ Función principal para la herramienta de triaje.
90
+
91
+ Parámetro:
92
+ - data: diccionario con las claves 'sintomas', 'intensidad', 'duracion', 'antecedentes'
93
+
94
+ Retorna:
95
+ - Diccionario con el 'score' obtenido y la 'recomendacion'
96
+ """
97
+ score = evaluar_triaje(
98
+ data.get("sintomas", ""),
99
+ data.get("intensidad", ""),
100
+ data.get("duracion", "0"),
101
+ data.get("antecedentes", "")
102
+ )
103
+ recomendacion = recomendar_atencion(score)
104
+ return {
105
+ "score": score,
106
+ "recomendacion": recomendacion
107
+ }
108
+
109
+ # %% [markdown]
110
+ # ## Ejemplo de Uso
111
+ #
112
+ # En la siguiente celda se muestra un ejemplo de cómo utilizar la herramienta con datos de entrada simulados.
113
+
114
+ # %%
115
+ # Ejemplo de datos de entrada
116
+ ejemplo_data = {
117
+ "sintomas": "El paciente presenta dolor intenso en el pecho y falta de aire.",
118
+ "intensidad": "intensa",
119
+ "duracion": "8", # en horas
120
+ "antecedentes": "El paciente tiene antecedentes de hipertensión."
121
+ }
122
+
123
+ # Ejecución de la herramienta de triaje
124
+ resultado = triaje_primer_tool(ejemplo_data)
125
+ print("Puntaje de riesgo:", resultado["score"])
126
+ print("Recomendación:", resultado["recomendacion"])