03-01-02 — Context window management

⏱ 10 minFontes validadas em: 2026-04-29

TL;DR

O context window é a memória de trabalho do LLM — tudo que cabe nele existe, o resto não existe. Quando você excede esse limite, o modelo trunca silenciosamente ou retorna erro. Gerenciar tokens ativamente é a diferença entre uma aplicação LLM robusta e uma que falha de forma imprevisível em produção.

O que é um token (e por que você deveria se importar)

Tokens não são palavras. São chunks de texto que o modelo processa internamente. Em inglês, 1 token ≈ 4 caracteres. Em português, a proporção é pior — palavras mais longas e acentuação fazem 1 token ≈ 3 caracteres. Na prática:

  • 1.000 palavras em inglês ≈ 1.300 tokens
  • 1.000 palavras em português ≈ 1.500–1.700 tokens
  • 1 página A4 de texto ≈ 500–700 tokens
  • Um contrato de 10 páginas ≈ 5.000–7.000 tokens

Limites dos modelos principais

ModeloContext windowCusto input (por 1M tokens)
GPT-4o128K tokens$2,50
GPT-4o mini128K tokens$0,15
Claude Opus 4200K tokens$15,00
Claude Sonnet 4200K tokens$3,00
Gemini 1.5 Pro1M tokens$1,25
⚠️ Atenção: Janela grande ≠ custo zero. Enviar 200K tokens por chamada em Claude Opus custa $3 por request. Em produção com 1.000 usuários simultâneos, isso vira $3.000/hora facilmente. Monitore ativamente.

O que acontece quando você excede o limite

Depende do provider e da configuração:

  • Erro 400: a API recusa a chamada (comportamento mais seguro)
  • Truncagem silenciosa: o início da conversa é descartado — o modelo perde contexto sem avisar você
  • Degradação de qualidade: modelos performam pior quando a janela está quase cheia ("lost in the middle" effect)
💡 Lost in the Middle: Pesquisas mostram que LLMs prestam mais atenção ao início e ao fim do contexto. Informações no meio de um documento longo tendem a ser ignoradas mesmo que caibam na janela. Posicione informações críticas no início ou no fim.

Contando tokens antes de enviar: tiktoken

tiktoken é a biblioteca da OpenAI para tokenização. Use-a para saber exatamente quantos tokens sua mensagem vai consumir:

import tiktoken

def count_tokens(messages: list[dict], model: str = "gpt-4o") -> int:
    """Conta tokens para um array de mensagens (formato OpenAI)."""
    encoding = tiktoken.encoding_for_model(model)
    
    tokens_per_message = 3  # overhead por mensagem
    tokens_per_name = 1     # overhead se houver campo 'name'
    
    total = 0
    for message in messages:
        total += tokens_per_message
        for key, value in message.items():
            total += len(encoding.encode(value))
            if key == "name":
                total += tokens_per_name
    
    total += 3  # overhead do array
    return total

# Exemplo de uso
messages = [
    {"role": "system", "content": "Você é um assistente de suporte técnico."},
    {"role": "user", "content": "Como faço para configurar um worker service no .NET 8?"},
]

token_count = count_tokens(messages)
print(f"Tokens: {token_count}")  # ~35 tokens
print(f"Custo estimado (GPT-4o): ${token_count / 1_000_000 * 2.50:.6f}")

Estratégias de gerenciamento

1. Truncagem por janela deslizante (sliding window)

Mantém as N mensagens mais recentes. Simples, mas perde contexto antigo:

def sliding_window(messages: list[dict], max_tokens: int = 4000, model: str = "gpt-4o") -> list[dict]:
    """Mantém o system prompt + mensagens recentes dentro do limite."""
    system_messages = [m for m in messages if m["role"] == "system"]
    conversation = [m for m in messages if m["role"] != "system"]
    
    # Começa do final e vai adicionando até o limite
    kept = []
    running_tokens = count_tokens(system_messages)
    
    for message in reversed(conversation):
        msg_tokens = count_tokens([message])
        if running_tokens + msg_tokens > max_tokens:
            break
        kept.insert(0, message)
        running_tokens += msg_tokens
    
    return system_messages + kept

