APIs de LLMs: OpenAI, Anthropic y Google
Las APIs de LLMs son la base de cualquier aplicación AI-First. En esta lección aprenderás a integrar los tres proveedores principales: OpenAI, Anthropic y Google AI, entendiendo sus SDKs, modelos, parámetros y diferencias.
Instalación de SDKs
# OpenAI
npm install openai
# Anthropic
npm install @anthropic-ai/sdk
# Google AI
npm install @google/generative-ai
OpenAI API
Configuración
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
Chat Completions
const response = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{ role: 'system', content: 'Eres un experto en TypeScript.' },
{ role: 'user', content: 'Explica los generics en TypeScript.' },
],
temperature: 0.7,
max_tokens: 1000,
});
console.log(response.choices[0].message.content);
console.log(response.usage); // { prompt_tokens, completion_tokens, total_tokens }
Modelos OpenAI (2025-2026)
| Modelo | Uso ideal | Context window |
|---|---|---|
gpt-4o |
Tareas complejas, razonamiento | 128K |
gpt-4o-mini |
Tareas simples, alto volumen, bajo costo | 128K |
o1 |
Razonamiento avanzado (matemáticas, código) | 200K |
o3-mini |
Razonamiento rápido y económico | 200K |
Parámetros clave
const response = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [...],
temperature: 0.7, // 0 = determinista, 2 = muy creativo
max_tokens: 2000, // Máximo tokens de respuesta
top_p: 1, // Nucleus sampling (alternativa a temperature)
frequency_penalty: 0, // Penaliza repetición de tokens
presence_penalty: 0, // Penaliza hablar del mismo tema
stop: ['\n\n'], // Secuencias donde parar
});
Anthropic API (Claude)
Configuración
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
Messages API
const response = await anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 1024,
system: 'Eres un experto en arquitectura de software.',
messages: [
{ role: 'user', content: 'Explica el patrón Repository.' },
],
});
// Claude retorna content como array de bloques
const text = response.content
.filter(block => block.type === 'text')
.map(block => block.text)
.join('');
console.log(text);
console.log(response.usage); // { input_tokens, output_tokens }
Modelos Claude (2025-2026)
| Modelo | Uso ideal | Context window |
|---|---|---|
claude-sonnet-4-20250514 |
Balance calidad/costo | 200K |
claude-opus-4-20250514 |
Máxima calidad, tareas complejas | 200K |
claude-haiku-3-20250307 |
Velocidad y bajo costo | 200K |
Diferencias clave con OpenAI
// OpenAI: system va en messages
messages: [
{ role: 'system', content: 'Instrucciones...' },
{ role: 'user', content: 'Pregunta' },
]
// Anthropic: system es un parámetro separado
system: 'Instrucciones...',
messages: [
{ role: 'user', content: 'Pregunta' },
]
// Anthropic: content es un array de bloques, no un string
response.content[0].text // No response.choices[0].message.content
Google AI (Gemini)
Configuración
import { GoogleGenerativeAI } from '@google/generative-ai';
const genAI = new GoogleGenerativeAI(process.env.GOOGLE_AI_API_KEY!);
const model = genAI.getGenerativeModel({ model: 'gemini-2.0-flash' });
Generar contenido
const result = await model.generateContent('Explica qué es una API REST.');
const text = result.response.text();
console.log(text);
Chat multi-turno
const chat = model.startChat({
history: [
{ role: 'user', parts: [{ text: 'Hola, soy un dev TypeScript.' }] },
{ role: 'model', parts: [{ text: '¡Hola! ¿En qué puedo ayudarte?' }] },
],
});
const result = await chat.sendMessage('Explica async/await.');
console.log(result.response.text());
Modelos Gemini (2025-2026)
| Modelo | Uso ideal | Context window |
|---|---|---|
gemini-2.0-flash |
Rápido, multimodal, bajo costo | 1M |
gemini-2.0-pro |
Tareas complejas, razonamiento | 1M |
gemini-2.5-pro |
Máxima capacidad | 1M |
Abstracción multi-proveedor
En producción, querrás soportar múltiples proveedores para fallback y flexibilidad:
interface LLMResponse {
content: string;
inputTokens: number;
outputTokens: number;
model: string;
}
interface LLMProvider {
chat(messages: Message[], options?: LLMOptions): Promise<LLMResponse>;
}
class OpenAIProvider implements LLMProvider {
async chat(messages: Message[], options?: LLMOptions): Promise<LLMResponse> {
const response = await openai.chat.completions.create({
model: options?.model ?? 'gpt-4o-mini',
messages,
temperature: options?.temperature ?? 0.7,
max_tokens: options?.maxTokens ?? 1000,
});
return {
content: response.choices[0].message.content!,
inputTokens: response.usage!.prompt_tokens,
outputTokens: response.usage!.completion_tokens,
model: response.model,
};
}
}
class AnthropicProvider implements LLMProvider {
async chat(messages: Message[], options?: LLMOptions): Promise<LLMResponse> {
const systemMsg = messages.find(m => m.role === 'system');
const userMsgs = messages.filter(m => m.role !== 'system');
const response = await anthropic.messages.create({
model: options?.model ?? 'claude-sonnet-4-20250514',
system: systemMsg?.content,
messages: userMsgs,
max_tokens: options?.maxTokens ?? 1000,
});
return {
content: response.content[0].type === 'text' ? response.content[0].text : '',
inputTokens: response.usage.input_tokens,
outputTokens: response.usage.output_tokens,
model: response.model,
};
}
}
Fallback automático
class LLMService {
private providers: LLMProvider[];
constructor(providers: LLMProvider[]) {
this.providers = providers;
}
async chat(messages: Message[], options?: LLMOptions): Promise<LLMResponse> {
for (const provider of this.providers) {
try {
return await provider.chat(messages, options);
} catch (error) {
console.warn(`Provider failed, trying next...`, error);
}
}
throw new Error('All LLM providers failed');
}
}
// Uso: intenta OpenAI, si falla usa Anthropic
const llm = new LLMService([
new OpenAIProvider(),
new AnthropicProvider(),
]);
Manejo de errores
import OpenAI from 'openai';
try {
const response = await openai.chat.completions.create({ ... });
} catch (error) {
if (error instanceof OpenAI.APIError) {
switch (error.status) {
case 429: // Rate limit
console.log('Rate limited. Retrying after delay...');
await sleep(error.headers?.['retry-after'] ?? 5000);
break;
case 500: // Server error
console.log('OpenAI server error. Using fallback...');
break;
case 401: // Auth error
throw new Error('Invalid API key');
}
}
}
Variables de entorno
# .env
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
GOOGLE_AI_API_KEY=AIza...
# Nunca commitear API keys!
# .gitignore
.env
.env.local
Regla de oro: Nunca hardcodees API keys en el código. Usa variables de entorno y un
.enven.gitignore.