Desafíos de Producción
Mover aplicaciones LangChain de desarrollo a producción implica manejar latencia, costos, confiabilidad y observabilidad. Esta guía cubre los patrones esenciales para aplicaciones LLM listas para producción.
🚨 Consideraciones de Producción
💰 Costo: Las llamadas a GPT-4 se acumulan rápido a escala
⏱️ Latencia: Las llamadas LLM son lentas (2-30 segundos)
🔄 Confiabilidad: Límites de tasa y caídas de API
📊 Monitoreo: Depurar salidas no deterministas
Caché de Respuestas
import { ChatOpenAI } from "@langchain/openai";
// Caché en memoria (desarrollo)
const cache = new Map<string, string>();
async function invocarConCache(model: ChatOpenAI, input: string) {
const cacheKey = input.trim().toLowerCase();
if (cache.has(cacheKey)) {
console.log("¡Hit de caché!");
return cache.get(cacheKey)!;
}
const response = await model.invoke(input);
const content = response.content as string;
cache.set(cacheKey, content);
return content;
}
// Caché Redis (producción)
import { Redis } from "ioredis";
const redis = new Redis(process.env.REDIS_URL!);
async function invocarConCacheRedis(model: ChatOpenAI, input: string) {
const cacheKey = `llm:${Buffer.from(input).toString("base64")}`;
const cached = await redis.get(cacheKey);
if (cached) return cached;
const response = await model.invoke(input);
const content = response.content as string;
// Caché por 1 hora
await redis.set(cacheKey, content, "EX", 3600);
return content;
}
Lógica de Reintento y Rate Limiting
import { ChatOpenAI } from "@langchain/openai";
// Reintento integrado con backoff exponencial
const model = new ChatOpenAI({
modelName: "gpt-4",
maxRetries: 3,
maxConcurrency: 5,
});
// Wrapper personalizado con timeout
async function invocarConReintento(
model: ChatOpenAI,
input: string,
maxReintentos = 3,
timeoutMs = 30000
) {
for (let intento = 1; intento <= maxReintentos; intento++) {
try {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), timeoutMs);
const response = await model.invoke(input, { signal: controller.signal });
clearTimeout(timeout);
return response;
} catch (error: any) {
console.error(`Intento ${intento} falló:`, error.message);
if (error.status === 429) {
await new Promise((r) => setTimeout(r, intento * 5000));
} else if (intento === maxReintentos) {
throw error;
}
}
}
}
Control de Costos
// Estrategias de ahorro de costos:
// 1. Usar modelos más baratos para tareas simples
const modelBarato = new ChatOpenAI({ modelName: "gpt-4o-mini" }); // 20x más barato
const modelPotente = new ChatOpenAI({ modelName: "gpt-4" });
// 2. Enrutar según complejidad
async function enrutamientoInteligente(input: string) {
const esComplejo = input.length > 200 || input.includes("analiza");
const model = esComplejo ? modelPotente : modelBarato;
return await model.invoke(input);
}
Cadenas de Respaldo
import { ChatOpenAI } from "@langchain/openai";
import { ChatAnthropic } from "@langchain/anthropic";
const modelPrimario = new ChatOpenAI({ modelName: "gpt-4" });
const modelRespaldo = new ChatAnthropic({ modelName: "claude-3-sonnet-20240229" });
const ultimoRecurso = new ChatOpenAI({ modelName: "gpt-4o-mini" });
// Respaldo integrado de LangChain
const modelConRespaldo = modelPrimario
.withFallbacks({
fallbacks: [modelRespaldo, ultimoRecurso],
});
// Prueba automáticamente cada modelo en orden
const result = await modelConRespaldo.invoke("Explica las redes de Docker");
// Si GPT-4 falla → intenta Claude → intenta GPT-4o-mini
Arquitectura de Producción
// lib/ai-service.ts — Servicio de IA listo para producción
class ServicioIA {
private model: ChatOpenAI;
private cache: Map<string, { respuesta: string; timestamp: number }>;
private readonly CACHE_TTL = 3600000; // 1 hora
constructor() {
this.model = new ChatOpenAI({
modelName: "gpt-4",
maxRetries: 3,
maxConcurrency: 10,
}).withFallbacks({
fallbacks: [new ChatOpenAI({ modelName: "gpt-4o-mini" })],
});
this.cache = new Map();
}
async consultar(input: string, userId?: string): Promise<string> {
const cacheKey = input.toLowerCase().trim();
const cached = this.cache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < this.CACHE_TTL) {
return cached.respuesta;
}
const prompt = ChatPromptTemplate.fromMessages([
["system", "Eres un asistente de programación útil."],
["human", "{input}"],
]);
const chain = prompt.pipe(this.model).pipe(new StringOutputParser());
const respuesta = await chain.invoke(
{ input },
{ metadata: { userId, feature: "chat" }, tags: ["produccion"] }
);
this.cache.set(cacheKey, { respuesta, timestamp: Date.now() });
return respuesta;
}
}
export const servicioIA = new ServicioIA();
🚀 Checklist de Producción
- ✓ Caché de respuestas (Redis o en memoria)
- ✓ Rate limiting por usuario
- ✓ Modelos de respaldo configurados
- ✓ Manejo de errores con mensajes amigables
- ✓ Monitoreo de costos y alertas
- ✓ Trazado LangSmith habilitado
- ✓ Validación y sanitización de entrada
- ✓ Límites de presupuesto de tokens por solicitud
💡 Puntos Clave
- • Cachea consultas idénticas para reducir costos en un 50-80%
- • Usa cadenas de respaldo para confiabilidad (GPT-4 → Claude → GPT-4o-mini)
- • Enruta tareas simples a modelos más baratos para reducir costos
- • LangSmith proporciona observabilidad esencial para depurar problemas en producción
- • Siempre implementa rate limiting, timeouts y seguimiento de costos