¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

Probar una app que responde preguntas

Después de esta lección: Puedo probar una app que responde preguntas con un pequeño conjunto de preguntas, cada una con el dato que la respuesta debe contener.

Lección de 60 min6 comandosLaboratorio JupyterLab de ciencia de datos: pandas, Matplotlib y scikit-learn en el navegador

Un ayudante de tienda que responde preguntas

Una tienda de alquiler de bicis crea un ayudante. Un cliente escribe una pregunta. La app busca el mejor párrafo entre las respuestas de la tienda y se lo da a un modelo de lenguaje, que redacta la respuesta.

Si la app encuentra el párrafo equivocado, el modelo redacta con mucha educación una respuesta equivocada. Esta lección prueba la búsqueda. Es código sencillo: se puede puntuar sin llamar a ningún modelo.

Al final de esta lección

Nota

Puedo probar una app que responde preguntas con un pequeño conjunto de preguntas, cada una con el dato que la respuesta debe contener.

Palabras clave

PalabraQué significaEjemplo
Búsquedaencontrar el texto que debe ayudar a responder una pregunta
Dato esperadoun trozo corto de texto que una buena respuesta debe contenerdoce euros
Tasa de aciertosla parte de las preguntas en las que se halló el texto correcto
Palabra vacíauna palabra muy común, como «el», que dice poco
Respuesta equivocadase halló un texto, pero no contiene el dato
Sin respuestanada coincidió, así que la app dice que no lo sabe

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Dos pasos, y solo uno se prueba bien

Muchas apps responden en dos pasos. Primero la búsqueda: elegir el párrafo que encaja con la pregunta. Después un modelo de lenguaje redacta la respuesta a partir de ese párrafo.

La respuesta de un modelo cambia de una ejecución a otra: se puntúa mal. La búsqueda da lo mismo cada vez: se puntúa bien. Si la búsqueda falla, nada después puede estar bien.

Contar las palabras en común

Aquí la coincidencia es tan sencilla como se puede. Parte la pregunta en palabras. Para cada párrafo, cuenta cuántas de esas palabras están también en él. Gana el párrafo con la cuenta más alta.

Compara palabras enteras: «abre» no coincide con «abrir». Ejecuta el código y lee las cuentas.

Contar las palabras en común de una pregunta

Código: python
def words(text):
    for mark in ".,?¿":
        text = text.replace(mark, "")
    return text.lower().split()

docs = [
    "La tienda abre a las nueve y cierra a las seis de lunes a sábado.",
    "Una bici cuesta doce euros por un día y cinco euros por una hora.",
    "Puedes devolver una bici en cualquiera de las tres estaciones de la ciudad.",
    "Si una bici se estropea, llama al número que está en el cuadro y vamos a repararla.",
    "Los cascos son gratis con cada alquiler, pero hay que pedirlos en el mostrador.",
]
question = "¿Cuál es el precio de las bicis de un día?"
for text in docs:
    shared = []
    for word in words(question):
        if word in words(text):
            shared.append(word)
    print(len(shared), shared, "<-", text[:28])
# Cambia la pregunta por "¿Me dan un casco?" y vuelve a ejecutar.

Un conjunto de prueba: preguntas y datos

Para puntuar la app necesitas un pequeño conjunto de prueba. Contiene preguntas que un cliente podría hacer. Cada una tiene el dato esperado que contiene el párrafo correcto.

Una pregunta es un acierto si el párrafo hallado contiene su dato. Es un fallo si se halló un párrafo sin él. Queda sin respuesta si nada coincidió.

Escribir las cinco respuestas de la tienda

Comando
docker exec jupyter sh -c "printf '%s\n' 'd1|La tienda abre a las nueve y cierra a las seis de lunes a sábado.' 'd2|Una bici cuesta doce euros por un día y cinco euros por una hora.' 'd3|Puedes devolver una bici en cualquiera de las tres estaciones de la ciudad.' 'd4|Si una bici se estropea, llama al número que está en el cuadro y vamos a repararla.' 'd5|Los cascos son gratis con cada alquiler, pero hay que pedirlos en el mostrador.' > faq.txt"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribir las seis preguntas de prueba

