¿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

Haz que una instrucción peor falle el control

Después de esta lección: Puedo hacer que una instrucción peor falle un control automático.

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

Hacer fallar un control por una mala instrucción

Un equipo cambia una instrucción el viernes. El lunes, los clientes ven respuestas peores. Nadie miró la nota, porque nada les obligó a mirarla.

Una prueba de regresión dentro del control automático lo evita. El módulo sobre evaluación y pruebas compara dos ejecuciones a mano. Esta lección hace que la comparación detenga un cambio sola.

Al final de esta lección

Nota

Puedo hacer que una instrucción peor falle un control automático.

Palabras clave

PalabraQué significaEjemplo
Control automáticolas comprobaciones que se ejecutan solas con cada cambio
Conjunto congeladoun conjunto de evaluación que no cambia entre ejecuciones
Umbralla tasa de aciertos más baja que puede tener un cambio80
Caso críticoun caso que no puede pasar nunca de aprobar a fallar
Código de salidael número con que acaba un programa; cero significa que va bien

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

Un conjunto congelado y un umbral

El control ejecuta tu función sobre el mismo conjunto congelado cada vez. Si el conjunto cambiara con la instrucción, no podrías comparar dos ejecuciones.

Después eliges un umbral, por ejemplo el 80 por ciento. Un cambio que saca menos que el umbral hace fallar el control.

Los casos que cambiaron importan más

Una tasa esconde el movimiento. Un caso puede romperse mientras otro se arregla, y la tasa queda igual.

Por eso el control también lista los casos que cambiaron. Un caso roto aprobaba antes y falla ahora. Un caso arreglado hace lo contrario.

Ejemplo resuelto: doce casos, dos ejecuciones

MedidaEjecución viejaEjecución nueva
Casos aprobados10 de 129 de 12
Tasa de aciertos, porcentaje entero8375
Casos rotos-4 y 7
Casos arreglados-6
Caso crítico roto-Sí, el caso 4

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

Un error frecuente

Advertencia

Mucha gente cree que una tasa por encima del umbral significa que el cambio es seguro. Un caso crítico puede romperse mientras la tasa sigue alta. Mira primero los casos críticos y después la tasa.

Un código de salida dirige el control

Un programa acaba con un número. Cero significa que va bien y cualquier otro número significa un problema. El control se detiene cuando ve un número que no es cero.

Usamos 2 para un caso crítico roto, 1 para una tasa bajo el umbral y 0 para un aprobado. Lo crítico se mira primero.

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 la puerta del control, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'const mark = 80;' 'const rows = [' '  \"1 c 1 1\", \"2 n 1 1\", \"3 n 1 1\", \"4 c 1 0\",' '  \"5 n 1 1\", \"6 n 0 1\", \"7 n 1 0\", \"8 n 1 1\",' '  \"9 c 1 1\", \"10 n 0 0\", \"11 n 1 1\", \"12 n 1 1\",' '].map(function (r) {' '  const p = r.split(\" \");' '  return { id: Number(p[0]), critical: p[1] === \"c\", old: p[2] === \"1\", now: p[3] === \"1\" };' '});' > gate.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 la puerta del control, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function rate(key) {' '  const n = rows.filter(function (r) { return r[key]; }).length;' '  return Math.floor(n * 100 / rows.length);' '}' 'const broken = rows.filter(function (r) { return r.old && r.now === false; });' 'const fixed = rows.filter(function (r) { return r.old === false && r.now; });' 'function ids(list) {' '  return list.length === 0 ? \"ninguno\" : list.map(function (r) { return r.id; }).join(\", \");' '}' >> gate.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 la puerta del control, parte 3

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function exitCode() {' '  if (broken.some(function (r) { return r.critical; })) return 2;' '  if (rate(\"now\") < mark) return 1;' '  return 0;' '}' 'async function main() {' '  console.log(\"tasa de aciertos: \" + rate(\"old\") + \" -> \" + rate(\"now\") + \" (umbral \" + mark + \")\");' '  console.log(\"rotos: \" + ids(broken) + \"   arreglados: \" + ids(fixed));' '  console.log(\"código de salida: \" + exitCode());' '  const q = \"Escribe una frase tranquila para una revisión de cambios: el caso 4 aprobaba antes y ahora falla.\";' '  const sample = \"El caso 4 aprobaba con la instrucción anterior y falla con esta, así que se detiene el control.\";' '  const reply = await ask([{ role: \"user\", content: q }], sample, 60);' '  console.log(\"comentario: \" + reply.text);' '}' 'main();' >> gate.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 la puerta del control

Comando
docker exec -w /home/node/project agent node gate.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 la puerta

LíneaQué muestra
tasa de aciertos: 83 -> 75 (umbral 80)La tasa vieja y la nueva, y el umbral
rotos: 4, 7 arreglados: 6Los casos que cambiaron
código de salida: 2El caso 4 es crítico, así que el control se detiene
comentario: ...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.