DEV Community

Juan Torchia
Juan Torchia Subscriber

Posted on • Originally published at juanchi.dev

DeepSeek API en TypeScript: integración segura y evaluación honesta del modelo para código

DeepSeek API en TypeScript: integración segura y evaluación honesta del modelo para código

Estuve meses convencido de que integrar un modelo nuevo al pipeline de TypeScript era la parte difícil. Después me di cuenta de que nunca lo fue. La parte difícil es decidir si ese modelo vale para lo que necesitás — sin comprar el hype ni descartarlo por moda. Con DeepSeek lo aprendí de nuevo.

Mi tesis antes de arrancar: la API de DeepSeek es compatible con el SDK de OpenAI, lo que hace la integración casi trivial en cualquier pipeline TypeScript existente. El diferenciador real no está en la plomería — está en el modelo. DeepSeek-Coder es competitivo en tareas de código, pero el criterio de elección depende del caso de uso específico, no del entusiasmo de Twitter.


Qué dice la documentación oficial — y qué no dice

La documentación oficial de DeepSeek tiene dos datos que cambian completamente la conversación sobre integración:

Compatibilidad con el SDK de OpenAI: DeepSeek expone su API bajo el mismo formato de mensajes que OpenAI. Eso significa que si ya usás openai npm package en un pipeline TypeScript, podés apuntar a la base URL de DeepSeek con mínimos cambios.

Modelos disponibles: A la fecha de este post, los modelos principales son deepseek-chat (propósito general) y deepseek-coder (orientado a código). La documentación lista el endpoint base como https://api.deepseek.com.

Lo que la documentación no dice: benchmarks independientes, comparaciones de latencia en producción real, ni garantías de SLA. Eso es trabajo propio — o de alguien que quiera correr el experimento con carga real. Yo no voy a inventar esos números acá.


Cómo se integra en TypeScript sin exponer la API key

Spine de la decisión: la API key de DeepSeek, como cualquier credential de un proveedor LLM, no puede vivir en el cliente. Nunca. En Next.js App Router eso tiene una respuesta concreta: la lógica que llama a la API vive en un Route Handler (server-side), y la key viaja exclusivamente via variable de entorno del servidor.

Paso 1: variable de entorno en .env.local

# .env.local — NUNCA commitear este archivo
DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Enter fullscreen mode Exit fullscreen mode

Agregalo a .gitignore si no está. En Railway, Vercel o cualquier plataforma de deploy, configurás la variable desde el panel — nunca desde el repositorio.

Paso 2: cliente TypeScript con compatibilidad OpenAI SDK

// lib/deepseek-client.ts
import OpenAI from "openai";

// Instancia apuntando al endpoint de DeepSeek
// Compatible con openai@^4 — mismo contrato de tipos
const deepseek = new OpenAI({
  apiKey: process.env.DEEPSEEK_API_KEY, // solo disponible server-side
  baseURL: "https://api.deepseek.com",
});

export default deepseek;
Enter fullscreen mode Exit fullscreen mode

La clave está en baseURL: el SDK de OpenAI acepta override del endpoint, y DeepSeek respeta el mismo contrato de mensajes. No necesitás un SDK propietario.

Paso 3: Route Handler en Next.js App Router

// app/api/code-review/route.ts
import { NextRequest, NextResponse } from "next/server";
import deepseek from "@/lib/deepseek-client";

export async function POST(req: NextRequest) {
  const { code } = await req.json();

  // Validación mínima antes de llamar al modelo
  if (!code || typeof code !== "string" || code.length > 8000) {
    return NextResponse.json({ error: "Payload inválido" }, { status: 400 });
  }

  const completion = await deepseek.chat.completions.create({
    model: "deepseek-coder", // modelo orientado a código
    messages: [
      {
        role: "system",
        content: "Revisá el código y señalá problemas concretos con justificación.",
      },
      { role: "user", content: code },
    ],
    max_tokens: 1024,
  });

  return NextResponse.json({
    review: completion.choices[0]?.message?.content ?? "",
  });
}
Enter fullscreen mode Exit fullscreen mode

