Cómo alojar un chatbot con IA

Un chatbot con IA es una API tuya que recibe la conversación, llama a un modelo de lenguaje con la clave en el servidor y devuelve la respuesta en streaming. Alójala como cualquier API web, en un proceso siempre encendido.

Actualizado el 7 min de lectura

Objetivos de aprendizaje

Después de leer este artículo podrás:

  • Entender la arquitectura de un chatbot con IA (front-end, API y modelo)
  • Escribir una API en FastAPI que responde en streaming
  • Poner el chatbot en línea protegiendo la clave y el gasto
En esta página

Alojar un chatbot con IA parece un tema nuevo, pero la parte que alojas es una vieja conocida: una API HTTP. El "cerebro" está en el proveedor del modelo (Anthropic, OpenAI, Google). Tu servidor recibe el mensaje, llama al proveedor y reenvía la respuesta.

Eso cambia lo que importa. No necesitas GPU ni mucha memoria. Necesitas un proceso siempre encendido, una clave de API bien guardada y protección contra el abuso, porque cada mensaje cuesta dinero.

Navegadorfront-endAPI delchatbotclave en variablede entornoProveedordel modeloAPI del LLMPOST /chat1prompt + clave2streaming3texto en streaming4
La clave queda en el backend, en una variable de entorno; el navegador solo habla con tu API y recibe el texto en streaming.

¿Cómo es la arquitectura de un chatbot con IA?#

Son tres piezas:

  1. Front-end: la pantalla de chat (un sitio, un widget, una app). Guarda la conversación y muestra el texto a medida que llega.
  2. Backend (lo que tú alojas): una API con un endpoint como POST /chat. Valida la entrada, añade el prompt de sistema, llama al modelo y devuelve la respuesta.
  3. Proveedor del modelo: la API del LLM. Para entender lo que hace por debajo, mira qué es un LLM.

El backend existe por un motivo central: la clave de API nunca puede llegar al navegador. Cualquiera que abra las DevTools puede copiarla. Mira también qué hacer si se filtra la clave.

¿Qué necesitas antes de empezar?#

  • Una versión de Python que todavía tenga soporte. La versión mínima que exigen el SDK de Anthropic, FastAPI y Uvicorn está en la documentación de cada uno.
  • Una clave de API del proveedor. Aquí usamos la de Anthropic, pero la estructura es la misma para cualquier otro.
  • Nociones básicas de variables de entorno.

Crea la carpeta del proyecto con un requirements.txt:

text
fastapi
uvicorn
anthropic

¿Cómo escribir la API con streaming?#

Sin streaming, el usuario mira una pantalla vacía hasta que el modelo termina la respuesta entera. Con streaming, el texto aparece a medida que se genera. El SDK de Anthropic lo expone con client.messages.stream y text_stream, y FastAPI lo reenvía con StreamingResponse.

python
import os
from typing import Literal

from anthropic import AsyncAnthropic
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
from pydantic import BaseModel, Field

client = AsyncAnthropic()  # lee ANTHROPIC_API_KEY del entorno
MODEL = os.environ["ANTHROPIC_MODEL"]  # sin ella, la app falla al iniciar con KeyError
SYSTEM = "Eres el asistente de la tienda Ejemplo. Responde en español, de forma breve."

app = FastAPI()


class Msg(BaseModel):
    role: Literal["user", "assistant"]
    content: str = Field(max_length=4000)


class ChatIn(BaseModel):
    messages: list[Msg] = Field(min_length=1, max_length=20)


@app.post("/chat")
async def chat(body: ChatIn):
    async def stream_text():
        async with client.messages.stream(
            model=MODEL,
            max_tokens=1024,
            system=SYSTEM,
            messages=[m.model_dump() for m in body.messages],
        ) as stream:
            async for text in stream.text_stream:
                yield text

    return StreamingResponse(stream_text(), media_type="text/plain; charset=utf-8")


if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app, host="0.0.0.0", port=int(os.environ.get("PORT", "8000")))

