TechLead
Lección 11 de 18
5 min de lectura
LangChain

Salida Estructurada y Análisis JSON

Obtén respuestas JSON estructuradas confiables de LLMs usando parsers de salida, esquemas Zod y llamadas a funciones

¿Por Qué Salida Estructurada?

Los LLMs naturalmente devuelven texto libre, pero la mayoría de las aplicaciones necesitan datos estructurados — objetos JSON, arrays, campos específicos. LangChain proporciona múltiples estrategias para asegurar que los LLMs devuelvan datos en el formato exacto que tu aplicación espera.

🎯 Cuándo Necesitas Salida Estructurada

  • Respuestas API: Devolver JSON desde endpoints con IA
  • Extracción de Datos: Extraer info estructurada de texto libre
  • Generación de Formularios: Crear formularios dinámicos
  • Inserciones en BD: Extraer datos para guardar en tu base de datos

Método 1: withStructuredOutput (Recomendado)

import { ChatOpenAI } from "@langchain/openai";
import { z } from "zod";

// Definir esquema con Zod
const PersonaSchema = z.object({
  nombre: z.string().describe("Nombre completo de la persona"),
  edad: z.number().describe("Edad en años"),
  ocupacion: z.string().describe("Título del trabajo actual"),
  habilidades: z.array(z.string()).describe("Lista de habilidades técnicas"),
  disponible: z.boolean().describe("Si está disponible para contratar"),
});

// Crear modelo que devuelve salida estructurada
const model = new ChatOpenAI({
  modelName: "gpt-4",
  temperature: 0,
}).withStructuredOutput(PersonaSchema);

const persona = await model.invoke(
  "Extrae info: Juan García es un desarrollador senior React de 32 años " +
  "que conoce TypeScript, Node.js y GraphQL. Actualmente busca trabajo."
);

console.log(persona);
// {
//   nombre: "Juan García",
//   edad: 32,
//   ocupacion: "Desarrollador Senior React",
//   habilidades: ["TypeScript", "Node.js", "GraphQL", "React"],
//   disponible: true
// }

Método 2: StructuredOutputParser

import { StructuredOutputParser } from "@langchain/core/output_parsers";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { z } from "zod";

const parser = StructuredOutputParser.fromZodSchema(
  z.object({
    resumen: z.string().describe("Un resumen breve"),
    sentimiento: z.enum(["positivo", "negativo", "neutral"]),
    temas: z.array(z.string()).describe("Temas principales discutidos"),
  })
);

const prompt = ChatPromptTemplate.fromTemplate(`
Analiza el siguiente texto y proporciona salida estructurada.

{format_instructions}

Texto: {text}
`);

const chain = prompt.pipe(model).pipe(parser);

const result = await chain.invoke({
  text: "React 19 introduce nuevas funcionalidades como Server Components...",
  format_instructions: parser.getFormatInstructions(),
});

console.log(result.sentimiento); // "positivo"
console.log(result.temas);      // ["React", "Server Components"]

Extrayendo Datos de Texto No Estructurado

import { z } from "zod";

const ReseñaSchema = z.object({
  nombreProducto: z.string(),
  calificacion: z.number().min(1).max(5),
  pros: z.array(z.string()),
  contras: z.array(z.string()),
  recomendaria: z.boolean(),
});

const model = new ChatOpenAI({ modelName: "gpt-4" })
  .withStructuredOutput(ReseñaSchema);

const reseña = await model.invoke(`
  Extrae los datos de la reseña de este texto:
  
  "Compré el XPS 15 el mes pasado. Calidad de pantalla increíble y 
  el teclado es genial para programar. La duración de la batería podría 
  ser mejor y se calienta bajo carga. Le doy un 4/5 
  y definitivamente lo recomendaría a desarrolladores."
`);

console.log(reseña);
// {
//   nombreProducto: "XPS 15",
//   calificacion: 4,
//   pros: ["Calidad de pantalla increíble", "Teclado genial para programar"],
//   contras: ["Duración de batería mejorable", "Se calienta bajo carga"],
//   recomendaria: true
// }

💡 Puntos Clave

  • • Usa withStructuredOutput() con esquemas Zod — es el método más confiable
  • • Establece temperature: 0 para salida estructurada más consistente
  • • El .describe() de Zod ayuda al LLM a entender qué debe contener cada campo
  • • StructuredOutputParser funciona con cualquier modelo, incluso sin llamadas a funciones
  • • Usa OutputFixingParser para reintento automático en respuestas mal formadas

Continuar aprendiendo