OperacionesAvanzado40 min
Testing de Aplicaciones IA
Unit tests · evals · benchmarks · cómo saber si tu IA funciona
TestingEvalsQA
✓ Guía gratuita · Acceso completo
Mapa rápido · salta al paso que te interese
01
Tipos de tests para aplicaciones IA
| Tipo | Qué testea | Determinista | Frecuencia |
|---|---|---|---|
| Unit tests | Parsers, validators, utils | Sí | Cada commit |
| Integration | API routes, DB queries | Sí | Cada commit |
| Evals | Calidad de respuestas LLM | No | Diario/semanal |
| Regression | Que no empeore con cambios | No | Antes de deploy |
⚠ Advertencia
No mockees el LLM en tests de eval. El punto es validar el comportamiento real del modelo con tu prompt.
02
Evals con datasets de golden examples
tests/evals/qa-eval.ts
import { describe, it, expect } from 'vitest'
import { generateAnswer } from '@/lib/ai/qa'
// Dataset de ejemplos "golden" - respuestas que sabemos correctas
const EVAL_DATASET = [
{
question: '¿Cuál es la capital de España?',
expectedContains: ['Madrid'],
expectedNotContains: ['Barcelona', 'Valencia'],
},
{
question: '¿Qué es TypeScript?',
expectedContains: ['JavaScript', 'tipos', 'Microsoft'],
expectedNotContains: ['Python', 'Ruby'],
},
]
describe('QA Evals', () => {
for (const example of EVAL_DATASET) {
it(`should answer: ${example.question.slice(0, 30)}...`, async () => {
const answer = await generateAnswer(example.question)
// Check expected content is present
for (const expected of example.expectedContains) {
expect(answer.toLowerCase()).toContain(expected.toLowerCase())
}
// Check unwanted content is absent
for (const notExpected of example.expectedNotContains) {
expect(answer.toLowerCase()).not.toContain(notExpected.toLowerCase())
}
}, 30000) // Timeout alto para llamadas a API
}
})03
LLM-as-judge para evaluación semántica
tests/evals/llm-judge.ts
import Anthropic from '@anthropic-ai/sdk'
const anthropic = new Anthropic()
interface EvalResult {
score: number // 1-5
reasoning: string
}
export async function evaluateWithLLM(
question: string,
answer: string,
criteria: string
): Promise<EvalResult> {
const response = await anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 500,
messages: [{
role: 'user',
content: `Evalúa esta respuesta del 1 al 5.
Pregunta: ${question}
Respuesta: ${answer}
Criterio: ${criteria}
Responde en JSON: {"score": N, "reasoning": "..."}`
}],
})
const text = response.content[0].type === 'text' ? response.content[0].text : ''
return JSON.parse(text)
}
// Uso
const result = await evaluateWithLLM(
'¿Cómo funciona React?',
'React es una librería de JavaScript para construir interfaces...',
'Precisión técnica y claridad'
)
console.log(result) // { score: 4, reasoning: "Respuesta correcta pero..." }Tip Pro
Usa un modelo diferente como judge del que genera las respuestas para evitar sesgo.
Guías relacionadas
¿Quieres el sistema completo?
500+ páginas, 25 capítulos, código de producción, acceso a todas las guías del Arsenal.
Curso Completo · €29PayPal · Acceso inmediato