Corte o histórico do chat para reduzir custos: janela deslizante ou resumo
Limite o que você reenvia a cada turno: mantenha as últimas mensagens ou um resumo curto. Aritmética de tokens para um chat de 50 turnos e um helper em Python.

Nesta página
Seu bot de suporte está conversando há 50 turnos, e cada nova mensagem custa mais que a anterior. A API não lembra de nada, então seu código reenvia a conversa inteira a cada vez. A solução é limitar o que você envia: mantenha o prompt de sistema e os últimos turnos (uma janela deslizante), ou troque turnos antigos por um resumo curto. Abaixo está a aritmética para um chat de 50 turnos e um helper que você pode copiar.
O guia de chat multi-turno da DeepSeek (api-docs.deepseek.com, verificado em 1 de novembro de 2026) diz claramente: o servidor não registra o contexto de requisições anteriores, então o cliente envia a lista completa de messages a cada chamada. O formato compatível com OpenAI no CheapTokens funciona da mesma forma. Se isso é novo para você, comece com por que um chat longo custa mais e como o array de mensagens funciona.
O que o turno 50 realmente envia#
Digamos que você tenha um bot de suporte com um prompt de sistema de 400 tokens. Em um turno típico, o usuário escreve cerca de 60 tokens e o bot responde com cerca de 190. Um turno completo adiciona 250 tokens ao histórico. Essas são suposições: substitua-as pelos números do campo usage das suas próprias respostas.
No turno 50, a requisição carrega o prompt de sistema, 49 turnos anteriores e a nova mensagem: 400 + 49 × 250 + 60 = 12,710 tokens de entrada, para obter uma resposta de 190 tokens. Some o chat inteiro. O prompt de sistema e a nova mensagem são enviados toda vez: 50 × 460 = 23,000. O histórico repetido adiciona 250 × 1,225 = 306,250. Juntos: 23,000 + 306,250 = 329,250 tokens de entrada, contra 50 × 190 = 9,500 tokens de saída.
O histórico em cada requisição cresce um turno, então o total cresce com o quadrado do comprimento do chat. Vá de 50 para 100 turnos e a parte do histórico repetido aproximadamente quadruplica.
Experimente você mesmoExperimente: se você enviasse apenas o prompt de sistema, os últimos 4 turnos e a nova mensagem, quantos tokens de entrada o turno 50 carregaria?Mostrar resposta
1.460 (400 + 4 × 250 + 60), contra 12.710 com o histórico completo. Mesma pergunta, mesmo tamanho de resposta, uma fração da entrada.
Opção 1: uma janela deslizante#
A ideia: sempre envie o prompt de sistema, descarte tudo exceto os últimos N turnos. Você mantém o histórico completo no seu próprio armazenamento e corta apenas a cópia que envia.
def trim_history(messages, keep_pairs=4):
"""System prompt + the last keep_pairs turns + the new user message."""
system = [m for m in messages if m["role"] == "system"]
rest = [m for m in messages if m["role"] != "system"]
return system + rest[-(keep_pairs * 2 + 1):]Chame-a depois de anexar a nova mensagem do usuário. Com keep_pairs=4, isso são 4 pares usuário/assistente mais a nova mensagem, 9 mensagens, e o slice sempre começa em uma mensagem do usuário. Aqui está ela conectada a uma chamada real:
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.cheaptokens.dev/v1",
api_key=os.environ["CHEAPTOKENS_API_KEY"],
)
MODEL = "deepseek-ai/DeepSeek-V4-Flash-0731"
history = [{"role": "system", "content": "You are a concise support assistant."}]
def ask(text):
history.append({"role": "user", "content": text})
resp = client.chat.completions.create(
model=MODEL,
messages=trim_history(history),
max_tokens=500,
)
answer = resp.choices[0].message.content
history.append({"role": "assistant", "content": answer})
print(resp.usage.prompt_tokens, resp.usage.completion_tokens)
return answerA linha print é a útil: observe o primeiro número. Sem o corte, ele sobe a cada turno. Com a janela, ele para de crescer assim que o chat passa do turno 4.

Em números: a partir do turno 5, cada requisição é de 400 + 4 × 250 + 60 = 1,460 tokens de entrada. Os primeiros quatro turnos ainda crescem normalmente e somam 3.340. O chat inteiro: 3,340 + 46 × 1,460 = 70,500 tokens de entrada, cerca de um quinto dos 329.250 que você envia com histórico completo. A saída permanece 50 × 190 = 9,500.