Guarda el código como main.py. Lo que vale la pena notar:

  • La API no guarda estado. El front-end envía la conversación entera en cada petición, y el modelo no "recuerda" nada entre llamadas. Los límites de 20 mensajes y 4.000 caracteres contienen el costo y el tamaño del contexto.
  • El modelo es configuración, no código. Anthropic retira modelos con el tiempo, así que el ID queda en la variable ANTHROPIC_MODEL, sin valor por defecto: si falta, la app se detiene al iniciar, en lugar de fallar con el primer mensaje. Copia el ID de la lista de modelos de Anthropic. Para tareas de alto volumen y baja latencia, lo habitual es un modelo pequeño, rápido y barato, como los de la línea Haiku.
  • max_tokens es obligatorio en la API y funciona como techo de costo por respuesta.
  • El bloque final permite iniciar con python main.py, escuchando en 0.0.0.0 en el puerto de la variable PORT (8000 si no existe).

Prueba local:

bash
pip install -r requirements.txt
export ANTHROPIC_API_KEY="pega-tu-clave-aqui"
export ANTHROPIC_MODEL="id-de-un-modelo-pequeno"
uvicorn main:app --port 8000
curl -N -X POST localhost:8000/chat \
  -H "Content-Type: application/json" \
  -d '{"messages":[{"role":"user","content":"Hola, ¿qué tal?"}]}'

El -N desactiva el búfer de curl, así que ves el texto llegar poco a poco.

¿Cómo lee el front-end la respuesta en streaming?#

En el navegador, fetch ya expone el cuerpo como un stream:

javascript
async function ask(messages, onText) {
  const res = await fetch("/chat", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ messages }),
  });
  if (!res.ok || !res.body) throw new Error(`Error ${res.status}`);

  const reader = res.body.pipeThrough(new TextDecoderStream()).getReader();
  for (;;) {
    const { value, done } = await reader.read();
    if (done) break;
    onText(value);
  }
}

Llama a ask con el historial y añade cada fragmento (onText) a la burbuja de la respuesta. Si el front-end está en otro dominio, configura CORS en FastAPI para aceptar solo el origen de tu sitio.

¿Cómo proteger la clave y el gasto?#

Un endpoint de chat público es una invitación al abuso. Antes de compartir el enlace:

  • La clave solo en una variable de entorno, nunca en el código ni en el repositorio.
  • Límite de peticiones por IP o por usuario, aplicado en el borde o con una librería en FastAPI.
  • Tope de gasto en el panel del proveedor. Es la red de seguridad si falla el límite de tu código.
  • Exige autenticación si el bot es de uso interno o para clientes.
  • Trata el texto del usuario como no confiable. Alguien puede intentar que el modelo ignore el prompt de sistema. Lee qué es el prompt injection antes de darle herramientas o datos sensibles al modelo.

Para estimar la factura, mira cuánto cuesta una API de LLM.

¿Qué necesita el servidor para alojar esto?#

  • Un proceso siempre encendido. Las plataformas que suspenden la app por inactividad provocan una primera respuesta lenta. Para un chat, prefiere un contenedor que no hiberne.
  • HTTPS. El navegador bloquea llamadas inseguras desde páginas HTTPS.
  • Soporte para respuestas en streaming. Los proxies que guardan la respuesta en búfer rompen el efecto. Prueba con curl -N ya en el entorno final.
  • Poca RAM. El servidor solo reenvía texto, así que el consumo es bajo. Mide con carga real y mira cómo dimensionar RAM y CPU.
  • Logs. Los vas a necesitar para descubrir por qué el proveedor devolvió un error 429 o 5xx. Para el framework en sí, mira alojar FastAPI, Flask y Django.

