Source: https://aiprimetech.io/pt/blog/reduce-llm-token-usage/ Jun 20, 2026 · 7 min · API # Como reduzir o uso de tokens com engenharia sem prejudicar a qualidade A Por [AI Prime Tech](https://aiprimetech.io/pt/) · Com auxílio de IA No mês passado, revisei um agente de suporte ao cliente que consumia 18,000–42,000 tokens de entrada por chamado antes de escrever uma única palavra. O problema real do usuário geralmente ocupava menos de 300 tokens. O restante era contexto incluído “por precaução”: todo o histórico da conversa, todas as páginas de políticas internas recuperadas por busca de palavras-chave, JSON resultados de ferramentas copiados na íntegra e um prompt de sistema de 900 tokens que havia crescido ao longo de seis meses. A solução não foi “usar um modelo menor” nem “reduzir max_tokens e torcer”. Reduzimos o uso mediano de tokens em cerca de 68% e mantivemos a qualidade das respostas estável com trabalho de engenharia rotineiro: enxugar o contexto, recuperar evidências mais específicas, resumir o estado, impor esquemas de saída e medir os tokens com precisão. Este artigo trata desse tipo de trabalho. Não de competições para encurtar prompts. Não de truques que pioram o modelo. Apenas de formas práticas de gastar menos tokens sem tornar seu sistema menos inteligente. ## O uso de tokens é um problema de arquitetura A maioria das equipes trata o custo dos tokens como um problema de preços dos modelos. Na prática, geralmente é um problema de roteamento de informações. Uma chamada típica a um LLM em produção tem quatro categorias de tokens: - Tokens de instrução: prompt de sistema, prompt do desenvolvedor, regras de formatação, restrições de segurança. - Tokens de contexto: histórico do chat, documentos recuperados, saídas de ferramentas, registros do banco de dados. - Tokens de raciocínio/tarefa: a solicitação real do usuário e os detalhes intermediários da tarefa. - Tokens de saída: a resposta gerada, o objeto JSON, a consulta SQL, o resumo ou a chamada de ferramenta. Quando o uso de tokens sai do controle, o contexto e a saída geralmente são os culpados. O modelo não é caro porque o usuário fez uma pergunta difícil. Ele é caro porque a aplicação colocou o mundo inteiro no prompt e depois deixou o modelo se alongar. Um primeiro exercício útil é registrar o uso de tokens por seção, não apenas o tamanho total da solicitação: ``` { "request_id": "ticket_81291", "model": "sonnet-4.6", "tokens": { "system": 742, "history": 3890, "retrieval": 12640, "tool_results": 2110, "user": 184, "output": 931 }, "latency_ms": 4820 } ``` Ao ver essa distribuição, o caminho para a otimização fica óbvio. Você não precisa debater se Claude Opus 4.8, Sonnet 4.6, GPT-5.5, Gemini 3, Fable 5 ou um modelo aberto como Qwen ou DeepSeek é o “melhor” em termos abstratos. Primeiro, precisa parar de enviar 12,000 tokens irrelevantes de conteúdo recuperado. ## Comece com um orçamento de tokens por rota Gosto de atribuir orçamentos por rota do produto, não globalmente. Uma revisão de contrato jurídico, um agente de programação e um bot de perguntas frequentes não devem compartilhar as mesmas premissas de uso de tokens. Exemplo de orçamento para um assistente de suporte: | Opção | Orçamento de entrada | Orçamento de saída | Classe de modelo | Observações | Classificar chamado | 600 | 50 | Modelo barato/rápido | Rótulos, urgência, idioma | Recuperar evidências | 1,500 | 0 | Embedding/busca | Não requer geração | Redigir resposta | 4,000 | 600 | Modelo robusto de nível intermediário/alto | Usa evidências selecionadas | Resumir conversa | 1,000 | 250 | Modelo barato/rápido | Atualiza o estado da memória | Análise de escalonamento | 6,000 | 900 | Modelo robusto | Apenas para casos complexos A questão não é que esses números sejam universalmente corretos. Eles são limites iniciais intencionalmente modestos. O comportamento útil é que cada etapa precisa justificar os tokens que usa. Uma armadilha comum: se você definir apenas max_tokens para a saída, sua entrada ainda poderá crescer silenciosamente. Limites de saída impedem respostas longas; eles não impedem o excesso de conteúdo recuperado. ## Enxugue o contexto antes da recuperação, não depois Muitos sistemas recuperam documentos usando a mensagem mais recente do usuário, mas ainda incluem todo o histórico da conversa no prompt final. Isso significa que digressões antigas, chamadas de ferramentas anteriores que falharam e premissas desatualizadas permanecem no contexto. Em vez disso, mantenha um estado de trabalho compacto: ``` { "user_goal": "Get refund for duplicate annual subscription charge", "known_facts": [ "User paid twice on 2025-01-08", "Invoice IDs: inv_1042 and inv_1077", "Account email: user@example.com" ], "constraints": [ "Refund policy allows duplicate-charge refunds within 90 days", "User prefers email follow-up" ], "open_questions": [ "Whether one charge has already been reversed" ], "last_updated_turn": 12 } ``` Assim, sua chamada final inclui: - O estado compacto. - A mensagem mais recente do usuário. - Apenas trechos relevantes das políticas recuperadas. - Talvez a última interação ou as duas últimas, se a continuidade do tom for importante. Não inclua cegamente todas as mensagens anteriores. O histórico do chat não é memória; é uma transcrição. A memória é o estado essencial necessário para continuar a tarefa. Na prática, uso três camadas: - Interações recentes: últimas 1–4 interações, dependendo da sensibilidade da tarefa. - Resumo contínuo: fatos e decisões estáveis. - Recuperação externa: documentos, registros do banco de dados, saídas de ferramentas. Isso geralmente funciona melhor do que incluir a transcrição bruta inteira, porque o modelo recebe menos ruído e menos instruções conflitantes. ## A recuperação deve ser seletiva, não decorativa A geração aumentada por recuperação muitas vezes começa como uma melhoria de qualidade e se transforma em desperdício de tokens. O padrão de falha é fácil de identificar: top-k é definido como 10 ou 20, cada trecho tem 1,000 tokens e o prompt final contém uma pilha de documentos vagamente relacionados. Uma recuperação melhor geralmente é uma recuperação mais barata. Um pipeline prático de recuperação: ``` def build_context(query, user_state): search_query = rewrite_for_search(query, user_state) candidates = vector_search( query=search_query, top_k=30, filters={"product": user_state["product"]} ) reranked = rerank_cross_encoder( query=search_query, docs=candidates, top_k=6 ) selected = [] token_budget = 1800 for doc in reranked: snippet = extract_relevant_span(doc.text, query=search_query, max_tokens=300) if token_count(selected) + token_count(snippet) <= token_budget: selected.append({ "doc_id": doc.id, "title": doc.title, "text": snippet }) return selected ``` Os detalhes importantes: - Recupere mais candidatos do que pretende incluir. - Reordene os resultados por relevância antes da geração. - Extraia passagens relevantes em vez de enviar trechos inteiros. - Imponha um orçamento de tokens para a recuperação. - Mantenha os IDs dos documentos para que o modelo possa citar ou referenciar as evidências internamente. O tamanho dos trechos importa. Se forem pequenos demais, o modelo perde contexto. Se forem grandes demais, cada correspondência traz texto irrelevante junto. Para documentação de produtos e páginas de políticas, geralmente começo com cerca de 300–600 tokens por trecho, preservando os títulos, e depois ajusto com base nos casos de falha. O que realmente acontece quando você inclui contexto recuperado em excesso? O modelo frequentemente se torna menos preciso. Ele tenta conciliar políticas próximas, mas irrelevantes, incorpora ressalvas obsoletas ou responde à versão errada da pergunta. A redução de tokens pode melhorar a qualidade porque remove distrações. ## Resumir é comprimir com responsabilidade Resumir pode economizar enormes quantidades de contexto, mas resumos malfeitos são perigosos. Se um resumo omitir uma restrição, seu agente poderá fazer a coisa errada com confiança. Prefiro resumos estruturados a texto corrido: ``` { "task": "Debug failing OAuth callback in staging", "environment": { "service": "auth-api", "branch": "release-2025-02-14", "runtime": "node 20" }, "confirmed": [ "Callback returns 302 to /login", "Provider sends code and state", "State validation passes" ], "suspected": [ "Session cookie is not persisted after callback" ], "rejected": [ "Provider credentials are invalid", "Redirect URI mismatch" ], "next_steps": [ "Inspect Set-Cookie attributes in staging response", "Compare SameSite and Secure flags with production" ] } ``` Isso é mais eficiente no uso de tokens e mais confiável do que: O usuário está depurando o OAuth e já tentou várias coisas… Uma boa etapa de sumarização deve preservar: - O objetivo do usuário. - Os fatos concretos. - As decisões já tomadas. - As restrições e preferências. - As tentativas que falharam. - As questões em aberto. - IDs, nomes de arquivos, registros de data e hora e outros identificadores exatos. Não elimine valores exatos ao resumir, a menos que sejam realmente irrelevantes. “O usuário tem um problema com uma fatura” custa pouco, mas é inútil. “Cobrança duplicada: inv_1042 e inv_1077 em 2025-01-08” é o tipo de compactação que você quer. Para agentes de longa duração, também armazeno versões dos resumos. Se o modelo produzir um resumo ruim, você precisa conseguir inspecionar quando o estado começou a divergir. ## Evite saídas prolixas com esquemas Uma quantidade surpreendente do desperdício de tokens ocorre na saída. O prompt diz “seja conciso”, mas o modelo escreve uma introdução, ressalvas, uma recapitulação e uma oferta de ajuda. Para saídas consumidas por máquinas, use esquemas. Não peça simplesmente “uma resposta em JSON”; defina a estrutura e rejeite qualquer outra coisa. Exemplo de chamada de classificação: ``` { "type": "object", "additionalProperties": false, "required": ["category", "priority", "needs_human", "reason"], "properties": { "category": { "type": "string", "enum": ["billing", "bug", "account", "how_to", "other"] }, "priority": { "type": "string", "enum": ["low", "normal", "high", "urgent"] }, "needs_human": { "type": "boolean" }, "reason": { "type": "string", "maxLength": 160 } } } ``` Para respostas voltadas ao usuário, forneça um formato com um limite rígido: ``` Write the answer in this structure: - First sentence: direct answer, max 25 words. - Then 2-4 bullets with concrete steps. - Do not include a greeting. - Do not include "let me know if you need anything else." - Stop after the final bullet. ``` Isso funciona melhor do que “seja breve” porque dá ao modelo uma estrutura. Uma armadilha comum: um valor baixo de max_tokens pode truncar uma saída útil no meio de uma ideia. Um esquema ou formato restrito reduz o tamanho da saída sem comprometer sua completude. O truncamento é um último recurso, não uma estratégia de formatação. ## Use sequências de parada com cuidado Sequências de parada são úteis quando a conclusão tem um limite natural. Por exemplo, se o modelo estiver gerando uma seção de um documento baseado em um modelo, você pode interromper a geração no marcador da próxima seção. ``` { "model": "gpt-5.5", "messages": [ { "role": "user", "content": "Generate only the Risk Summary section for this review..." } ], "max_tokens": 500, "stop": ["\n## Mitigations", "\n## Appendix"] } ``` Sequências de parada são menos úteis em respostas abertas do assistente porque podem cortar conteúdo válido. Elas também se comportam de maneiras diferentes entre APIs e famílias de modelos, especialmente quando há chamadas de ferramentas ou saídas estruturadas. Trate-as como mecanismos de delimitação, não como uma técnica principal de compactação. Bons usos: - Gerar uma seção de um modelo de documento conhecido. - Impedir que o modelo continue gerando exemplos. - Parar em um delimitador durante o processamento em lote. - Restringir prompts legados no estilo de completamento. Usos arriscados: - Parar em sinais de pontuação comuns. - Parar em palavras que podem aparecer em respostas normais. - Usar sequências de parada em vez de um esquema de saída adequado. - Pressupor um comportamento idêntico entre Claude, GPT, Gemini e gateways de modelos abertos. ## Distribua tarefas entre modelos mais baratos Nem toda etapa precisa do seu modelo mais potente. Em sistemas de produção, costumo encaminhar subtarefas para modelos menores ou mais baratos: | Subtarefa | Requisito típico | Opção adequada | Detecção de idioma | Classificação simples | Modelo pequeno/barato | Categoria do chamado | Saída de rótulos estruturada | Modelo pequeno ou médio | Reescrita de consultas | Transformação curta | Modelo pequeno ou médio | Reclassificação de documentos | Reclassificador especializado ou modelo pequeno | Não generativo, quando possível | Resposta final | Raciocínio e tom | Modelo mais potente | Exceção à política | Nuances e risco | Modelo mais potente disponível É aqui que o acesso a vários modelos se torna útil operacionalmente. Você pode querer usar Sonnet 4.6 para a maior parte da escrita por agentes, GPT-5.5 para uma linha de raciocínio complexa, Gemini 3 para certos fluxos de trabalho multimodais ou de contexto longo, Fable 5 quando a janela de contexto de 1M for realmente necessária e modelos abertos como Llama, Qwen, DeepSeek, MiniMax ou Kimi para tarefas internas controladas. O ponto de engenharia é o roteamento, não a lealdade à marca. A limitação: a sobrecarga de orquestração é real. Cada chamada adicional a um modelo acrescenta latência, modos de falha, complexidade nos logs e mais aspectos a avaliar. Se um classificador barato economiza 300 tokens, mas acrescenta 600 ms e outro fluxo de novas tentativas, talvez não valha a pena. Um padrão de que gosto: ``` if route == "simple_faq": model = "haiku-4.5" elif route == "standard_support": model = "sonnet-4.6" elif route == "legal_or_financial_exception": model = "opus-4.8" else: model = "sonnet-4.6" ``` Os nomes exatos vão mudar. A política deve permanecer: use o modelo mais barato que atenda de forma confiável ao nível de qualidade exigido pela tarefa. ## Meça os tokens de entrada e saída com honestidade A otimização de tokens falha quando as equipes observam apenas o custo médio por solicitação. Você precisa de distribuições, detalhadas por rota e etapa. Acompanhe pelo menos: - Tokens de entrada por seção do prompt. - Tokens de saída. - Quantidade de documentos recuperados e tokens de recuperação. - Nome e versão do modelo. - Percentis de latência. - Taxa de acertos do cache, se estiver usando cache de prompts ou de contexto. - Quantidade de novas tentativas. - Indicadores de qualidade percebidos pelo usuário. - Taxas de encaminhamento para atendimento humano ou de correção humana. Um painel útil mostra p50, p90 e p99. Problemas no uso de tokens costumam se concentrar na cauda da distribuição. Exemplo de linha de log: ``` { "route": "support.draft_answer", "model": "sonnet-4.6", "input_tokens": 3820, "output_tokens": 514, "retrieved_docs": 4, "retrieval_tokens": 1320, "latency_ms": 3100, "cache_hit": false, "quality": { "user_thumb": "up", "human_edited": false } } ``` Tenha cuidado com afirmações como “reduzimos os tokens em 40%”. As novas tentativas aumentaram? Os encaminhamentos para atendimento humano aumentaram? Os usuários fizeram mais perguntas de acompanhamento porque as respostas ficaram sucintas demais? O modelo mais barato produziu mais JSON inválido, exigindo chamadas de correção? A métrica honesta não é tokens por chamada. É tokens por tarefa concluída com sucesso. ## Contexto longo não é permissão para ser preguiçoso Janelas de contexto grandes são realmente úteis. A classe de contexto de 1M do Fable 5, os pontos fortes do Gemini em contexto longo e os modos de contexto longo dos modelos de ponta viabilizam fluxos de trabalho que eram difíceis há alguns anos: análise de código em todo o repositório, revisão de documentos extensos, transcrições de várias horas e conjuntos densos de material de pesquisa. Mas contexto longo é uma capacidade, não uma arquitetura padrão. Chamadas com contexto longo podem ser apropriadas quando: - A resposta depende de muitas partes distantes da entrada. - A recuperação deixaria passar relações entre documentos. - A tarefa é exploratória e você ainda não sabe o que importa. - O custo de perder um detalhe é maior do que o custo de ler mais. Elas geralmente são um desperdício quando: - O usuário faz uma pergunta factual específica. - Alguns trechos das fontes são suficientes. - O contexto contém informações duplicadas ou obsoletas. - O modelo está sendo usado como filtro de banco de dados. Um padrão comum é usar contexto longo para análise offline e produzir artefatos compactos para uso online. Por exemplo, analise um corpus completo de políticas uma vez e depois gere um mapa estruturado das políticas, embeddings, resumos e casos de teste. O assistente em execução não deve reler todo o corpus a cada chamado. ## Um fluxo de trabalho prático de otimização Quando assumo um sistema de LLM que consome muitos tokens, geralmente faço o seguinte, nesta ordem: - Instrumente primeiro Adicione a contabilização de tokens por seção. Não otimize às cegas. - Limite o contexto recuperado Defina um limite rígido de tokens para recuperação. Reclassifique e extraia trechos. - Substitua o acúmulo de transcrições por um estado Mantenha as interações recentes junto com uma memória estruturada. - Restrinja as saídas Use esquemas para saídas destinadas a máquinas e formatos explícitos para saídas voltadas ao usuário. - Encaminhe subtarefas Transfira tarefas de classificação, reescrita e resumo para modelos mais baratos quando forem confiáveis. - Avalie a qualidade no nível da tarefa Compare resoluções bem-sucedidas, não apenas o custo por chamada. - Monitore a cauda da distribuição Investigue picos de tokens em p95 e p99. Eles costumam revelar falhas na recuperação de informações ou um histórico que cresce sem controle. Aqui está uma proteção simples que tenho usado em serviços: ``` TOKEN_LIMITS = { "support.classify": {"input": 800, "output": 80}, "support.retrieve": {"input": 500, "output": 0}, "support.draft": {"input": 4500, "output": 700}, "support.summarize": {"input": 1800, "output": 300}, } def assert_token_budget(route, prompt_sections, max_output_tokens): input_tokens = { name: count_tokens(text) for name, text in prompt_sections.items() } total_input = sum(input_tokens.values()) limits = TOKEN_LIMITS[route] if total_input > limits["input"]: raise TokenBudgetError(route, total_input, input_tokens) if max_output_tokens > limits["output"]: raise TokenBudgetError(route, max_output_tokens, {"output": max_output_tokens}) ``` Falhar rapidamente é melhor do que descobrir uma semana depois que uma consulta de recuperação mal formulada gastou seu orçamento com PDFs irrelevantes. ## Recomendações práticas - A redução de tokens deve começar pela visibilidade: registre os tokens de entrada e saída por seção do prompt, rota e modelo. - A recuperação de informações supera o acúmulo de conteúdo quando é seletiva: reordene por relevância, extraia trechos e imponha um orçamento de contexto. - Os resumos devem representar um estado estruturado, não ser textos vagos. Preserve fatos exatos, IDs, restrições e tentativas malsucedidas. - Esquemas de saída reduzem a prolixidade com mais segurança do que simplesmente diminuir max_tokens. - Sequências de parada são úteis para delimitar a saída, mas não substituem saídas estruturadas. - Encaminhe subtarefas simples para modelos mais baratos apenas quando a latência adicional e os modos de falha compensarem. - Avalie a economia pelos tokens por tarefa bem-sucedida, não pelos tokens por chamada individual. - Modelos de contexto longo são poderosos, mas não eliminam a necessidade de uma arquitetura da informação. [Inferência](/pt/blog/tag/inference/)[Prompts](/pt/blog/tag/prompts/)[Modelos](/pt/blog/tag/models/)[API](/pt/blog/tag/api/) A [AI Prime Tech](https://aiprimetech.io/pt/) A AI Prime Tech publica este blog. Os artigos são redigidos com assistência de IA; confira detalhes específicos de cada versão, como IDs de modelos, preços e limites, na documentação oficial antes de se basear neles. Obtenha acesso mais barato à API do Claude Uma única chave de API para Claude Opus 5.5, Sonnet 5, Haiku 4.5 e Fable 5.1, além de GPT-6 modelos. Pague conforme o uso, sem assinatura. [Obtenha Sua Chave de API →](/register) A AI Prime Tech é um gateway de API independente de terceiros. Claude™ e Anthropic® são marcas comerciais da Anthropic, PBC. Não há afiliação nem endosso implícitos.