¿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: 0para 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