Cómo comparar dos versiones de IA con justicia
Una prueba A/B da la versión A a un grupo de usuarios y la B a otro. Después compara con qué frecuencia funciona cada una. Una prueba en la sombra ejecuta la versión nueva con peticiones reales, pero nadie ve sus respuestas.
Las dos pueden engañarte. Una diferencia de nueve puntos puede ser solo ruido.
Al final de esta lección
Nota
Puedo comparar dos versiones sin que me engañe el azar.
Palabras clave
| Palabra | Qué significa |
|---|---|
| Prueba A/B | dos grupos de usuarios, una versión cada uno |
| Prueba en la sombra | una versión nueva que se ejecuta sin que nadie la vea |
| Tasa de aprobados | la parte de peticiones que funcionaron |
| Diferencia | una tasa menos la otra, en puntos |
| Oscilación | cuánto se mueve una diferencia por azar |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Una diferencia debe superar la oscilación
La versión B aprueba 138 de 200 y la A aprueba 120 de 200. La diferencia es de 9 puntos. Pero dos grupos de 200 usuarios también difieren por azar.
La oscilación es cuánto se mueve una diferencia por azar. Una regla práctica: fíate de una diferencia solo cuando sea al menos el doble de la oscilación.
Ejemplo resuelto: dos pruebas
| Prueba | Usuarios por grupo | Diferencia | Oscilación | Doble de la oscilación | Veredicto |
|---|---|---|---|---|---|
| A frente a B | 200 | 9,0 | 4,8 | 9,6 | No probado |
| A frente a C | 1000 | 5,0 | 2,2 | 4,3 | Fiable |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Un error frecuente
Advertencia
Mucha gente cree que gana la nota más alta. Una nota más alta en una prueba pequeña puede ser azar. Declara un ganador solo cuando la diferencia sea al menos el doble de la oscilación; si no, di «no probado» y reúne más datos.
La sombra halla fallos nuevos sin riesgo
Ejecuta la versión nueva con las mismas peticiones reales y mantén ocultas sus respuestas. Por cada petición tienes un par: el resultado antiguo y el nuevo.
Dos totales iguales pueden esconder un cambio. Dos casos pueden empeorar mientras otros dos mejoran. Cuenta los que empeoran y lee cada uno.
Ejemplo resuelto: doce pares
| Par (antiguo, nuevo) | Significado | Cuántos |
|---|---|---|
| aprueba, aprueba | Igual | 7 |
| falla, falla | Igual | 1 |
| falla, aprueba | La nueva mejora | 2 |
| aprueba, falla | La nueva empeora, léelos | 2 |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Escribe el ayudante del modelo, parte 1
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
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 de comparación, parte 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'function wobble(a, an, b, bn) {' ' const p = (a + b) / (an + bn);' ' return Math.sqrt(p * (1 - p) * (1 / an + 1 / bn)) * 100;' '}' 'function gap(a, an, b, bn) { return (b / bn - a / an) * 100; }' 'function verdict(a, an, b, bn) {' ' const ok = Math.abs(gap(a, an, b, bn)) >= 2 * wobble(a, an, b, bn);' ' return ok ? \"fiable\" : \"no probado\";' '}' > ab.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 de comparación, parte 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const tests = [' ' { name: \"A frente a B\", a: 120, an: 200, b: 138, bn: 200 },' ' { name: \"A frente a C\", a: 600, an: 1000, b: 650, bn: 1000 },' '];' 'const pairs = \"pp pp pf pp fp pp ff pp pf pp pp fp\".split(\" \");' 'function count(kind) { return pairs.filter(function (p) { return p === kind; }).length; }' >> ab.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 de comparación, parte 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' tests.forEach(function (t) {' ' console.log(t.name + \": diferencia \" + gap(t.a, t.an, t.b, t.bn).toFixed(1) + \" puntos, oscilación \" + wobble(t.a, t.an, t.b, t.bn).toFixed(1) + \" -> \" + verdict(t.a, t.an, t.b, t.bn));' ' });' ' console.log(\"sombra: iguales \" + (count(\"pp\") + count(\"ff\")) + \", la nueva mejor \" + count(\"fp\") + \", la nueva peor \" + count(\"pf\"));' ' const q = \"En una frase corta, ¿por qué una diferencia de 9 puntos puede ser solo ruido?\";' ' const sample = \"Con solo 200 usuarios por grupo, el azar por sí solo puede mover una nota tanto.\";' ' const reply = await ask([{ role: \"user\", content: q }], sample, 60);' ' console.log(\"el modelo dijo: \" + reply.text);' '}' 'main();' >> ab.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 comparación
docker exec -w /home/node/project agent node ab.jsSe 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ínea | Qué muestra |
|---|---|
| A frente a B: diferencia 9.0 puntos, oscilación 4.8 -> no probado | Una diferencia grande, una prueba pequeña |
| A frente a C: diferencia 5.0 puntos, oscilación 2.2 -> fiable | Una diferencia menor, una prueba mayor |
| sombra: iguales 8, la nueva mejor 2, la nueva peor 2 | Contado sobre doce pares grabados |
| 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.