ACCESO PRIVADO

Investigación

Introduce la contraseña para consultar la hoja de ruta.

Hoja de ruta de la tesis

Del corpus a la redacción.

Una secuencia para fundamentar el trabajo, preparar el material, codificarlo con rigor, analizar los resultados y convertirlos en una tesis clara y verificable.

00

Epistemología

Fundamentar la investigación desde el constructivismo relacional.

01

Corpus

Reunir y ordenar el conjunto de transcripciones que forman la base del estudio.

02

Desidentificación

Preparar las transcripciones protegiendo la identidad y la confidencialidad de los participantes.

03

Segmentación

Dividir el corpus protegido en unidades consistentes y adecuadas para el análisis.

04

Codificación humana interjuez

Entrenar a los jueces, aplicar el sistema de categorías y dejar trazabilidad de las decisiones.

05

Codificación con IA local

Programar las instrucciones para los modelos IA, ejecutar los programas y documentar todo.

06

Análisis

Evaluar codificaciones y contrastar resultados humanos-IA + IA-IA.

07

Redacción

Integrar epistemología, método, resultados y discusión en una narrativa académica coherente.

Guía de reproducción

Guía completa paso a paso

Procedimiento para rehacer el estudio desde cero con los archivos ya en tu ordenador: qué haces en cada paso, los comandos de Terminal y cómo comprobar el resultado.

Cómo usar esta guía

Orden de trabajo: la guía recorre los 33 pasos en orden, desde la preparación del equipo (paso 1) hasta el cierre y archivo del estudio (paso 33). Los pasos con letra (15a y 17b) se intercalan entre los indicados.

Reglas de oro

  • Todo se procesa en tu Mac, sin conexión a servicios externos. No pegues texto de las transcripciones en ningún asistente en línea, y esto incluye a Claude.
  • Las hojas de Excel de 04_jueces y 01_original contienen texto de sesiones: no las subas a la nube, no las envíes por correo y consérvalas solo en el ordenador cifrado y en los USB cifrados.
  • En las hojas solo se rellenan las columnas amarillas; no se añaden, borran ni reordenan filas.
  • Los scripts se ejecutan siempre desde la carpeta codigo, con el entorno activado. Al empezar cada sesión de trabajo, abre Terminal y escribe:
cd ~/Desktop/Estudio_HSS/codigo
source ../.venv/bin/activate

El indicador de Terminal debe empezar por (.venv). Si un comando da error, copia el mensaje completo antes de tocar nada.

Quién es quién. D es quien dirige el estudio (tú). J son los dos jueces (A y B). El juez A es quien revisa la segmentación.

Si pierdes archivos. Los scripts, las plantillas y los datos son cosas distintas:

  • Los scripts (codigo) y las plantillas (06_instrucciones) se restauran desde tu copia de seguridad cifrada, no desde esta página.
  • Los datos (transcripciones, hojas de revisión, hojas de los jueces) solo existen en tu Mac. Haz las copias de seguridad solo en dos USB cifrados con contraseña (una copia periódica y una segunda copia en otro USB igual, guardado en un lugar fijo y sin otros usos) y no las dejes en la nube.

Fase 0

Preparación del equipo

pasos 1 a 4
1Preparar el equipo

Qué haces: dejar el Mac listo para trabajar con datos confidenciales.

  1. Activa FileVault (Ajustes del Sistema > Privacidad y seguridad > FileVault) y comprueba en Terminal:
fdesetup status

Debe responder «FileVault is On.».

  1. Comprueba que iCloud Drive no sincroniza «Carpetas Escritorio y Documentos» (ni OneDrive, Dropbox o Google Drive el Escritorio). La carpeta del estudio y la carpeta Corpus van en el Escritorio (en Terminal, ~/Desktop).
  2. No uses Time Machine ni copias en la nube: las copias de seguridad se hacen solo en los dos USB cifrados con contraseña.
  3. En Word y Excel, desactiva las experiencias conectadas que analizan el contenido y el guardado automático en la nube. No uses Copilot ni otros asistentes con estos archivos.
  4. Para editar texto plano usa VS Code con las funciones de IA desactivadas, o TextEdit en modo texto (Formato > Convertir a texto sin formato) con las comillas inteligentes desactivadas.
  5. Desactiva la wifi siempre que trabajes con el corpus. Solo hace falta conexión en los pasos 2, 3 y 24, y en esos momentos no se abre ningún archivo del corpus.

Resultado: FileVault activo y nada sincronizado con la nube.

2Crear la carpeta del estudio

Qué haces: crear las carpetas, copiar los scripts y las plantillas e iniciar el diario.

  1. Abre Terminal (Aplicaciones > Utilidades > Terminal) y crea las carpetas:
cd ~/Desktop
mkdir -p Estudio_HSS/{00_admin,01_original/transcripciones,02_protegido}
mkdir -p Estudio_HSS/{03_unidades,04_jueces,05_modelos,06_instrucciones}
mkdir -p Estudio_HSS/{07_ejecuciones,08_resultados,codigo}
  1. Copia dentro de Estudio_HSS/codigo los 27 scripts (comun.py, de p04 a p33 y los de los pasos con letra, p14b y p17b) y dentro de Estudio_HSS/06_instrucciones los 7 archivos de plantillas (ver el Anexo). Hazlo con el Finder desde tu copia de los archivos.
  2. Crea el diario y ábrelo:
cd ~/Desktop/Estudio_HSS
printf "# Diario del estudio\n\n" > 00_admin/diario.md
open -e 00_admin/diario.md

Escribe en él una línea como esta y guarda:

- 2026-10-04: Equipo preparado: FileVault activo, sin iCloud, copias cifradas.
  1. No usas git. No hace falta hacer nada más.

Resultado: la carpeta Estudio_HSS con sus subcarpetas, los scripts, las plantillas y el diario.

Comprobación: ls codigo muestra comun.py y los scripts de p04 a p33.

3Instalar Python y las bibliotecas

Qué haces: crear un entorno de Python aislado con las bibliotecas.

  1. Instala Python 3.12 con el instalador de macOS de python.org («macOS 64-bit universal2 installer»). El Python que trae el Mac (3.9) es demasiado antiguo: la instalación de spaCy falla con él (error de thinc). Cierra Terminal y ábrela de nuevo. python3.12 --version debe indicar 3.12.x.
  2. Con conexión, y con la carpeta codigo ya dentro de Estudio_HSS:
