Few-shot prompting: un ejemplo vale más que 500 palabras
Llevas dos horas afinando el system prompt. Has añadido tres párrafos sobre el tono, cuatro sobre el formato, dos sobre los casos de borde. El agente sigue devolviendo la clasificación equivocada en el 30% de los casos.
El error no está en el modelo. Está en la estrategia: los LLMs entienden los ejemplos mejor que las instrucciones. Eso tiene un nombre —few-shot prompting— y la mayoría de equipos lo subutiliza porque nadie les enseñó cuándo usarlo.
Instrucciones largas vs ejemplos: por qué el modelo se pierde
Cuando escribes una instrucción larga en un system prompt, el modelo la sigue de forma aproximada. Cuanto más larga y más condicional ("si el campo A está vacío pero el campo B tiene valor, entonces..."), más se desvía del comportamiento que esperas.
Los LLMs son fundamentalmente motores de completado de patrones. Le das un patrón y completan lo que sigue. Cuando le das ejemplos concretos de input → output, estás definiendo el patrón directamente. Las instrucciones abstraen ese patrón; los ejemplos lo demuestran.
Un sistema prompt con 600 palabras de instrucciones suele perder frente a uno con 150 palabras de instrucciones + 3 ejemplos bien elegidos. No es intuición: es cómo funcionan los transformers internamente.
Cuándo usar few-shot (y cuándo no)
Few-shot no es la solución universal. Funciona bien en estos escenarios:
Úsalo cuando:
- Necesitas un formato de output específico que no sale bien solo con descripción
- El agente hace clasificaciones con matices que son difíciles de articular verbalmente
- Quieres consistencia de tono — ejemplos capturan el registro mejor que adjetivos
- Hay casos de borde que inevitablemente aparecen en producción
No lo uses cuando:
- La tarea es simple y zero-shot funciona (los ejemplos desperdician tokens)
- El contenido de los ejemplos puede quedar desactualizado rápido
- Necesitas ejemplos diferentes por usuario — mejor hacerlo dinámico (ver más abajo)
- El budget de tokens es muy ajustado y cada llamada tiene contexto largo
Cómo estructurar few-shot en tu system prompt
La estructura más limpia en TypeScript con el SDK de Anthropic es separar los ejemplos dentro del system prompt usando etiquetas XML claras:
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const SYSTEM_PROMPT = `Clasificas tickets de soporte en tres categorías: URGENTE, NORMAL o INFORMATIVO.
Un ticket es URGENTE si el usuario no puede operar en producción.
Un ticket es NORMAL si hay un problema funcional que tiene workaround.
Un ticket es INFORMATIVO si es una pregunta o solicitud de mejora.
<ejemplos>
<ejemplo>
<ticket>La pasarela de pago devuelve 500 y no podemos procesar ningún cobro</ticket>
<clasificacion>URGENTE</clasificacion>
</ejemplo>
<ejemplo>
<ticket>El filtro de fechas del informe no funciona si el mes tiene 31 días</ticket>
<clasificacion>NORMAL</clasificacion>
</ejemplo>
<ejemplo>
<ticket>¿Podéis añadir exportación a PDF en los informes?</ticket>
<clasificacion>INFORMATIVO</clasificacion>
</ejemplo>
</ejemplos>
Responde solo con la palabra de la clasificación.`;
async function clasificarTicket(ticket: string): Promise<string> {
const response = await client.messages.create({
model: "claude-haiku-4-5-20251001",
max_tokens: 20,
system: SYSTEM_PROMPT,
messages: [{ role: "user", content: ticket }],
});
return (response.content[0] as { text: string }).text.trim();
}
Tres detalles que importan en este patrón:
- El modelo más barato (Haiku) es suficiente para clasificación con few-shot. No necesitas Opus.
- Los ejemplos van después de las instrucciones cortas, no antes.
max_tokens: 20es intencional — el output es una sola palabra, no lo dejes abierto.
Si trabajas con agentes de clasificación o extracción, la integración IA en procesos de empresa puede ahorrarte semanas de prueba y error.
Few-shot dinámico: ejemplos relevantes en tiempo real
El few-shot estático tiene un límite: tus 3-5 ejemplos tienen que cubrir el espacio de casos posibles. Cuando el dominio es amplio, el few-shot dinámico lo resuelve.
La idea: guardas una colección de pares input→output validados en una base de datos. En cada llamada, recuperas los N más similares al input actual y los insertas dinámicamente en el prompt.
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
interface Ejemplo {
input: string;
output: string;
}
// En producción: búsqueda semántica contra tu colección
async function recuperarEjemplosRelevantes(
query: string,
n: number = 3
): Promise<Ejemplo[]> {
// Aquí iría la llamada a tu vector DB (pgvector, Pinecone, etc.)
// Devuelve los N ejemplos más similares al query actual
return ejemplosDB.slice(0, n); // simplificado
}
async function agenteDinamico(input: string): Promise<string> {
const ejemplos = await recuperarEjemplosRelevantes(input);
const ejemplosFormateados = ejemplos
.map(
(e) => `<ejemplo>
<input>${e.input}</input>
<output>${e.output}</output>
</ejemplo>`
)
.join("\n");
const systemPrompt = `Eres un agente de clasificación de soporte técnico.
<ejemplos_relevantes>
${ejemplosFormateados}
</ejemplos_relevantes>
Clasifica el ticket siguiendo el patrón de los ejemplos.`;
const response = await client.messages.create({
model: "claude-haiku-4-5-20251001",
max_tokens: 50,
system: systemPrompt,
messages: [{ role: "user", content: input }],
});
return (response.content[0] as { text: string }).text.trim();
}
El few-shot dinámico tiene un coste de latencia (la búsqueda semántica añade ~50-150ms), pero el resultado es notablemente más preciso cuando el dominio tiene muchos casos distintos. Si estás construyendo un agente de este tipo, los patrones de AI Driven Development te dan la arquitectura lista para no reinventar la rueda.
Tres casos donde few-shot desbloqueó lo que las instrucciones no podían
Clasificación de emails de soporte: Un equipo tenía instrucciones de 400 palabras para categorizar emails entrantes. Tasa de error: 28%. Reemplazamos por 8 ejemplos representativos. Tasa de error: 6%. Tiempo de procesamiento: igual. Coste de tokens: ligeramente mayor, pero el ahorro en errores justificó el cambio.
Generación de respuestas en el tono de marca: Un agente de atención al cliente generaba respuestas correctas pero con un tono corporativo que no encajaba con la marca. Tres ejemplos de respuestas reales escritas por el equipo lo corrigieron donde cuatro párrafos de descripción del tono habían fallado.
Extracción de datos de contratos: Extraer campos de contratos con formatos variables requería manejar docenas de formas distintas de escribir fechas, importes y partes. Few-shot estático con 5 ejemplos cubrió el 80% de los casos. Few-shot dinámico con 50 ejemplos en base de datos cubrió el 96%.
Por qué esto importa en un agente real
En un agente de producción, cada turno de conversación consume tokens. La diferencia entre un system prompt de 800 palabras con instrucciones y uno de 300 palabras con ejemplos puede ser 500 tokens por llamada. Con 100.000 llamadas al mes, eso es dinero y latencia real.
Además, los ejemplos son más fáciles de mantener que las instrucciones: cuando el comportamiento cambia, añades o modificas un ejemplo. No tienes que reescribir una lógica condicional anidada.
¿Estás construyendo un agente que clasifica, extrae o genera texto con formato específico y los resultados no son consistentes? Escríbeme por WhatsApp y revisamos si few-shot dinámico puede ser la palanca que falta en tu pipeline.