2026-04-15
Como usar DeepSeek V4 em Node.js: TypeScript, streaming, tool use
DeepSeek V4 é compatível com OpenAI, então no Node.js basta o pacote openai no npm. Esse tutorial passa, em TypeScript, pelo setup, primeira chamada, streaming com route handler do Next.js, tool use validado com Zod e boas práticas de custo.
1. Instalação e configuração
O pacote openai oficial aceita baseURL apontando para DeepSeek. Guarde a chave em .env, nunca comite no Git e nunca exponha no navegador.
npm install openai zod
echo "DEEPSEEK_API_KEY=sk-..." >> .env.local2. Primeira chamada em TypeScript
Instancie o cliente uma vez só. baseURL para o endpoint DeepSeek e model deepseek-chat para uso geral.
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.DEEPSEEK_API_KEY,
baseURL: "https://api.deepseek.com/v1",
});
export async function ask(question: string): Promise<string> {
const res = await client.chat.completions.create({
model: "deepseek-chat",
messages: [
{ role: "system", content: "You are a concise technical assistant." },
{ role: "user", content: question },
],
temperature: 0.2,
});
return res.choices[0].message.content ?? "";
}3. Streaming no route handler do Next.js
Para um chat UI com tokens em tempo real, o caminho mais simples é converter o iterable async do SDK em ReadableStream e devolver como Response.
// app/api/chat/route.ts
import OpenAI from "openai";
export const runtime = "nodejs";
const client = new OpenAI({
apiKey: process.env.DEEPSEEK_API_KEY,
baseURL: "https://api.deepseek.com/v1",
});
export async function POST(req: Request) {
const { messages } = await req.json();
const stream = await client.chat.completions.create({
model: "deepseek-chat",
messages,
stream: true,
});
const encoder = new TextEncoder();
const body = new ReadableStream({
async start(controller) {
for await (const chunk of stream) {
const delta = chunk.choices[0]?.delta?.content ?? "";
if (delta) controller.enqueue(encoder.encode(delta));
}
controller.close();
},
});
return new Response(body, {
headers: { "Content-Type": "text/plain; charset=utf-8" },
});
}4. Validação de tool use com Zod
O tool use do V4 é estável o suficiente para agentes reais, mas o modelo pode errar argumentos. Sempre parse com schema Zod antes de executar a função.
import { z } from "zod";
const GetWeatherArgs = z.object({ city: z.string().min(1) });
const tools = [{
type: "function" as const,
function: {
name: "get_weather",
description: "Get the current weather for a city",
parameters: {
type: "object",
properties: { city: { type: "string" } },
required: ["city"],
},
},
}];
const res = await client.chat.completions.create({
model: "deepseek-chat",
messages: [{ role: "user", content: "Weather in Tokyo?" }],
tools,
});
const call = res.choices[0].message.tool_calls?.[0];
if (call?.function.name === "get_weather") {
const args = GetWeatherArgs.parse(JSON.parse(call.function.arguments));
// … execute tool and feed result back as a { role: "tool" } message …
}5. Controle de custo no Node.js
Entrada e saída separadas, saída a ~2×. System prompt e histórico contam como entrada, então conversas longas escalam a conta rápido.
Defina maxTokens, sumarize turnos antigos e cacheie chunks de RAG. Para alto volume, /pricing tem chaves oficiais com desconto.
FAQ
Posso chamar DeepSeek direto do navegador?
Não, expõe a chave. Sempre via server Node.js, serverless ou route handler do Next.js.
Funciona em Bun, Deno e Cloudflare Workers?
Sim. O SDK openai tem build ESM e exige apenas fetch. Para streaming longo, prefira Node.js.
Compatível com LangChain / Vercel AI SDK?
Sim. Qualquer lib que aceite baseURL compatível com OpenAI funciona.
Chave barata?
/pricing lista chaves oficiais com desconto.
Se você já roda Node.js ou Next.js, migrar para DeepSeek V4 é literalmente trocar baseURL e model. Mantém prompts, ferramentas e retries, e corta o custo por tokens em uma ordem de grandeza.