MÓDULO 2 · PROMPT ENGINEERING · 35 MIN

Structured outputs (JSON mode): técnicas de prompting para obtener datos estructurados

35 min Intermedio Claude ChatGPT Gemini cualquier LLM
"Dame JSON" no alcanza. Un prompt para structured output necesita 4 cosas: schema explícito (qué campos y tipos), ejemplo concreto (cómo se ve un caso real), restricciones de formato (solo JSON, nada de texto extra), y manejo de ausencias (qué hacer si falta un dato).
El problema

Cuando solicitás JSON en un prompt normal, el LLM frecuentemente retorna respuestas que no podés usar directamente.

Situación típica 1 — JSON envuelto en texto: pedís "dame los datos en formato JSON" y recibís "Claro, aquí tienes los datos: ```json {...}``` Como puedes ver, extraje el nombre y el email correctamente." El JSON está ahí, pero envuelto en explicaciones — si intentás procesarlo automáticamente, falla el parseo.

Situación típica 2 — Estructura inconsistente: ejecución 1 devuelve {"name": "Juan", "email": "..."}, ejecución 2 devuelve {"nombre": "Juan Garcia", "correo": "..."}, ejecución 3 anida todo en un objeto "usuario". Cada ejecución produce una estructura diferente — imposible de automatizar.

Situación típica 3 — Tipos mezclados: esperabas {"precio": 99.99, "disponible": true, "cantidad": 5} y recibiste {"precio": "99.99 euros", "disponible": "sí", "cantidad": "cinco"} — strings donde esperabas números y booleanos.

Por qué es importante: sin outputs estructurados consistentes, cada respuesta requiere limpieza manual antes de usarla, no podés alimentar los datos a otros sistemas (Excel, bases de datos, APIs), no podés comparar resultados entre ejecuciones, y la automatización es imposible.

La solución: técnicas de prompting para JSON estructurado
TÉCNICA 1 Schema explícito → Define la estructura exacta TÉCNICA 2 Ejemplos de output → Muestra el formato esperado TÉCNICA 3 Restricciones de formato → Elimina texto extra TÉCNICA 4 Manejo de ausencias → Qué hacer si falta un dato
Cómo funciona
Técnica 1 — Schema explícito

Definí exactamente qué campos esperás, sus tipos, y cuáles son obligatorios.

prompt sin schema — inconsistenteExtrae los datos de contacto de este texto y devuélvelos en JSON. Texto: "María López, ingeniera de software, trabaja en TechCorp. Contacto: maria.lopez@techcorp.com, teléfono 555-1234"
prompt con schema — consistenteExtrae los datos de contacto del texto y devuélvelos en JSON. Schema requerido: { "nombre": string, "cargo": string, "empresa": string, "email": string, "telefono": string | null } Reglas: - Usa exactamente estos nombres de campos (en español, minúsculas) - Si un dato no está disponible, usa null - No añadas campos adicionales Texto: "María López, ingeniera de software, trabaja en TechCorp. Contacto: maria.lopez@techcorp.com, teléfono 555-1234"

Elementos del schema efectivo: nombres de campos exactos (nombre o name, email o correo), tipos de datos (string, number, boolean, array, null), opcionalidad (qué campos pueden ser null), y restricciones ("No añadas campos adicionales", "Usa solo estos valores para X").

Técnica 2 — Ejemplos de output (few-shot para formato)

Mostrar 1-2 ejemplos del formato exacto que esperás es más efectivo que describirlo.

markdownExtrae información de productos y devuélvela en JSON. Ejemplo de formato esperado: Input: "iPhone 15 Pro - $999 - Disponible en negro y blanco" Output: { "nombre": "iPhone 15 Pro", "precio": 999, "moneda": "USD", "disponible": true, "colores": ["negro", "blanco"] } Ahora extrae de este texto: "Samsung Galaxy S24 Ultra - €1.299 - Agotado temporalmente, viene en titanio"

Por qué funciona: el LLM ve el patrón exacto (precio como número, colores como array), elimina ambigüedad sobre formato de moneda y booleanos, y el ejemplo sirve como "contrato" implícito.