El cliente nunca ve la key. El browser llama a /api/code-review; el Route Handler llama a DeepSeek. Ese es el patrón.


Dónde se equivoca la gente — y cuánto cuesta

Hay tres errores comunes que aparecen en integraciones rápidas de APIs LLM. Los listo como criterio prudente, porque los patrones son reproducibles aunque la experiencia sea genérica:

Error 1: exponer la key en el cliente
El caso típico es un dev que copia el snippet de la documentación directamente en un componente React. process.env.DEEPSEEK_API_KEY en el cliente es undefined en Next.js por defecto — pero si alguien prefija la variable con NEXT_PUBLIC_, la expone en el bundle del browser. Costo: la key queda accesible en DevTools y en cualquier scraper que revise el JS público.

Error 2: tratar deepseek-chat y deepseek-coder como sinónimos
Son modelos distintos con sesgos distintos. deepseek-coder fue entrenado específicamente para tareas de generación y revisión de código; deepseek-chat es más general. Usar el modelo equivocado no rompe la API — rompe la calidad de la respuesta. La documentación los distingue explícitamente.

Error 3: asumir que la compatibilidad con OpenAI SDK es total
La compatibilidad es a nivel de formato de mensajes y estructura de respuesta. No significa que DeepSeek soporte todas las features del API de OpenAI: function calling, embeddings, fine-tuning y herramientas avanzadas pueden tener diferencias o limitaciones. Antes de asumir paridad completa, revisá la documentación de DeepSeek para el feature específico que necesitás.


Matriz de decisión: DeepSeek-Coder vs Claude para tareas de código

Esta es la parte donde la mayoría de posts te da un winner y cierra el tema. Yo no voy a hacer eso — porque la respuesta honesta depende de variables que no puedo medir por vos.

Lo que sí puedo darte es el criterio de decisión:

Criterio DeepSeek-Coder Claude (Sonnet/Opus)
Costo de API Más bajo a fecha de publicación Más alto en modelos potentes
Contexto largo Revisar documentación oficial Claude tiene 200k tokens en Opus/Sonnet
Integración con SDK OpenAI Nativa, mismo contrato Requiere SDK de Anthropic o wrapper
Razonamiento multi-paso Competitivo en código Más fuerte en razonamiento general
Disponibilidad / uptime Proveedor más nuevo, historial más corto Anthropic tiene historial más largo
Restricciones de contenido Documentación menos detallada Más documentada y predecible

Cuándo vale probar DeepSeek-Coder primero:

  • El pipeline es exclusivamente de generación o revisión de código
  • El costo de API es una variable relevante en el diseño
  • Ya usás el SDK de OpenAI y querés mínima fricción para probar

Cuándo quedarse con Claude:

  • Necesitás razonamiento multi-paso o contexto muy largo
  • La predictibilidad del comportamiento del modelo importa más que el costo
  • El pipeline mezcla tareas de código con razonamiento general o análisis

Lo que no podés decidir sin vos propio experimento: velocidad de respuesta percibida en producción, calidad en el dominio específico del código que generás, y comportamiento bajo carga. Esos datos no existen en ningún post — existen en logs propios.


Lo que esta guía no puede concluir

Ser honesto acá es parte del trabajo:

  • No hay benchmarks propios: no corrí comparaciones sistemáticas entre DeepSeek-Coder y Claude con casos de uso reales. Los benchmarks públicos que circulan tienen metodologías distintas y no siempre son reproducibles.
  • La documentación de DeepSeek puede cambiar: es una plataforma en crecimiento activo. Lo que está disponible hoy puede cambiar. Revisá siempre https://platform.deepseek.com/api-docs/ antes de tomar decisiones de arquitectura.
  • La compatibilidad con OpenAI SDK no es garantía de paridad: es un punto de entrada, no un contrato completo. Testeá el feature específico que necesitás.
  • El costo relativo de las APIs fluctúa: no pongas decisiones de arquitectura en números de pricing que cambian cada trimestre.

