¿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 reparar una mala respuesta de un modelo

Después de esta lección: Puedo reintentar una mala respuesta con el error como aviso, unas pocas veces y no más.

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

Dile qué estaba mal

Un bucle de reparación vuelve a preguntar tras una mala respuesta y le devuelve los fallos al modelo para que los corrija. Importa porque un segundo intento que conoce el problema suele acertar donde un reintento a ciegas no lo haría.

Una herramienta de formularios recibe una respuesta con una palabra que el esquema no permite. Rechazarla pierde el trabajo. Preguntar de nuevo, con el fallo en el mensaje, muchas veces lo salva.

Al final de esta lección

Nota

Puedo reintentar una mala respuesta con el error como aviso, unas pocas veces y no más.

Palabras clave

PalabraQué significa
Bucle de reparaciónpreguntar otra vez tras una mala respuesta, con un aviso
Avisolos fallos, devueltos en un mensaje nuevo
Límite de reintentosel máximo de intentos extra que permites
Salida de reservalo que se hace al llegar al límite
Lista de mensajesla conversación que se envía en cada llamada
Rendirseparar y usar la salida de reserva

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

Devuelve los fallos

Para reparar una respuesta, pregunta de nuevo con toda la conversación hasta ahora. Añade la mala respuesta como mensaje del asistente. Luego añade un mensaje del usuario que liste los fallos y repita la regla: responde solo con el JSON.

La lista de mensajes crece de dos en dos. El modelo ve lo que dijo y lo que estaba mal.

Ejemplo resuelto: tres intentos

IntentoRespuestaFallo encontradoSe envía después
1Seguramente sí, el trigo lo lleva.No es un objeto JSONEl fallo y la regla de responder solo con el JSON
2{"answer": "quizá"}answer debe ser sí o noEl fallo y la regla otra vez
3{"answer": "sí"}NingunoNada: se acepta

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

Un límite y una salida de reserva

Cada reintento cuesta tiempo y crédito. Por eso fija un límite de reintentos: el primer intento y como mucho dos más. Al llegar al límite, ríndete y usa la salida de reserva.

Una salida de reserva es un valor seguro como «desconocido», o un error que verá una persona. Anota que ocurrió, para ver con qué frecuencia pasa.

Escribir la ayuda 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.

Escribir la ayuda 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.

Escribir el bucle de reparación, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' '' 'const allowed = [\"sí\", \"no\"];' 'const MAX_TRIES = 3; // el primer intento y como mucho dos más' '' 'function pullJson(text) {' '  const start = text.indexOf(\"{\");' '  const end = text.lastIndexOf(\"}\");' '  if (start === -1 || end < start) return null;' '  try { return JSON.parse(text.slice(start, end + 1)); } catch (error) { return null; }' '}' > repair3.js"

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 bucle de reparación, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function problemsOf(text) {' '  const reply = pullJson(text);' '  if (reply === null) return [\"la respuesta no es un objeto JSON\"];' '  if (Object.prototype.hasOwnProperty.call(reply, \"answer\") === false) return [\"falta la clave answer\"];' '  if (allowed.includes(reply.answer) === false) return [\"answer debe ser sí o no\"];' '  return [];' '}' >> repair3.js"

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 bucle de reparación, parte 3

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function repairLoop(question, samples) {' '  const messages = [{ role: \"user\", content: question }];' '  for (let go = 1; go <= MAX_TRIES; go = go + 1) {' '    const reply = await ask(messages, samples, 60);' '    const found = problemsOf(reply);' '    console.log(\"Intento \" + go + \": \" + (found.length === 0 ? \"ok\" : found.join(\"; \")));' '    if (found.length === 0) return { ok: true, reply: pullJson(reply), tries: go };' '    messages.push({ role: \"assistant\", content: reply });' '    messages.push({ role: \"user\", content: \"Corrige estos problemas y responde solo con el JSON: \" + found.join(\"; \") });' '  }' '  return { ok: false, reply: null, tries: MAX_TRIES };' '}' >> repair3.js"

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 bucle de reparación, parte 4

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  const question = \"¿Lleva gluten el pan de trigo? Responde con un objeto JSON con la clave answer, que vale sí o no. Responde solo con el JSON.\";' '  // Muestras grabadas, usadas solo si ningún modelo responde: dos respuestas malas y luego una buena.' '  const samples = [\"Seguramente sí, el trigo lo lleva.\", JSON.stringify({ answer: \"quizá\" }), JSON.stringify({ answer: \"sí\" })];' '  const result = await repairLoop(question, samples);' '  const fallback = { answer: \"desconocido\" };' '  console.log(\"Intentos usados:\", result.tries);' '  console.log(\"Resultado:\", JSON.stringify(result.ok ? { answer: result.reply.answer } : fallback));' '}' 'main();' >> repair3.js"

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

Ejecutar el bucle

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

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

Una salida posible

LíneaLo que puede mostrar
Intento 1ok, si el modelo respondió JSON limpio a la primera
Intento 2 e Intento 3Solo si el intento 1 falló: el fallo, o ok
Intentos usadosUn número de 1 a 3
ResultadoLa respuesta, o la salida de reserva {"answer":"desconocido"}

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

Un error frecuente

Advertencia

Mucha gente cree que reintentar hasta que funcione es seguro. Si el modelo nunca acierta, un bucle sin límite no termina, y cada intento cuesta tiempo y crédito. Fija siempre un límite y decide antes la salida de reserva.

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.