Reglas para ejemplos efectivos: usá datos realistas (no placeholders genéricos), incluí todos los tipos de campo (strings, números, arrays, nulls), y si hay casos límite (campo vacío, valor especial) inclúyelos también en el ejemplo.

Técnica 3 — Restricciones de formato estrictas

El LLM tiende a "ser útil" añadiendo explicaciones. Debés prohibirlo explícitamente.

markdownResponde SOLO con JSON válido. Reglas estrictas: 1. Tu respuesta EMPIEZA con { y TERMINA con } 2. NO incluyas ```json``` ni ningún markdown 3. NO añadas texto explicativo antes ni después 4. NO uses comentarios dentro del JSON

// Variantes: "restricción directa" (prohibí explicaciones), "formato de respuesta explícito" (definí qué está prohibido/permitido), o "rol restrictivo" ("Eres una API que solo retorna JSON"). Combinarlas es lo más robusto.

Técnica 4 — Manejo de datos ausentes

Definí explícitamente qué hacer cuando un dato no existe en el input.

sin instrucciones — impredecibleEl LLM podría: - Omitir el campo: {"nombre": "Juan"} - Inventar datos: {"nombre": "Juan", "telefono": "000-0000"} - Usar string vacío: {"nombre": "Juan", "telefono": ""} - Usar null: {"nombre": "Juan", "telefono": null}
con instrucciones claras — predecibleReglas para datos faltantes: - Si un campo de texto no está disponible: usa null - Si un campo numérico no está disponible: usa null - Si un array no tiene elementos: usa [] - NUNCA inventes datos que no estén en el texto original - NUNCA omitas campos del schema; todos deben aparecer
Plantilla completa — combina las 4 técnicas
markdown# ROL Eres un extractor de datos que solo responde en JSON. # TAREA Extrae [tipo de información] del texto proporcionado. # SCHEMA Retorna un objeto JSON con esta estructura exacta: { "campo1": tipo (descripción), "campo2": tipo (descripción), "campo3": tipo | null (descripción, null si no disponible) } # EJEMPLO Input: "[ejemplo de texto de entrada]" Output: { "campo1": "valor ejemplo", "campo2": 123, "campo3": null } # REGLAS 1. Responde SOLO con el JSON, sin texto adicional 2. Tu respuesta empieza con { y termina con } 3. Usa null para datos no disponibles, nunca inventes 4. Mantén exactamente los nombres de campos del schema # INPUT [Texto a procesar]
Cuándo aplicarlo
SituaciónTécnica recomendada
Primera vez que definís el formatoSchema explícito + 1 ejemplo
El LLM añade texto fuera del JSONRestricciones de formato estrictas
Resultados inconsistentes entre ejecucionesFew-shot con 2-3 ejemplos diversos
El LLM inventa datos faltantesReglas explícitas para null/valores vacíos
Schema complejo con muchos camposSchema + ejemplo + validación verbal de campos críticos
Outputs para uso en automatizaciónTodas las técnicas combinadas
Ejercicio práctico

Objetivo: crear prompts que extraigan datos estructurados de diferentes tipos de texto y verificar consistencia entre ejecuciones.

Contexto inicial: usá Claude.ai, ChatGPT, o cualquier interfaz de LLM. No necesitás código ni APIs.

Paso 1 — Prompt básico vs estructurado

Ejecutá primero el prompt básico (sin técnicas):

promptExtrae la información de este perfil profesional y devuélvela en JSON: "Ana Martínez | Senior Product Manager | 7 años de experiencia Empresa actual: Spotify (2021-presente) Anteriormente: Google (2018-2021), Startup XYZ (2017-2018) Contacto: ana.martinez@email.com | LinkedIn: /in/anamartinez Skills: Product Strategy, Agile, SQL, User Research, A/B Testing"

Anotá: ¿el JSON es válido (empieza con {, termina con })? ¿hay texto explicativo antes o después? ¿qué nombres usó para los campos? Ejecutá el mismo prompt 2 veces más y comparás: ¿son idénticos los campos?