2. Sumarização automática

Quando o histórico fica longo, chama o próprio LLM para criar um resumo e substitui as mensagens antigas pelo resumo:

def summarize_history(messages: list[dict], client, model: str = "gpt-4o-mini") -> list[dict]:
    """Substitui histórico longo por um resumo conciso."""
    system = [m for m in messages if m["role"] == "system"]
    history = [m for m in messages if m["role"] != "system"]
    
    if count_tokens(messages) < 3000:
        return messages  # não precisa sumarizar ainda
    
    # Pede ao modelo para resumir a conversa
    summary_response = client.chat.completions.create(
        model=model,  # usa modelo mais barato para sumarização
        messages=[
            {"role": "system", "content": "Resuma a conversa abaixo em bullet points concisos. Preserve fatos importantes e decisões tomadas."},
            {"role": "user", "content": str(history)}
        ]
    )
    
    summary = summary_response.choices[0].message.content
    
    # Retorna: system + mensagem de resumo + últimas 2 mensagens reais
    return system + [
        {"role": "assistant", "content": f"[Resumo da conversa anterior]: {summary}"}
    ] + history[-2:]

3. Retrieval-Augmented Generation (prévia do Módulo 04)

Em vez de injetar toda a documentação no contexto, você recupera apenas os trechos relevantes via busca semântica. É a estratégia mais escalável para bases de conhecimento grandes — detalhada no Módulo 04 (RAG).

Prompt tokens vs completion tokens

A cobrança é diferente para entrada e saída. Você controla o tamanho do prompt; você estima o completion via max_tokens:

response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    max_tokens=500  # limita o tamanho da resposta — controla custo e latência
)

# Inspeciona o uso real
usage = response.usage
print(f"Prompt tokens:     {usage.prompt_tokens}")
print(f"Completion tokens: {usage.completion_tokens}")
print(f"Total:             {usage.total_tokens}")

# Custo real (GPT-4o pricing)
cost = (usage.prompt_tokens / 1_000_000 * 2.50) + (usage.completion_tokens / 1_000_000 * 10.00)
print(f"Custo: ${cost:.6f}")
🏢 Azure OpenAI: No Azure, o uso de tokens aparece no Azure Monitor e no Cost Management. Configure alertas de custo no portal para evitar surpresas. O Azure também oferece PTU (Provisioned Throughput Units) para workloads previsíveis — mais barato que pay-per-token em alto volume.

Implementação em C# (.NET)

using Azure.AI.OpenAI;
using System.ClientModel;

var client = new AzureOpenAIClient(
    new Uri(Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")),
    new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY"))
);

var chatClient = client.GetChatClient("gpt-4o");

var messages = new List<ChatMessage>
{
    new SystemChatMessage("Você é um assistente técnico especializado em .NET."),
    new UserChatMessage("Como configurar health checks no ASP.NET Core?")
};

var response = await chatClient.CompleteChatAsync(messages, new ChatCompletionOptions
{
    MaxOutputTokenCount = 500  // controla custo
});

Console.WriteLine($"Prompt tokens: {response.Value.Usage.InputTokenCount}");
Console.WriteLine($"Completion tokens: {response.Value.Usage.OutputTokenCount}");
Console.WriteLine(response.Value.Content[0].Text);

Como isso se conecta

  • 03-01-01 Roles: o histórico multi-turn que cresce a cada turno é o principal consumidor de tokens
  • → Módulo 04 RAG: RAG existe em grande parte para resolver o problema de context window — injetar só o que é relevante
  • 03-03-02 Avaliação de prompts: custo por token é uma das métricas que você deve monitorar continuamente

Fontes

  1. OpenAI — Managing tokens
  2. Microsoft Learn — How to estimate token counts (Azure OpenAI)
  3. Lost in the Middle: How Language Models Use Long Contexts (arXiv:2307.03172)
  4. Anthropic — Working with long context