cd ~/Desktop/Estudio_HSS
python3.12 -m venv .venv
source .venv/bin/activate
python --version
python -m pip install --upgrade pip
pip install pandas numpy scikit-learn openpyxl python-docx spacy matplotlib
python -m spacy download en_core_web_lg
pip freeze > codigo/requirements.txt

python --version debe indicar 3.12.x; si indica otra, no sigas (usa python3.12 para crear el entorno, no python3). Después desactiva la wifi.

  1. Comprobación. Ninguna de las dos órdenes debe dar error:
python -c "import pandas, sklearn, openpyxl, docx, spacy, matplotlib"
python -c "import spacy; spacy.load('en_core_web_lg')"

Resultado: la carpeta .venv y codigo/requirements.txt.

4Importar las transcripciones

Qué haces: copiar las 78 transcripciones al estudio, con el código de cada sesión.

La carpeta ~/Desktop/Corpus tiene una subcarpeta por serie con el nombre sin «Therapy Over Time» (Rational Emotive Behavior, Cognitive, Behavioral, Emotion-Focused, Person-Centered, Existential-Humanistic, Brief Dynamic, Psychoanalytic, Accelerated Experiential Dynamic, Constructivist, Narrative, Feminist, Relational-Cultural) y, dentro, 1.docx a 6.docx. En tu caso las transcripciones están en ~/Desktop/Corpus/Original.

python p04_importar.py ~/Desktop/Corpus/Original

El script comprueba las 13 carpetas y las 6 sesiones de cada una; si algo falla, no copia nada y lo indica. Si te dice que una carpeta «no corresponde a ninguna serie», la ruta es la equivocada: usa la carpeta que contiene directamente las 13 subcarpetas.

Resultado: 78 archivos en 01_original/transcripciones/S01 a S13 y 00_admin/importacion.csv. Termina con «Correcto: 78 transcripciones copiadas en 01_original/transcripciones».

Cuando el paso 5 confirme las 78, guarda la carpeta Corpus solo en el ordenador cifrado y en los USB cifrados, fuera de carpetas sincronizadas.


Fase 1

Preparación del corpus

pasos 5 a 8
5Comprobar las transcripciones

Qué haces: limpiar las transcripciones, comprobar que están las 78 y registrar la huella de cada archivo.

  1. Limpia cada transcripción antes de continuar. Cada .docx debe contener solo la conversación (nada de títulos, notas ni texto ajeno). Se hace en Word, una vez, y debe estar hecho antes de bloquearlas.
  2. Ejecuta:
python p05_inventario.py

Si falta algún archivo, el script lo indica («Faltan: S03/S03_s4.docx») y se detiene. Si sobra alguno, lo indica con «Sobran»: bórralo para que en cada serie queden solo sus 6 transcripciones.

  1. Protege las transcripciones contra cambios accidentales:
chmod -R a-w ../01_original/transcripciones

Resultado: 00_admin/inventario.csv (una fila por sesión) y 00_admin/series.csv. Termina con «Correcto: 78 transcripciones en el inventario».

6Asignar los hablantes

Qué haces: decir qué etiqueta es el terapeuta y cuál el paciente en cada serie.

  1. Ejecuta:
python p06_hablantes.py
  1. Abre 01_original/hablantes.xlsx. Hay una fila por serie y etiqueta. En la columna amarilla rol escribe:
  • T si la etiqueta es el terapeuta;
  • P si es el paciente (las etiquetas Unknown son el paciente);
  • X si es otra voz o un encabezado que se excluye (narrador, «END OF SESSION»);
  • N si no es una etiqueta sino el comienzo de una frase con dos puntos, que se conserva como texto.
  1. Guarda y cierra. Ninguna fila debe quedar sin rol. Revisa las etiquetas con pocas apariciones: su ejemplo indica si son un hablante o una frase.

Nota sobre el formato de tus transcripciones: cada línea empieza con la marca de tiempo pegada al nombre (00:15:20Nombre y un espacio duro antes del texto). El script ya lo entiende. Si el script dice que «no se ha reconocido ninguna etiqueta de hablante», el formato de esa transcripción no es ninguno de los admitidos.

Resultado: hablantes.xlsx con un rol para cada etiqueta.

7Convertir a turnos

Qué haces: pasar cada sesión a una tabla de turnos (hablante y texto).

  1. Ejecuta:
python p07_convertir.py
  1. Revisa los avisos del final (también en 00_admin/informe_conversion.csv): «líneas sin hablante» (unas pocas son normales), «falta terapeuta o paciente» (revisa los roles de esa serie), «menos de 20 turnos» (transcripción incompleta) y «turnos repetidos» (posible pasaje duplicado). En tu caso hubo avisos en 4 sesiones (S02_s2, S05_s3, S07_s2, S13_s5); los revisaste y los turnos estaban bien.
  2. Abre dos o tres tablas de 01_original/turnos y compáralas con su .docx: primer y último turno, y algún turno largo.
  3. Solo si hay que corregir una transcripción: permite cambios en su serie, corrige el documento en Word, vuelve a protegerla y repite los pasos 5 y 7. Anota la corrección en el diario.
chmod -R u+w ../01_original/transcripciones/S03
open ../01_original/transcripciones/S03/S03_s4.docx
chmod -R a-w ../01_original/transcripciones/S03
python p05_inventario.py
python p07_convertir.py

Resultado: 01_original/turnos/S01_s1.csv y siguientes, con las columnas serie, sesion, turno, hablante (T o P) y texto. El carácter «|» del texto se cambia por «/», porque queda reservado.

8Sortear las sesiones de desarrollo

Qué haces: elegir al azar una sesión de cada serie para el conjunto de desarrollo (13 sesiones); las otras 65 son la evaluación.

  1. La semilla es un número entero que se anota en el diario antes de usarla. Para reproducir el estudio original se usó la fecha 20261004.
  2. Ejecuta con esa semilla:
python p08_sorteo.py 20261004

Resultado: la columna conjunto del inventario dice desarrollo o evaluacion. Hay 13 sesiones de desarrollo y 65 de evaluación. El sorteo no se puede repetir.


Fase 2

Desidentificación

pasos 9 a 13

Un programa local sustituye los identificadores por códigos estables dentro de cada serie. Después una persona revisa todo el corpus y aprueba cada sesión. Solo lo aprobado pasa al análisis.