FAQ — Preguntas frecuentes sobre DeepSeek API en TypeScript

¿Necesito un SDK especial para usar DeepSeek en TypeScript?
No. Podés usar el paquete oficial openai de npm apuntando el baseURL a https://api.deepseek.com. DeepSeek respeta el mismo formato de mensajes, así que el tipado TypeScript del SDK de OpenAI funciona sin modificaciones.

¿Cuál es la diferencia real entre deepseek-chat y deepseek-coder?
Según la documentación oficial, deepseek-coder fue entrenado específicamente para tareas de código: generación, explicación, debugging y revisión. deepseek-chat es el modelo de propósito general. Para un pipeline enfocado en código, deepseek-coder es el punto de partida lógico.

¿Cómo protejo la API key en un proyecto Next.js?
La key vive en .env.local (nunca en el repositorio) y se usa exclusivamente en código server-side: Route Handlers o Server Actions. Nunca prefijés la variable con NEXT_PUBLIC_ porque eso la expone en el bundle del browser. En producción, configurala desde el panel de la plataforma de deploy.

¿Puedo usar DeepSeek y Claude en el mismo pipeline?
Sí, y es un patrón razonable: usar DeepSeek-Coder para tareas mecánicas de código (generación de boilerplate, conversiones, snippets) y Claude para razonamiento más complejo o contexto largo. El router entre modelos es lógica que escribís vos. Esto conecta con la misma decisión de diseño que aparece en rate limiting en aplicaciones web: decidir qué capa protegés y con qué herramienta.

¿La compatibilidad con OpenAI SDK garantiza que todas las features van a funcionar igual?
No. La compatibilidad es a nivel de chat completions básico. Features como function calling, embeddings, batch API o fine-tuning pueden tener diferencias o directamente no estar disponibles en DeepSeek. Antes de asumir paridad, verificá en la documentación oficial el feature específico que necesitás.

¿Tiene sentido usar DeepSeek en un pipeline que ya usa Claude o GPT-4?
Depende del caso. Si el costo de API es relevante y las tareas son mecánicas (generación de código repetitivo, formateo, snippets cortos), vale evaluarlo. Si el pipeline depende de razonamiento multi-paso o contexto muy largo, el cambio puede deteriorar la calidad de las respuestas. La decisión honesta viene de correr el experimento en el propio dominio, no de benchmarks generales.


La decisión real, sin adornos

La integración de DeepSeek en TypeScript es fácil — intencionalmente fácil. La compatibilidad con el SDK de OpenAI es una decisión de producto que baja la fricción de adopción a casi cero. Eso es una ventaja real y vale reconocerla.

Lo que no es fácil es la decisión de modelo. Y acá mi postura es clara: no le compro a nadie la idea de que DeepSeek-Coder es mejor que Claude para código "en general" — porque "en general" no existe en producción. Existe el dominio específico, el tipo de tarea, el volumen de tokens y el presupuesto del proyecto.

Lo que sí acepto como punto de partida: si ya tenés un pipeline con el SDK de OpenAI y querés evaluar DeepSeek-Coder, el costo de la prueba es mínimo. Cambiás el baseURL, cambiás el modelo, corrés el mismo conjunto de prompts que ya tenés y mirás los resultados. Esa es la única forma honesta de comparar.

El hype de Twitter no reemplaza ese experimento. Yo tampoco.

Si el tema de arquitectura de pipelines te interesa, el post sobre Node.js y el event loop tiene contexto útil sobre cómo pensar el runtime detrás de estas integraciones. Y si estás pensando en cómo proteger estos endpoints antes de exponerlos, el post de rate limiting es el paso siguiente.


Fuente original:


Este artículo fue publicado originalmente en juanchi.dev

Top comments (0)