Ahora ejecutá el prompt estructurado, con schema, ejemplo, reglas de formato y de campos faltantes combinados (usá la plantilla completa de la sección anterior, con schema para nombre, cargo_actual, años_experiencia (number), empresa_actual, empresas_anteriores (array), email, linkedin (nullable), skills (array), y el mismo texto de Ana Martínez como input). Comparás: ¿el output es JSON puro sin texto extra? ¿años_experiencia es número (7) o string ("7 años")? ¿los campos coinciden exactamente con el schema?

Paso 2 — Extracción de múltiples entidades

Creá un prompt para extraer varios items de una lista, con un array anidado en el schema:

markdown# SCHEMA { "productos": [ {"nombre": string, "precio": number, "moneda": "EUR" | "USD", "disponible": boolean} ], "total_productos": number } # REGLAS 1. Responde SOLO con JSON válido 2. precio es número sin símbolo de moneda 3. disponible es true/false, no "sí"/"no" 4. Si no se menciona disponibilidad, asume true # INPUT "Catálogo de verano: - Camiseta básica: 19,99€ (últimas unidades) - Pantalón chino: 49,99€ - Zapatillas running: 89,99€ (agotado) - Gorra deportiva: 15€ (disponible)"

Verificá: ¿los precios son números (19.99) o strings ("19,99€")? ¿usó punto decimal en lugar de coma? ¿"últimas unidades" se interpretó correctamente como disponible?

Paso 3 — Manejo de datos ambiguos

Probá cómo maneja el LLM información incompleta, con un schema donde casi todo puede ser null y el input solo trae el nombre:

input"Mensaje de contacto: Hola, soy Carlos. Me interesa el puesto. Pueden contactarme cuando quieran. Saludos"

// Resultado esperado: {"nombre": "Carlos", "email": null, "telefono": null, "cargo": null, "empresa": null}

Verificá: ¿el LLM inventó un email o teléfono, o respetó el null?

Paso 4 — Consistencia entre ejecuciones

Ejecutá este prompt 5 veces (refrescando la conversación cada vez):

markdown# SCHEMA { "categoria": "billing" | "technical" | "feature_request" | "other", "prioridad": "alta" | "media" | "baja", "resumen": string (máximo 10 palabras) } # INPUT "No puedo iniciar sesión desde esta mañana. Ya intenté resetear la contraseña pero sigue sin funcionar. Necesito acceder urgente porque tengo una presentación en 2 horas."

Registrá categoría, prioridad y resumen de cada una de las 5 ejecuciones. Analizá: ¿cuántas dieron exactamente el mismo resultado? ¿la categoría fue consistente (todas "technical")? ¿la prioridad fue consistente (todas "alta")? Si hay variación, añadí un ejemplo few-shot y repetí el test.

Paso 5 — Validación con schema complejo

Escenario: extraer información de una factura. Diseñá vos el prompt completo (con las 4 técnicas) para este schema:

input de pruebaFACTURA Nº: F-2024-0892 Fecha: 15 de marzo de 2024 Cliente: Tecnologías Avanzadas S.L. NIF: B-12345678 Descripción Cant. Precio Total Consultoría técnica 10h 75,00€ 750,00€ Desarrollo de módulo 1 500,00€ 500,00€ Soporte mensual 1 150,00€ 150,00€ Subtotal: 1.400,00€ IVA (21%): 294,00€ TOTAL: 1.694,00€
Troubleshooting rápido
Si ves esto...CausaSolución
Usa ```json``` markdownTendencia a formatear códigoAñadí: "NO uses bloques de código markdown"
Campos con nombres diferentes al schemaSchema no lo suficientemente explícitoMostrá un ejemplo completo del output esperado
Números como strings ("100" vs 100)Ambigüedad de tiposEspecificá: "precio es number, no string"
Inventa datos que no existenNo definiste manejo de ausenciasAñadí: "Si no está en el texto, usa null. NUNCA inventes."
Resultados diferentes en cada ejecuciónFalta de ejemplos y schemaAñadí 2 ejemplos few-shot con casos diversos
Puntos clave

Concepto central: "Dame JSON" no es suficiente. Un prompt para structured output necesita: schema explícito (qué campos y tipos), ejemplo concreto (cómo se ve), restricciones de formato (solo JSON, nada más), y manejo de ausencias (qué hacer si falta un dato).

Para recordar: