Inicio / Inteligencia Artificial / AI-First Full Stack: Construye Apps con IA / APIs de LLMs: OpenAI, Anthropic y Google

APIs de LLMs: OpenAI, Anthropic y Google

Integración con OpenAI, Anthropic y Google AI APIs. SDKs, autenticación, modelos y parámetros.

Principiante

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 .env en .gitignore.

Ejercicio de práctica

Simula un cliente de API de LLM

Implementa funciones que simulen la interacción con una API de LLM.

function buildMessages(system: string, history: [string,string][], userMsg: string): Message[]
  // Construye array de mensajes con roles: system, user/assistant del history, y user final

function estimateTokens(text: string): number
  // Estima tokens: Math.ceil(text.length / 4)

function selectModel(budget: 'low'|'medium'|'high', task: 'chat'|'code'|'analysis'): string
  // low → gpt-4o-mini, medium+code → gpt-4o, high+analysis → claude-3-opus, default → gpt-4o