Qué significa la frase
La gente usa "API OpenAI para LLM local" para dos cosas relacionadas. La primera es un modelo de lenguaje que ejecutas tú mismo, en un portátil o un servidor doméstico, que escucha en un puerto local y habla el formato de chat de OpenAI. La segunda es el hábito de escribir tu aplicación contra ese formato para que el modelo detrás pueda cambiarse.
El formato es un contrato simple. Tu app envía un cuerpo JSON con un nombre de model y una lista de messages, cada uno con un role de system, user o assistant. El servidor responde con un objeto JSON que contiene el mensaje generado, o con un stream de pequeños chunks si pides streaming. Los SDKs oficiales para Python y JavaScript envuelven esto, y te permiten sobrescribir la base URL, que es el truco completo.
Muchas herramientas locales exponen este contrato. Ollama, LM Studio, el servidor llama.cpp y vLLM ofrecen cada uno una ruta al estilo de OpenAI. Los servicios alojados también, por eso las mismas veinte líneas de código cliente pueden hablar con cualquiera de los dos. El endpoint de este sitio es de los alojados. Acepta POST /v1/chat/completions y GET /v1/models, y se encuentra en https://api.onekeyllmapi.com/v1.
Local versus alojado de un vistazo
Ninguno es mejor en general. Intercambian control por esfuerzo. La tabla se centra en las diferencias que aplican para la categoría, no para ningún producto en particular.
| Pregunta | Ejecutor local | API alojada al estilo de OpenAI |
|---|---|---|
| A dónde van los prompts | Permanecen en tu máquina | Viaja al proveedor por HTTPS |
| Hardware | Proporcionas GPU o CPU y memoria | Ninguno por tu parte |
| Tamaño del modelo | Limitado por tu memoria | Lo que sirva el proveedor |
| Modelo de costo | Hardware y energía | Por token, con crédito prepago aquí |
| Disponibilidad | Mientras tu máquina esté encendida | Servidor siempre activo, límites compartidos |
| Configuración | Instalar, descargar pesos, ajustar | Crear una clave, configurar la URL base |
Si tus datos no deben salir nunca de una máquina que controlas, gana lo local y lo alojado es la herramienta incorrecta. Si necesitas un modelo más grande que el que cabe en tu hardware, o un bot que permanezca accesible desde muchos lugares, gana lo alojado. Una configuración común mantiene ambos y elige por tarea.
Cambio de cliente de local a alojado
Si tu código ya habla con un ejecutor local, el cambio son tres valores. Todo lo demás, incluyendo cómo construyes mensajes y lees fragmentos en streaming, se mantiene igual.
- Base URL. Usa
https://api.onekeyllmapi.com/v1en lugar de tu dirección local. - Clave de API. Los servidores locales a menudo ignoran la clave. Uno alojado la requiere como
Authorization: Bearer <key>, y el SDK la envía por ti. - ID del modelo. Los nombres locales son lo que descargaste. Aquí el ID es
uncensored.
Una forma ordenada de mantener esto flexible es leer los tres desde variables de entorno, así un archivo funciona en ambos lugares.
import os
from openai import OpenAI
client = OpenAI(
base_url=os.environ.get("LLM_BASE_URL", "https://api.onekeyllmapi.com/v1"),
api_key=os.environ.get("LLM_API_KEY", "YOUR_KEY"),
)
MODEL = os.environ.get("LLM_MODEL", "uncensored")
models = client.models.list()
print([m.id for m in models.data])
resp = client.chat.completions.create(
model=MODEL,
messages=[
{"role": "system", "content": "Answer in two sentences."},
{"role": "user", "content": "Why do OpenAI-style endpoints make switching models easy?"},
],
temperature=0.5,
)
print(resp.choices[0].message.content)
La misma llamada desde la línea de comandos, útil para una prueba rápida de humo:
curl https://api.onekeyllmapi.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "uncensored", "messages": [{"role": "user", "content": "ping"}], "max_tokens": 20}'
Con Node, el patrón es idéntico:
import OpenAI from "openai";
const client = new OpenAI({
baseURL: process.env.LLM_BASE_URL ?? "https://api.onekeyllmapi.com/v1",
apiKey: process.env.LLM_API_KEY,
});
const res = await client.chat.completions.create({
model: process.env.LLM_MODEL ?? "uncensored",
messages: [{ role: "user", content: "Name three uses for JSON mode." }],
});
console.log(res.choices[0].message.content);
Lo que hace y no hace la compatibilidad con OpenAI
Compatible significa que el formato de la red coincide. No promete que todas las funciones que ofrece el servicio original estén presentes. Antes de migrar una app real, comprueba cada una de estas contra el objetivo.
Lo que esta API soporta
- Chat completions en
POST /v1/chat/completionsy una lista de modelos enGET /v1/models. - Streaming sobre eventos enviados por el servidor con
stream: true, con el uso reportado al final del stream. - Llamadas a funciones a través de
toolsytool_choice,tool_callsen streaming, y resultados enviados como mensajesrole: "tool". - Modo JSON a través de
response_format: {"type": "json_object"}. - Controles de muestreo: temperature, top_p, stop, seed y los parámetros de penalización se pasan a través.
Lo que no hace
- Sin generación de imágenes, audio o video. Solo es texto.
- Sin endpoint de embeddings ni fine-tuning. Si tu app construye un índice vectorial, necesitas una fuente de embedding separada.
- Solo un modelo. El modelo es un modelo de pesos abiertos ejecutado por un proveedor independiente. No es la API oficial de ningún gran proveedor, y no es un router entre proveedores, así que no puedes elegir entre familias de modelos cambiando el ID.
Los ejecutores locales a veces difieren al revés: un servidor local puede ofrecer una ruta de embeddings o dejarte cargar varios modelos, y el tamaño de la ventana de contexto es lo que configures. Lee la documentación del objetivo para cada uno, y mantén una lista corta de las funciones que realmente usa tu app. La documentación de inicio rápido muestra los campos de petición completos.
Diferencias de contexto, límites y coste
Tres números cambian cuando dejas un servidor local. El primero es la ventana. La longitud de la ventana de contexto de un ejecutor local es una configuración ligada a tu memoria. Aquí está fija en 100,000 tokens, compartida por el prompt y la completion, y max_tokens es opcional. El segundo es la concurrencia. Tu propia máquina puede estar en cola tan profunda como quieras, pero una clave completa aquí permite 8 peticiones simultáneas y 300 por minuto, y una clave de prueba 2 y 60. El tercero es la factura.
El uso alojado cuesta $0.15 por 1M tokens de entrada y $0.50 por 1M tokens de salida, pago por uso desde crédito prepago. Trabaja a través de un trabajo diario como ejemplo: un resumidor procesa 400 documentos al día, cada uno de 3,000 tokens de entrada y 300 tokens de salida. La entrada es 400 x 3,000 = 1,200,000 tokens, que cuesta 1.2 x $0.15 = $0.18. La salida es 400 x 300 = 120,000 tokens, que cuesta 0.12 x $0.50 = $0.06. El día suma $0.24, y un mes de 30 días es $7.20. Compara eso con el coste de mantener una GPU encendida y de la tarjeta misma antes de decidir.
Cuando excedes un límite, la API responde HTTP 429 con el código rate_limited o concurrency. Para una sobrecarga breve añade Retry-After: 5. Mantén la lógica de reintento que espera y vuelve a intentar. Las peticiones que fallan o son rechazadas no se cobran. El crédito no caduca, así que un mes inactivo no cuesta nada.
Una petición en streaming mantiene su espacio de concurrencia hasta que finalice el flujo; cierra los flujos que dejes de leer. Las recargas comienzan en $20; los niveles y bonificaciones están en la página de precios.
Depuración cuando el cambio falla
La mayoría de las migraciones fallidas se deben a un puñado de causas. Revisa estos puntos en este orden.
- Errores 404 o de conexión. Es probable que la URL base no tenga el sufijo
/v1o tenga una ruta extra. Úsala exactamente comohttps://api.onekeyllmapi.com/v1. - Errores de autenticación. La clave falta o se envía en el encabezado incorrecto. El formato es
Authorization: Bearer <key>. Los usuarios de SDK deben confirmar que la variable de entorno se cargó efectivamente. - Modelo no encontrado. El nombre antiguo del modelo local sigue en tu configuración. Llama a
GET /v1/modelsy usa el ID que liste, que esuncensored. - 429 bajo carga. Has superado 8 peticiones simultáneas o 300 por minuto con una clave completa. Añade una cola o un semáforo.
- Parece que se ignora un parámetro. Comprueba que sea uno de los campos pasados listados arriba y compara el comportamiento con un
seedfijo y una temperatura baja.
Cada respuesta incluye un encabezado X-Request-Id. Regístralo junto con tu propio ID de petición para poder rastrear una respuesta errónea más tarde. Si ejecutas tráfico en producción y quieres medir la calidad a lo largo del tiempo, el artículo del sitio LLM Observability: Myths vs Facts es una buena lectura siguiente. Los encabezados de respuesta X-Balance-USD, X-RateLimit-Limit-Requests y X-RateLimit-Limit-Concurrency también valen la pena capturarlos.
Prueba sin compromiso
La forma más económica de probar si tu código se adapta sin problemas es ejecutarlo una vez. Crea una cuenta con Google o correo electrónico y contraseña, luego reclama el crédito de prueba de $0.50 desde la página de claves. Se requiere un clic, no necesita tarjeta, está limitado a uno por persona y es válido durante 7 días. Obtén tu clave en la página de claves de API, establece las tres variables de entorno mencionadas arriba y ejecuta tu conjunto de pruebas existente.
Si las pruebas pasan y el uso se ajusta a tu presupuesto, recarga desde $20, con tarjeta (Visa, Mastercard, Apple Pay, Google Pay) o cripto (USDT en TRC20, USDC en Base). Los prompts no se usan para entrenamiento. El modelo está ajustado para responder sin rechazos de contenido para uso adulto lícito, con una regla fija: sin contenido sexual que involucre a menores de edad.
