Processamento em lote com o DeepSeek Flash v4.1: como rodar milhares de chamadas sem se perder

O processamento em lote com o DeepSeek Flash v4.1 acontece no cliente: a referência oficial da API documenta Chat Completions, Responses, FIM Completion e listagem de modelos, e não há endpoint de batch offline documentado. Na prática, você fatia a fila com ID estável por item, força saída JSON com response_format, segura a concorrência com semáforo abaixo do limite da conta (a tabela oficial lista 2500 conexões simultâneas para deepseek-v4-flash), grava resultado parcial em JSONL e reprocessa só os IDs que faltaram. Some reasoning_effort = none nas tarefas mecânicas, prompt-prefixo fixo pro cache automático e rodada fora do pico, onde o preço é metade do de pico.
Fala aí, beleza? A DeepSeek soltou o DeepSeek-V4.1-Flash em 10/09/2026, já disponível na API e com suporte multimodal nativo, e a primeira coisa que passa na cabeça de quem trabalha com volume é a mesma: dá pra jogar minha fila de 50 mil itens nisso?
Dá, mas tem um detalhe que muda TODO o desenho do seu código
A referência oficial da API DeepSeek documenta Chat Completions, Responses, FIM Completion e listagem de modelos
Não tem endpoint de batch offline ali (aquela fila assíncrona onde você sobe um arquivo, vai tomar um café e volta pra buscar o resultado)
Ou seja: o lote é orquestrado por você, no cliente, com requisições concorrentes normais
E isso é menos assustador do que parece 🙂 Você precisa de quatro coisas: ID estável por item, um teto de concorrência, gravação parcial e uma fila de reprocesso. O resto é ajuste fino de custo.
O motor combina bem com esse papel: é um MoE multimodal com 552B de parâmetros no backbone, arquitetura Causal Encoder-Decoder de 40 camadas (20 de encoder causal + 20 de decoder), ativando 8B de parâmetros por token no prefill e 16B no decode
Bora montar o pipeline?
O que você precisa antes de disparar a primeira leva
Antes de escrever o loop, resolve essas decisões. Elas evitam refazer a rodada inteira depois.
Chave da API e SDK
A API DeepSeek é compatível com o formato da OpenAI, então dá pra usar o SDK da OpenAI só trocando a base_url para https://api.deepseek.com
Se você já tem código escrito pra OpenAI, é praticamente plug and play
Formação Claude Code
Domine Claude Code do absoluto zero até o avançado
- 120 aulas
- 4 projetos
- 9h 45min
from openai import OpenAI
client = OpenAI(
api_key=os.environ["DEEPSEEK_API_KEY"],
base_url="https://api.deepseek.com",
)
Qual identificador de modelo usar
O identificador pra chamar o V4.1-Flash é deepseek-flash
Os antigos deepseek-v4-flash e deepseek-v4-flash-vision-exp roteiam temporariamente pro V4.1-Flash por compatibilidade, então código legado não quebra
E se liga nisso, porque mexe com orçamento: a partir de 04:00 UTC de 14/09/2026, todas as requisições para deepseek-v4-pro passam a ser roteadas pro V4.1-Flash e cobradas nas tarifas do V4.1-Flash, até o lançamento do V4.1-Pro
Se o seu pipeline hoje aponta pro Pro, vale antes revisar quando usar Pro e quando usar Flash em cada etapa do projeto
Thinking ligado ou desligado?
O modo de raciocínio é controlado pelo parâmetro reasoning_effort
O valor none desativa o thinking, e low, high e max ativam. O padrão é high
Pra lote mecânico (classificar, extrair campo, normalizar), thinking ligado é output caro pagando por raciocínio que você nem vai ler
max_tokens
max_tokens aceita de 1 a 384K (393216)
O padrão é 8K sem thinking e 64K com thinking (128K quando reasoning_effort é max)
Em lote, deixar o padrão passar é convite pra resposta gorda. Aperte o teto de acordo com a tarefa.
Passo a passo: montando o pipeline em lote com o DeepSeek Flash v4.1
A lógica é sempre a mesma, muda só o prompt lá dentro
- Fatie a fila em unidades pequenas, com ID estável por item
ID estável é o item que carrega identidade própria e não depende da ordem do arquivo. Se você usar o número da linha como ID, o dia que a fila for reordenada seu reprocesso vira loteria.
import hashlib, json
def carregar_fila(caminho):
itens = []
with open(caminho, encoding="utf-8") as f:
for linha in f:
reg = json.loads(linha)
item_id = reg.get("id") or hashlib.sha1(
reg["texto"].encode("utf-8")
).hexdigest()
itens.append({"id": item_id, "texto": reg["texto"]})
return itens
O erro comum deste passo: usar índice de array como ID. Funciona na primeira rodada e te destrói na segunda
- Padronize a saída com JSON mode
Pra forçar saída em JSON é preciso configurar response_format como {"type": "json_object"}, citar a palavra "json" no system ou user prompt E dar um exemplo do formato desejado
As três coisas juntas, não duas
SYSTEM = (
"Você classifica tickets de suporte. "
"Responda em json seguindo este formato: "
'{"categoria": "cobranca|tecnico|outro", "confianca": 0.0}'
)
resp = client.chat.completions.create(
model="deepseek-flash",
messages=[
{"role": "system", "content": SYSTEM},
{"role": "user", "content": item["texto"]},
],
response_format={"type": "json_object"},
reasoning_effort="none",
max_tokens=256,
)
O erro comum deste passo: esquecer a palavra "json" no prompt. Você configurou o response_format, jurou que estava certo, e o lote volta torto
Tem um caminho alternativo quando o contrato precisa ser mais duro: o modo strict de function calling, que exige a base_url https://api.deepseek.com/beta e strict: true em todas as functions do parâmetro tools, com o servidor validando o JSON Schema que você mandou
- Controle a concorrência com um semáforo
A DeepSeek define limite de concorrência por user_id, calculado no nível da CONTA, independentemente da API Key usada
Ou seja: criar cinco chaves não te dá cinco filas, beleza?
A tabela oficial de rate limit lista deepseek-v4-pro com 500 conexões simultâneas, deepseek-v4-flash com 2500 e deepseek-v4-flash-vision-exp com 2500
E aqui vale um aviso, porque é fácil se embananar: esses são os nomes que aparecem na tabela oficial, e o identificador que a gente usa no código é o deepseek-flash
A tabela não traz uma linha própria pro deepseek-flash, então não dá pra afirmar por achismo qual é o teto exato dele
Na prática isso não muda o desenho do seu pipeline: deixe o semáforo BEM abaixo de qualquer um desses valores, observe se aparece 429 e confira a tabela oficial antes de subir o teto
import asyncio
SEM = asyncio.Semaphore(64)
async def processar(item):
async with SEM:
return await chamar_api(item)
async def rodar(itens):
return await asyncio.gather(
*(processar(i) for i in itens), return_exceptions=True
)
O erro comum deste passo: abrir um gather com a lista inteira sem semáforo. Você não dispara 50 mil requisições, você dispara 50 mil erros
- Isole filas concorrentes com
user_id
O user_id é uma string no padrão [a-zA-Z0-9\-_]+, com no máximo 512 caracteres
Ele serve pra separar filas diferentes dentro da mesma conta: se um user_id específico estoura, só as requisições com aquele user_id recebem 429
resp = client.chat.completions.create(
model="deepseek-flash",
messages=mensagens,
response_format={"type": "json_object"},
extra_body={"user_id": "lote-classificacao-tickets"},
)
O erro comum deste passo: rodar o lote gigante no mesmo user_id do app em produção. Aí o batch derruba o usuário real, e ninguém merece isso
- Salve resultado parcial linha a linha
JSONL com append é o melhor amigo de quem roda lote. Cada item concluído vira uma linha no disco, na hora.
def gravar(caminho, item_id, payload):
with open(caminho, "a", encoding="utf-8") as f:
f.write(json.dumps(
{"id": item_id, "resultado": payload}, ensure_ascii=False
) + "\n")
O erro comum deste passo: acumular tudo numa lista em memória e gravar no final. Um Ctrl+C, uma queda de rede, e horas de tokens pagos vão pro ralo
- Reprocesse só o que falhou
Como o ID é estável e você gravou linha a linha, o reprocesso é uma subtração
def ja_feitos(caminho):
feitos = set()
try:
with open(caminho, encoding="utf-8") as f:
for linha in f:
feitos.add(json.loads(linha)["id"])
except FileNotFoundError:
pass
return feitos
pendentes = [i for i in itens if i["id"] not in ja_feitos(SAIDA)]
Rodar de novo é rodar o mesmo script. Ele simplesmente pula o que já existe
O erro comum deste passo: gravar o item que falhou no MESMO arquivo de sucesso. Aí o filtro considera pronto o que está quebrado. Falha vai pra outro arquivo
- Ajuste o custo antes de escalar
Duas alavancas aqui
A primeira é reasoning_effort = none nas tarefas mecânicas, porque output é a parte cara da conta
A segunda é o cache de contexto em disco, que fica ativo por padrão pra todos os usuários, sem parâmetro pra ativar e sem mudar código
Pra ele pegar, o começo do seu prompt precisa ser IGUAL entre os itens: instrução fixa, exemplo de formato, taxonomia, tudo no prefixo, e o conteúdo variável do item por último
A unidade de armazenamento do cache é de 64 tokens, e conteúdo menor que isso não é cacheado. Prompt-prefixo minúsculo simplesmente não entra no jogo
Pra conferir se está funcionando, olhe a resposta:
u = resp.usage
print(u.prompt_cache_hit_tokens, u.prompt_cache_miss_tokens)
Se o prompt_cache_hit_tokens continua zerado depois de centenas de chamadas, seu prefixo não é tão fixo quanto você acha
O erro comum deste passo: carimbar timestamp, ID do item ou contador no começo do system prompt. Isso muda o prefixo e mata o cache
- Agende a rodada fora do pico
A janela de pico da API DeepSeek é 01:00 às 04:00 UTC e 06:00 às 10:00 UTC, de segunda a sexta
Todas as demais horas são fora de pico, e os preços em horário de pico são o DOBRO dos de fora de pico
A tabela do Flash em vigor, por 1 milhão de tokens fora de pico:
| Componente | Off-peak (US$ por 1M de tokens) |
|---|---|
| Input com cache hit | 0,003 |
| Input com cache miss | 0,15 |
| Output | 0,60 |
Esses valores entraram em vigor às 04:00 UTC de 10/09/2026 (12:00 no horário de Pequim), revertendo a alta que tinha sido aplicada à série V4 em 17/08/2026, 23 dias antes
Pra fechar a conta do seu volume específico, vale a pena aprender a estimar o gasto por token antes de disparar a fila inteira
O erro comum deste passo: assumir que o horário do seu cron é UTC. Não é, e o lote de madrugada no Brasil pode cair BEM no meio do pico
Quando o lote quebra: 429, respostas fora do formato e parsing travado
Lote quebra. A diferença entre um pipeline maduro e um script de sexta-feira é o que acontece DEPOIS da quebra.
Sintoma: uma enxurrada de HTTP 429
Causa: estourar o limite de concorrência retorna erro HTTP 429. E como o limite é calculado no nível da conta por user_id, outro processo seu rodando ao mesmo tempo entra na mesma conta
Solução: derrube o teto do semáforo, isole a fila com um user_id próprio e mande o item de volta pra fila de pendentes em vez de descartar
Como prevenir: se o volume é real e recorrente, dá pra solicitar ampliação de capacidade à DeepSeek, sem custo adicional, dimensionada conforme a necessidade real do negócio. É pedido, não gambiarra
Sintoma: JSON malformado ou texto solto no meio do lote
Causa: quase sempre é response_format ausente, ou prompt sem a palavra "json", ou sem o exemplo do formato desejado
Solução: fixe o contrato (as três condições juntas) e trate o parse com try/except, mandando o item pra fila de reprocesso em vez de derrubar a rodada inteira
Como prevenir: valide a saída contra um schema antes de gravar, ou vá de function calling em modo strict, onde o servidor valida o JSON Schema enviado
Um cuidado extra que pega gente desprevenida: temperature, top_p, presence_penalty e frequency_penalty NÃO são suportados no modo thinking
Se seu wrapper injeta temperature=0 por padrão em tudo, você tem uma surpresa esperando
Sintoma: seu parser trava no streaming
Causa: requisições em streaming retornam linhas SSE do tipo : keep-alive
Solução: ignore essas linhas, elas não afetam o parsing do corpo JSON
Como prevenir: em lote, streaming raramente compensa. Se a saída é um JSON curto de classificação, resposta completa é mais simples de gravar e de reprocessar
Três lotes que valem a pena rodar no Flash v4.1
Classificação em massa
O caso mais óbvio e o mais barato
Rótulo curto, saída mínima, reasoning_effort = none, max_tokens apertado em algumas dezenas e prompt-prefixo fixo com a taxonomia inteira pro cache pegar
Aqui o custo mora quase todo no input, e é justo onde o cache hit faz o maior estrago a seu favor
Extração de campos de documentos
Nota fiscal, contrato, currículo, ficha de cadastro
Use json_object com exemplo do formato, ou function calling em modo strict quando o schema é grande e você quer validação do lado do servidor
max_tokens acompanha o tamanho real do registro extraído, não o do documento de entrada. Documento de 20 páginas pode virar um JSON de 300 tokens
Resumo de volumes grandes
O contexto de 1 milhão de tokens é o padrão em todos os serviços oficiais da DeepSeek, então o item por chamada pode ser BEM gordo
E como o V4.1-Flash chegou com multimodal nativo, dá pra montar lote com imagem também
Atenção ao bolso neste: resumo é a tarefa que mais gera output, e output custa 0,60 contra 0,15 do input com cache miss em off-peak, ou seja, quatro vezes mais por token
Aqui, sim, vale medir se um reasoning_effort mais alto melhora o resultado o suficiente pra justificar
Veja o DeepSeek na prática
Pra quem está começando do zero com o DeepSeek, este vídeo do canal mostra a construção de um app completo usando o DeepSeek dentro do Claude Code, do início até o deploy
Conclusão
Sem endpoint de batch offline documentado, o processamento em lote DeepSeek Flash v4.1 é um problema de engenharia do SEU lado, e a boa notícia é que ele é um problema conhecido
ID estável, gravação parcial linha a linha e fila de reprocesso resolvem a maior parte da dor
O resto é o teto do semáforo bem abaixo do limite da conta, user_id isolando a fila e prompt-prefixo fixo pra deixar o cache automático trabalhar
Próximo passo concreto, e faça o teste antes de escalar: rode uma amostra de 100 itens fora do pico, olhe usage.prompt_cache_hit_tokens e usage.prompt_cache_miss_tokens, ajuste o prefixo até o hit subir, e SÓ ENTÃO aumente a concorrência
E marca no calendário: em 14/09/2026, às 04:00 UTC, o tráfego de deepseek-v4-pro passa a cair no V4.1-Flash e a ser cobrado nas tarifas do Flash. Se você tem pipeline apontando pro Pro, é bom saber disso antes da rodada, não depois…
até o próximo post! 😀
Perguntas frequentes
Como o cache de contexto ajuda a economizar num lote grande de chamadas ao DeepSeek Flash v4.1?
O cache de contexto em disco fica ativo por padrão pra todo mundo, sem precisar mudar código ou configurar nada
A unidade mínima de cache é 64 tokens, então prompts repetidos entre itens do lote (aquele system prompt fixo, por exemplo) tendem a cair em cache hit
Dá pra acompanhar isso direto na resposta da API, nos campos usage.prompt_cache_hit_tokens e usage.prompt_cache_miss_tokens
Vale a pena programar o lote pra rodar fora do horário de pico da API DeepSeek?
Vale, porque o preço em horário de pico é o dobro do preço fora de pico
O pico vai das 01:00 às 04:00 UTC e das 06:00 às 10:00 UTC, de segunda a sexta, então fora dessas janelas (e nos fins de semana) já é considerado fora de pico
Pra série Flash, fora de pico fica em US$ 0,003 por 1M de tokens de input com cache hit, US$ 0,15 com cache miss e US$ 0,60 de output por 1M de tokens
Meu pipeline chama deepseek-v4-pro. O que muda a partir de 14/09/2026?
A partir de 04:00 UTC de 14/09/2026, toda requisição pra deepseek-v4-pro passa a ser roteada automaticamente pro V4.1-Flash, e cobrada nas tarifas do V4.1-Flash
Isso vale até o lançamento do V4.1-Pro
Se seu lote hoje aponta pro Pro, o custo por chamada muda sem você precisar alterar o identificador do modelo no código
Dá pra usar streaming num processamento em lote com o DeepSeek Flash v4.1?
Dá, e é uma opção válida quando você quer começar a gravar o resultado antes da resposta terminar
Só fica atento se você faz parsing manual do SSE: aparecem linhas de keep-alive no formato ": keep-alive" no meio do stream
Elas não afetam o corpo JSON da resposta, mas seu parser precisa ignorá-las em vez de tentar interpretar como dado
Dá pra aumentar o limite de concorrência da conta pra rodar um lote maior?
Dá. A DeepSeek permite solicitar ampliação de capacidade sem custo adicional, dimensionada conforme a necessidade real do negócio
Enquanto isso não acontece, vale olhar a tabela oficial de rate limit, que lista os tetos por nome de modelo: deepseek-v4-pro com 500 conexões simultâneas por user_id, deepseek-v4-flash com 2500 e deepseek-v4-flash-vision-exp com 2500, sempre calculados no nível da conta
Repara que a tabela não traz uma linha própria pro identificador deepseek-flash, o mesmo que você usa nas chamadas, então o caminho seguro é manter a concorrência bem abaixo desses valores e conferir a tabela oficial antes de subir o teto
Por que minha chamada em lote com thinking ligado ignora o parâmetro temperature?
Porque o modo thinking não suporta alguns parâmetros de amostragem: temperature, top_p, presence_penalty e frequency_penalty não funcionam nele
Isso acontece sempre que reasoning_effort está em low, high ou max (o padrão é high)
Se o seu lote depende de ajustar temperature, considere reasoning_effort = none pra desativar o thinking
Formações
Formação Vibe Coding
Do Prompt ao Produto: Crie Software Real com IA
- 474 aulas
- 20 projetos
- 39h 27min
Blog | Mais populares
Como rodar o DeepSeek Harness com npx e abrir o Web UI no navegador
Aprenda a rodar o DeepSeek Harness npx e abrir o Web UI em http://127.0.0.1:3080 automaticamente no navegador, direto do terminal com Node.js instalado.
DeepSeek V4 Pro: o que é e quando compensa usar em vez do V4 Flash?
DeepSeek V4 Pro tem 1,6 tri de parâmetros e janela de 1 milhão de tokens. Entenda o preço, o desempenho e quando vale mais a pena que o V4 Flash.
Como rodar o DeepSeek V4 no Ollama: o passo a passo e o que checar antes de tentar
Rodar o DeepSeek V4 no Ollama hoje é via tag cloud: veja como fazer login, baixar a tag e usar via CLI ou API local, e quando vale ir de GGUF offline.
