📊IA

Guia Completo de Monitoramento de Tokens

Tokenização, custos, rate limits, prompt caching, observabilidade (LangSmith, Langfuse, Helicone).

Progresso
0%

O que são Tokens

Tokens são as unidades básicas que os LLMs usam para processar texto. Não são palavras, nem caracteres — são fragmentos subpalavra definidos pelo tokenizador do modelo (geralmente BPE — Byte Pair Encoding).

~4 chars por token (EN)

Regra de bolso para textos em inglês.

~3 chars por token (PT)

Português consome mais tokens que inglês — acentos e palavras compostas.

0.75 palavras por token

Aproximação média — útil para estimar custo de um corpus.

750 palavras ≈ 1.000 tokens

Uma página A4 tem cerca de 500 palavras, logo ~660 tokens.

Exemplos de Tokenização

"Hello world"          -> ["Hello", " world"]          = 2 tokens
"Tokenizacao"          -> ["Token", "iza", "cao"]       = 3 tokens
"def fibonacci(n):"    -> ["def", " fibonacci", "(n):", ""] = 4 tokens
"rocket"               -> [" rocket", " emoji", ...]    = 3-5 tokens

# Emojis e caracteres especiais custam mais tokens!

Input vs Output Tokens

  • Input tokens: Tudo que você envia — system prompt + histórico + nova mensagem + contexto RAG.
  • Output tokens: A resposta gerada. Geralmente 2-3x mais caros que input.
  • Cache tokens: Anthropic e OpenAI oferecem preços reduzidos para partes do prompt em cache.
Atenção: Em multiturno (chat), você reenvia TODO o histórico a cada mensagem. Com 10 turnos de 500 tokens cada, o 10º turno já envia 5.000 tokens de contexto antes da nova pergunta.

Como Contar Tokens

Contar tokens antes de enviar requisições permite estimar custo, respeitar limites e truncar contexto quando necessário.

Python — tiktoken (OpenAI/GPT)

import tiktoken

enc = tiktoken.encoding_for_model("gpt-4o")
text = "Ola mundo! Isso e um teste de tokenizacao."
tokens = enc.encode(text)
print(f"Tokens: {len(tokens)}")  # -> 12
print(f"Custo estimado input: ${len(tokens) * 0.0000025:.6f}")

# Para mensagens formatadas (inclui overhead de roles)
def count_chat_tokens(messages, model="gpt-4o"):
    enc = tiktoken.encoding_for_model(model)
    total = 0
    for msg in messages:
        total += 4  # overhead por mensagem
        total += len(enc.encode(msg["content"]))
    return total + 2  # overhead inicial

JavaScript — js-tiktoken

import { encodingForModel } from 'js-tiktoken';

const enc = encodingForModel('gpt-4o');
const tokens = enc.encode('Hello, world!');
console.log('Token count:', tokens.length);

// Para Anthropic - usar API de contagem
const { input_tokens } = await anthropic.messages.countTokens({
  model: 'claude-sonnet-4-6',
  system: systemPrompt,
  messages: messages
});

Estimativa Rápida Sem Biblioteca

// Regra de bolso: chars / 4 para ingles, chars / 3 para portugues
function estimateTokens(text: string, lang = 'pt'): number {
  const divisor = lang === 'en' ? 4 : 3;
  return Math.ceil(text.length / divisor);
}

// +/-20% de precisao - bom para estimativas rapidas

Custos por Plataforma

Os preços abaixo são referência (por 1M tokens). Consulte sempre a página oficial do provedor, pois mudam frequentemente.

ModeloInput ($/1M)Output ($/1M)Cache Read
Claude Opus 4.7$15$75$1.50
Claude Sonnet 4.6$3$15$0.30
Claude Haiku 4.5$0.80$4$0.08
GPT-4o$2.50$10$1.25
GPT-4o mini$0.15$0.60$0.075
o3$10$40$2.50
Gemini 2.5 Pro$1.25$10
Gemini 2.5 Flash$0.15$0.60

Calculando Custo Mensal

// Calculadora simples de custo
interface Usage { inputTokens: number; outputTokens: number }
interface Pricing { input: number; output: number } // por 1M tokens

function calcCost(usage: Usage, pricing: Pricing): number {
  return (usage.inputTokens / 1_000_000) * pricing.input
       + (usage.outputTokens / 1_000_000) * pricing.output;
}

