Skip to content

Modo Think-Aloud

Los anotadores hablan mientras trabajan y Potato guarda la transcripción literal como justificación. El paso de voz a texto se ejecuta enteramente en local con faster-whisper, así que el audio no sale de la máquina y no hay API en la nube ni LLM en la cadena.

Nuevo en v2.7.0

Antes de los LLM, la referencia para entender cómo se toma una decisión era el protocolo de pensamiento en voz alta, y nunca sobrevivió al contacto con las herramientas de anotación. El modo Think-Aloud deja que los anotadores simplemente hablen mientras trabajan.

La transcripción literal se guarda como justificación, deliberadamente sin resumir, porque parafrasear un protocolo de pensamiento en voz alta contamina justo el artefacto que intentas recoger. Las etiquetas se pueden confirmar por voz usando fórmulas fijas que detecta un analizador basado en reglas, sin ningún LLM en toda la cadena.

El paso de voz a texto se ejecuta enteramente en local con faster-whisper, que va en tiempo real sobre CPU con el modelo tiny.en de 39 MB. El audio nunca sale de la máquina, y no hay ninguna API en la nube que llamar ni factura por token que pagar.

Nota: Think-Aloud transcribe a tus anotadores. Si lo que quieres es anotar transcripciones que ya tienes, salidas de Whisper, de una API de ASR en la nube o subtítulos descargados, eso es otra función distinta: consulta Formatos de transcripción. Ambas se confunden porque las dos tienen que ver con Whisper.

Una transcripción literal del razonamiento hablado con una etiqueta detectada por voz: la cadena de razonamiento humana, para compararla con la del modelo.

Grabar la cadena de razonamiento humana

La idea no es solo recoger justificaciones. Think-Aloud captura cómo razona realmente una persona hasta llegar a una etiqueta, para que puedas poner esa cadena de razonamiento humana frente a la cadena de razonamiento de un modelo sobre el mismo elemento.

La anotación de recompensa de proceso de Potato segmenta cómo razona un modelo, paso a paso. Think-Aloud captura cómo lo hace una persona. Ambas son superficies de captura, y ponerlas una al lado de la otra sobre el mismo elemento es donde aparecen las divergencias interesantes.

Cómo funciona

  1. El anotador toca 🎤 Pensar en voz alta y habla con libertad.
  2. El audio se captura en fragmentos completos de seis segundos y se transcribe en local.
  3. Para confirmar una etiqueta por voz, usa una de las fórmulas aceptadas:
    • "I label this Polite" / "I'd call it neutral"
    • "My answer is impolite"
    • "Final answer: polite" / "I go with neutral"
  4. La detección selecciona automáticamente la opción correspondiente en la interfaz, se dispara el guardado habitual y la etiqueta lo confirma: Oído: Impolite ✓. Decir otra fórmula más adelante cambia la etiqueta, así que gana la última confirmación.
  5. Con require_spoken_label: true, pulsar Siguiente sin ninguna etiqueta confirmada lanza un aviso, una sola vez, con la fórmula esperada. Un segundo Siguiente pasa de largo, y hacer clic en las etiquetas funciona siempre.

Todo lo que se dice mientras se piensa se ignora. "This seems polite, but…" no confirma nada. Solo confirman las fórmulas fijas, y eso es lo que hace suficiente un análisis basado en reglas. Los errores de audición los absorbe la coincidencia difusa de etiquetas, así que "in polite" se resuelve como Impolite.

Instalación

bash
pip install faster-whisper   # local STT; first recording downloads the model (~39 MB)

El navegador necesita permiso de micrófono. localhost cuenta como contexto seguro.

Configuración

yaml
thinkaloud:
  enabled: true
  schema: politeness          # scheme whose labels can be spoken (default: first radio)
  stt: auto                   # faster_whisper | mock | auto
  model: tiny.en              # tiny.en is CPU real-time; base.en is sturdier
  chunk_seconds: 6            # recording chunk length
  require_spoken_label: true  # nudge on Next without a committed label
  # stems:                    # override accepted phrasing regexes (advanced)
  # fillers: [um, uh, hmm, i guess, maybe]
  # language: en
OpciónPor defectoDescripción
sttautofaster_whisper (local), mock (pruebas y desarrollo) o auto, que elige faster-whisper y avisa con claridad si no está instalado.
modeltiny.enCualquier id de modelo de faster-whisper.
chunk_seconds6Cada fragmento es un archivo de audio completo.
stemslos integradosRaíces regex de las fórmulas aceptadas; cada una captura las palabras que la siguen.
fillersum, uh, hmm, …Léxico para el contador de titubeos.
require_spoken_labeltrueAviso único en el botón Siguiente cuando no se ha confirmado nada.

Qué obtienes

  • Flujos de justificación literales alineados con cada par (anotador, instancia), con la frase de la etiqueta separada aparte. La transcripción menos la frase de confirmación es la justificación.
  • Señales de titubeo deterministas: recuento de fragmentos en silencio y de muletillas sobre un léxico configurable, calculados con aritmética y no con modelos.
  • Una página de revisión en /thinkaloud/review (administración) con la transcripción de cada sesión, la etiqueta confirmada por voz, la confianza y las estadísticas de titubeo.
  • Anotación con las manos libres como efecto secundario, con beneficios reales de accesibilidad y de alivio de lesiones por esfuerzo repetitivo.

Datos y API

Las transcripciones se guardan en {output_annotation_dir}/thinkaloud/transcripts.jsonl (solo anexado, un registro por fragmento).

EndpointMétodoAutenticaciónPara qué sirve
/thinkaloud/api/chunkPOSTsesiónFragmento de audio multipart → transcripción + detección
/thinkaloud/api/textPOSTsesiónFragmento de texto (vía sin audio)
/thinkaloud/api/stateGETsesiónAgregado de sesión para una instancia
/thinkaloud/reviewGETadministraciónPágina de revisión de transcripciones
/thinkaloud/api/exportGETadministraciónTodas las sesiones en JSON

Notas de diseño

  • El analizador recorre una ventana deslizante con los dos últimos fragmentos, así que las frases que quedan partidas entre fragmentos también se detectan.
  • La coincidencia de etiquetas es primero exacta, luego por prefijo y luego con difflib a un umbral de 0.8, dando preferencia a las coincidencias exactas. "polite" nunca colisiona de forma difusa con "Impolite".
  • Añadir un backend de STT consiste en heredar de STTBackend en potato/thinkaloud/stt.py y registrarlo en create_stt.

Lecturas adicionales