¿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

Cómo probar un chatbot con usuarios simulados

Después de esta lección: Puedo probar un diálogo con un usuario guionizado y puntuar la conversación.

Lección de 65 min6 comandosLaboratorio de agente de programación con IA: usa opencode para explicar y corregir código, y comprueba su trabajo

Una clienta que cambia de opinión

Un usuario simulado es un script que hace de cliente en una conversación con tu asistente. Sirve porque un diálogo no tiene una única respuesta correcta, y escribir chats de prueba a mano no escala.

Marta pide un reembolso, nombra un pedido y luego cambia de opinión. ¿Lo sigue el asistente?

Al final de esta lección

Nota

Puedo probar un diálogo con un usuario guionizado y puntuar la conversación.

Palabras clave

PalabraQué significa
Usuario simuladoun script que hace de cliente
Personajequién es el usuario y cómo escribe
Objetivolo que quiere el usuario al final
Condición de finla regla que detiene el diálogo
Transcripcióntoda la conversación, línea por línea

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

Escribe al usuario como un script

Dale al usuario un personaje, un objetivo y una lista de líneas. Añade una condición de fin, como un adiós o un máximo de turnos, para que el diálogo siempre pare.

Un script da el mismo usuario en cada ejecución. Un modelo que hiciera de usuario variaría, gastaría crédito en cada línea y haría difícil repetir un fallo. Empieza con un script.

Ejemplo resuelto: las cuatro líneas de Marta

LíneaLo que dice MartaLo que prueba
1hola, un reembolso por favorsi el asistente pregunta qué pedido
2pedido A17si inicia el reembolso
3mejor dicho, el pedido B02si maneja el cambio de opinión
4gracias, adióssi termina el diálogo

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

Puntúa la transcripción, no cada respuesta

Comprueba tres cosas en toda la transcripción. ¿Se logró el objetivo? ¿Los turnos están dentro del límite? ¿La acción ocurrió el número correcto de veces?

La última comprobación encuentra un fallo discreto. Un asistente que inicia un reembolso para A17 y otro para B02 logró el objetivo y reembolsó dos veces.

Escribe el ayudante del modelo, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' 'async function ask(messages, sample, max) {' '  try {' '    const res = await fetch(base + \"/v1/chat/completions\", {' '      method: \"POST\",' '      headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' '      body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 200 }),' '      signal: AbortSignal.timeout(30000),' '    });' '    if (res.ok === false) throw new Error(\"estado \" + res.status);' '    return (await res.json()).choices[0].message.content;' > model.js"

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

Escribe el ayudante del modelo, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' '  } catch (error) {' '    console.log(\"Muestra grabada: ningún modelo respondió (\" + error.message + \").\");' '    const list = [].concat(sample);' '    const turn = messages.filter(function (m) { return m.role === \"assistant\"; }).length;' '    return list[Math.min(turn, list.length - 1)];' '  }' '}' 'module.exports = { ask };' >> model.js"

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

Escribe el conductor del diálogo, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' '// Un usuario guionizado: un personaje, un objetivo, las líneas y un cambio de opinión en la línea 3.' 'const user = {' '  persona: \"Marta, con prisa, escribe mensajes cortos\",' '  goal: \"un reembolso del pedido B02\",' '  lines: [\"hola, un reembolso por favor\", \"pedido A17\", \"mejor dicho, el pedido B02\", \"gracias, adiós\"],' '};' '// Un asistente de sustitución hecho de reglas. Uno real sería el agente que se prueba.' 'function assistant(text) {' '  const order = text.match(/[AB][0-9][0-9]/);' '  if (order) return \"Reembolso iniciado para \" + order[0] + \".\";' '  if (text.includes(\"adiós\")) return \"Adiós.\";' '  return \"¿Cuál es el número de pedido?\";' '}' > sim.js"

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

Escribe el conductor del diálogo, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function drive(maxTurns) {' '  const transcript = [];' '  for (let i = 0; i < user.lines.length && i < maxTurns; i = i + 1) {' '    transcript.push(\"usuario: \" + user.lines[i]);' '    const reply = assistant(user.lines[i]);' '    transcript.push(\"asistente: \" + reply);' '    if (reply.includes(\"Adiós\")) break;' '  }' '  return transcript;' '}' 'const transcript = drive(6);' 'transcript.forEach(function (line) { console.log(line); });' 'const refunds = transcript.filter(function (line) { return line.includes(\"Reembolso iniciado\"); });' >> sim.js"

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

Escribe el conductor del diálogo, parte 3

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'console.log(\"Objetivo logrado: \" + transcript.join(\" \").includes(\"Reembolso iniciado para B02\"));' 'console.log(\"Turnos usados: \" + transcript.filter(function (line) { return line.startsWith(\"usuario\"); }).length);' 'console.log(\"Reembolsos iniciados: \" + refunds.length + \" (el usuario quería uno)\");' 'async function main() {' '  const system = \"Eres un asistente de soporte de una tienda. Pide el número de pedido antes de reembolsar nada. Responde con brevedad.\";' '  const sample = \"Claro. ¿Cuál es el número de pedido?\";' '  const text = await ask([{ role: \"system\", content: system }, { role: \"user\", content: user.lines[0] }], sample, 60);' '  console.log(\"Respuesta en vivo: \" + text.trim());' '  console.log(\"Pregunta por el pedido: \" + text.toLowerCase().includes(\"pedido\"));' '}' 'main();' >> sim.js"

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

Conduce al asistente con Marta

Comando
docker exec -w /home/node/project agent node sim.js

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

Lo que imprime el conductor

LíneaLo que muestra
TranscripciónCuatro líneas del usuario y cuatro del asistente
Objetivo logradotrue
Turnos usados4
Reembolsos iniciados2, el usuario quería uno
Respuesta en vivoUna salida posible: una pregunta sobre el pedido

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

Pruébalo

Consejo

En sim.js quita la tercera línea, "mejor dicho, el pedido B02", y lanza otra vez. Los reembolsos iniciados bajan a 1, pero el objetivo ya no se logra. Explica por qué.

Un error frecuente

Advertencia

Mucha gente cree que un diálogo aprueba cuando su última respuesta suena bien. Un adiós amable puede seguir a dos reembolsos. Puntúa lo que hizo el asistente en toda la transcripción: el objetivo, las acciones y los turnos.

Sobre este laboratorio y su código: Laboratorio de agente de programación con IA: usa opencode para explicar y corregir código, y comprueba su trabajo

¿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.