// Exemplo: 1000 requisicoes/dia de 2k input + 500 output com Sonnet
const daily = calcCost(
  { inputTokens: 1000 * 2000, outputTokens: 1000 * 500 },
  { input: 3, output: 15 }
);
console.log(`Custo diario: $${daily.toFixed(2)}`); // -> $13.50
console.log(`Custo mensal: $${(daily * 30).toFixed(2)}`); // -> $405

Estratégias de Otimização

Reduzir tokens sem sacrificar qualidade é uma habilidade crítica em sistemas de IA de produção.

1. Prompt Compression

// Verboso (150 tokens)
"Por favor, analise cuidadosamente o seguinte codigo JavaScript que
foi enviado pelo usuario e forneca uma explicacao detalhada sobre o
que ele faz, incluindo possiveis problemas ou melhorias que possam
ser feitas para torna-lo mais eficiente e legivel."

// Conciso (45 tokens) - mesma instrucao
"Analise este codigo JS: explique o que faz, identifique problemas
e sugira melhorias de performance e legibilidade."

2. Prompt Caching

// Anthropic: marque partes estaticas do prompt para cache
const response = await anthropic.messages.create({
  model: 'claude-sonnet-4-6',
  system: [
    {
      type: 'text',
      text: longStaticSystemPrompt, // 10.000 tokens
      cache_control: { type: 'ephemeral' } // cacheia!
    }
  ],
  messages: userMessages
});
// Primeira req: cobra full. Seguintes: 90% desconto no system prompt.

3. Gerenciar Contexto em Chat

// Estrategia: sliding window com resumo
class ContextManager {
  private messages: Message[] = [];
  private maxTokens = 50_000;

  async add(msg: Message) {
    this.messages.push(msg);
    if (await this.countTokens() > this.maxTokens) {
      await this.compress();
    }
  }

  private async compress() {
    // Resumir as mensagens mais antigas em um bloco
    const oldest = this.messages.splice(0, 10);
    const summary = await summarize(oldest);
    this.messages.unshift({ role: 'system', content: '(Resumo: ' + summary + ')' });
  }
}

4. Structured Output

// Pedir JSON em vez de prosa reduz tokens da resposta
"Responda APENAS com JSON valido, sem explicacao:
{\"sentiment\": \"positive|negative|neutral\", \"confidence\": 0.0-1.0}"

// vs. pedir uma resposta em paragrafo que depois precisa ser parseada
RAG Optimization: Limite chunks a 512-800 tokens. Use MMR (Maximal Marginal Relevance) para evitar chunks repetitivos. Limite top-k a 3-5 documentos para não inflar o contexto.

Ferramentas de Observabilidade

Observabilidade em IA vai além de logs — inclui tracing de chamadas, análise de qualidade e alertas de custo.

LangSmith

Da LangChain. Tracing completo, avaliação automática, dataset management. Melhor para projetos LangChain/LangGraph.

Helicone

Proxy transparente. Não muda código — só troca a base URL. Analytics, rate limiting, cache, retry automático.

Langfuse

Open-source. Auto-hostável. Tracing, feedback, scores, prompts versionados. Ótima alternativa a LangSmith.

Braintrust

Focado em avaliação e evals. Compara versões de prompts com dados reais. Excelente para prompt engineering.

OpenTelemetry + OTLP

Padrão aberto. Integra com Grafana, Datadog, etc. Bom se já tem stack de observabilidade.

Portkey

Gateway de IA com observabilidade, rate limiting, fallbacks e cache semântico.

Exemplo: Integração com Langfuse

import Anthropic from '@anthropic-ai/sdk';
import { Langfuse } from 'langfuse';

const langfuse = new Langfuse({
  publicKey: process.env.LANGFUSE_PUBLIC_KEY,
  secretKey: process.env.LANGFUSE_SECRET_KEY
});

async function chat(userMessage: string) {
  const trace = langfuse.trace({ name: 'chat', userId: 'user-123' });
  const span = trace.span({ name: 'llm-call' });

  const response = await anthropic.messages.create({
    model: 'claude-sonnet-4-6',
    max_tokens: 1024,
    messages: [{ role: 'user', content: userMessage }]
  });

  span.end({
    output: response.content[0].text,
    usage: {
      input: response.usage.input_tokens,
      output: response.usage.output_tokens
    }
  });

  await langfuse.flushAsync();
  return response.content[0].text;
}

Exemplo: Helicone (zero código)

// Apenas mude a base URL!
const anthropic = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY,
  baseURL: 'https://anthropic.helicone.ai',
  defaultHeaders: {
    'Helicone-Auth': `Bearer ${process.env.HELICONE_API_KEY}`
  }
});
// Pronto - 100% das chamadas sao monitoradas automaticamente