Identificador Tipo en nombres.xlsx Código
Paciente PACIENTE [CLIENT]
Terapeuta TERAPEUTA [THERAPIST]
Otras personas PERSONA [PERSON_1], [PERSON_2]…
Lugares LUGAR [PLACE_1]…
Organizaciones ORGANIZACION [ORGANIZATION_1]…
Fechas y detalles que identifican Revisión manual Descripción entre corchetes, por ejemplo [DATE]
9Preparar la muestra de control

Qué haces: anotar a mano los identificadores de 2 sesiones, sin ver lo que hace el programa, para medir después su precisión.

Antes: el paso 11 todavía no se ha ejecutado.

  1. Anota una semilla en el diario y ejecuta (la semilla fue 7; elige 2 sesiones de desarrollo, y con --sesiones 3 elegiría 3):
python p09_muestra_control.py 7

Te salieron S09_s1 y S12_s6.

  1. Abre cada libro de 01_original/muestra_control y escribe en la columna identificadores, separados por punto y coma, todos los fragmentos que identifican a una persona, un lugar o una organización, tal como aparecen en el texto. Incluye los nombres del paciente y del terapeuta. No anotes parentescos genéricos («my mom»), expresiones de tiempo relativas («last week»).
texto identificadores
My sister Anna called me from Boston. Anna; Boston
Dr. Greenberg, can I ask you something? Dr. Greenberg
I told my boss at Greenfield Bank. Greenfield Bank
  1. Anota en el diario el criterio de coincidencia: un fragmento detectado y uno anotado coinciden si uno contiene al otro («Dr. Greenberg» y «Greenberg»).

Resultado: las dos hojas de la muestra de control, anotadas.

10Anotar los nombres conocidos

Qué haces: dar al programa la lista de nombres de cada serie.

  1. Crea la plantilla:
python p10_nombres.py
  1. Abre 01_original/nombres.xlsx. La hoja datos ya trae a cada terapeuta (con sus variantes) y a los pacientes cuya etiqueta es un nombre. Añade, serie por serie: el paciente cuando la etiqueta es genérica (tipo PACIENTE), familiares y otras personas (PERSONA), lugares (LUGAR) y organizaciones (ORGANIZACION).
  2. Usa la columna mismo_que para agrupar variantes de una misma persona (Annie con mismo_que Anna).
  3. La hoja no_sustituir recoge palabras que spaCy confunde con nombres (Mom, God, Mm-hmm, Zoloft). Amplíala cuando lo detectes.

Si más adelante se añaden pacientes nuevos, python p10_nombres.py --completar los incorpora sin tocar lo ya escrito.

Resultado: nombres.xlsx completo.

11Desidentificar automáticamente

Qué haces: sustituir los identificadores por códigos y crear una hoja de revisión por sesión (tarda unos minutos).

python p11_desidentificar.py

Resultado:

  • 01_original/revision_desidentificacion/S0x_sN.xlsx: una hoja por sesión con turno, hablante, original, cambios y las columnas amarillas texto_final, revisado y nota.
  • 01_original/sustituciones/S0x.csv: la correspondencia entre cada nombre y su código (se conserva cifrada).

Las hojas que ya existen no se sobrescriben.

12Medir la precisión y la sensibilidad

Qué haces: medir, una sola vez, cómo funciona la desidentificación automática frente a tu muestra de control. Entre el paso 11 y este no se añaden nombres a nombres.xlsx.

python p12_precision.py

Resultado: 08_resultados/desidentificacion_precision.csv y una línea en el diario, para spaCy solo y para spaCy con la lista de nombres (precisión y sensibilidad). Una sensibilidad baja no detiene el procedimiento: todas las sesiones se revisan a mano.

13Revisar y aprobar

Qué haces: revisar a mano las 78 hojas de 01_original/revision_desidentificacion y aprobarlas.

  1. Lee cada turno en texto_final, con original y cambios al lado.
  2. Deshaz las sustituciones erróneas: si el programa ha tomado por un nombre algo que no lo es («Zoloft -> [ORGANIZATION_1]»), escribe de nuevo la palabra original en texto_final. Si la palabra coincide con un nombre conocido usado con otro sentido (Will como verbo), escribe además mantener en nota.
  3. Si falta un nombre, añádelo a nombres.xlsx (serie y tipo) en lugar de escribir el código a mano. Al terminar una serie, aplica los nombres nuevos a todas sus hojas (las filas que cambian vuelven a quedar sin revisar):
python p11_desidentificar.py --actualizar --series S04
  1. Generaliza a mano en texto_final, con una descripción entre corchetes, los detalles que permitirían reconocer a alguien (fechas, nombres de escuelas, edades, años, etc.). Conserva lo que tiene valor clínico.
original texto_final
I was born on May 3rd, 1984. I was born on [DATE].
I teach at the only music school in [PLACE_1]. I teach at [A MUSIC SCHOOL] in [PLACE_1].
My wife was on the news after the 2011 flood. My wife was on the news after [A LOCAL EVENT].
  1. Cuando hayas revisado un turno, pon si en revisado.
  2. Aprueba las sesiones revisadas (en lugar de EC, tus iniciales; se puede ejecutar tantas veces como haga falta):
python p13_aprobar.py --revisor EC

El script aprueba las sesiones en las que todas las filas están revisadas, ningún texto_final está vacío, no queda ningún nombre conocido (salvo en filas con mantener) y las filas coinciden con las del original. Las demás aparecen como pendientes, con el motivo.

Resultado: 02_protegido/S0x_sN.csv de cada sesión aprobada. Termina con «Total aprobadas: 78 de 78» (así te salió). Una vez fijadas las unidades en el paso 17, el corpus protegido ya no puede cambiarse.


Fase 3

Segmentación

pasos 14 a 17

La unidad de análisis es la oración gramatical del terapeuta, con al menos sujeto y verbo, según las reglas de Hill (2020, Web Form F), adaptadas de Auld y White (1956). Python propone la división y un solo juez (A) la revisa. Esa segmentación queda fijada y es común a jueces y modelos. El acuerdo entre jueces se mide después, en la codificación. Es una limitación que se declara en la tesis: la segmentación no tiene una medida de acuerdo entre personas.

Si algún día la revisaran dos jueces, basta cambiar JUECES_SEGMENTACION en codigo/comun.py a ("A", "B") y hacer también el paso 16.

14Proponer la segmentación

Qué haces: el programa corta cada turno del terapeuta y crea las hojas del juez.

