Engenharia de contexto sem cálculo de custo é wishful thinking. Cada provedor tem um tokenizer próprio, cada modelo tem um preço diferente, e a diferença entre frontier e low-cost pode ser de 50× no custo por 1M tokens. Aqui você aprende a estimar antes de pagar — e a escolher o modelo certo para a tarefa.
🧮 Estimar custo ANTES de chamar
Use o tokenizer offline do provedor para calcular tokens de uma chamada antes de mandar. Custos não-triviais devem ser orçados, não chutados.
- •Anthropic:
client.messages.count_tokens()ou Anthropic Tokenizer. - •OpenAI: biblioteca
tiktokenroda local sem chamar API. - •Google:
model.count_tokens()também local. - •OSS: tokenizer do HuggingFace (
AutoTokenizer.from_pretrained).
📊 Comparação real de custo (2026-Q2, ordens de grandeza)
- Frontier (ex: Claude Sonnet 4.6): ~$3 input / $15 output por 1M tokens.
- Low-cost (ex: GPT-5 mini): ~$0.15 input / $0.60 output por 1M tokens.
- Cache hit (Anthropic): 10% do preço normal — economiza 90%.
- OSS local (qwen2.5-7b): $0 por chamada (custo de hardware amortizado).
💡 Regra dos 80%
Se a tarefa é estruturada (classificação, extração) E o input cabe em <8k tokens, low-cost ou OSS resolvem 80% dos casos com 1/20 do custo. Só vá para frontier quando precisar do reasoning.
🔤 Tokenização: BPE e SentencePiece
Por que tokens ≠ palavras
BPE (Byte-Pair Encoding) e SentencePiece aprendem um vocabulário sub-palavra otimizando frequência. A consequência é que palavras comuns viram 1 token, mas palavras raras ou em outras línguas se quebram em vários. Em PT-BR, a média gira em torno de ~3 caracteres por token com tokenizers focados em inglês — pior que os ~4 chars/token do inglês. Em código, símbolos e indentação geram custos imprevisíveis. Por isso, estimar com tokenizer real é a única forma confiável.
# Anthropic
from anthropic import Anthropic
n = Anthropic().messages.count_tokens(model='claude-sonnet-4-6',
messages=[{'role':'user','content': texto}]).input_tokens
# OpenAI
import tiktoken
enc = tiktoken.encoding_for_model('gpt-5-mini')
n = len(enc.encode(texto))
# HuggingFace (modelos OSS)
from transformers import AutoTokenizer
tok = AutoTokenizer.from_pretrained('Qwen/Qwen2.5-7B-Instruct')
n = len(tok.encode(texto))
📑 Resumo navegável
💰 Custo: input vs. output (cuidado com a ratio)
Output é caro mas input é volume
Output tokens custam tipicamente 3-5× o preço dos input tokens — em alguns provedores até 10×. Mas o input total normalmente é MUITO maior (5k-50k tokens de contexto vs 200-500 tokens de saída). Resultado: em janelas longas, o input domina o custo. Otimizar o tamanho da resposta sem reduzir o input é trocar troco por nota.
| Modelo | Input (10M tokens) | Output (200k tokens) | Total |
|---|---|---|---|
| Frontier (~$3 in / $15 out por M) | $30.00 | $3.00 | $33.00 |
| Low-cost (~$0.15 in / $0.60 out) | $1.50 | $0.12 | $1.62 |
| Frontier + cache 80% hit | $6.00 | $3.00 | $9.00 |
| OSS local (Qwen2.5-7B) | — | — | $0.00 + hardware |
📑 Resumo navegável
🏗️ Os três níveis de modelo
Frontier, low-cost, OSS local
Engenheiros frequentemente jogam todas as tarefas em 'frontier' por inércia. Em volume alto, isso queima orçamento. A heurística: tarefas estruturadas (classificação, extração de entidades, sumarização curta) com input <8k tokens rodam tão bem em low-cost por 1/20 do preço. Frontier vale quando há raciocínio multi-passo, contexto realmente grande, ou qualidade de prosa importa. OSS local é o caminho quando privacidade é restritiva ou volume é tão alto que API paga não escala.
regra rápida de roteamento por tarefa
- ▸Classificação binária / multi-classe → low-cost ou OSS
- ▸Extração de entidades / structured output → low-cost
- ▸Sumarização <500 palavras → low-cost (input médio) ou frontier (qualidade crítica)
- ▸Raciocínio multi-passo / código complexo → frontier
- ▸Pipeline com 10k+ chamadas/dia em PII → OSS local
📑 Resumo navegável
⏱️ Latência: prefill vs. decode
TTFT em janelas longas
Quando o usuário pergunta algo, o modelo precisa primeiro ler toda a janela (prefill) antes de gerar o primeiro token. Em uma janela de 100k tokens, isso pode levar 1-3 segundos só de prefill. Decode (geração) é mais rápido — ~30-100 tokens/s. Para UX de chat ao vivo, TTFT (time-to-first-token) é o que o usuário sente. Cache reduz prefill drasticamente: se 90% do prefixo está cacheado, o TTFT pode cair de 2s para 200ms.
| Input tokens | Sem cache | Com cache 80% hit | Decode 200 tokens |
|---|---|---|---|
| 1k | ~150ms | ~80ms | ~2s |
| 10k | ~500ms | ~150ms | ~2s |
| 50k | ~1.5s | ~400ms | ~2s |
| 100k | ~3s | ~700ms | ~2s |
📑 Resumo navegável
🔁 Prompt caching: como obter desconto real
10% do preço para tokens cacheados
Prompt caching marca um ponto do prefixo como cacheável. Tokens lidos do cache custam ~10% do preço de input normal. Em chats com system prompt + few-shot fixos (5-10k tokens estáveis), o ganho real é de 80-90% no custo do input. Mas o cache só vale se o prefixo NÃO MUDAR entre chamadas — qualquer alteração invalida tudo daquele ponto em diante. TTL é curto (5 min na Anthropic), então chamadas espaçadas perdem o benefício.
resp = client.messages.create(
model='claude-sonnet-4-6',
system=[
{'type':'text', 'text': system_grande, # 5k tokens
'cache_control': {'type':'ephemeral'}} # cacheia até aqui
],
messages=[{'role':'user', 'content': pergunta}],
)
# resp.usage:
# input_tokens, cache_creation_input_tokens, cache_read_input_tokens
hit_rate = resp.usage.cache_read_input_tokens / (
resp.usage.cache_read_input_tokens + resp.usage.cache_creation_input_tokens)
📑 Resumo navegável
🆓 OSS local: a matriz de hardware
O que cabe na sua máquina
Modelos OSS com 7-13B parâmetros em quantização q4 (4 bits por peso) cabem em hardware comum. Qwen2.5-7B-Instruct q4 roda em 16GB de RAM SEM GPU (CPU lento, mas funcional); com GPU 8GB acelera 5-10×. Modelos >13B exigem GPU 24GB+ ou quantização mais agressiva (q3) que degrada qualidade. OLLAMA-MATRIZ.md tem a matriz testada por lab do curso.
| Modelo | RAM mín | GPU recomendada | Throughput |
|---|---|---|---|
| Qwen2.5-7B-Instruct q4 | 16GB | opcional (8GB acelera) | ~20 tok/s CPU, ~80 tok/s GPU |
| Llama-3.1-8B-Instruct q4 | 16GB | opcional | ~15 tok/s CPU, ~70 tok/s GPU |
| Mistral-7B-Instruct q4 | 16GB | opcional | ~25 tok/s CPU, ~90 tok/s GPU |
| Llama-3.1-70B q4 | 48GB OU GPU 24GB | GPU 24GB obrigatória | ~5 tok/s GPU |
📑 Resumo navegável
OLLAMA-MATRIZ.md.📑 Resumo navegável dos tópicos
1 🔤 Tokenização: BPE e SentencePiece — Por que tokens ≠ palavras
2 💰 Custo: input vs. output (cuidado com a ratio) — Output é caro mas input é volume
3 🏗️ Os três níveis de modelo — Frontier, low-cost, OSS local
4 ⏱️ Latência: prefill vs. decode — TTFT em janelas longas
5 🔁 Prompt caching: como obter desconto real — 10% do preço para tokens cacheados
6 🆓 OSS local: a matriz de hardware — O que cabe na sua máquina
OLLAMA-MATRIZ.md.✓ O que FAZER
- ✓Estimar tokens com tokenizer offline antes de mandar
- ✓Usar low-cost para tarefas estruturadas em volume
- ✓Habilitar prompt caching em chats com prefixo grande
- ✓Pinar versão exata do modelo (com data)
✗ O que NÃO fazer
- ✗Chutar 'mais ou menos' o tamanho da janela
- ✗Mandar tudo para frontier por inércia
- ✗Reescrever o system prompt a cada turn (invalida cache)
- ✗Apontar para apelido genérico que pode mudar
🚫 Quando NÃO usar
- •Quando a chamada é única ou rara: custo total é trivial; gaste seu tempo em qualidade, não em centavos.
- •Em prototipagem inicial: use frontier para estabelecer o teto de qualidade; otimize depois.
- •Quando otimização frita qualidade: trocar frontier por low-cost que cai groundedness em 20% NÃO é economia.
- •Quando privacidade exige local: custo deixa de ser o critério; OSS é a única opção.
💻 Exemplo de código
from fec_sdk import check_compat
check_compat("modulo-1-2", expected_sdk_version=">=1.0,<2.0")
# Estimativa local — sem chamar API
system_prompt = "Você é um assistente conciso."
user_query = "Resuma este texto em 3 bullets."
contexto = open("documento.txt").read()
# PT-BR: ~3 chars/token (use tokenizer real do provedor para precisão)
tokens_input = (len(system_prompt) + len(user_query) + len(contexto)) // 3
tokens_output = 200 # estimativa do tamanho da resposta
# Frontier hipotético
custo_frontier = tokens_input * 3.00 / 1_000_000 + tokens_output * 15.00 / 1_000_000
# Low-cost
custo_low_cost = tokens_input * 0.15 / 1_000_000 + tokens_output * 0.60 / 1_000_000
print(f"Frontier: ${custo_frontier:.4f} | Low-cost: ${custo_low_cost:.4f}")
🏋️ Exercício hands-on
Em exercicios/modulo-1-2/: dado um conjunto de chamadas LLM, decida qual modelo (frontier/low-cost/OSS) usar para minimizar custo mantendo qualidade. Teste em pytest exercicios/modulo-1-2/test.py.
📚 Bibliografia
- Sennrich et al. (2016) — Neural Machine Translation of Rare Words with Subword Units (BPE)
- Kudo & Richardson (2018) — SentencePiece: simple subword tokenizer
- Hsieh et al. (2024) — RULER: long-context benchmark
- Anthropic (2024) — Prompt caching with Claude
🎯 Resumo do Módulo
- ✓Tokens não são palavras — use tokenizer do provedor para estimativa.
- ✓Output 3-5× mais caro que input, mas input domina em janelas longas.
- ✓Três níveis de modelo: frontier, low-cost, OSS — cada um para um caso.
- ✓Prompt caching reduz input cacheado para 10% do preço.
- ✓OSS local é viável para muitos labs do curso (ver OLLAMA-MATRIZ.md).
Próximo Módulo:
T2 — Engenharia da Mensagem