¿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

Disyuntores y alternativas que degradan bien

Después de esta lección: Puedo mantener útil una función mientras su modelo falla.

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

Cómo funciona un disyuntor

Un disyuntor es una regla sencilla que deja de llamar a un servicio que no para de fallar. Mientras está abierto, la función usa una alternativa en vez de esperar una llamada que va a fallar.

El módulo sobre coste, trazas y fiabilidad enumera las alternativas. Esta lección va más allá: cuándo dejar de llamar, cuándo volver a probar y un interruptor de emergencia que una persona puede pulsar.

Al final de esta lección

Nota

Puedo mantener útil una función mientras su modelo falla.

Palabras clave

PalabraQué significaEjemplo
Disyuntoruna regla que corta las llamadas a un servicio que falla
Cerradoel estado normal: las llamadas pasan
Abiertoel estado de corte: no hay llamadas y contesta una alternativa
Semiabiertouna llamada de prueba para ver si el servicio ha vuelto
Enfriamientolos pasos que se espera antes de una prueba4
Interruptor de emergenciaun control que apaga una función al instante

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

Tres estados

Un disyuntor está cerrado cuando todo va bien. Las llamadas pasan. Cuenta los fallos seguidos. Cuando la cuenta llega al umbral, aquí 3, se abre.

Mientras está abierto no hace ninguna llamada. Tras el enfriamiento, aquí 4 pasos, se pone semiabierto y deja pasar una llamada. Un éxito lo cierra. Un fallo lo abre otra vez.

Ejemplo resuelto: pasos 3 a 9

PasoLa llamadaEstado halladoServidoMotivo
3FallaríaCerradoFalloPrimer fallo seguido, cuenta 1
4FallaríaCerradoFalloCuenta 2
5FallaríaCerradoFalloLa cuenta llega a 3, así que se abre
6FuncionaríaAbiertoOmitidoSin llamada. 1 paso desde que se abrió
7FuncionaríaAbiertoOmitido2 pasos desde que se abrió
8FuncionaríaAbiertoOmitido3 pasos desde que se abrió
9FuncionaríaSemiabiertoModelo4 pasos, la prueba funciona, así que se cierra

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

Un error frecuente

Advertencia

Mucha gente cree que un disyuntor debe abrirse con el primer fallo. Un solo fallo suele ser un tropiezo. Cuenta los fallos seguidos y deja que un éxito ponga la cuenta a cero, o una sola llamada mala cortará un servicio sano.

Lo que dice la alternativa

Una alternativa debe ser honesta y útil. La mejor es una respuesta guardada a la misma pregunta. Si no la hay, di con claridad que el asistente está ocupado y cuándo probar de nuevo.

Nunca muestres una respuesta inventada como si la hubiera dado el modelo.

El interruptor es una decisión de una persona

Un disyuntor reacciona a los fallos. Una persona pulsa el interruptor de emergencia cuando el modelo funciona pero no debería usarse. Quizá da respuestas erróneas o cuesta demasiado.

Mientras está activo se omite cada llamada. No toca el disyuntor, que conserva su propia cuenta y su estado.

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\";' '// Los tokens de una respuesta, o null si no trae ninguno.' 'function count(data, name) {' '  return data.usage && typeof data.usage[name] === \"number\" ? data.usage[name] : null;' '}' > 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' '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 || 100 }),' '      signal: AbortSignal.timeout(30000),' '    });' '    if (res.ok === false) throw new Error(\"estado \" + res.status);' '    const d = await res.json();' '    return { text: d.choices[0].message.content, inTokens: count(d, \"prompt_tokens\"), outTokens: count(d, \"completion_tokens\"), recorded: false };' '  } catch (error) {' '    console.log(\"Muestra grabada: ningún modelo respondió (\" + error.message + \").\");' '    return { text: sample, inTokens: null, outTokens: null, recorded: true };' '  }' '}' '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 script del disyuntor, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'function step(b, outcome, i, threshold, cooldown, kill) {' '  if (kill) return [b.state, \"omitido\"];' '  if (b.state === \"abierto\" && i - b.openedAt >= cooldown) b.state = \"semiabierto\";' '  const found = b.state;' '  if (found === \"abierto\") return [found, \"omitido\"];' '  if (outcome === 1) { b.state = \"cerrado\"; b.fails = 0; return [found, \"modelo\"]; }' '  b.fails = b.fails + 1;' '  if (found === \"semiabierto\" || b.fails >= threshold) { b.state = \"abierto\"; b.openedAt = i; b.fails = 0; }' '  return [found, \"fallo\"];' '}' > breaker.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 script del disyuntor, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const outcomes = [1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1];' 'function drive(kills) {' '  const b = { state: \"cerrado\", fails: 0, openedAt: 0 };' '  return outcomes.map(function (o, k) {' '    const r = step(b, o, k + 1, 3, 4, kills.includes(k + 1));' '    return r[0] + \":\" + r[1];' '  });' '}' >> breaker.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 script del disyuntor, parte 3

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  const trace = drive([]);' '  console.log(trace.slice(0, 10).join(\" \"));' '  console.log(trace.slice(10).join(\" \"));' '  const made = trace.filter(function (t) { return t.endsWith(\"omitido\") === false; }).length;' '  console.log(\"llamadas hechas \" + made + \" de \" + trace.length);' '  console.log(\"interruptor en 9 y 10: \" + drive([9, 10]).slice(8, 11).join(\" \"));' '  const q = \"En una frase corta, ¿qué debe decir una función cuando su modelo no está disponible?\";' '  const reply = await ask([{ role: \"user\", content: q }], \"Debe decir con claridad que el asistente está ocupado y ofrecer una respuesta guardada u otra vía.\", 60);' '  console.log(\"el modelo dijo: \" + reply.text);' '}' 'main();' >> breaker.js"

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

Ejecuta el disyuntor

Comando
docker exec -w /home/node/project agent node breaker.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 Run

LíneaQué muestra
cerrado:modelo cerrado:modelo cerrado:fallo ...Pasos 1 a 10, el estado hallado y cómo se sirvió
abierto:omitido abierto:omitido abierto:omitido semiabierto:modeloEl disyuntor se abre, espera y una prueba funciona
llamadas hechas 14 de 20Se ahorraron seis llamadas
interruptor en 9 y 10: abierto:omitido abierto:omitido semiabierto:modeloEl interruptor omitió dos pasos y el enfriamiento siguió
el modelo dijo: ...Una frase del laboratorio. Una muestra grabada si ningún modelo responde

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

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.