python p14_segmentar.py

El programa divide cada turno en oraciones y pone un // entre las cláusulas principales unidas por and, or, but, nor o por punto y coma, y separa right? / is that right? al final. Marca con NU: las anotaciones entre corchetes y las facilitaciones mínimas (mm-hmm, yeah, right, okay, sure, I see) que no responden a una pregunta directa. Python no puede aplicar el resto de las reglas (elipsis, comienzos fallidos, interrupciones, muletillas): las decide el juez en el paso 15.

Resultado: una hoja por sesión en 04_jueces/segmentacion/juez_A/S01_s1.xlsx … S13_s6.xlsx. No se sobrescriben las hojas que ya existen; si quieres regenerarlas, borra antes la carpeta juez_A.

15aGuardar la propuesta original de Python (antes de editar las hojas)

Qué haces: guardar aparte la propuesta automática de segmentación, para tener dos versiones de cada sesión: la propuesta de Python (intacta) y tu revisión (la hoja que editas).

Para qué sirve: medir cuánto cambias la propuesta (tasa de edición, paso 17b) y ver qué errores comete el segmentador, para mejorar sus reglas en futuras investigaciones y que cada vez requiera menos revisión manual.

Cuándo hacerlo: justo después del paso 14 y antes de editar las hojas. Si ya has editado algunas, sigue siendo posible: el paso 14 nunca sobrescribe una hoja que ya existe, y la propuesta es determinista (mismo texto protegido, mismo programa y misma versión de spaCy). Este script vuelve a generarla en otra carpeta y no lee ni modifica tus hojas.

cd ~/Desktop/Estudio_HSS/codigo
source ../.venv/bin/activate
python p14b_copia_propuesta.py

Resultado: 04_jueces/propuesta_python/segmentacion/juez_A/S0x_sN.xlsx (78 hojas). Debe decir «78 hojas de propuesta creadas». Si lo repites, dice 0: las hojas existentes no se tocan.

Reglas:

  • Sigue editando solo 04_jueces/segmentacion/juez_A. No abras ni modifiques propuesta_python.
  • Si actualizas spaCy, su modelo o comun.py a mitad del proceso, la propuesta regenerada podría diferir de la original. Por eso conviene ejecutar este paso justo después del paso 14.
  • La carpeta propuesta_python contiene texto del corpus ya desidentificado: es confidencial. Mantenla en el ordenador cifrado, fuera de carpetas sincronizadas y de repositorios, y consérvala cifrada con el resto del corpus.
  • Haz de vez en cuando una copia de seguridad local de 04_jueces/segmentacion/juez_A: la propuesta se recupera, tu revisión no.
15Revisar la segmentación

Qué haces: revisar los cortes de las 78 hojas de 04_jueces/segmentacion/juez_A. Quien revisa es el juez A, sin codificar.

