Por qué OpenAI y no otra API de IA
Hay muchas opciones hoy para integrar IA en tus aplicaciones: Anthropic Claude, Google Gemini, Mistral, y modelos open source como Llama vía Ollama. En mis proyectos uso varias dependiendo del caso, pero OpenAI sigue siendo el punto de partida más práctico para la mayoría de los casos de uso: la documentación es excelente, el SDK de JavaScript es maduro y la calidad de GPT-4o para tareas de producción es muy consistente.
En esta guía voy a mostrar cómo lo integro en proyectos Node.js reales, con los patrones que uso en producción.
Instalación y configuración inicial
npm install openai
Configurá tu API key en el archivo .env:
OPENAI_API_KEY=sk-...
Creá un cliente centralizado en services/openai.js:
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
export default openai;
Tu primera llamada: Chat Completions
La API principal de OpenAI para generar texto es Chat Completions. Funciona con un array de mensajes con roles (system, user, assistant):
import openai from './services/openai.js';
const response = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'system',
content: 'Sos un asistente especializado en atención al cliente para una empresa de software.',
},
{
role: 'user',
content: '¿Cuánto cuesta desarrollar una app?',
},
],
temperature: 0.7,
max_tokens: 500,
});
console.log(response.choices[0].message.content);
Streaming: respuestas en tiempo real
Para interfaces de chat donde querés que el texto aparezca mientras se genera (como ChatGPT), usás streaming. Con Express y Server-Sent Events:
app.get('/api/chat/stream', async (req, res) => {
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
const stream = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: req.query.message }],
stream: true,
});
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content || '';
if (content) {
res.write(`data: ${JSON.stringify({ content })}
`);
}
}
res.write('data: [DONE]
');
res.end();
});
Mantener contexto de conversación
OpenAI no guarda historial entre llamadas. Para mantener el contexto de una conversación, tenés que enviar el historial completo en cada request. Guardo las conversaciones en MongoDB:
// Al recibir un mensaje nuevo:
const conversation = await Conversation.findById(conversationId);
const messages = conversation.messages; // array de { role, content }
messages.push({ role: 'user', content: userMessage });
const response = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [systemMessage, ...messages],
});
const assistantMessage = response.choices[0].message;
messages.push(assistantMessage);
await Conversation.findByIdAndUpdate(conversationId, { messages });
Control de costos en producción
El mayor riesgo al integrar OpenAI es que el costo escale de forma inesperada. Medidas que aplico:
- Limit de tokens por request: siempre pongo
max_tokensexplícito. - Rate limiting por usuario: middleware con express-rate-limit o conteo en Redis.
- Modelos más baratos para tareas simples:
gpt-4o-minipara clasificaciones, resumenes cortos o validaciones. - Caché de respuestas: si la misma pregunta puede repetirse, guardo la respuesta en Redis con TTL.
Errores comunes y cómo manejarlos
Los errores más frecuentes en producción son: rate limit (429), context window excedido (400), y problemas de red. Uso un wrapper con retry logic:
const callWithRetry = async (fn, retries = 3) => {
for (let i = 0; i < retries; i++) {
try {
return await fn();
} catch (err) {
if (err.status === 429 && i < retries - 1) {
await new Promise(r => setTimeout(r, 2000 * (i + 1)));
continue;
}
throw err;
}
}
};
Casos de uso que implementé en producción
Estos son los usos reales que integré en proyectos:
- Análisis de texto en bot de cobranzas: clasificar la respuesta del cliente para decidir el siguiente paso.
- Generación de contenido en CRM: sugerir respuestas de email basadas en el historial del cliente.
- Extracción de datos de documentos: parsear facturas y presupuestos en PDF para cargarlos en un sistema.