Rate Limits e Quotas

Todos os provedores impõem limites de requisições e tokens por minuto/dia. Gerenciar bem esses limites é essencial para aplicações de produção.

Limites Comuns (Anthropic — Tier 1)

RPM

Requests per minute. Geralmente 50-1000 dependendo do tier e modelo.

TPM

Tokens per minute. Input + output. Ex: 40k TPM para Sonnet no tier 1.

TPD

Tokens per day. Limite diário acumulado. Reset a meia-noite UTC.

Retry com Exponential Backoff

async function callWithRetry<T>(
  fn: () => Promise<T>,
  maxRetries = 5
): Promise<T> {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (e: any) {
      if (e.status === 429) { // Rate limit
        const delay = Math.min(1000 * 2 ** i + Math.random() * 1000, 60000);
        console.log(`Rate limited. Aguardando ${delay}ms...`);
        await new Promise(r => setTimeout(r, delay));
        continue;
      }
      throw e; // Outros erros: nao retenta
    }
  }
  throw new Error('Max retries exceeded');
}
SDKs oficiais da OpenAI e Anthropic já incluem retry automático com backoff. Configure maxRetries na instanciação do cliente.

Cache Semântico

Cache semântico armazena respostas de queries similares (não apenas idênticas) e as reutiliza, reduzindo drasticamente custos e latência.

import { Redis } from 'ioredis';
import { cosineSimilarity } from './utils';

class SemanticCache {
  private redis: Redis;
  private threshold = 0.95; // similaridade minima

  async get(query: string): Promise<string | null> {
    const queryEmbedding = await embed(query);
    const keys = await this.redis.keys('cache:*');

    for (const key of keys) {
      const cached = JSON.parse(await this.redis.get(key)!);
      const sim = cosineSimilarity(queryEmbedding, cached.embedding);
      if (sim >= this.threshold) {
        console.log(`Cache hit! Similaridade: ${sim.toFixed(3)}`);
        return cached.response;
      }
    }
    return null;
  }

  async set(query: string, response: string, ttl = 3600) {
    const embedding = await embed(query);
    const key = `cache:${Date.now()}`;
    await this.redis.setex(key, ttl, JSON.stringify({ embedding, response }));
  }
}

Ferramentas de Cache Semântico Prontas

  • GPTCache: Biblioteca Python com múltiplos backends (Redis, Milvus, FAISS).
  • Portkey AI: Cache semântico como serviço, transparente na API.
  • Prompt Cache (Anthropic/OpenAI): Cache nativo para system prompts longos.

Alertas e Dashboards

Configure alertas proativos antes que custos ou erros surpreendam em produção.

// Middleware de tracking de tokens por usuario/feature
import { EventEmitter } from 'events';

const tokenTracker = new EventEmitter();

interface TokenEvent {
  userId: string;
  feature: string;
  model: string;
  inputTokens: number;
  outputTokens: number;
  cost: number;
}

async function trackUsage(event: TokenEvent) {
  // Persiste no banco
  await db.tokenUsage.create({ data: event });

  // Acumula por usuario no Redis (janela de 30 dias)
  const key = `usage:${event.userId}:${new Date().toISOString().slice(0,7)}`;
  await redis.incrbyfloat(key, event.cost);
  await redis.expire(key, 60 * 60 * 24 * 35);

  // Alerta se usuario passou de $10 no mes
  const monthCost = await redis.get(key);
  if (parseFloat(monthCost!) > 10) {
    await sendAlert(`Usuario ${event.userId} passou $10 este mes`);
  }
}

Métricas Importantes para Monitorar

  • Cost per request: Média e p95 de custo por chamada.
  • Tokens per feature: Qual feature consome mais tokens.
  • Cache hit rate: Percentual de chamadas servidas do cache.
  • Error rate 429: Frequência de rate limit errors.
  • Latency p50/p95/p99: Latência de ponta a ponta.
  • Daily/monthly spend: Gasto total com alertas de threshold.
Budget Alerts: Configure billing alerts no console de cada provedor (OpenAI, Anthropic, Google). Defina alertas em 50%, 80% e 100% do budget mensal.
Modelos de IA← Todos os treinamentos