| name | ai-unified-proxy |
| description | Unified AI Proxy - API multi-proveedor gratuita con rotación automática, streaming, y zero vendor lock-in |
| trigger | ai-proxy OR multi-provider OR free-tier OR ai-routing OR streaming OR unified-ai OR round-robin OR bun-api |
| scope | global |
| weight | 4.5 |
AI Unified Proxy Architecture
🎯 Objetivo
Crear una API unificada de IA que:
- ✅ No dependa de NADIE (zero vendor lock-in)
- ✅ Use capas gratuitas de múltiples proveedores
- ✅ Rote servicios automáticamente (round-robin)
- ✅ Soporte streaming de tokens (SSE)
- ✅ Sea extensible (local + cloud)
- ✅ Se despliegue fácil en VPS (Coolify)
🧱 Stack Tecnológico
Runtime: Bun (B)
Por qué Bun:
- ⚡ Ultra rápido (alternativa a Node.js)
- 📦
bun install - gestor de paquetes integrado
- 🚀
bun run - ejecutor nativo
- 📘 TypeScript nativo sin configuración
- 🎯 Ideal para APIs livianas
Instalación:
curl -fsSL https://bun.sh/install | bash
Servidor: Bun.serve()
Características:
- HTTP server nativo (sin Express/Fastify)
- Puerto dinámico:
process.env.PORT || 3000
- Manejo manual de rutas (control total)
- Performance superior
🧠 Arquitectura Lógica
Client
|
POST /chat
|
API Gateway (Bun)
|
Round-Robin Selector
|
AI Service Adapter (contrato común)
|
┌─────────┬──────────┬─────────┬────────────┬─────────┐
│ Grok │ Cerebras │ Gemini │ OpenRouter │ Local │
└─────────┴──────────┴─────────┴────────────┴─────────┘
|
Streaming Response (SSE)
Flujo de datos:
- Cliente envía mensajes a
/chat
- Gateway valida y parsea JSON
- Selector elige próximo servicio (round-robin)
- Servicio procesa con su SDK específico
- Tokens se streamean vía Server-Sent Events
- Cliente recibe respuesta progresiva
📜 Contrato Común (Clave del Sistema)
Tipo: ChatMessage
type ChatMessage = {
role: "system" | "user" | "assistant";
content: string;
};
Interfaz: AIService
interface AIService {
name: string;
chat(messages: ChatMessage[]): AsyncIterable<string>;
}
👉 Regla de Oro
Todo proveedor que cumpla este contrato entra al sistema sin tocar el core.
Beneficios:
- ✅ Adapter Pattern implementado
- ✅ Plug & Play de nuevos servicios
- ✅ Cero acoplamiento con proveedores
- ✅ Testing aislado por servicio
🔁 Balanceo: Round Robin
Estado Global
const services: AIService[] = [];
let currentServiceIndex = 0;
Selector
function getNextService(): AIService {
const service = services[currentServiceIndex];
currentServiceIndex = (currentServiceIndex + 1) % services.length;
return service;
}
Ventajas
- ✅ Reparte carga equitativamente
- ✅ Extiende cuotas gratuitas
- ✅ Evita bloqueos por rate limit
- ✅ Sin estado complejo (stateless)
Evolución Futura
const services = [
{ service: grok, weight: 3 },
{ service: cerebras, weight: 2 },
{ service: gemini, weight: 1 },
];
services.filter((s) => s.isHealthy());
🌊 Streaming (Clave Diferencial)
Técnica: Async Generator + yield
async function* streamResponse(service: AIService, messages: ChatMessage[]) {
for await (const token of service.chat(messages)) {
yield token;
}
}
Respuesta: Server-Sent Events (SSE)
Headers requeridos:
{
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
}
Formato de datos:
data: {"token":"Hola"}\n\n
data: {"token":" mundo"}\n\n
data: {"done":true}\n\n
Beneficios
- ⚡ Respuesta progresiva (tipo ChatGPT)
- 📉 Menor latencia percibida
- 🔗 Compatible con frontend en tiempo real
- 🎯 Backpressure natural
🧩 Servicios IA (Plugins)
1️⃣ Grok (xAI)
Free Tier:
- ~60 req/min
- Modelos: Moonshot, Kimi K2
Implementación:
import { OpenAI } from "openai";
const client = new OpenAI({
apiKey: process.env.GROK_API_KEY,
baseURL: "https://api.x.ai/v1",
});
export const grokService: AIService = {
name: "Grok",
async *chat(messages) {
const stream = await client.chat.completions.create({
model: "grok-beta",
messages,
stream: true,
});
for await (const chunk of stream) {
const token = chunk.choices[0]?.delta?.content;
if (token) yield token;
}
},
};
2️⃣ Cerebras
Free Tier:
- 30 req/min
- 1M tokens/día
- Modelos: GPT-OSS, Zhipu GLM-4.6
Características:
- Muy rápido en inferencia
- Excelente para tareas simples
Implementación:
import { Cerebras } from "@cerebras/cerebras_cloud_sdk";
const client = new Cerebras({
apiKey: process.env.CEREBRAS_API_KEY,
});
export const cerebrasService: AIService = {
name: "Cerebras",
async *chat(messages) {
const stream = await client.chat.completions.create({
model: "llama3.1-8b",
messages,
stream: true,
});
for await (const chunk of stream) {
const token = chunk.choices[0]?.delta?.content;
if (token) yield token;
}
},
};
🔌 Otros Servicios Compatibles
| Servicio | Free Tier | Velocidad | Casos de uso |
|---|
| Gemini (Google) | 15 RPM | Media | Razonamiento general |
| OpenRouter | Modelos gratis | Variable | Agregador multi-modelo |
| Ollama | Ilimitado (local) | Depende HW | Offline, privacidad |
| LM Studio | Ilimitado (local) | Depende HW | UI + local |
Ejemplo Gemini:
import { GoogleGenerativeAI } from "@google/generative-ai";
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY);
export const geminiService: AIService = {
name: "Gemini",
async *chat(messages) {
const model = genAI.getGenerativeModel({ model: "gemini-pro" });
const chat = model.startChat({ history: messages.slice(0, -1) });
const result = await chat.sendMessageStream(
messages[messages.length - 1].content,
);
for await (const chunk of result.stream) {
yield chunk.text();
}
},
};
📁 Estructura de Proyecto
ai-unified-proxy/
├── services/
│ ├── grok.ts # Integración Grok/xAI
│ ├── cerebras.ts # Integración Cerebras
│ ├── gemini.ts # Integración Google Gemini
│ └── ollama.ts # Integración local Ollama
├── types/
│ ├── chat-message.ts # Tipo ChatMessage
│ └── ai-service.ts # Interfaz AIService
├── index.ts # API Gateway principal
├── .env # Variables de entorno (NUNCA commitear)
├── .env.example # Template de .env
├── package.json # Dependencias
├── nixpacks.toml # Config de build Coolify
├── tsconfig.json # Config TypeScript
└── README.md # Documentación
⚙️ Implementación: index.ts (API Gateway)
Código completo:
import { grokService } from "./services/grok";
import { cerebrasService } from "./services/cerebras";
import type { ChatMessage, AIService } from "./types/ai-service";
const services: AIService[] = [grokService, cerebrasService];
let currentServiceIndex = 0;
function getNextService(): AIService {
const service = services[currentServiceIndex];
currentServiceIndex = (currentServiceIndex + 1) % services.length;
return service;
}
Bun.serve({
port: process.env.PORT || 3000,
async fetch(req) {
const url = new URL(req.url);
if (req.method === "POST" && url.pathname === "/chat") {
try {
const body = req.();
messages = body. [];
(!.(messages) || messages. === ) {
(, { : });
}
service = ();
.();
stream = ({
() {
{
( token service.(messages)) {
data = ;
controller.( ().(data));
}
controller.(
().(
,
),
);
} (error) {
.(, error);
controller.(
().(
,
),
);
} {
controller.();
}
},
});
(stream, {
: {
: ,
: ,
: ,
},
});
} (error) {
(, { : });
}
}
(, { : });
},
});
.();
🔐 Variables de Entorno
.env (NUNCA commitear)
GROK_API_KEY=xai-xxxxxxxxxxxxx
CEREBRAS_API_KEY=csk-xxxxxxxxxxxxx
GEMINI_API_KEY=AIzaxxxxxxxxxxxxx
PORT=3000
NODE_ENV=production
.env.example (Template)
GROK_API_KEY=your_grok_key_here
CEREBRAS_API_KEY=your_cerebras_key_here
GEMINI_API_KEY=your_gemini_key_here
PORT=3000
NODE_ENV=production
⚠️ Buenas Prácticas
- Solo runtime, no buildtime
- Usar
.gitignore para .env
- Nunca hardcodear keys
- Validar keys al inicio
🚀 Deploy en Coolify
Paso 1: Preparar VPS
Requisitos mínimos:
- 2 vCPU
- 8 GB RAM (4 GB suficiente)
- 20 GB disco
- Ubuntu 22.04 LTS
Proveedores recomendados:
- Hostinger VPS (~$5/mes)
- Hetzner Cloud (~€4/mes)
- DigitalOcean Droplets (~$6/mes)
Paso 2: Instalar Coolify
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
Acceder: http://your-vps-ip:8000
Paso 3: Configurar proyecto en Coolify
- New Resource → Git Repository
- Conectar tu repo (GitHub/GitLab)
- Configurar:
- Build Pack: Nixpacks
- Port: 3000
- Environment Variables: Agregar API keys
Paso 4: nixpacks.toml
[setup]
packages = ["bun"]
[install]
cmds = ["bun install"]
[start]
cmd = "bun run index.ts"
[variables]
PORT = "3000"
Paso 5: Deploy
- Coolify detecta cambios en Git
- Build automático con Nixpacks
- Deploy con zero-downtime
- Logs en vivo en UI
🧪 Testing
Testing Local
bun install
cp .env.example .env
bun run index.ts
Testing con curl
curl -N -X POST http://localhost:3000/chat \
-H "Content-Type: application/json" \
-d '{
"messages":[
{"role":"user","content":"Explica Fibonacci en JavaScript"}
]
}'
Resultado esperado:
data: {"token":"Aquí"}
data: {"token":" tienes"}
data: {"token":" una"}
data: {"token":" implementación"}
...
data: {"done":true}
Testing con JavaScript
const eventSource = new EventSource("/chat", {
method: "POST",
body: JSON.stringify({
messages: [{ role: "user", content: "Hola mundo" }],
}),
});
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.done) {
eventSource.close();
} else {
console.log(data.token);
}
};
🧠 Metodologías Implícitas
| Pattern | Descripción | Beneficio |
|---|
| Adapter Pattern | Cada proveedor es un plugin | Extensibilidad |
| Gateway Pattern | API única para múltiples servicios | Simplicidad |
| Backpressure Natural | Streaming controla flujo | Performance |
| Fail Soft | Rotación automática | Resiliencia |
| Cost-Aware Architecture | Gratis primero, pago último | Economía |
🔮 Extensiones Naturales
1. Weighted Round Robin
const services = [
{ service: grok, weight: 3, quality: 0.9 },
{ service: cerebras, weight: 2, quality: 0.85 },
{ service: gemini, weight: 1, quality: 0.95 },
];
function getWeightedService() {
const totalWeight = services.reduce((sum, s) => sum + s.weight, 0);
let random = Math.random() * totalWeight;
for (const item of services) {
random -= item.weight;
if (random <= 0) return item.service;
}
}
2. Health Checks
interface AIService {
name: string;
chat(messages: ChatMessage[]): AsyncIterable<string>;
healthCheck(): Promise<boolean>;
}
async function getHealthyService() {
const healthy = await Promise.all(
services.map(async (s) => ({
service: s,
isHealthy: await s.healthCheck(),
})),
);
return healthy.find((h) => h.isHealthy)?.service;
}
3. Fallback Local Automático
const services = [
grokService,
cerebrasService,
geminiService,
ollamaService,
];
4. Cache Semántica
import { similarity } from "ml-distance";
const cache = new Map<string, string>();
function getCachedResponse(prompt: string) {
for (const [cachedPrompt, response] of cache) {
if (similarity(prompt, cachedPrompt) > 0.95) {
return response;
}
}
return null;
}
5. Rate Limit Aware Routing
interface AIService {
name: string;
rateLimitRemaining: number;
rateLimitReset: Date;
chat(messages: ChatMessage[]): AsyncIterable<string>;
}
function getRateLimitSafeService() {
return services.find((s) => s.rateLimitRemaining > 0) || services[0];
}
6. Observabilidad
import { logger } from "./logger";
for await (const token of service.chat(messages)) {
logger.info({
service: service.name,
timestamp: Date.now(),
tokenLength: token.length,
});
yield token;
}
7. Policy Engine
function selectServiceByTask(task: string) {
if (task.includes("código")) return cerebrasService;
if (task.includes("razonamiento")) return geminiService;
return grokService;
}
🚨 Troubleshooting
Problema: "No streaming"
Causa: Headers SSE incorrectos
Solución:
{
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
}
Problema: "Rate limit exceeded"
Causa: Todas las APIs agotadas
Solución: Agregar más proveedores o fallback local
Problema: "Bun not found en Coolify"
Causa: nixpacks.toml incorrecto
Solución:
[setup]
packages = ["bun"]
Problema: "CORS errors"
Solución:
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
'Content-Type': 'text/event-stream',
}
📚 Related Skills
cloud-ready - Deploy y gestión en VPS
ai-security - Protección contra prompt injection
conventional-commits - Versionado semántico
machine-health - Monitoreo de recursos
🧠 Resumen Brutal (1 Línea)
Una API de IA modular, gratuita, extensible y sin vendor lock-in, basada en contratos, streaming y rotación inteligente de proveedores.
Ready to deploy. 🚀