No código, a mudança inteira é um argumento na chamada:
Comparar
A mudança de uma linha
Antes
messages=historyDepois
messages=trim_history(history)O problema: uma janela esquece. Se o usuário perguntar no turno 40 "qual era o número do meu pedido?" e o número estava no turno 3, o modelo nunca o viu. Duas correções baratas. Extraia fatos estáveis (nome, número do pedido, plano) do chat no seu próprio código e anexe-os ao prompt de sistema, onde a janela nunca os corta. Ou adicione um resumo, que é a próxima opção.
Opção 2: um resumo dos turnos antigos#
Em vez de descartar turnos antigos, você os comprime. A cada poucos turnos, envie ao modelo os turnos que acabaram de sair da janela, mais o resumo atual, e peça um novo resumo curto. Depois coloque esse resumo na mensagem de sistema.
def summarize(summary, old_messages):
transcript = "\n".join(f"{m['role']}: {m['content']}" for m in old_messages)
prompt = (
f"Summary so far:\n{summary}\n\nNew turns:\n{transcript}\n\n"
"Rewrite the summary in under 200 words. "
"Keep names, numbers, decisions and open questions."
)
resp = client.chat.completions.create(
model=MODEL,
messages=[{"role": "user", "content": prompt}],
max_tokens=400,
)
return resp.choices[0].message.content
def build_messages(history, summary, keep_pairs=4):
system = history[0]["content"]
if summary:
system += "\n\nEarlier in this chat: " + summary
recent = history[1:][-(keep_pairs * 2 + 1):]
return [{"role": "system", "content": system}] + recentO resumo não é gratuito: é uma chamada extra ao modelo. Suponha um resumo de cerca de 300 tokens, atualizado a cada 5 turnos (9 vezes em 50 turnos), cada atualização lendo cerca de 1.600 tokens (o resumo antigo mais cinco turnos mais a instrução) e escrevendo 300. Para ficar do lado seguro, conte o resumo em toda requisição a partir do turno 5 (na realidade ele aparece após a primeira atualização, então isso é uma leve superestimativa): 400 + 300 + 4 × 250 + 60 = 1,760 tokens de entrada.
Totais do chat: requisições principais 3,340 + 46 × 1,760 = 84,300 tokens de entrada, chamadas de resumo 9 × 1,600 = 14,400 de entrada e 9 × 300 = 2,700 de saída. Ao todo, 84,300 + 14,400 = 98,700 tokens de entrada e 9,500 + 2,700 = 12,200 tokens de saída.
O resumo custa um pouco mais que a janela pura, e em troca o modelo ainda sabe o que aconteceu no turno 3.
Quanto custam as três configurações#
Aqui está o mesmo chat de 50 turnos no DeepSeek-V4-Flash, com preços ao vivo a partir dos totais acima:
Os preços vêm da lista de preços ao vivo, então os números se atualizam quando a tarifa muda. A ordem não muda: a janela envia menos, o resumo fica no meio, o histórico completo é o mais caro.
Para um chat como este, o modelo CheapTokens para começar é o DeepSeek-V4-Flash. Ele tem uma janela de contexto de 380K (um chat de 50 turnos cabe até sem corte), até 32.768 tokens de saída por resposta, um preço fixo em qualquer hora do dia e, no total, com entrada e saída contadas juntas, é mais barato que o OpenRouter. O id do modelo é deepseek-. Se você quiser comparar modelos na configuração de janela (1.410 tokens de entrada por requisição em média, 190 de saída, 50 requisições), aqui está a tabela ao vivo:
| Modelo | Entrada $/1M | Saída $/1M | Por solicitação | 50 solicitações | OpenRouter, 50 solicitações |
|---|---|---|---|---|---|
| GLM-5.3-Flash | $0.02 | $0.04 | $0.000036 | $0.0018 | $0.0032 |
| DeepSeek-V4-Flash | $0.015 | $0.10 | $0.00004 | $0.002 | $0.0063 |
| MiniMax-M2.7 | $0.05 | $0.15 | $0.000099 | $0.005 | $0.0594 |
1.410 tokens de entrada e 190 tokens de saída por solicitação. Os preços por 1M de tokens são atuais e mudam junto com nossas tarifas; a coluna OpenRouter mostra preços de referência para a mesma carga de trabalho.
GLM-5.3-Flash tem um contexto de 390K e MiniMax-M2.7 tem 180K, o que é suficiente para um chat com corte. Os preços atuais estão na página de preços, e a documentação mostra como enviar a primeira requisição.
Qual escolher#
Uma janela é o padrão: três linhas de código, sem chamadas extras, sem modo de falha extra. Use-a para bots de suporte, tutores e role-play, onde os últimos turnos carregam a conversa e o prompt de sistema carrega as regras. Adicione o resumo quando os usuários se referirem a coisas ditas há muito tempo, como em um assistente pessoal com uma conversa sem fim. Mantenha a janela pequena o suficiente para que o modelo ainda veja o contexto imediato, e grande o suficiente para conter uma troca completa de pergunta e resposta. Quanto cabe ao todo é um limite separado, abordado em o que é uma janela de contexto.
Verificação rápida
O usuário pergunta no turno 40 sobre um número de pedido dado no turno 3. Você usa uma janela de 4 turnos sem resumo. O que acontece?
Mostrar resposta
Resposta: O modelo não consegue vê-lo, porque o turno 3 foi cortado da requisição
A API é sem estado. O modelo só vê o que está na requisição, então fatos que você ainda precisa devem permanecer no prompt de sistema ou em um resumo.