Comando
docker exec jupyter sh -c "printf '%s\n' '¿Cuándo abre la tienda?|las nueve' '¿Cuál es el precio de las bicis de un día?|doce euros' '¿Dónde puedo devolver una bici?|tres estaciones' '¿Qué hago si se estropea mi bici?|llama al número' '¿Me dan un casco?|gratis' '¿Qué días cierran?|sábado' > preguntas.txt"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribir el script de puntuación

Comando
docker exec jupyter sh -c "printf '%s\n' 'import sys' '' 'SKIP = [\"el\", \"la\", \"los\", \"las\", \"un\", \"una\", \"de\", \"del\", \"es\", \"cuál\", \"cuánto\", \"qué\", \"cuándo\", \"dónde\", \"por\", \"a\", \"en\", \"si\", \"se\", \"y\", \"mi\", \"me\", \"puedo\"]' '' '' 'def words(text):' '    for mark in \".,?¿\":' '        text = text.replace(mark, \"\")' '    return text.lower().split()' '' '' 'docs = []' 'for line in open(\"faq.txt\", encoding=\"utf-8\"):' '    docs.append(line.strip().split(\"|\")[1])' 'skip = []' 'if sys.argv[1] == \"vacias\":' '    skip = SKIP' 'hit = 0' 'wrong = 0' 'none = 0' 'for line in open(\"preguntas.txt\", encoding=\"utf-8\"):' '    question, fact = line.strip().split(\"|\")' '    asked = []' '    for word in words(question):' > steps/ask.py"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribir el resto del script de puntuación

Comando
docker exec jupyter sh -c "printf '%s\n' '        if word not in skip:' '            asked.append(word)' '    best = \"\"' '    best_shared = 0' '    for text in docs:' '        shared = 0' '        for word in asked:' '            if word in words(text):' '                shared = shared + 1' '        if shared > best_shared:' '            best = text' '            best_shared = shared' '    if best == \"\":' '        none = none + 1' '        print(\"nada:\", question)' '    elif fact.lower() in best.lower():' '        hit = hit + 1' '        print(\"acierto:\", question)' '    else:' '        wrong = wrong + 1' '        print(\"fallo:\", question)' 'print(\"aciertos\", hit, \"fallos\", wrong, \"nada\", none, \"tasa\", round(hit / (hit + wrong + none), 2))' >> steps/ask.py"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Puntuar la coincidencia sencilla

Comando
docker exec jupyter python3 steps/ask.py crudo

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Arreglar una cosa y puntuar de nuevo

Dos preguntas fueron al párrafo equivocado por palabras pequeñas como «de» y «un». Quita de la pregunta esas palabras vacías antes de contar y puntúa de nuevo.

Se cambia una sola cosa cada vez. Si cambiaras tres a la vez, no sabrías cuál ayudó.

Puntuar de nuevo ignorando las palabras vacías

Comando
docker exec jupyter python3 steps/ask.py vacias

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Un error frecuente

Advertencia

Mucha gente cree que la app mejoró porque la tasa subió de 0,5 a 0,67. Mira los demás números. Los dos fallos pasaron a acierto o a sin respuesta, lo cual es mejor, pero dos preguntas siguen sin hallar nada. Un conjunto de prueba tan pequeño dice dónde mirar, no lo buena que es la app.

Ejemplo resuelto: las dos ejecuciones juntas

EjecuciónAciertosFallosSin respuestaTasa
Palabras enteras, nada ignorado3210.5
Palabras vacías ignoradas4020.67

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Para ir más lejos: añade tus preguntas

Añade cuatro preguntas al archivo de prueba, cada una con un dato. Incluye una que las cinco respuestas de la tienda no puedan contestar.

Puntúa de nuevo las dos ejecuciones. ¿Qué resultado sería el correcto para la pregunta sin respuesta en el texto de la tienda? ¿Lo da la app?

Sobre este laboratorio y su código: Laboratorio JupyterLab de ciencia de datos: pandas, Matplotlib y scikit-learn en el navegador

¿Enseñas a una clase? Asigna este módulo a tus alumnos con guía del profesor, tareas con corrección automática y un laboratorio para cada alumno.