← Blog

Cómo integrar OpenAI en tu aplicación Node.js: guía práctica con ejemplos reales

D
Damián Oliva
·5 de febrero de 2025

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_tokens explícito.
  • Rate limiting por usuario: middleware con express-rate-limit o conteo en Redis.
  • Modelos más baratos para tareas simples: gpt-4o-mini para 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.
Newsletter

Ideas directamente
a tu bandeja de entrada

Comparto lo que estoy construyendo, lo que aprendo y lo que me parece interesante del mundo tech y startups. Sin spam. Cuando tenga algo que valga la pena.

Sin spam. Unsubscribe en cualquier momento.