Usa el Vercel AI SDK con UberLLM (modelos más baratos, mismo código)
Instala @ai-sdk/openai-compatible, crea un proveedor con baseURL https://api.uberllm.dev/v1 y tu clave de UberLLM, y pasa uberllm("<model id>") dondequiera que tu aplicación pase un modelo hoy. Nada más en la aplicación cambia.
Pasos
- Crea una clave en tu página de claves y añade un poco de crédito (las cuentas empiezan en $0).
- Instala el proveedor:
npm i ai @ai-sdk/openai-compatible
- Pon la clave en
.env.local(Next.js) o en el entorno de tu servidor:
UBERLLM_API_KEY=ull_your_key
- Crea el proveedor una vez, por ejemplo en
lib/uberllm.ts:
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
export const uberllm = createOpenAICompatible({
name: "uberllm",
baseURL: "https://api.uberllm.dev/v1",
apiKey: process.env.UBERLLM_API_KEY, // sent as Authorization: Bearer <key>
includeUsage: true, // token counts on streamed answers too
});
- Úsalo donde usabas un modelo antes:
import { generateText } from "ai";
import { uberllm } from "@/lib/uberllm";
const { text } = await generateText({
model: uberllm("deepseek/deepseek-v4.1-flash"),
prompt: "Write a one-line welcome message.",
});
Migrar una aplicación que ya usa @ai-sdk/openai
Cambia el argumento del modelo y mantén todo lo demás:
// before
import { openai } from "@ai-sdk/openai";
const model = openai("gpt-4o");
// after
import { uberllm } from "@/lib/uberllm";
const model = uberllm("deepseek/deepseek-v4.1-flash");
Los IDs de modelo son los IDs en uberllm.dev/models y siempre llevan un fabricante delante (openai/…, anthropic/…, deepseek/…). Así es como puedes ejecutar GPT, Claude, Gemini y modelos abiertos desde una única key y compararlos cambiando una sola string.
Una ruta de chat de Next.js para useChat
useChat de @ai-sdk/react envía a /api/chat por defecto. Esta ruta lo responde:
// app/api/chat/route.ts
import { streamText, convertToModelMessages, type UIMessage } from "ai";
import { uberllm } from "@/lib/uberllm";
export async function POST(req: Request) {
const { messages }: { messages: UIMessage[] } = await req.json();
const result = streamText({
model: uberllm("deepseek/deepseek-v4.1-flash"),
messages: await convertToModelMessages(messages),
});
return result.toUIMessageStreamResponse();
}
Mantén la clave en el servidor. Nunca la pongas en una NEXT_PUBLIC_ variable: cualquiera podría leerla desde la página y gastar tu saldo.
Limita lo que una llamada puede costar
Las solicitudes de chat aceptan provider.max_price (dólares por millón de tokens). Pásalo a través de providerOptions con el proveedor name que elegiste:
await generateText({
model: uberllm("deepseek/deepseek-v4.1-flash"),
prompt: "Hi",
providerOptions: { uberllm: { provider: { max_price: { prompt: 0.2, completion: 0.4 } } } },
});
Si nadie vende el modelo por debajo de ese precio en este momento, la llamada se rechaza con max_price_exceeded y no se cobra nada.
Solución de problemas
- 401
invalid_api_key: la API key no llegó al servidor. Reinicianext devdespués de editar.env.local, y verifica queprocess.env.UBERLLM_API_KEYesté configurado donde se ejecuta el código (servidor, no el navegador). - 402
insufficient_credits: añade crédito en la página de créditos. - 404
model_not_found: el id es incorrecto o le falta su creador. Cópialo de la página del modelo. - 400
wrong_endpoint: pasaste un modelo de imagen o video astreamText. Los modelos de imagen pasan poruberllm.imageModel(…)congenerateImage; el video es un trabajo, consulta Crear un video o imagen. - El uso está vacío en los streams: configura
includeUsage: trueen el proveedor, como se indicó anteriormente.
Sigue leyendo
- La referencia completa con llamadas a herramientas e imágenes: Vercel AI SDK doc
- Endpoint compatible con OpenAI explicado
- Precios de LLM en vivo