¿Qué errores son comunes?#

  • El streaming llega todo de golpe: hay un proxy o una compresión guardando en búfer entre la app y el navegador. Prueba directamente en la app con curl -N.
  • Error 401 del proveedor: la variable ANTHROPIC_API_KEY no está definida en el entorno de producción.
  • Error 404 o "model not found": el ID de ANTHROPIC_MODEL está mal o el modelo fue retirado. Elige otro de la lista oficial y reinicia la app, sin tocar el código.
  • Error 422 de FastAPI: el cuerpo no coincide con el modelo de Pydantic (por ejemplo, role distinto de user/assistant, o una conversación vacía).
  • Factura alta a fin de mes: falta un límite por usuario o el max_tokens es demasiado alto. Mira la sección de protección.

Cómo hacerlo en Square Cloud#

La sección sobre el servidor pedía un proceso siempre encendido, HTTPS, streaming sin búfer y logs. En Square Cloud, la API corre en un contenedor aislado y siempre encendido, sin cold start ni modo de suspensión, y toda aplicación web recibe un subdominio *.squareweb.app con HTTPS. El proxy delante de la aplicación no corta conexiones largas y deja pasar SSE y WebSocket sin búfer; aun así, repite la prueba con curl -N en el subdominio.

  1. Sube main.py y requirements.txt como ZIP en el panel, o usa la CLI, GitHub o la extensión de VS Code. Al iniciar, la plataforma instala el requirements.txt. El archivo squarecloud.app es opcional: el panel lo genera en el deploy, o lo escribes en la raíz del proyecto.
  2. Elige main.py como archivo principal. El bloque final del código ya escucha en 0.0.0.0, en el puerto de la variable PORT, que define la plataforma. Una aplicación web usa al menos 512 MB del pool de RAM del plan.
  3. Registra ANTHROPIC_API_KEY y ANTHROPIC_MODEL en las variables de entorno de la aplicación. El cambio se aplica en el siguiente reinicio, sin rebuild.
  4. Sigue los logs en tiempo real para ver los errores 429 o 5xx del proveedor.

Si prefieres no mantener una cuenta en un proveedor de modelos, el AI Gateway, disponible desde el plan Standard (R$44,99 al mes), es una API compatible con la de OpenAI para el modelo cubic, en beta con acceso anticipado sin costo extra. Con el SDK openai usas la base URL https://api.squarecloud.app/v2/ai, una clave de la cuenta con el scope ai:chat y model="cubic"; el modelo también puede llamar a tus funciones (hasta 32 tools) y buscar en la web por su cuenta. Para este chatbot hay dos salvedades: el gateway todavía no hace streaming, así que la respuesta llega entera al final; y el Standard atiende una solicitud a la vez, hasta 1000 por día. Un chat público con muchos visitantes simultáneos sigue mejor servido por un proveedor con streaming. Los límites y los planes pueden cambiar cuando termine la beta.

El Hobby, desde R$12,49 al mes, aloja la API, pero no incluye el gateway. Mira los planes en hosting de APIs.

IA

Aloja apps con IA en contenedores siempre encendidos

Más información

Preguntas frecuentes

¿Necesito GPU para alojar un chatbot con IA?

No, si usas un modelo por API (Claude, GPT, Gemini). Quien ejecuta la inferencia es el proveedor, y tu servidor solo reenvía texto. La GPU solo entra si alojas tú mismo un modelo abierto.

¿Puedo llamar a la API del modelo directamente desde el navegador?

No. La clave quedaría visible para cualquier visitante y otra persona podría gastar tu crédito. La llamada tiene que salir de un backend tuyo.

¿Cuánta memoria usa un chatbot así?

Poca, porque solo reenvía texto. Mide con carga real antes de dimensionar.

¿Cómo evito que alguien gaste mi crédito de IA?

Limita las peticiones por IP o por usuario, limita el tamaño de la conversación y el max_tokens, y configura un tope de gasto en el panel del proveedor.

Siguiente artículo¿Cuánto cuesta usar la API de un LLM?La API de un LLM cobra por token y la salida cuesta más que la entrada. Mira un cálculo paso a paso para un bot y cómo recortar el gasto.