Contenido detallado
🔌 Por qué una API local
Una interfaz de chat es excelente para conversar. Pero una programa no conversa a través de una pantalla; necesita una dirección para enviar texto y recibir una respuesta. Esa dirección es la API. El truco de Ollama es hablar exactamente el mismo "formato" que usa OpenAI: así, cualquier app, script o agente que ya sabe comunicarse con ChatGPT funciona con tu modelo local cambiando una sola línea.
🆕 ¿Eres nuevo por aquí?
"API" (Interfaz de Programación de Aplicaciones) es una puerta de entrada por la que un programa le pide algo a otro. "Endpoint" es la dirección exacta de ese puerto: una URL como http://localhost:11434/v1/chat/completions. "Compatible con OpenAI" quiere decir que el formato de la solicitud y la respuesta es idéntico al de la API de OpenAI: las mismas claves model, messages, choices — solo que servido por tu máquina.
🔑 La idea central
La compatibilidad es la palanca. Con ella obtienes tres cosas a la vez:
- •Reutilización: las bibliotecas, los SDK y las herramientas hechas para OpenAI funcionan sin reescribir nada.
- •Portabilidad: cambia entre la nube y el entorno local modificando solo la base_url — el código sigue igual.
- •Automatización: scripts y agentes (Trilha 4) pasan a usar el modelo sin que tengas que abrir ninguna pantalla.
✗ Sin API (solo chat en pantalla)
- ✗Cada uso requiere que escribas manualmente
- ✗Nada de automatización ni programación de tareas
- ✗Imposible de conectar a otros programas
- ✗Sin agentes 24/7
✓ Con API local
- ✓Cualquier script llama al modelo mediante HTTP
- ✓El mismo SDK de OpenAI, el modelo en tu máquina
- ✓Base para automatizaciones, RAG y agentes
- ✓Todo offline, sin pagar por token
🌐 El endpoint de Ollama
Cuando instalaste Ollama (Módulo 3.1), ya inició un servidor HTTP que escucha en http://localhost:11434. localhost = la propia máquina; 11434 = el puerto. Este servidor ofrece dos conjuntos de rutas: las nativas de Ollama y las Compatibles con OpenAI bajo /v1. Para reutilizar apps y SDK existentes, usa siempre las de /v1.
El recorrido de una solicitud, desde tu programa hasta el modelo y de vuelta:
Tu programa arma la solicitud
Un JSON con el model y la lista de messages — exactamente el formato de OpenAI.
El servidor Ollama recibe las solicitudes en :11434
Carga el modelo en la memoria (si aún no está) y ejecuta la inferencia localmente.
La respuesta vuelve en JSON
En el mismo formato de OpenAI: el texto viene en choices[0].message.content.
🗺️ Las rutas que importan
Objetivo: conocer las direcciones. Las de /v1 son las que usas con SDK listos.
Cómo verificar: ejecuta curl http://localhost:11434/v1/models — debe enumerar, en JSON, los modelos que ya descargaste.
💡 Consejo práctico
Si el puerto 11434 no responde, el servidor no está en ejecución. En Linux/macOS, la aplicación de Ollama ya lo mantiene en funcionamiento; si necesitas iniciarlo manualmente, usa ollama serve. "Connection refused" casi siempre significa esto: el servicio no está activo o está en otra máquina.
⌨️ Primera llamada con curl
La forma más rápida de comprobar que la API funciona es el curl — una herramienta de terminal que hace solicitudes HTTP. Sin instalar bibliotecas ni escribir código: solo la terminal y un JSON. Si esto responde, tu API local está funcionando.
⌨️ Ejemplo práctico: chat mediante curl
Objetivo: enviar un mensaje al modelo y recibir la respuesta en JSON. Pégalo en el terminal (con Ollama en ejecución y el modelo qwen2.5:7b ya descargado).
Cómo verificar: la salida es un JSON con un campo choices. El texto de la respuesta está en choices[0].message.content. Si aparece, acabas de servir tu modelo por API.
📊 Anatomía del JSON de respuesta
- model — qué modelo respondió.
- choices[0].message.content — el texto generado (es lo que quieres).
- choices[0].finish_reason — por qué se detuvo (p. ej., stop).
- usage — conteo de tokens de entrada y salida.
🐍 Del código: SDK de OpenAI apuntado a lo local
Aquí destaca la compatibilidad. El SDK oficial de OpenAI (la biblioteca openai en Python) funciona con Ollama — basta con cambiar la base_url para tu endpoint local y pasar una api_key cualquiera (Ollama no valida la clave; solo se requiere porque el SDK la pide).
🐍 Ejemplo práctico: chat en Python
Objetivo: llamar al modelo local con el SDK de OpenAI. Instálalo con pip install openai y ejecuta.
Cómo verificar: el script imprime la frase generada por el modelo. Para volver a la nube, cambia base_url y la clave; el resto del código queda idéntico. Este es el punto central.
💡 Consejo práctico
En JavaScript/TypeScript es la misma historia: el paquete openai acepta baseURL: "http://localhost:11434/v1" e apiKey: "ollama". Guarda la base_url en una variable de entorno (OPENAI_BASE_URL) para alternar entre local y nube sin tocar el código.
✓ Hazlo
- ✓Usa el nombre del modelo que aparece en ollama list
- ✓Centraliza base_url en una env var
- ✓Maneja los timeouts: la 1.ª solicitud carga el modelo (más lento)
✗ Evita
- ✗Olvidar el /v1 al final de base_url
- ✗Usar un nombre de modelo que no se descargó
- ✗Poner una clave real de OpenAI en el código local
🌊 Streaming, embeddings y múltiples modelos
La misma API hace otras tres cosas que vas a usar mucho: streaming (la respuesta llega palabra por palabra, como en ChatGPT), embeddings (convertir texto en vectores — la base del RAG, en el próximo módulo) y dirigir según el modelo (basta con cambiar el campo model).
🌊 Streaming: respuesta token a token
Objetivo: mostrar el texto mientras se genera, sin esperar al final. Basta stream=True.
Cómo verificar: el texto aparece poco a poco, no de una vez. En curl, lo equivalente es poner "stream": true en el cuerpo JSON.
🧮 Embeddings: el texto se convierte en vector
Objetivo: generar el vector de significado de un texto — el bloque básico del RAG (Módulo 3.6). Usa un modelo de embeddings como nomic-embed-text (descarga con ollama pull nomic-embed-text).
Cómo verificar: la respuesta incluye data[0].embedding — una larga lista de números. Eso es lo que guarda una base de datos vectorial para buscar por similitud.
🔀 Varios modelos, un solo endpoint
No creas un servidor por modelo. El mismo endpoint sirve a todos los que están descargados; basta con cambiar el campo model: un modelo pequeño y rápido para clasificar, uno más grande para razonar y uno de embedding para RAG. Ollama carga y descarga los modelos según la demanda.
🔒 Exponiendo en la tailnet de forma segura
Por defecto, la API solo responde en localhost — nadie de afuera puede acceder. Pero en el Módulo 2.4 configuraste una tailnet (red privada vía Tailscale). Al combinar las dos piezas, usas el modelo de casa desde la laptop del trabajo o el celular, todo dentro de tu red privada, sin exponer nada a Internet.
Lee de izquierda a derecha: el app/script (morado) activa la API local en el puerto 11434, donde se ejecuta el modelo. La rama en cian muestra otro dispositivo accediendo a la misma API a través de la tailnet, sin exponer nada a la internet pública.
⌨️ Ejemplo práctico: abrir en la tailnet
Objetivo: hacer que Ollama escuche en toda la interfaz (no solo en localhost) para que los otros dispositivos de tu tailnet puedan acceder.
Cómo verificar: del segundo dispositivo, el curl con la IP 100.x debe responder en JSON. Si no responde, revisa si ambos están en la tailnet (tailscale status).
⚠️ Alerta: nunca lo expongas a Internet pública
OLLAMA_HOST=0.0.0.0 abre el puerto para cualquier red a la que esté conectada la máquina. Dentro de la tailnet esto es seguro: solo tus dispositivos autenticados pueden ver el 100.x. En la Internet abierta, no. La API de Ollama no tiene inicio de sesión ni contraseña: cualquiera que llegue al puerto puede usar (y abusar de) tu modelo.
- ✗NUNCA hagas port forwarding del puerto 11434 en el router.
- ✗NUNCA apuntes el puerto a una IP pública.
- ✓Accede de forma remota SOLO por la tailnet (IP 100.x) — es la forma segura.
✓ Tailnet (seguro)
- ✓Solo tus dispositivos autenticados
- ✓Tráfico cifrado de extremo a extremo
- ✓Ningún puerto abierto en el router
✗ Internet pública (peligrosa)
- ✗Cualquiera en la web puede acceder al puerto
- ✗Sin iniciar sesión: API totalmente abierta
- ✗Modelo secuestrado y la cuenta de la luz la pagas tú
Autoevaluación (opcional): para usar el SDK de OpenAI con tu modelo local, ¿qué ajustas?
📌 Resumen del módulo
Siguiente módulo:
3.6 — Embeddings, memoria y RAG