Construye un Chatbot con
OpenAI API

Implementa un asistente virtual interactivo embebido en HTML/JS puro. Incorpora interfaz flotante, streaming en tiempo real y memoria de conversación.

Flujo de Interacción API
UI Cliente Worker/Proxy GPT-4o

La integración de Modelos de Lenguaje Grande (LLMs) directamente en un frontend web moderno es sorprendentemente accesible. En este tutorial, construiremos un componente de Chatbot flotante inyectable en cualquier sitio web, conectándolo de forma segura a la API de OpenAI (GPT-4o-mini).

Requisitos Previos

Asegúrate de tener lo siguiente antes de empezar:

La Regla de Oro: Protege tu API Key

Advertencia Crítica

NUNCA expongas tu OPENAI_API_KEY en el código JavaScript del cliente (frontend). Cualquiera podría inspeccionar el código, robarla y realizar peticiones a tu costa. Siempre envía la petición a tu propio backend y que este se comunique con OpenAI.

1. El Backend: Proxy Seguro

Configuraremos un Endpoint sencillo. Usando Hono/Cloudflare Workers, el código para recibir el mensaje del frontend y reenviarlo a OpenAI sería así:

import { Hono } from 'hono'
import { cors } from 'hono/cors'

const app = new Hono()
app.use('/*', cors())

app.post('/api/chat', async (c) => {
  const { messages } = await c.req.json();
  const apiKey = c.env.OPENAI_API_KEY; // Obtenido del entorno seguro

  const response = await fetch('https://api.openai.com/v1/chat/completions', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': \`Bearer \${apiKey}\`
    },
    body: JSON.stringify({
      model: "gpt-4o-mini",
      messages: messages,
      stream: false // Para simplicidad. Soporte de stream requiere EventSource.
    })
  });

  const data = await response.json();
  return c.json({ reply: data.choices[0].message });
})

export default app;

2. Frontend: La Interfaz Flotante

Añade el siguiente contenedor HTML al final del <body> de tu página. Usa clases Tailwind para un diseño limpio y moderno:

<!-- Chat Widget (Oculto por defecto, mostrable mediante JS) -->
<div id="chat-widget" class="fixed bottom-6 right-6 w-80 h-96 bg-gray-900 rounded-2xl shadow-2xl flex flex-col border border-gray-700 hidden">
  <!-- Header -->
  <div class="p-4 bg-emerald-600 rounded-t-2xl font-bold flex justify-between">
    <span>Soporte iaDATA</span>
    <button onclick="document.getElementById('chat-widget').classList.add('hidden')">✕</button>
  </div>

  <!-- Área de mensajes -->
  <div id="chat-messages" class="flex-1 p-4 overflow-y-auto space-y-3"></div>

  <!-- Input -->
  <div class="p-3 border-t border-gray-700 flex gap-2">
    <input id="chat-input" class="flex-1 bg-gray-800 rounded px-3 py-2 text-sm text-white" placeholder="Pregunta algo...">
    <button id="chat-send" class="bg-emerald-600 px-3 py-2 rounded"><i class="fas fa-paper-plane"></i></button>
  </div>
</div>

3. Lógica JavaScript y Memoria

Para que el LLM "recuerde" de qué estáis hablando, debe enviarse todo el historial de la conversación en cada petición (Role: system, user, assistant).

let conversation = [
  { role: "system", content: "Eres un asistente de iaDATA útil y conciso." }
];

const input = document.getElementById('chat-input');
const messagesDiv = document.getElementById('chat-messages');

async function askBot() {
  const userText = input.value;
  if (!userText) return;
  
  // Mostrar mensaje de usuario
  messagesDiv.innerHTML += \`
\${userText}
\`; input.value = ''; // Actualizar contexto conversation.push({ role: "user", content: userText }); // Petición al proxy (NO directamente a OpenAI) const res = await fetch('https://tu-worker.workers.dev/api/chat', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ messages: conversation }) }); const data = await res.json(); const botReply = data.reply.content; // Añadir al contexto y renderizar conversation.push({ role: "assistant", content: botReply }); messagesDiv.innerHTML += \`
\${botReply}
\`; messagesDiv.scrollTop = messagesDiv.scrollHeight; } document.getElementById('chat-send').addEventListener('click', askBot);

Siguientes Pasos (Streaming)

Para una experiencia de usuario perfecta (como ChatGPT), en lugar de esperar la respuesta completa, puedes implementar Streaming. Esto requiere:

  1. Activar stream: true en la petición de tu Backend hacia OpenAI.
  2. Devolver la respuesta del Worker usando TransformStream.
  3. En el Frontend, procesar la respuesta usando la Web Streams API o la librería eventsource-parser.

Regresa al directorio principal para explorar más herramientas de IA generativa.

Volver a iaDATA
Creado por Enrique M.