Cómo es la hoja. Cada fila es un turno del terapeuta. Columnas: turno; paciente_antes (solo contexto: te dice si el terapeuta responde a una pregunta directa); texto (el turno original, no se toca); segmentacion (amarilla: el mismo turno ya cortado, cada // marca el final de una unidad); comentario (amarilla, libre). Hay una hoja instrucciones con el resumen.

Qué haces con cada hoja:

  1. Abre la hoja en Excel, pestaña datos.
  2. Lee cada turno completo y revisa sus cortes en segmentacion.
  3. Cambia solo cortes y marcas, según esta tabla:
Quiero… Qué hago
Dejar el turno como está No toco la celda
Quitar un corte Borro el //
Añadir un corte Escribo // entre las dos palabras, con un espacio a cada lado
Marcar un trozo que no es unidad (facilitación mínima, comienzo fallido, anotación) Escribo NU: delante del trozo, al principio de la celda o justo después de un //
Marcar un trozo ininteligible Escribo NA: delante del trozo
  1. Regla de oro: no cambies, borres ni añadas palabras, signos ni mayúsculas. Solo cortes y marcas. Los puntos de la transcripción no son límites de unidad: una oración puede estar partida en dos filas del original; la unidad la decide la gramática.
  2. Anota tus dudas en comentario, guarda y cierra el archivo.

Ejemplo. El programa propone:

We have some time to talk today and I thought that maybe, uh, you could tell me what brings you here. // I would like to hear it in your own words, // if you feel like it.

«and I thought…» es una segunda cláusula principal (se corta antes de and) y el corte antes de «if you feel like it» sobra, porque es una subordinada sin principal propia. Lo dejas así:

We have some time to talk today // and I thought that maybe, uh, you could tell me what brings you here. // I would like to hear it in your own words, if you feel like it.

Reglas de decisión (en este orden, la primera que se cumpla decide):

  1. ¿El trozo es ininteligible o inaudible? Pon NA: delante.
  2. ¿Es una facilitación mínima (mm-hmm, yeah, right, okay…), un silencio o una anotación entre corchetes? Mira paciente_antes: si el paciente acaba de hacer una pregunta directa, es una unidad (sin marca); si no, NU:.
  3. ¿Hay dos cláusulas principales sin corte entre ellas (unidas por and, or, nor, but, un adverbio conjuntivo como however, moreover, therefore, thus, then, yet…, o un punto y coma), o un right? final pegado? Escribe // antes de la conjunción.
  4. ¿Hay un corte que deja un trozo que no puede estar solo (una subordinada sin su principal)? Borra ese //.
  5. En cualquier otro caso, déjalo como está.

Casos habituales:

Caso Antes Después
Una sola unidad (un solo sujeto con dos verbos) You went to the store and bought milk. Igual
Subordinada dentro de la unidad When you said that, I felt sad. Igual
Dos principales con and I hear that you were sad, and you didn't know what to do. I hear that you were sad, // and you didn't know what to do.
Tres cláusulas You felt sad and you wanted to cry, but you held it in. You felt sad // and you wanted to cry, // but you held it in.
Adverbio conjuntivo You wanted to leave; however, you stayed. You wanted to leave; // however, you stayed.
Cortó de más (subordinada) Because you were afraid, // you left. Because you were afraid, you left.
Cortó de más (I think) I think you were upset // and you wanted to leave. I think you were upset and you wanted to leave.
Facilitación pegada a otra frase Mm-hmm, so what did you do then? NU: Mm-hmm, // so what did you do then?
Facilitación que responde a una pregunta directa del paciente NU: Mm-hmm. (propuesta) Mm-hmm. (quitas NU:)
Confirmación final You felt trapped, right? You felt trapped, // right?
Comienzo fallido So when you, uh, when you said that ... // you felt alone. So when you, uh, when you said that ... you felt alone.
Enunciado cortado pero con sentido claro And he would ask her to write the... Igual (es unidad)
Enunciado cortado sin sentido claro The little girl ... NU: The little girl ...
Muletillas (you know, I guess, um, uh) Some, you know, very serious thing may be, you know, happening. Igual (no se cortan)

Caso raro (cláusula interrumpida por otra independiente): I wanted to ask ... well, what I really wonder is how you felt ... about the meeting. Según Hill son dos unidades, pero la hoja no permite partir una unidad en trozos separados: no cortes y escribe parentética en comentario.

Consejos para las 78 hojas:

  • Trabaja por series (S01, S02…) y anota en el diario hasta qué sesión has llegado.
  • Si un turno ya está bien cortado, no lo toques.
  • Un trozo no puede ser a la vez unidad y no unidad: si una parte lo es y otra no, pon un // entre ellas y NU: delante de la que no lo sea.
  • Aplica el mismo criterio en las 78 sesiones. Si descubres una regla que no sabías aplicar, vuelve a revisar los turnos anteriores.
  • Puedes comprobar errores en cualquier momento ejecutando python p17_fijar_unidades.py: si una celda no reproduce el texto, te dice sesión y turno. Si no hay errores, crea 03_unidades/unidades.csv; cuando termines las 78 hojas, repítelo con --forzar para que recoja todos los cambios.
  • Confidencialidad: las hojas contienen texto de sesiones ya desidentificado, pero siguen siendo material confidencial. No las copies ni las pegues en servicios externos, y consérvalas solo en el ordenador cifrado.

Terminado cuando: las 78 hojas están revisadas y python p17_fijar_unidades.py --forzar no da errores.

Referencia: Hill, C. E. (2020). Helping skills: Facilitating exploration, insight, and action (5.ª ed.). APA. Las reglas proceden de Web Form F.

16Acuerdo de segmentación (solo con dos jueces)

Este paso solo se hace si la segmentación la revisan dos jueces. Con un solo juez, python p16_acuerdo_segmentacion.py lo indica y se detiene: pasa al paso 17.

17Fijar las unidades

Qué haces: cuando las 78 hojas estén revisadas, fijar una segmentación única, común a jueces y modelos.

python p17_fijar_unidades.py --forzar

(Sin --forzar si es la primera vez que se ejecuta.) Si una hoja tiene un error (una celda segmentacion que no reproduce el texto del turno), el script lo enumera por sesión y turno y se detiene; el juez lo corrige y se repite el paso.

Resultado: 03_unidades/unidades.csv (una fila por unidad: unidad, serie, sesion, turno, conjunto, texto, estado, analizable), la columna unidades del inventario y 08_resultados/inventario_unidades.csv. Los identificadores son S07_s3_t0042_u02 (sesión, turno y número de unidad).


Fase 4

Codificación humana

pasos 18 a 23

Dos jueces con formación en psicoterapia y competencia en inglés codifican cada unidad con una de las doce categorías del HSS (Hill, 2020). Al menos uno de ellos es ajeno a la elaboración de las instrucciones de los modelos. Hay tres rondas:

Ronda Sesiones Para qué sirve
entrenamiento De desarrollo, por tandas Alcanzar el 80 % de acuerdo y fijar las reglas de decisión
evaluacion Las 65 de evaluación Referencia humana para el acuerdo entre jueces (H1) y para evaluar los modelos
recodificacion Las 13 de desarrollo, con las reglas definitivas Describir las seis sesiones de cada serie y servir de referencia en el desarrollo de los modelos
17bTasa de edición y errores del segmentador (opcional, tras el paso 17)

Qué haces: comparar, turno a turno, la propuesta de Python (paso 15a) con tu versión revisada. Da la tasa de edición (cuánto trabajo humano queda) y una lista de los patrones que más corriges, que son las reglas candidatas para mejorar el segmentador en futuras investigaciones.

python p17b_tasa_edicion.py

Si vas a medias y quieres una cifra provisional, limita el cálculo a lo que ya hayas terminado (las sesiones que aún no has revisado cuentan como «sin cambios»):

python p17b_tasa_edicion.py --series S01 S02
python p17b_tasa_edicion.py --sesiones S01_s1 S01_s2

Resultado:

  • 08_resultados/edicion_segmentacion_resumen.csv: turnos cambiados (%), cortes quitados y añadidos, precisión, exhaustividad y F1 de los cortes, marcas NU/NA.
  • 08_resultados/edicion_segmentacion_sesiones.csv: las mismas cifras por sesión.
  • 08_resultados/edicion_segmentacion_patrones.csv: palabras junto a los cortes cambiados (por ejemplo, «corte añadido antes de and»), solo patrones que se repiten 3 veces o más. Son datos agregados.
  • 04_jueces/propuesta_python/cambios_detalle.csv: cada cambio con su contexto. Confidencial: contiene texto del corpus; no sale del equipo cifrado.

Cómo leerlo (y para qué usarlo):

  • La precisión dice qué parte de los cortes propuestos acertó; la exhaustividad, qué parte de los cortes finales ya estaban propuestos. Una tasa de edición baja indica que la segmentación automática se acerca a ser utilizable con revisión mínima.
  • Un patrón frecuente (por ejemplo, borras casi siempre el corte tras I think) es una regla que añadir a proponer_segmentos en comun.py.
  • Cautela: partiste de la propuesta, así que el acuerdo sale inflado por anclaje. Para mejorar el segmentador sin trampas, ajusta las reglas con las sesiones de desarrollo, congela la versión y mídela con las de evaluación; o segmenta a ciegas una muestra pequeña.
  • No modifica ninguna hoja. Si una hoja tiene un error (una celda que no reproduce el texto), lo indica por sesión y turno.
18Preparar las categorías y las hojas de entrenamiento

Quién: D.

  1. Abre 06_instrucciones/categorias.json con un editor de texto plano. Comprueba la grafía de las doce categorías principales y sustituye los subtipos por los del Web Form E (los de la plantilla son provisionales). Respeta el formato: comillas rectas, comas entre elementos y ninguna coma tras el último. Comprueba que sigue siendo válido (muestra su contenido si lo es, y si no, la línea del error):
python -m json.tool ../06_instrucciones/categorias.json
  1. Crea las hojas de la primera tanda con tres o cuatro sesiones de desarrollo de series distintas (los códigos están en el diario y en el inventario):
python p18_hojas_codificacion.py --ronda entrenamiento \
    --sesiones S01_s2 S05_s4 S09_s1

Resultado: un libro por sesión y juez en 04_jueces/codificacion/entrenamiento/juez_A y juez_B, con tres hojas: datos (una fila por unidad analizable, con terapeuta_marcado y las columnas amarillas categoria, subtipo, duda, comentario), sesion (la transcripción completa) y tiempo (minutos dedicados, celda B1). Cada juez recibe solo su carpeta. Durante el entrenamiento los jueces eligen siempre el subtipo cuando la categoría lo tiene.

19Entrenar a los jueces

Quién: J, por separado; J + J y D en las reuniones.

  1. Los jueces se entrenan primero con la transcripción de práctica del manual de Hill, fuera de estos scripts.
  2. Codifican por separado la primera tanda y, cuando ambos terminan, D calcula su acuerdo:
python p19_acuerdo_jueces.py --ronda entrenamiento \
    --sesiones S01_s2 S05_s4 S09_s1
  1. Revisan juntos las discrepancias con el informe 04_jueces/acuerdo/acuerdo_entrenamiento_FECHA.xlsx. Las reglas de decisión que acuerden se guardan en 00_admin/reglas_de_decision.md, sin texto de las sesiones.
  2. Repiten el ciclo con nuevas tandas (paso 18, punto 2, y este paso) hasta que el acuerdo de una tanda alcance el 80 %.
  3. Si en la tanda con la que se alcanza el criterio la kappa con subtipos no llega a .60, en las rondas siguientes se codifican solo las categorías principales; si llega, se siguen codificando los subtipos.

Resultado: reglas de decisión y decisión sobre los subtipos anotadas en el diario, con el acuerdo de cada tanda y la fecha en que se alcanzó el criterio.

20Codificar las sesiones de evaluación

Quién: D prepara las hojas; J codifica.

  1. Crea las hojas de evaluación:
python p18_hojas_codificacion.py --ronda evaluacion
  1. Cada juez codifica las 65 sesiones de su carpeta con acceso a la sesión completa (hoja sesion), sin ver las hojas del otro juez ni las salidas de los modelos y sin comentar casos concretos hasta el paso 22. Anota los minutos de cada sesión en la hoja tiempo.
  2. Las hojas se intercambian en un disco externo cifrado.

El acuerdo de evaluación no se calcula hasta que los dos jueces han terminado todas las sesiones.

Resultado: 130 libros codificados.

21Calcular el acuerdo antes de la discusión

Quién: D.

  1. Ejecuta:
python p19_acuerdo_jueces.py --ronda evaluacion --consenso

El script comprueba que cada unidad tiene una categoría válida y que cada subtipo corresponde a su categoría; si hay errores, los enumera y el juez los corrige. Después guarda en 04_jueces/acuerdo/acuerdo_evaluacion_FECHA.xlsx el porcentaje de acuerdo, la kappa de Cohen con su intervalo del 95 %, el acuerdo por categoría y la matriz de confusión; guarda las huellas de las hojas; y crea en 04_jueces/consenso/evaluacion una hoja por sesión para la reunión de consenso.

  1. Protege las hojas de los jueces:
chmod -R a-w ../04_jueces/codificacion/evaluacion

Comprobación: el archivo de acuerdo existe, con su fecha, antes de la primera reunión de consenso.

22Llegar al consenso

Quién: J + J y D.

  1. En cada hoja de 04_jueces/consenso/evaluacion, los jueces discuten las unidades con coincide igual a no y eligen la categoría acordada y, si se codifican, el subtipo en subtipo_consenso. Si no llegan a un acuerdo, marcan si en sin_consenso y explican el motivo en nota (esas unidades no se asignan a Other).
  2. Reúne el consenso en una tabla:
python p22_consenso.py --ronda evaluacion

Resultado: 04_jueces/consenso_evaluacion.csv.

23Recodificar las sesiones de desarrollo

Quién: J, J + J y D.

Se repiten los pasos 20 a 22 con la ronda recodificacion (hojas nuevas, no se reutilizan las del entrenamiento):

python p18_hojas_codificacion.py --ronda recodificacion
python p19_acuerdo_jueces.py --ronda recodificacion --consenso
python p22_consenso.py --ronda recodificacion

La primera se ejecuta al empezar; la segunda, cuando los dos jueces han terminado; la tercera, después de la reunión de consenso.

Resultado: 04_jueces/consenso_recodificacion.csv.


Fase 5

Codificación automatizada

pasos 24 a 30

Se comparan modelos de pesos abiertos de al menos dos familias, ejecutados sin conexión y sin modificar sus pesos. Una configuración combina un modelo con una versión de las instrucciones (sin ejemplos o con ejemplos). Cada ejecución añade un nivel de contexto y un número de repetición.

Nivel --contexto Qué recibe el modelo Uso
Unidad aislada aislada Solo la oración Comparación principal (H4)
Intercambio inmediato intercambio El turno del terapeuta con la unidad entre >> y <<, y los turnos del paciente anterior y siguiente Comparación principal (H4) y selección de la configuración
Sesión completa sesion Toda la sesión, con los turnos numerados, y al final el turno con la unidad señalada Complementaria

Cada ejecución escribe un archivo MODELO__PLANTILLA__CONTEXTO__eN.jsonl en 07_ejecuciones/desarrollo o 07_ejecuciones/evaluacion, sin texto de las sesiones.

24Descargar y registrar los modelos

Quién: D, con conexión y sin ningún archivo del corpus abierto.

  1. Instala el motor y comprueba que puede usar la GPU (Metal):
pip install llama-cpp-python
python -c "import llama_cpp as l; print(l.llama_supports_gpu_offload())"
pip freeze > requirements.txt

Debe responder True. Si responde False, reinstala con Metal:

CMAKE_ARGS="-DGGML_METAL=on" pip install --force-reinstall --no-cache-dir \
    llama-cpp-python
  1. Elige modelos: versiones ajustadas para seguir instrucciones, de pesos abiertos y licencia que permita investigación; al menos dos familias; formato GGUF con cuantización de 4 o 5 bits (Q4_K_M o Q5_K_M); con 16 GB, entre 7.000 y 14.000 millones de parámetros; ventana de contexto de entrenamiento de al menos 16.384 tokens; descargados del repositorio del desarrollador, anotando la dirección exacta.
  2. Descarga los .gguf en 05_modelos y regístralos (calcula la huella de cada uno):
python p24_modelos.py
  1. Completa en 00_admin/modelos.xlsx la familia, la cuantización, la fuente y la licencia de cada modelo. Desactiva la wifi.

Resultado: 00_admin/modelos.xlsx con nombre, tamaño y huella SHA-256 de cada modelo.

25Redactar las instrucciones y elegir los ejemplos

Quién: D. El juez ajeno a la elaboración de las instrucciones no participa.

  1. En 06_instrucciones/definiciones.txt escribe en inglés la definición de cada categoría (Web Form E) y las reglas de decisión que los jueces fijaron hasta el final del entrenamiento (paso 19). No incorpores las que se acordaron después, al discutir unidades de evaluación. No incluyas texto de las sesiones.
  2. Revisa las plantillas (Anexo). plantilla_sistema.txt contiene las variables $categorias, $definiciones, $ejemplos y $formato; las tres plantilla_usuario_* usan $unidad, $turno, $paciente_antes, $terapeuta_marcado, $paciente_despues y $sesion. Se puede ajustar el texto, pero no el nombre de las variables.
  3. Propón los ejemplos con una semilla anotada en el diario:
python p25_ejemplos.py 25

Elige al azar, para cada categoría, una unidad de desarrollo en la que los dos jueces coincidieron desde el principio, y guarda su identificador y categoría en 06_instrucciones/ejemplos.xlsx, sin texto (con --por_categoria 2 elige dos). Revisa cada ejemplo en la hoja de consenso de su sesión; si alguno no es claro, sustituye su identificador por el de otra unidad con la misma categoría y anota el cambio en el diario.

  1. En 06_instrucciones/dominios.json fija la correspondencia entre categorías y dominios (exploración, insight, acción) a partir de Hill (2020), antes de analizar. Anota la versión definitiva en el diario.

Resultado: 06_instrucciones completo.

26Probar el funcionamiento

Quién: D.

  1. Prueba con el modelo simulado, que responde al azar y no necesita archivo de modelo:
python p26_codificar_modelo.py --modelo simulado --plantilla con_ejemplos \
    --contexto intercambio --ronda desarrollo --semilla 1 --limite 20
  1. Prueba cada modelo con pocas unidades y con los mensajes del motor a la vista, primero con el intercambio inmediato y después con la sesión completa:
python p26_codificar_modelo.py --modelo MODELO.gguf --plantilla con_ejemplos \
    --contexto intercambio --ronda desarrollo --semilla 1 \
    --limite 20 --detalle
python p26_codificar_modelo.py --modelo MODELO.gguf --plantilla con_ejemplos \
    --contexto sesion --ronda desarrollo --semilla 1 --limite 5 --detalle

Comprueba que el modelo se carga en la GPU (Metal) y que su ventana de entrenamiento (n_ctx_train) no es menor que --n_ctx (16384 por defecto). Abre Monitor de Actividad y anota la memoria del proceso python.

  1. Calcula la duración prevista: divide los segundos de la línea «Hecho» entre las unidades codificadas y multiplica por el número de unidades de evaluación (08_resultados/inventario_unidades.csv) y por el número de ejecuciones del nivel (paso 30).
  2. Borra las salidas de prueba:
rm -r ../07_ejecuciones/desarrollo

Resultado: tiempo por unidad y memoria de cada modelo, anotados en el diario.

27Ejecutar en desarrollo

Quién: D.

  1. Para cada modelo, las dos versiones de las instrucciones:
caffeinate -i python p26_codificar_modelo.py --modelo MODELO.gguf \
    --plantilla sin_ejemplos --contexto intercambio \
    --ronda desarrollo --semilla 11
caffeinate -i python p26_codificar_modelo.py --modelo MODELO.gguf \
    --plantilla con_ejemplos --contexto intercambio \
    --ronda desarrollo --semilla 11

caffeinate -i impide que el Mac entre en reposo. Mantén el equipo conectado a la corriente; si una ejecución se interrumpe, repite la misma orden y continúa donde se quedó.

  1. La temperatura es 0 por defecto y la ventana de contexto 16.384 tokens (--n_ctx).
  2. Si cambias las instrucciones, guarda antes los resultados anteriores y vuelve a lanzar todas las ejecuciones del punto 1:
mkdir -p ../07_ejecuciones/anteriores/v1
mv ../07_ejecuciones/desarrollo ../07_ejecuciones/anteriores/v1/

Anota cada cambio en el diario.

Resultado: un archivo por modelo y versión de las instrucciones en 07_ejecuciones/desarrollo.

28Seleccionar la configuración

Quién: D.

python p28_seleccion.py

Resultado: 08_resultados/seleccion_desarrollo.csv, ordenada de mejor a peor, con macro-F1, kappa, proporción de fallos y segundos por unidad. La primera fila es la configuración principal; las demás son las de sensibilidad. Anota la elección en el diario.

29Congelar

Quién: D.

Fija las instrucciones, el formato de salida y los parámetros antes de abrir la evaluación. Ejecuta el script con la configuración principal (primera fila de seleccion_desarrollo.csv), las demás como sensibilidad y los parámetros definitivos. Añade --subtipos si en el paso 19 se decidió codificar los subtipos:

python p29_congelar.py --principal MODELO_A.gguf:con_ejemplos \
    --sensibilidad MODELO_A.gguf:sin_ejemplos \
    MODELO_B.gguf:con_ejemplos MODELO_B.gguf:sin_ejemplos \
    --temperatura 0 --semillas 11 12 13 --n_ctx 16384 --semilla_bootstrap 2026

La congelación no se puede repetir: comprueba la orden antes de ejecutarla.

Resultado: 00_admin/congelacion.json, con las configuraciones, los parámetros y la huella SHA-256 de todos los archivos de 06_instrucciones, de los modelos y de p26 y comun.py. Los archivos de 06_instrucciones quedan como solo lectura. Desde este momento no cambia nada en ellos: antes de cada ejecución de evaluación el script compara las huellas y se detiene si algo es distinto.

30Ejecutar en evaluación

Quién: D.

Lanza las ejecuciones, empezando por la configuración principal. Cada configuración se ejecuta tres veces en cada nivel de contexto (en total 36 ejecuciones con dos modelos y dos versiones de las instrucciones):

Configuración Contexto Ejecuciones (semillas)
Principal intercambio y aislada 1, 2 y 3 (11, 12 y 13)
Principal sesion 1, 2 y 3 (11, 12 y 13)
Cada configuración de sensibilidad intercambio, aislada y sesion 1, 2 y 3 (11, 12 y 13)

Una ejecución:

caffeinate -i python p26_codificar_modelo.py --modelo MODELO_A.gguf \
    --plantilla con_ejemplos --contexto intercambio \
    --ronda evaluacion --ejecucion 1 --semilla 11

Las nueve ejecuciones de una configuración seguidas (se escribe tal cual en Terminal; añade --subtipos al final si procede; repite cambiando el modelo y la plantilla para cada configuración):

for E in 1 2 3; do
  for C in intercambio aislada sesion; do
    caffeinate -i python p26_codificar_modelo.py --modelo MODELO_A.gguf \
        --plantilla con_ejemplos --contexto $C --ronda evaluacion \
        --ejecucion $E --semilla $((10 + E))
  done
done

El script se niega a ejecutar una configuración que no está congelada, si ha cambiado algún archivo o si no coinciden temperatura, ventana de contexto, subtipos o semilla. Las salidas inválidas se registran como fallos y no se corrigen a mano.

Resultado: los archivos de cada ejecución en 07_ejecuciones/evaluacion. La línea «Hecho» de cada ejecución indica los fallos; anótalos en el diario.


Fase 6

Análisis y cierre

pasos 31 a 33
31Analizar

Quién: D.

python p31_analisis.py

Toma como referencia el consenso de evaluación, cuenta las salidas inválidas como desacuerdos, excluye las unidades sin consenso solo de las comparaciones con el consenso y calcula intervalos del 95 % con 2000 remuestreos de series completas, con la semilla congelada. Repetirlo da los mismos números.

Resultado: 08_resultados/resultados.xlsx (hojas: jueces, modelos, por_categoria, confusiones, por_serie, contexto, entre_modelos, estabilidad, cobertura, perfiles, categorias_por_sesion, perfiles_modelo, tiempo_memoria, sesion_completa), la figura 08_resultados/perfiles_por_sesion.png y 08_resultados/etiquetas_por_unidad.csv (sin texto).

Cómo leerlo: kappa superior a .60 y .80 = acuerdo sustancial y casi perfecto (Landis y Koch, 1977), junto con la incertidumbre y la frecuencia de cada categoría. Con 13 series, los intervalos tienen alcance descriptivo.

32Comprobar las salidas

Quién: D.

python p32_comprobar_salidas.py

Busca, en las carpetas que no deben contener texto de las sesiones y que podrían depositarse (00_admin, codigo, 06_instrucciones, 07_ejecuciones, 08_resultados), cualquier secuencia de ocho palabras seguidas que aparezca en las sesiones. Si encuentra alguna, muestra dónde está: elimina el fragmento y repite la comprobación. Hazla también antes de enviar cualquier resultado fuera del equipo.

Resultado: el mensaje «Correcto» y una línea en el diario.

33Cerrar y archivar el estudio

Quién: D.

  1. Valora, según los criterios de propiedad intelectual e industrial y de transferencia, si el código se comparte o no en repositorios públicos, nunca con datos del corpus. El repositorio, la licencia, el posible embargo y los demás materiales sin texto que se depositen (por ejemplo, las etiquetas por unidad) se confirman al finalizar la tesis. Anota la decisión en el diario.
  2. Haz la comprobación del paso 32.
  3. Ejecuta el cierre, que no elimina nada: resume cada carpeta y guarda la huella de cada archivo del código, de las instrucciones y de los resultados:
python p33_cierre.py

Las huellas se guardan en 08_resultados/huellas_cierre.csv y el cierre se anota en el diario. Todo lo demás se conserva en el archivo privado cifrado y sin conexión; antes de la defensa, comprueba con la fuente de la colección que sus condiciones de uso permiten conservar el corpus.

  1. Actualiza las dos copias de seguridad en los USB cifrados (la periódica y la segunda, guardada en un lugar fijo y sin otros usos) y comprueba que se abren con su contraseña.
  2. Añade al diario la lista de lo que se conserva.

Resultado: se conserva todo el estudio, con y sin texto, en el archivo privado cifrado, y queda anotado en el diario qué materiales sin texto se valora depositar.


ANEXO. Las plantillas de 06_instrucciones

Los 7 archivos de 06_instrucciones (categorias.json, definiciones.txt, dominios.json, plantilla_sistema.txt, plantilla_usuario_aislada.txt, plantilla_usuario_intercambio.txt y plantilla_usuario_sesion.txt) ya deben estar en esa carpeta antes del paso 18. Comprueba que están con ls ~/Desktop/Estudio_HSS/06_instrucciones.

Problemas que ya tuviste y cómo se resolvieron

Problema Causa Solución
Error de thinc al instalar spaCy; requirements.txt no existe Python 3.9 del Mac, demasiado antiguo Instalar Python 3.12 y crear el entorno con python3.12 -m venv .venv
p04: «La carpeta «Original» no corresponde a ninguna serie» Ruta equivocada Usar ~/Desktop/Corpus/Original, la carpeta que contiene las 13 series
p06: ValueError: 'rol' is not in list El script no reconocía el formato 00:15:20Nombre + espacio duro Corregido en comun.py (TIEMPO_NOMBRE_PEGADO); si no se reconoce ninguna etiqueta, el script lo dice
Avisos de turnos repetidos en S02_s2, S05_s3, S07_s2, S13_s5 Pasajes repetidos en las transcripciones Se revisaron y los turnos estaban bien
Una organización mal marcada en la revisión (p. ej. Zoloft) spaCy confunde palabras con nombres Restituir la palabra en texto_final y marcar si en revisado; añadirla a no_sustituir
Una organización sin marcar El programa no la detectó Añadirla a nombres.xlsx y ejecutar python p11_desidentificar.py --actualizar --series SXX
p17: «la celda segmentacion no reproduce el texto» Se borró, añadió o cambió alguna palabra, o hay un NU:/NA: en mitad de una unidad Comparar con la columna texto: solo se pueden mover // y poner NU:/NA: al principio de un trozo

Todo el procesamiento es local. No pegues transcripciones ni salidas clínicas en servicios externos.