Regression evals - suite fija en el PR
Los regression evals son la suite inmutable: dataset cerrado, gate en el merge, comparación contra un baseline. Es lo que convierte 'creo que quedó mejor' en 'la métrica X cayó 2 puntos, bloquear el PR'.
Qué es
Un regression eval es una suite de casos que no cambia junto con el código. Congelas el dataset (input, gabarito, métrica), y cada PR se evalúa contra ese dataset. Si una métrica cae por debajo del baseline, el PR falla y el merge se traba. El objetivo es simple: dejar de discutir si el cambio mejoró o empeoró.
La diferencia con el eval genérico es la inmutabilidad. El eval del PR puede crecer, editarse, incluir casos nuevos. El regression eval es un contrato: igual al de la última release, con el único cambio permitido siendo la versión del baseline.
Dataset inmutable versus dataset vivo
El mantenimiento del dataset es donde la mayoría de los equipos se equivoca. Dos caminos. Inmutable puro: un dataset congelado en cada release, que solo crece cuando se detecta una regresión y se agrega como caso nuevo. Versátil: un dataset versionado (git LFS), donde un PR puede proponer casos, y el merge solo acepta si aumenta la cobertura.
La elección cambia lo que 'regresión' significa. El inmutable puro detecta solo drift; el versátil detecta drift y agrega nuevos huecos. Para equipos que todavía están aprendiendo qué medir, gana el versátil. Para equipos con un producto estable desde hace meses, gana el inmutable, porque la suite se vuelve un contrato de SLA.
Gate en el PR: el esqueleto
El esqueleto de abajo mezcla dos referencias conocidas (promptfoo y Braintrust) para mostrar la mecánica real: archivo de casos en YAML, runner que compara contra el baseline y veredicto booleano que consume el step de CI.
import fs from "node:fs";
import { runAgent } from "../src/agent";
import { assertFidelidade, assertRelevancia } from "./asserts";
import { loadBaseline, saveBaseline } from "./baseline";
type Case = { id: string; pergunta: string; gabarito: string; contexto: string };
type Metric = "fidelidade" | "relevancia";
async function runOne(c: Case) {
const out = await runAgent({ pergunta: c.pergunta, contexto: c.contexto });
return {
id: c.id,
fidelidade: await assertFidelidade(out, c.gabarito, c.contexto),
relevancia: await assertRelevancia(out, c.pergunta),
};
}
export async function runRegressionSuite(path: string) {
const cases: Case[] = parseCases(fs.readFileSync(path, "utf8"));
const baseline = loadBaseline("regression.baseline.json");
const results = await Promise.all(cases.map(runOne));
const report: Record<Metric, number> = { fidelidade: 0, relevancia: 0 };
for (const m of ["fidelidade", "relevancia"] as Metric[]) {
const avg = results.reduce((a, r) => a + r[m], 0) / results.length;
report[m] = avg;
const drop = baseline[m] - avg;
if (drop > 0.02) throw new Error(`regresión en ${m}: baseline ${baseline[m]} vs actual ${avg}`);
}
return report; // el CI lo consume y decide el gateBaseline, umbral y muestreo
El baseline es la última release verde. Persistes (en un artefacto, en git, en un object store) la métrica por caso, y el runner compara caso a caso. El umbral define cuánto puede caer antes de fallar. Un umbral de 0.02 (2 puntos porcentuales) suele ser conservador; por debajo, los falsos positivos se comen el tiempo del equipo. Por encima, una regresión real se convierte en release.
No todo PR necesita correr la suite completa. Para un PR pequeño, basta un muestreo aleatorio del 20% de los casos. Para un PR de release, la suite completa. El costo es el principal motivo por el que los equipos abandonan la suite fija: correr 500 casos en cada PR tarda cinco minutos y pronto se vuelve blanco de bypass.
Dónde entra en el pipeline
Antes del merge, en un step dedicado de CI, con el baseline congelado por rama protegida (main/release). El gate no es opcional: un pipeline sin suite fija no cuenta como eval. Es como hacer un deploy sin smoke test.
Después del merge, una versión completa corre de noche para detectar el drift acumulado. El resultado alimenta el dataset: un caso nuevo que apareció en la corrida nocturna se vuelve caso de la suite fija en la próxima release.
Cómo mantener sana la suite
Regla de oro: cuando una regresión aparece en producción pero pasa la suite, el caso se vuelve un caso nuevo de la suite en el mismo PR. Sin esta política la suite se vuelve una cobertura falsa y el equipo pierde la fe en ella.
La segunda regla es auditar la suite una vez por trimestre. Los casos desactualizados (gabarito equivocado, contexto eliminado) se vuelven ruido y contaminan el baseline. Limpiar es trabajo, pero limpiar es lo que mantiene útil la suite.
Puntos fuertes
- bloqueo automático: una regresión real se convierte en un fallo de CI, sin necesidad de alguien leyendo el PR
- historial rastreable: cada baseline es un commit, y cualquier caída apunta al PR que la causó
- cultura: el equipo deja de discutir opiniones y empieza a discutir números, y el número tiene dueño
Limitaciones
- falso negativo: la suite solo detecta regresiones cubiertas, el resto se vuelve un incidente de producción
- mantenimiento constante: un dataset desactualizado miente, y el mantenimiento es trabajo que nadie pide
- costo de runtime: correr 500 casos en cada PR necesita presupuesto de tiempo y de API
conexiones en el mapa
- Regression evals - suite fija en el PRprotege el baselineEvals - calidad medida en producción
actualizado el 14/10/2026 · fuentes para profundizar · reportar un error
en otros dominios
- Respuesta a incidentes en la nubecloudseccada incidente se vuelve un caso de prueba
Estudia antes
pon a prueba lo que entendiste
Cargando preguntas…