Engenharia de LLMs, da atenção à produção
Uma apostila para quem já programa e quer dominar modelos de linguagem em profundidade: a matemática da atenção, o ciclo de vida de um LLM, recuperação vetorial, RAG de ponta e tudo que separa um protótipo de um sistema em produção — com foco direto no mercado de Engenharia de IA.
Fundamentos: como máquinas representam linguagem
Antes da arquitetura, o insumo. Este capítulo estabelece o vocabulário que todo o resto assume: tokens, embeddings, o problema que as RNNs não resolveram e a ideia que mudou tudo.
1.1 Tokens: a unidade atômica
Um LLM não lê texto — lê uma sequência de inteiros. A tokenização converte texto em unidades de um vocabulário fixo (tipicamente 32k–256k entradas). O algoritmo dominante é o BPE (Byte-Pair Encoding): parte-se de bytes individuais e, iterativamente, funde-se o par de símbolos adjacentes mais frequente no corpus, criando novos tokens até atingir o tamanho de vocabulário desejado.
- byte-level BPE (GPT-2 em diante): opera sobre bytes UTF-8, então qualquer string é tokenizável — não existe token desconhecido.
- SentencePiece/Unigram (Llama, Gemma): trata o texto como stream bruto e aprende um vocabulário por máxima verossimilhança, removendo tokens que menos contribuem.
- Palavras comuns viram 1 token; palavras raras ou em português frequentemente viram 2–4 tokens. Isso tem consequência direta em custo (APIs cobram por token) e em desempenho (línguas sub-representadas gastam mais tokens pelo mesmo conteúdo).
Muitos bugs "misteriosos" de LLM são tokenização: aritmética falha porque números são fatiados de forma inconsistente; strings com espaços à esquerda tokenizam diferente de sem espaço (" casa" ≠ "casa"); limites de contexto e custos de API são medidos em tokens, não caracteres. Use tiktoken (OpenAI) ou tokenizers (Hugging Face) para inspecionar antes de otimizar.
1.2 Embeddings: significado como geometria
Cada token do vocabulário é associado a um vetor denso em ℝd (d tipicamente 768–16384), armazenado numa matriz de embedding E ∈ ℝ^{V×d} aprendida junto com o modelo. A intuição central, herdada do word2vec (2013), é a hipótese distribucional: palavras que ocorrem em contextos parecidos ganham vetores próximos. A geometria do espaço passa a codificar semântica — proximidade é similaridade, e direções podem codificar relações.
A diferença crucial dos embeddings modernos: word2vec dava um vetor por palavra ("banco" de sentar e "banco" financeiro colidiam). Um Transformer produz embeddings contextuais: o vetor de "banco" na camada 20 depende de toda a frase ao redor. É essa contextualização progressiva, camada a camada, que a atenção implementa — e é ela que reaparece no Capítulo 4 como base das buscas vetoriais.
1.3 De RNNs à atenção: o problema e a virada
Até 2017, sequências eram processadas por RNNs/LSTMs: um estado oculto h_t atualizado token a token. Dois defeitos estruturais:
- Gargalo sequencial — h_t depende de h_{t-1}; impossível paralelizar no tempo. Treinar em corpora de trilhões de tokens era inviável.
- Memória comprimida — toda a história precisa caber num vetor de tamanho fixo; dependências longas se degradam (gradientes que somem/explodem, mitigados mas não resolvidos por gates).
O mecanismo de atenção surgiu primeiro como remendo para tradução (Bahdanau, 2014): em vez de comprimir a frase-fonte num vetor, o decoder "olha" para todos os estados do encoder com pesos aprendidos. O paper "Attention Is All You Need" (Vaswani et al., 2017) fez a pergunta radical: e se removêssemos a recorrência e ficássemos só com atenção? O resultado — o Transformer — trocou profundidade temporal por largura paralela: todos os tokens são processados simultaneamente, e a comunicação entre posições acontece via atenção. Isso casou perfeitamente com GPUs e destravou a era do scaling.
Em entrevistas de Engenheiro de IA, "por que Transformers substituíram RNNs?" é pergunta de aquecimento. A resposta forte tem três pontos: paralelização total no treino (uma multiplicação de matrizes vs. um loop), caminho de gradiente O(1) entre quaisquer posições (vs. O(n) na RNN) e escalabilidade empírica (scaling laws, Cap. 3). Cite o trade-off: atenção custa O(n²) na sequência, o que motiva metade das inovações do Capítulo 2.
A arquitetura Transformer em profundidade
O coração da apostila. Aqui você deriva a atenção da intuição à fórmula, entende cada componente do bloco moderno (RMSNorm, SwiGLU, RoPE, GQA), as otimizações que tornam a inferência viável (KV cache, FlashAttention, MLA) e implementa um GPT funcional do zero.
2.1 Self-attention: derivando a fórmula
A pergunta que a atenção responde: para atualizar a representação do token i, quanta informação buscar de cada token j? A solução é um mecanismo de recuperação suave (soft lookup) com três projeções lineares aprendidas por token:
- Query (Q) — "o que estou procurando": q_i = x_i W_Q
- Key (K) — "o que eu ofereço como índice": k_j = x_j W_K
- Value (V) — "o conteúdo que entrego se for selecionado": v_j = x_j W_V
A afinidade entre a posição i e a posição j é o produto escalar q_i · k_j. Normalizamos as afinidades de cada query com softmax, obtendo uma distribuição de probabilidade sobre as posições, e usamos esses pesos para fazer uma média ponderada dos values:
Por que dividir por √d_k? Se as componentes de q e k são i.i.d. com média 0 e variância 1, então Var(q·k) = d_k. Com d_k = 128, os logits teriam desvio-padrão ~11 — o softmax saturaria em quase one-hot, e os gradientes através dele desapareceriam. Dividir por √d_k devolve variância 1 aos logits e mantém o softmax numa região "macia" e treinável. É o tipo de detalhe que separa quem decorou a fórmula de quem a entende.
Máscara causal. Em modelos autorregressivos (GPT-like), o token i não pode ver o futuro. Antes do softmax, soma-se −∞ nas posições j > i, zerando esses pesos. Encoders bidirecionais (BERT, e a maioria dos modelos de embedding do Cap. 4) não usam máscara causal — cada token vê a frase inteira.
Cada camada de atenção computa, para cada token, uma combinação convexa dos values — a saída vive no fecho convexo dos v_j. A atenção move informação entre posições (mixing no eixo da sequência); a FFN que vem depois processa informação dentro de cada posição (mixing no eixo dos canais). Essa divisão de trabalho — comunicação vs. computação — é o jeito mais útil de pensar o Transformer, e é a base da literatura de interpretabilidade (circuits, induction heads).
2.2 Multi-Head Attention — e suas descendentes MQA, GQA e MLA
Uma única atenção força o modelo a resumir todos os tipos de relação (sintaxe, correferência, posição, semântica) numa distribuição só. Multi-Head Attention (MHA) divide o espaço em h cabeças de dimensão d_k = d/h; cada cabeça tem suas próprias W_Q, W_K, W_V, atende de forma independente e as saídas são concatenadas e projetadas por W_O:
Na inferência, porém, MHA tem um custo escondido: o KV cache (seção 2.5) guarda K e V de todas as cabeças para todos os tokens — e memória de cache é o gargalo real de serving. Daí a linhagem de otimizações:
| Variante | Ideia | KV cache | Quem usa |
|---|---|---|---|
| MHA | h cabeças completas de Q, K e V | 2·n·h·d_k por camada | GPT-2/3, BERT |
| MQA (Multi-Query) | h queries, mas uma única cabeça de K/V compartilhada | ÷h (enorme economia, alguma perda de qualidade) | PaLM, Falcon |
| GQA (Grouped-Query) | g grupos de K/V (1 < g < h); meio-termo | ÷(h/g), qualidade ≈ MHA | Llama 2/3, Mistral, Qwen — o padrão atual |
| MLA (Multi-head Latent) | comprime K/V num vetor latente de baixo posto; descomprime on-the-fly | ~1/10 do MHA com qualidade igual ou melhor | DeepSeek-V2/V3/R1 |
MLA merece atenção especial por ser o estado da arte em eficiência: em vez de cachear K e V, cacheia-se apenas uma projeção latente c_t = x_t W_DKV de dimensão pequena (ex.: 512), e K/V são reconstruídos por up-projections absorvíveis nas matrizes de Q e O. Foi uma das chaves para o DeepSeek treinar e servir modelos de fronteira a custo radicalmente menor.
2.3 Posição: de senos e cossenos ao RoPE
A atenção é permutation-equivariant: sem informação posicional, "cão morde homem" e "homem morde cão" seriam idênticos. Soluções, em ordem histórica:
- Sinusoidal (Transformer original): soma-se ao embedding um vetor fixo de senos/cossenos em frequências geométricas. Simples, mas posição vira "ruído aditivo" no conteúdo.
- Embeddings posicionais aprendidos (GPT-2, BERT): uma linha de tabela por posição. Não extrapola além do contexto de treino.
- ALiBi: sem embedding; penaliza logits de atenção linearmente pela distância |i−j|. Extrapola bem; usado no MPT e BLOOM.
- RoPE (Rotary Position Embedding) — o padrão moderno (Llama, Qwen, Mistral, DeepSeek, Gemma).
A ideia do RoPE: em vez de somar posição ao conteúdo, rotacionar os vetores q e k. Divide-se o vetor em pares de dimensões; cada par (2t, 2t+1) é tratado como um número complexo e rotacionado por um ângulo proporcional à posição m, com frequência θ_t = base^{−2t/d} (base tipicamente 10.000 a 1M):
A mágica: como rotações preservam norma e o produto interno de dois vetores rotacionados depende só da diferença dos ângulos, o score de atenção passa a codificar posição relativa automaticamente — sem parâmetros extras, aplicado dentro de cada camada. Dimensões de alta frequência distinguem vizinhos imediatos; as de baixa frequência, distâncias longas.
RoPE treinado até 8k degrada além disso — as rotações extrapolam para ângulos nunca vistos. As técnicas de extensão manipulam as frequências: Position Interpolation comprime as posições (m → m/s); NTK-aware scaling aumenta a base θ para esticar só as baixas frequências; YaRN combina interpolação por faixa de frequência com um ajuste de temperatura na atenção, e é o método usado em vários modelos de contexto longo. Na prática de mercado: contexto longo ≠ atenção uniforme — avalie sempre com testes tipo needle-in-a-haystack e atenção ao fenômeno de lost in the middle.
2.4 O bloco Transformer moderno, peça por peça
Um decoder block de 2026 (Llama 3, Qwen 3, DeepSeek-V3) difere do paper de 2017 em quase todos os detalhes. A receita atual:
# Pseudocódigo do bloco moderno (pre-norm)
x = x + Attention( RMSNorm(x) ) # GQA/MLA + RoPE, com máscara causal
x = x + SwiGLU( RMSNorm(x) ) # FFN gated, d_ff ≈ 2.7·d
- Pre-norm em vez de post-norm. Normalizar antes de cada sub-camada (e não depois da soma residual) cria um "fluxo residual" limpo da entrada à saída — gradientes fluem sem atravessar normalizações, permitindo treinar centenas de camadas sem warm-up delicado.
- RMSNorm em vez de LayerNorm. Remove a centralização pela média e o bias; apenas reescala pela raiz da média dos quadrados: x̂ = x / RMS(x) · g. Mais barato, igualmente estável.
- SwiGLU em vez de ReLU/GELU. A FFN vira uma unidade com gate: FFN(x) = (Swish(xW_gate) ⊙ xW_up) W_down. O gate multiplicativo dá à rede um mecanismo de seleção de features; empiricamente melhora perplexidade de forma consistente.
- Sem biases nas projeções lineares (estabilidade e menos parâmetros); weight tying entre a matriz de embedding e a cabeça de saída em modelos menores.
- A FFN concentra ~2/3 dos parâmetros do modelo. A literatura de interpretabilidade a descreve como memória associativa chave-valor — onde grande parte do "conhecimento factual" reside.
2.5 Inferência autorregressiva: KV cache e FlashAttention
Gerar texto é um loop: prever a distribuição do próximo token, amostrar, anexar, repetir. Recalcular a atenção de toda a sequência a cada passo custaria O(n²) por token. O KV cache resolve: como K e V dos tokens passados não mudam (a máscara é causal), guardamo-los; a cada passo novo, computa-se apenas q, k, v do token atual e atende-se contra o cache.
Ex.: Llama-3-70B, 8k tokens, FP16 ≈ 2·80·8·128·8192·2 ≈ 2.7 GB por requisição
Duas consequências de engenharia que caem em entrevista:
- Prefill vs. decode. O processamento do prompt (prefill) é paralelo e compute-bound; a geração token a token (decode) é memory-bandwidth-bound — o tempo é dominado por ler os pesos e o KV cache da HBM. Por isso batching agressivo (continuous batching, vLLM) multiplica o throughput: dilui a leitura dos pesos entre várias sequências.
- PagedAttention (vLLM). Alocar cache contíguo por requisição fragmenta memória. O vLLM gerencia o KV cache como memória virtual de SO: blocos (pages) de tamanho fixo, tabela de páginas por sequência, compartilhamento copy-on-write entre requisições com prefixo comum (prefix caching). Resultado: 2–4× mais throughput.
FlashAttention ataca o outro gargalo: a matriz de atenção n×n nunca deveria materializar na HBM. O kernel computa a atenção em tiles que cabem na SRAM do chip, usando online softmax (mantém máximo corrente e soma corrente, reescalando parcialmente) para nunca precisar da matriz inteira. Memória cai de O(n²) para O(n), e a parede de banda é evitada. FlashAttention-2/3 refinam paralelismo e uso de FP8 em Hopper. É exemplo canônico de hardware-aware algorithm — e resposta pronta para "como você faria atenção escalar em contexto longo?".
2.6 Mixture of Experts (MoE): parâmetros ≠ FLOPs
Em modelos densos, todo token ativa todos os pesos. Um MoE substitui a FFN de cada bloco por E experts (FFNs independentes) e um router aprendido que escolhe o top-k (tipicamente k=1–8) para cada token:
- Desacopla capacidade de custo: DeepSeek-V3 tem 671B parâmetros, mas ativa ~37B por token. Qwen3-MoE, Mixtral, GPT-4 (reportadamente) e a maioria dos modelos de fronteira atuais seguem o padrão.
- Desafios reais: balanceamento de carga entre experts (auxiliary losses ou, no DeepSeek-V3, estratégia loss-free com bias ajustável por expert), custo de comunicação all-to-all em treino distribuído, e maior pegada de memória no serving (todos os experts residem na GPU mesmo que poucos ativem).
- Tendências: experts finos e numerosos + shared experts sempre ativos (DeepSeek), roteamento por sequência vs. por token, e MoE também na atenção (mais raro).
2.7 Implementação: um GPT mínimo e moderno em PyTorch
O código abaixo implementa um decoder-only com as escolhas modernas (RMSNorm, RoPE, GQA, SwiGLU, pre-norm, KV cache). É pequeno o bastante para treinar em um corpus de brinquedo e fiel o bastante para servir de base de estudo séria — digno de repositório de portfólio.
import math, torch
import torch.nn as nn
import torch.nn.functional as F
class RMSNorm(nn.Module):
def __init__(self, d, eps=1e-5):
super().__init__(); self.g = nn.Parameter(torch.ones(d)); self.eps = eps
def forward(self, x):
return x * torch.rsqrt(x.pow(2).mean(-1, keepdim=True) + self.eps) * self.g
def rope_freqs(d_head, max_len, base=10_000.0, device="cpu"):
inv = 1.0 / (base ** (torch.arange(0, d_head, 2, device=device) / d_head))
t = torch.arange(max_len, device=device)
ang = torch.outer(t, inv) # (max_len, d_head/2)
return torch.polar(torch.ones_like(ang), ang) # e^{i·mθ}
def apply_rope(x, freqs): # x: (B, n_heads, T, d_head)
xc = torch.view_as_complex(x.float().reshape(*x.shape[:-1], -1, 2))
out = torch.view_as_real(xc * freqs[None, None, :xc.shape[2]])
return out.reshape(*x.shape).type_as(x)
class GQAttention(nn.Module):
def __init__(self, d, n_heads=8, n_kv_heads=2):
super().__init__()
self.nh, self.nkv, self.dh = n_heads, n_kv_heads, d // n_heads
self.wq = nn.Linear(d, n_heads * self.dh, bias=False)
self.wk = nn.Linear(d, n_kv_heads* self.dh, bias=False)
self.wv = nn.Linear(d, n_kv_heads* self.dh, bias=False)
self.wo = nn.Linear(d, d, bias=False)
self.cache_k = self.cache_v = None # KV cache p/ inferência
def forward(self, x, freqs, use_cache=False):
B, T, _ = x.shape
q = self.wq(x).view(B, T, self.nh, self.dh).transpose(1, 2)
k = self.wk(x).view(B, T, self.nkv, self.dh).transpose(1, 2)
v = self.wv(x).view(B, T, self.nkv, self.dh).transpose(1, 2)
q, k = apply_rope(q, freqs), apply_rope(k, freqs)
if use_cache: # decode: anexa ao cache
if self.cache_k is not None:
k = torch.cat([self.cache_k, k], dim=2)
v = torch.cat([self.cache_v, v], dim=2)
self.cache_k, self.cache_v = k, v
k = k.repeat_interleave(self.nh // self.nkv, dim=1) # GQA: expande grupos
v = v.repeat_interleave(self.nh // self.nkv, dim=1)
# SDPA despacha p/ FlashAttention quando disponível
out = F.scaled_dot_product_attention(q, k, v, is_causal=not use_cache)
return self.wo(out.transpose(1, 2).reshape(B, T, -1))
class SwiGLU(nn.Module):
def __init__(self, d, mult=8/3):
super().__init__()
h = int(mult * d)
self.gate = nn.Linear(d, h, bias=False)
self.up = nn.Linear(d, h, bias=False)
self.down = nn.Linear(h, d, bias=False)
def forward(self, x):
return self.down(F.silu(self.gate(x)) * self.up(x))
class Block(nn.Module):
def __init__(self, d, n_heads, n_kv_heads):
super().__init__()
self.n1, self.n2 = RMSNorm(d), RMSNorm(d)
self.attn, self.ffn = GQAttention(d, n_heads, n_kv_heads), SwiGLU(d)
def forward(self, x, freqs, use_cache=False):
x = x + self.attn(self.n1(x), freqs, use_cache) # pre-norm residual
return x + self.ffn(self.n2(x))
class ModernGPT(nn.Module):
def __init__(self, vocab=32_000, d=512, n_layers=8,
n_heads=8, n_kv_heads=2, max_len=2048):
super().__init__()
self.emb = nn.Embedding(vocab, d)
self.blocks = nn.ModuleList(Block(d, n_heads, n_kv_heads) for _ in range(n_layers))
self.norm = RMSNorm(d)
self.head = nn.Linear(d, vocab, bias=False)
self.head.weight = self.emb.weight # weight tying
self.register_buffer("freqs", rope_freqs(d // n_heads, max_len), persistent=False)
def forward(self, idx, targets=None):
x = self.emb(idx)
for b in self.blocks: x = b(x, self.freqs)
logits = self.head(self.norm(x))
loss = None
if targets is not None: # next-token prediction: cross-entropy
loss = F.cross_entropy(logits.view(-1, logits.size(-1)),
targets.view(-1), ignore_index=-100)
return logits, loss
@torch.no_grad()
def generate(self, idx, max_new=100, temperature=0.8, top_p=0.95):
for _ in range(max_new):
logits, _ = self(idx[:, -2048:])
logits = logits[:, -1] / max(temperature, 1e-6)
probs = F.softmax(logits, dim=-1)
sp, si = torch.sort(probs, descending=True) # nucleus (top-p)
mask = sp.cumsum(-1) - sp > top_p
sp[mask] = 0.0; sp /= sp.sum(-1, keepdim=True)
nxt = si.gather(-1, torch.multinomial(sp, 1))
idx = torch.cat([idx, nxt], dim=1)
return idx
- Trace as shapes de cada tensor no papel — entrevistas técnicas adoram "qual a shape aqui?".
- Meça o efeito de
n_kv_headsno tamanho do cache; troque SDPA por uma atenção manual e compare velocidade. - Exercícios de extensão: adicionar sliding-window attention, um router MoE simples no lugar da SwiGLU, e speculative decoding no
generate. - Referências de ouro para aprofundar: nanoGPT/nanochat (Karpathy), os papers do Llama 3 e do DeepSeek-V3 (relatórios de engenharia excepcionais).
LLMs: o ciclo de vida completo
Um Transformer vira um LLM através de um pipeline: pré-treino em trilhões de tokens, adaptação supervisionada, alinhamento por preferências, e — na fronteira atual — treino de raciocínio por RL. Depois, tudo precisa ser servido rápido e barato.
3.1 Pré-treino: next-token prediction em escala
O objetivo é enganosamente simples: maximizar a verossimilhança do próximo token em um corpus gigante.
Prever bem o próximo token exige, implicitamente, sintaxe, fatos, raciocínio, tradução, código — o pré-treino é aprendizado multitarefa disfarçado. Os ingredientes de escala:
- Dados (o diferencial real). Web filtrada (Common Crawl → pipelines como FineWeb), código, artigos, livros, dados multilíngues e crescentemente dados sintéticos (gerados/reescritos por LLMs, ex.: linhagem Phi e boa parte dos modelos 2025+). O pipeline de dados — dedupe (MinHash), filtros de qualidade por classificadores, mistura de domínios, currículo (dados melhores no fim do treino) — é hoje mais decisivo que a arquitetura.
- Scaling laws. Kaplan (2020) mostrou que a loss cai como lei de potência em parâmetros N, dados D e compute C. Chinchilla (2022) corrigiu a alocação: para um orçamento fixo de FLOPs (C ≈ 6·N·D), o ótimo é D ≈ 20·N tokens. Mas o "ótimo de treino" ignora inferência: modelos modernos são deliberadamente overtrained (Llama 3 8B viu ~15T tokens, ~200× N) porque um modelo menor e mais treinado é mais barato de servir pelo resto da vida.
- Treino distribuído. Nenhuma GPU comporta o modelo. Combina-se Data Parallelism (réplicas com gradientes agregados; ZeRO/FSDP fragmentam pesos, gradientes e estados do otimizador), Tensor Parallelism (fatiar matrizes individuais entre GPUs do mesmo nó), Pipeline Parallelism (camadas em estágios, com micro-batches para reduzir bolhas) e, em MoE, Expert Parallelism. Treina-se em BF16 com acumulação FP32; a fronteira usa FP8 (DeepSeek-V3) com escalonamento fino por bloco.
3.2 Pós-treino I — SFT e fine-tuning eficiente (LoRA/QLoRA)
O modelo base completa texto; não conversa. SFT (Supervised Fine-Tuning) treina o mesmo objetivo de next-token, mas em pares instrução→resposta de alta qualidade, mascarando a loss nos tokens do prompt (só a resposta gera gradiente). Qualidade > quantidade: alguns milhares a poucas centenas de milhares de exemplos curados superam milhões medíocres.
LoRA (Low-Rank Adaptation) é a técnica de fine-tuning que você mais usará no mercado. Hipótese: a atualização de pesos necessária para adaptar um modelo tem posto baixo. Então congela-se W e aprende-se só uma correção fatorada:
- Treina-se ~0,1–1% dos parâmetros; B inicia em zero (o modelo começa idêntico ao base); após o treino, BA pode ser fundido em W — latência de inferência zero.
- QLoRA: o modelo base fica quantizado em NF4 (4 bits, formato ótimo p/ pesos normalmente distribuídos) com double quantization, e os adaptadores LoRA treinam em BF16 por cima. Fine-tuning de um 70B em uma única GPU de 48 GB.
- Serving multi-tenant: dezenas de LoRAs sobre o mesmo base model, trocados por requisição (S-LoRA, vLLM multi-LoRA) — padrão em produtos B2B.
Regra prática que impressiona em entrevista: prompt engineering para comportamento e formato (custo zero); RAG para conhecimento que muda ou precisa de citação (o modelo não deve "decorar" seu banco de dados); fine-tuning para estilo, formato estrito, domínio de vocabulário e destilar capacidade de um modelo caro num barato. Fine-tuning não é a ferramenta certa para injetar fatos atualizáveis — conhecimento paramétrico não tem citação, não expira e sofre de esquecimento catastrófico.
3.3 Pós-treino II — Alinhamento por preferências: RLHF, DPO, GRPO
SFT ensina a imitar; preferências ensinam o que é melhor. O pipeline clássico RLHF (InstructGPT, 2022):
- Coletam-se comparações humanas entre respostas (A ≻ B).
- Treina-se um reward model r_φ com loss de Bradley-Terry: maximizar log σ(r(x, y_w) − r(x, y_l)).
- Otimiza-se a política com PPO, maximizando a reward com uma penalidade KL contra o modelo de referência para evitar reward hacking e colapso: max E[r(x,y)] − β·KL(π‖π_ref).
DPO (Direct Preference Optimization) eliminou o reward model e o loop de RL: mostra-se que a solução ótima do objetivo RLHF tem forma fechada, e o reward implícito pode ser expresso pela própria política. A loss vira uma classificação direta sobre os pares de preferência:
Simples, estável, sem amostragem online — tornou-se o caminho padrão para times fora dos grandes laboratórios. Variantes: IPO (regulariza contra overfitting da preferência), KTO (não precisa de pares, só rótulos bom/ruim), ORPO (funde SFT + preferência).
GRPO (Group Relative Policy Optimization), popularizado pelo DeepSeek: remove o modelo de valor (critic) do PPO. Para cada prompt amostram-se G respostas; a vantagem de cada uma é sua reward normalizada dentro do grupo (z-score). Barato, e brilha quando a reward é verificável — nota de teste unitário, resposta matemática exata — o regime chamado RLVR (RL with Verifiable Rewards), motor dos modelos de raciocínio.
3.4 Modelos de raciocínio e test-time compute
A fronteira 2024–2026 deslocou o scaling do treino para a inferência: deixar o modelo "pensar mais" antes de responder.
- Chain-of-Thought (CoT): gerar passos intermediários melhora tarefas de raciocínio — cada token gerado é compute adicional condicionando os próximos.
- Modelos de raciocínio (OpenAI o1/o3, DeepSeek-R1, Claude com extended thinking, Gemini thinking, Qwen QwQ): treinados com RL (tipicamente GRPO/RLVR) para produzir longas cadeias internas de pensamento — com verificação, backtracking e autocorreção emergentes — antes da resposta final. O DeepSeek-R1 demonstrou que raciocínio forte emerge de RL puro sobre recompensas verificáveis, sem supervisão de cadeias humanas (R1-Zero), destilável depois para modelos pequenos.
- Test-time compute como eixo de scaling: best-of-N com verificador, self-consistency (votação entre cadeias), busca guiada por process reward models. O custo por resposta vira um dial: problemas fáceis pensam pouco, difíceis pensam muito ("reasoning effort").
- Implicação para engenheiros: latência e custo de modelos de raciocínio são ordens de magnitude maiores e variáveis — roteie: modelo rápido para o trivial, modelo pensante para o difícil (model routing/cascading é padrão de arquitetura em produção).
3.5 Inferência: sampling, quantização e serving de alto desempenho
Estratégias de decodificação
- Temperatura T reescala logits (z/T): T→0 vira greedy (determinístico); T alto achata a distribuição. Top-p (nucleus) amostra do menor conjunto cuja massa acumulada ≥ p; top-k e min-p são alternativas. Para extração estruturada use T baixa; para criatividade, T 0.7–1.0.
- Decodificação especulativa: um modelo rascunho pequeno (ou cabeças extras — Medusa/EAGLE) propõe k tokens; o modelo grande os verifica em um único forward paralelo, aceitando o prefixo que bate com sua própria distribuição (via rejection sampling que preserva exatamente a distribuição original). Speedups de 2–3× sem perda de qualidade — só é possível porque verificar k tokens custa quase o mesmo que gerar 1 (decode é memory-bound, lembra?).
- Saída estruturada: constrained decoding com gramáticas/JSON Schema (Outlines, XGrammar, structured outputs das APIs) mascara logits inválidos a cada passo — elimina "JSON quebrado" por construção.
Quantização
| Método | Como funciona | Uso típico |
|---|---|---|
| GPTQ | Quantização pós-treino camada a camada, minimizando erro com informação de segunda ordem (Hessiana aproximada) | 4-bit para serving em GPU |
| AWQ | Identifica ~1% de canais salientes (por magnitude de ativação) e os protege reescalando antes de quantizar | 4-bit, robusto, muito usado com vLLM |
| GGUF (llama.cpp) | Formato + esquemas k-quants/i-quants (2–8 bits) para inferência em CPU/Apple Silicon | Local/edge |
| FP8 / INT8 | Quantização de pesos e ativações com suporte nativo de hardware (Hopper/Blackwell); SmoothQuant migra dificuldade das ativações para os pesos | Serving de alta escala |
| KV cache quant | Cache em FP8/INT4 — dobra/quadruplica sequências simultâneas | Contexto longo |
Regra de bolso: 4-bit weight-only preserva ~99% da qualidade na maioria das tarefas e corta memória em ~4× vs FP16 — mas sempre avalie na sua tarefa (raciocínio e código degradam primeiro).
Motores de serving
- vLLM — continuous batching + PagedAttention + prefix caching; padrão de facto open-source.
- SGLang — RadixAttention (reuso agressivo de prefixos em árvore), forte em workloads agênticos e structured output.
- TensorRT-LLM — kernels NVIDIA máximos; mais atrito, mais performance.
- llama.cpp / Ollama — local, CPU/metal, prototipagem e edge.
- Métricas que você reportará em produção: TTFT (time to first token, dominado pelo prefill), TPOT/ITL (tempo por token de decode), throughput (tokens/s agregado) e goodput sob SLO. Desagregar prefill e decode em pools separados (prefill/decode disaggregation) é a tendência de arquitetura de serving em larga escala.
Embeddings e bases vetoriais
Busca semântica é o alicerce do RAG. Aqui você entende como modelos de embedding são treinados, a matemática da similaridade, os algoritmos de busca aproximada (HNSW, IVF, PQ) e como escolher e operar um banco vetorial de verdade.
4.1 Modelos de embedding modernos
Um modelo de embedding mapeia um texto inteiro para um único vetor e ∈ ℝ^d tal que textos semanticamente próximos fiquem geometricamente próximos. Arquitetura típica: um encoder Transformer (bidirecional, ou um LLM decoder adaptado como nos modelos Qwen3-Embedding/NV-Embed) com pooling (média dos tokens ou último token) e normalização L2.
Como são treinados — contrastive learning. O objetivo dominante é o InfoNCE: aproximar pares positivos (pergunta ↔ documento relevante) e afastar negativos, com os demais exemplos do batch servindo de negativos ("in-batch negatives"):
- Hard negatives (documentos parecidos mas errados, minerados por BM25 ou outro modelo) são o que separa embeddings medianos de excelentes.
- Pipeline moderno: pré-treino contrastivo fraco em pares massivos da web → fine-tuning supervisionado com hard negatives → frequentemente destilação de um cross-encoder ou LLM.
- Assimetria query/documento: muitos modelos usam prefixos de instrução (
"query: …"vs"passage: …") — ignorar isso derruba o recall silenciosamente. Leia sempre o cartão do modelo. - Matryoshka Representation Learning (MRL): treina-se a loss em prefixos aninhados do vetor (ex.: primeiras 64, 128, 256… dims), permitindo truncar o embedding para economizar armazenamento com perda mínima — recurso padrão nas APIs atuais (OpenAI text-embedding-3, Gemini embedding, vários open-source).
- Onde comparar modelos: benchmark MTEB (com ceticismo saudável — contaminação e overfitting a benchmark existem; valide no seu domínio). Famílias fortes: BGE/BGE-M3, E5, GTE, Qwen3-Embedding, Voyage, Cohere Embed, OpenAI, Gemini.
4.2 A matemática da similaridade
| Métrica | Fórmula | Quando usar |
|---|---|---|
| Cosseno | (a·b)/(‖a‖‖b‖) | Padrão para texto; ignora magnitude |
| Produto interno (dot) | a·b | Se o modelo foi treinado p/ isso; magnitude carrega sinal (ex.: relevância) |
| Euclidiana (L2) | ‖a−b‖ | Dados não normalizados; visão geométrica |
Detalhe que evita bugs: com vetores L2-normalizados, as três métricas induzem o mesmo ranking (‖a−b‖² = 2 − 2·a·b). Por isso a maioria dos pipelines normaliza tudo e usa dot product (mais rápido). Cuidado clássico: usar métrica diferente da usada no treino do modelo degrada resultados de forma silenciosa.
Em alta dimensão, distâncias entre pontos aleatórios concentram (contraste entre o vizinho mais próximo e o mais distante colapsa). Embeddings funcionam porque os dados não são aleatórios: vivem numa variedade de dimensão intrínseca muito menor (manifold hypothesis). Ainda assim, a geometria de alta dimensão é contraintuitiva — quase todo o volume de uma bola está na casca; vetores aleatórios são quase ortogonais — e é ela que motiva índices aproximados em vez de busca exata.
4.3 Busca aproximada (ANN): HNSW, IVF e Product Quantization
Busca exata (k-NN por força bruta) é O(N·d) por query — inviável para milhões/bilhões de vetores com latência de milissegundos. Índices ANN (Approximate Nearest Neighbor) trocam recall marginal por ordens de magnitude de velocidade. Os três pilares:
HNSW — Hierarchical Navigable Small World
- Um grafo de proximidade em camadas: a camada superior tem poucos nós e arestas longas ("rodovias"); camadas inferiores são densas e locais ("ruas"). A busca entra pelo topo, desce gulosamente em direção à query, e na camada 0 faz best-first search com uma fila de candidatos.
- Complexidade de busca ~O(log N); recall altíssimo. Parâmetros que você vai tunar: M (grau do grafo; ↑M = ↑recall, ↑memória), efConstruction (qualidade do índice) e efSearch (largura da busca; o dial recall × latência em runtime).
- Custo: memória (grafo + vetores residem em RAM) e deleções/updates são desajeitados (tombstones + rebuild periódico). É o índice default de Qdrant, Weaviate, Milvus, pgvector.
IVF — Inverted File Index
- Clusteriza o espaço com k-means em nlist células; cada vetor entra na lista invertida do seu centróide. Na busca, compara-se a query só com as nprobe células mais próximas.
- Mais simples e amigável a disco/updates que HNSW; recall depende de nprobe. Base do FAISS clássico e de sistemas bilionários.
PQ — Product Quantization (compressão)
- Divide o vetor em m sub-vetores; cada sub-vetor é quantizado para o centróide mais próximo de um codebook de 256 entradas → o vetor vira m bytes (ex.: 1024 dims float32 = 4 KB → 64 bytes, 64×).
- Distâncias são aproximadas por lookup tables (ADC), sem descomprimir. Combina-se: IVF-PQ (padrão em bilhões de vetores), com re-ranking dos top candidatos pelos vetores originais (refine).
- Quantização binária/int8: mais simples que PQ, muito popular em 2024+ — vetores binários (1 bit/dim) com distância de Hamming para o primeiro corte + rescore float nos top-k; corta custo em ~30× com recall ~95%+ em embeddings MRL grandes.
Além dos três
- DiskANN/Vamana: grafo otimizado para SSD (vetores comprimidos em RAM, grafo+full vectors em disco) — bilhões de vetores por máquina.
- ScaNN (Google): quantização anisotrópica que otimiza o erro na direção que afeta o ranking por dot product, não o erro de reconstrução.
- GPU ANN (FAISS-GPU, cuVS/CAGRA): construção e busca aceleradas — relevante em ingestão massiva.
4.4 Bancos vetoriais na prática
Um banco vetorial de produção é mais que um índice ANN: é CRUD + filtragem por metadados + busca híbrida + replicação + multi-tenancy em cima do índice.
| Opção | Perfil | Quando escolher |
|---|---|---|
| pgvector / pgvectorscale | Extensão do Postgres (HNSW, halfvec, binary quant; StreamingDiskANN no pgvectorscale) | Você já tem Postgres; < dezenas de milhões de vetores; quer transações, joins e um stack só. Default racional para a maioria dos produtos. |
| Qdrant | Rust, HNSW com filtragem integrada ao grafo, quantização nativa, ótimo custo-benefício | Serviço dedicado self-hosted/cloud com filtros pesados |
| Milvus | Distribuído, separa storage/compute, GPU, muitos tipos de índice | Bilhões de vetores, time de infra disponível |
| Weaviate | Híbrido nativo (BM25+vetor), módulos de vetorização | Busca híbrida out-of-the-box |
| Pinecone | Serverless gerenciado | Zero ops, pagar pelo conforto |
| FAISS / usearch | Biblioteca, não banco | Pesquisa, batch offline, ou embutido no seu serviço |
| Elasticsearch/OpenSearch | HNSW + BM25 maduro | Você já opera Elastic e quer híbrido |
"Buscar top-10 similares onde tenant_id=X e data>Y" quebra índices ingênuos: pós-filtrar os top-k pode devolver zero resultados se o filtro for seletivo; pré-filtrar e fazer força bruta é lento se o filtro for amplo. Soluções reais: filtragem durante a travessia do grafo (Qdrant, com heurísticas que trocam de estratégia conforme a cardinalidade estimada), particionamento por tenant, e índices por segmento. Em entrevista de system design, mencionar esse trade-off é sinal claro de senioridade.
from qdrant_client import QdrantClient, models
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("BAAI/bge-m3") # 1024 dims, multilíngue
client = QdrantClient(url="http://localhost:6333")
client.create_collection(
collection_name="docs",
vectors_config=models.VectorParams(
size=1024, distance=models.Distance.COSINE,
on_disk=True, # vetores originais em disco
),
quantization_config=models.ScalarQuantization( # int8 em RAM p/ 1º corte
scalar=models.ScalarQuantizationConfig(type=models.ScalarType.INT8,
always_ram=True)),
hnsw_config=models.HnswConfigDiff(m=16, ef_construct=256),
)
chunks = [{"id": 1, "text": "Política de reembolso: até 30 dias…",
"tenant": "acme", "doc": "politicas.pdf"}]
client.upsert("docs", points=[
models.PointStruct(id=c["id"],
vector=model.encode(c["text"], normalize_embeddings=True),
payload=c)
for c in chunks])
hits = client.query_points(
"docs",
query=model.encode("qual o prazo para devolver um produto?",
normalize_embeddings=True),
query_filter=models.Filter(must=[ # filtro DURANTE a busca
models.FieldCondition(key="tenant", match=models.MatchValue(value="acme"))]),
search_params=models.SearchParams(hnsw_ef=128), # dial recall × latência
limit=10,
).points
- Medir recall@k contra ground truth de força bruta ao tunar ef/nprobe — nunca confie no default.
- Planejar re-embedding: trocar de modelo de embedding invalida o índice inteiro; versione (
embedding_v2) e faça migração dual-read. - Dimensionar memória: HNSW ≈ vetores + ~M·8 bytes de arestas por vetor; quantização int8/binária corta 4–32×.
- Isolamento multi-tenant por payload ou por coleção/partição — e teste o pior caso do filtro.
- Backups e reindexação sem downtime (blue/green de coleções).
RAG: do pipeline canônico ao agêntico
Retrieval-Augmented Generation conecta LLMs a conhecimento externo: atualizável, citável e privado. É também onde a maioria dos projetos de IA corporativos vive — e onde a maioria falha por detalhes de recuperação, não de geração.
5.1 O pipeline canônico — e onde ele quebra
Indexação (offline): carregar documentos → limpar/parsear → chunking → embeddar → indexar com metadados. Consulta (online): embeddar a pergunta → recuperar top-k → montar o prompt com os trechos → gerar resposta com citações.
Chunking: a decisão mais subestimada
- Tamanho: chunks pequenos (128–256 tokens) dão precisão de recuperação mas perdem contexto; grandes (1024+) diluem o sinal do embedding. Ponto de partida sensato: 300–800 tokens com overlap de 10–15% — e avalie.
- Estratégias: por estrutura (headers de Markdown, seções de PDF — a melhor quando existe estrutura), recursiva por separadores, semântica (quebra onde a similaridade entre sentenças adjacentes cai), e por elemento em documentos complexos (tabelas separadas de prosa).
- Small-to-big / parent document: indexe chunks pequenos (bons de buscar), devolva ao LLM o pai maior (bom de ler). Simples e eficaz.
- Contextual retrieval (Anthropic, 2024): antes de embeddar, um LLM prefixa cada chunk com 1–2 frases situando-o no documento ("Este trecho é da seção de garantias do contrato X…"). Reduz falhas de recuperação em ~35–49% combinado com híbrida+rerank. Custo de indexação maior, amortizado por prompt caching.
- Parsing é metade do jogo: PDFs com tabelas, múltiplas colunas e figuras destroem pipelines ingênuos. Ferramentas: Docling, Unstructured, marker; modelos de visão para páginas complexas.
Falhas se dividem em: (1) recuperação — o trecho certo não veio (chunking ruim, embedding fraco no domínio, vocabulário divergente, filtro errado); (2) uso do contexto — veio, mas o modelo ignorou (contexto poluído, lost-in-the-middle, conflito com conhecimento paramétrico); (3) a resposta não existe no corpus — e o sistema deveria dizer "não sei". Instrumente cada etapa separadamente (seção 5.4): otimizar geração quando o problema é recall é o erro nº 1 de times iniciantes.
5.2 Busca híbrida, fusão e reranking
Denso + esparso
Embeddings capturam parafrase mas erram termos exatos (códigos de erro, nomes próprios, siglas, números de peça). BM25 — o clássico léxico baseado em TF-IDF saturado com normalização por tamanho de documento — captura exatamente isso. Busca híbrida roda os dois e funde os rankings. Alternativa neural ao BM25: SPLADE (esparso aprendido, com expansão de termos).
RRF é robusto porque usa posições, não scores (que vivem em escalas incomparáveis). Weaviate, Qdrant, OpenSearch e pgvector (via SQL) suportam nativamente.
Reranking: o upgrade de melhor custo-benefício
- Bi-encoder (o que indexa): query e doc viram vetores independentes; interação limitada a um dot product. Rápido, mas grosseiro.
- Cross-encoder (o reranker): concatena query+documento e passa pelo Transformer inteiro — atenção total entre cada palavra da pergunta e do texto. Muito mais preciso; caro demais para o corpus todo, perfeito para reordenar os top 50–150 recuperados.
- Opções: Cohere Rerank, Voyage/Jina rerankers, BGE-reranker, ou um LLM como juiz de relevância (listwise). Pipeline padrão de mercado: híbrida (top 100) → cross-encoder (top 100 → top 5–10) → LLM.
- ColBERT (late interaction): meio-termo elegante — um vetor por token, score = soma dos MaxSim entre tokens da query e do doc. Pré-computável como um índice, quase tão preciso quanto cross-encoder. Implementações: RAGatouille, Qdrant multivector, Jina-ColBERT.
Transformação de consultas
- Query rewriting: reescrever a pergunta do usuário (coloquial, com dêixis de conversa: "e no plano anual?") em consulta autocontida — obrigatório em chat multi-turno.
- Multi-query: gerar 3–5 variações e fundir resultados (RRF).
- HyDE: gerar uma resposta hipotética e buscar por ela — alinha a query ao espaço dos documentos.
- Decomposição: quebrar perguntas multi-hop ("compare a política de 2023 com a de 2025") em sub-consultas.
- Roteamento: classificar a intenção e direcionar (vetorial vs. SQL vs. web vs. responder direto). Text-to-SQL sobre dados estruturados é um irmão do RAG que aparece nos mesmos produtos.
5.3 RAG avançado e agêntico
- Self-RAG / CRAG (corretivo): o sistema critica a própria recuperação — um avaliador leve nota os trechos; se insuficientes, reformula a busca, amplia a janela ou cai para busca web; a geração é verificada contra as evidências antes de sair.
- GraphRAG: na indexação, um LLM extrai entidades e relações, montando um grafo de conhecimento + resumos hierárquicos por comunidade (Leiden). Responde o que RAG vetorial não alcança: perguntas globais ("quais os temas dominantes neste corpus?") e multi-hop por relações. Custo de indexação alto; variantes leves (LightRAG, LazyGraphRAG) reduzem. Use quando as relações entre entidades são o cerne do domínio (jurídico, investigação, engenharia de requisitos).
- RAG agêntico — o padrão 2025/26: em vez de um pipeline fixo, um LLM em loop com ferramentas de busca decide quando, o quê e quantas vezes buscar: reformula após resultados ruins, navega entre documentos, junta evidências de múltiplas fontes e para quando tem o suficiente (o padrão por trás de "deep research"). Custa mais latência/tokens; brilha em perguntas complexas. O termo guarda-chuva atual para projetar o que entra no modelo — instruções, memória, trechos recuperados, resultados de tools — é context engineering.
- Contexto longo mata o RAG? Não: custo/latência crescem com o contexto (e prefill é O(n²) na atenção), atenção degrada no meio de contextos enormes, corpora corporativos excedem qualquer janela, e citação/controle de acesso exigem recuperação. A síntese prática: janelas maiores permitem chunks maiores e top-k maior, com prompt caching baixando o custo de contexto repetido — RAG e long context são complementares.
- Multimodal: embeddings de imagem-texto (CLIP-like, ColPali para PDFs como imagens) permitem recuperar figuras, tabelas e páginas inteiras sem OCR perfeito — tendência forte para documentos corporativos.
5.4 Avaliação de RAG: sem isso, você está dirigindo vendado
Avalie recuperação e geração separadamente, sempre contra um conjunto de teste do seu domínio (100–300 perguntas com respostas e trechos-fonte anotados; LLMs ajudam a gerar o rascunho, humanos validam).
| Camada | Métricas | Como medir |
|---|---|---|
| Recuperação | Recall@k, Precision@k, MRR, nDCG | Contra os trechos-fonte anotados; é aqui que se tuna chunking, híbrida, rerank |
| Geração | Faithfulness (a resposta é sustentada pelos trechos? — mede alucinação), answer relevancy, correção vs. gabarito | LLM-as-judge com rubricas (frameworks: RAGAS, DeepEval, TruLens) + amostra humana para calibrar o juiz |
| Sistema | Taxa de "não sei" correta, latência p95, custo/consulta, satisfação | Telemetria em produção + testes de regressão a cada mudança |
from qdrant_client import QdrantClient, models
from sentence_transformers import SentenceTransformer, CrossEncoder
emb = SentenceTransformer("BAAI/bge-m3")
reranker = CrossEncoder("BAAI/bge-reranker-v2-m3")
qc = QdrantClient("http://localhost:6333")
def retrieve(question: str, k_dense=50, k_final=6):
# 1) híbrida: densa + BM25 fundidas por RRF no servidor
res = qc.query_points(
"docs",
prefetch=[
models.Prefetch(query=emb.encode(question).tolist(),
using="dense", limit=k_dense),
models.Prefetch(query=models.Document(text=question, model="bm25"),
using="sparse", limit=k_dense),
],
query=models.FusionQuery(fusion=models.Fusion.RRF),
limit=k_dense,
).points
# 2) rerank com cross-encoder: precisão onde importa
pares = [(question, p.payload["text"]) for p in res]
scores = reranker.predict(pares)
top = sorted(zip(res, scores), key=lambda t: -t[1])[:k_final]
return [p for p, _ in top]
def recall_at_k(testset, k=6):
# testset: [{"q": ..., "gold_ids": {...}}] — anotado no SEU domínio
hits = 0
for case in testset:
ids = {p.id for p in retrieve(case["q"], k_final=k)}
hits += bool(ids & set(case["gold_ids"]))
return hits / len(testset)
PROMPT = """Responda APENAS com base nos trechos abaixo, citando [n].
Se a resposta não estiver nos trechos, diga que não encontrou.
{contexto}
Pergunta: {pergunta}"""
1) Corrija parsing e chunking → 2) adicione BM25 + RRF → 3) adicione reranker → 4) query rewriting p/ chat → 5) contextual retrieval → 6) só então considere GraphRAG/agêntico. Cada degrau só sobe com o conjunto de avaliação dizendo que o anterior saturou. Contar essa história num projeto de portfólio — com números — vale mais que citar dez frameworks.
Produção e LLMOps
O que separa o notebook do produto: arquitetura, segurança, observabilidade, custo e agentes. É o capítulo que mais aparece em descrições de vaga de Engenheiro de IA — e o que menos aparece em cursos.
6.1 Arquitetura de sistemas com LLM
Um sistema LLM de produção raramente é "uma chamada de API". A anatomia típica:
- Gateway de modelo: uma camada única por onde passam todas as chamadas (LiteLLM, OpenRouter, gateway próprio) — centraliza chaves, retries com backoff, fallback entre provedores, timeouts, rate limiting e telemetria. Trocar de modelo vira config, não refactor.
- Roteamento e cascata: classifique a dificuldade/intenção e roteie — modelo pequeno/barato para o trivial (classificação, extração), grande/pensante para o difícil. Cascading: tente o barato, escale ao caro se a confiança for baixa. Corta 50–90% do custo em workloads reais.
- Caching em camadas: exact-match (mesma requisição → mesma resposta), prompt caching do provedor (prefixos repetidos — system prompt, few-shots, documentos — com desconto de até 90% e TTFT muito menor; ordene o prompt do estável para o variável) e, com cautela, caching semântico (respostas para perguntas similares — cuidado com falsos positivos).
- Filas e streaming: chamadas de LLM são lentas (segundos) e falham; desacople com filas para trabalhos batch e use streaming (SSE) para UX interativa — TTFT percebido importa mais que tempo total.
- Saída estruturada e validação: JSON Schema/structured outputs + validação com Pydantic + retry com o erro no prompt. Nunca confie em parsing de texto livre para dados que entram no seu sistema.
- Versionamento de prompts: prompts são código — versione, revise, teste em CI contra o conjunto de avaliação antes de fazer deploy. Mudança de prompt sem regression test é a causa nº 1 de incidentes silenciosos.
API (OpenAI, Anthropic, Google, etc.): fronteira de qualidade, zero infra, custo variável, dados saem do perímetro (verifique contratos de retenção). Self-host (vLLM/SGLang + Llama/Qwen/DeepSeek): controle total, dados internos, custo fixo — mas exige GPUs, MLOps e aceitar qualidade um degrau abaixo da fronteira. Padrão de mercado: começar com API, migrar workloads estáveis e de alto volume para open-source fine-tunado quando o custo justificar. A conta de break-even (tokens/mês × preço API vs. custo de GPU dedicada + time) é pergunta clássica de entrevista sênior.
6.2 Segurança: prompt injection e o OWASP LLM Top 10
A vulnerabilidade definidora de sistemas LLM é a prompt injection: o modelo não distingue estruturalmente instruções do desenvolvedor de texto malicioso vindo de dados. Variantes:
- Direta: o usuário tenta sobrescrever instruções ("ignore tudo acima e…").
- Indireta (a perigosa): a instrução maliciosa vem de conteúdo que o sistema processa — uma página web, um PDF no RAG, um e-mail, a descrição de um issue. Num agente com ferramentas, isso vira execução de ações: exfiltrar dados via uma tool de e-mail, apagar registros, seguir links maliciosos.
Defesas (em profundidade, nenhuma é suficiente sozinha):
- Privilégio mínimo nas ferramentas: escopos de acesso por usuário (a permissão é do usuário, não do agente), tools de escrita exigem confirmação humana (human-in-the-loop) para ações irreversíveis.
- Separar dados de instruções: delimitadores claros, marcar conteúdo externo como não-confiável no prompt, e tratar toda saída do LLM como entrada não-confiável para o resto do sistema (nada de
eval, SQL direto ou HTML sem sanitizar). - Classificadores de entrada/saída (guardrails: Llama Guard, moderação de provedor, regras próprias) para injection, jailbreak, PII e conteúdo fora de escopo.
- Regra de ouro para agentes (a "tríade letal"): evite combinar num mesmo agente acesso a dados privados + exposição a conteúdo não-confiável + canal de saída externo. Se as três coexistem, exfiltração é questão de tempo — quebre uma das pernas.
O OWASP Top 10 para LLMs organiza o restante: vazamento de dados sensíveis no prompt/logs, envenenamento de dados de treino/RAG, negação de serviço por prompts caros, supply chain de modelos/pesos, excesso de agência das tools, e overreliance (confiar sem verificar). Conhecer a lista pelo nome é diferencial imediato em entrevistas.
6.3 Observabilidade, avaliação contínua e custo
- Tracing: cada requisição vira um trace com spans (retrieval, rerank, chamadas de modelo, tools), com prompt, resposta, tokens, latência e custo. Ferramentas: Langfuse, LangSmith, Phoenix/Arize, Braintrust, W&B Weave — ou OpenTelemetry + seu stack.
- Métricas de produto: taxa de thumbs-down, taxa de escalada para humano, retenção da resposta (usuário copiou/usou?), custo por sessão. Métricas de modelo sem métricas de produto enganam.
- Avaliação contínua: o conjunto de teste do Cap. 5 roda em CI a cada mudança de prompt/modelo/índice; amostras de produção entram num loop de curadoria (as falhas de hoje são o dataset de teste — e de fine-tuning — de amanhã). LLM-as-judge calibrado com auditoria humana periódica.
- Drift: provedores atualizam modelos por baixo; fixe versões (
model-2026-01-15) e monitore benchmarks internos para detectar mudanças. - Custo: orçamento por feature/tenant; alertas de anomalia; otimize na ordem — cache → roteamento → prompt menor → modelo menor/fine-tunado → batch API (50% de desconto para o que não é interativo).
6.4 Agentes, function calling e MCP
Um agente é um LLM num loop: recebe um objetivo, decide chamar ferramentas, observa resultados e itera até concluir. A base mecânica é o function calling: você declara tools com JSON Schema; o modelo emite uma chamada estruturada; seu código executa e devolve o resultado; o modelo continua.
import anthropic, json
client = anthropic.Anthropic()
TOOLS = [{
"name": "buscar_pedido",
"description": "Busca o status de um pedido pelo ID.",
"input_schema": {"type": "object",
"properties": {"pedido_id": {"type": "string"}},
"required": ["pedido_id"]},
}]
def executar(nome, args):
if nome == "buscar_pedido":
return db.pedidos.get(args["pedido_id"]) # valide permissões AQUI
msgs = [{"role": "user", "content": "Cadê meu pedido A-1042?"}]
while True:
resp = client.messages.create(model="claude-sonnet-4-6", max_tokens=1024,
tools=TOOLS, messages=msgs)
if resp.stop_reason != "tool_use":
break # resposta final
msgs.append({"role": "assistant", "content": resp.content})
resultados = [
{"type": "tool_result", "tool_use_id": b.id,
"content": json.dumps(executar(b.name, b.input))}
for b in resp.content if b.type == "tool_use"]
msgs.append({"role": "user", "content": resultados})
- MCP (Model Context Protocol): padrão aberto (Anthropic, 2024; adotado amplamente em 2025) que desacopla ferramentas de aplicações — um servidor MCP expõe tools/recursos/prompts por um protocolo comum, e qualquer cliente compatível os consome. É o "USB-C das integrações de IA": escreva o conector uma vez, use em qualquer agente. Saber construir um servidor MCP é linha de currículo em 2026.
- Padrões de projeto: comece com workflows determinísticos (cadeias fixas com um passo LLM onde precisa) e só adote autonomia de agente onde a variabilidade da tarefa exige; um agente forte com boas tools supera hierarquias complexas de multiagentes na maioria dos casos; contexto é o recurso escasso — resuma, pagine resultados de tools, isole subtarefas em sub-agentes com contexto limpo (context engineering de novo).
- Confiabilidade: limite de iterações, orçamento de tokens/custo por execução, timeouts por tool, checkpoints para retomar, e trilha de auditoria de cada ação. Avalie agentes por resultado (a tarefa foi concluída?) e por trajetória (fez chamadas absurdas no caminho?).
Carreira: Engenheiro de IA/LLM
Como converter o conteúdo desta apostila em contratação: o que as vagas pedem de verdade, que projetos construir, e como são as entrevistas.
7.1 O que o mercado cobra (de verdade)
O título "AI Engineer" consolidou-se como engenharia de software que integra e opera modelos — distinto de ML Engineer clássico (treina modelos) e de Research. A distribuição típica de requisitos em vagas:
| Bloco | Peso | Nesta apostila |
|---|---|---|
| Engenharia de software sólida (Python, APIs, testes, Docker, cloud, SQL) | Alto — é a base eliminatória | pré-requisito seu |
| RAG + bases vetoriais + avaliação | Altíssimo — o grosso dos projetos corporativos | Caps. 4–5 |
| Agentes, function calling, MCP, orquestração | Alto e crescendo rápido | Cap. 6.4 |
| LLMOps: observabilidade, custo, guardrails, segurança | Alto — diferencia sênior | Cap. 6 |
| Fine-tuning (LoRA/QLoRA, DPO) e serving open-source (vLLM) | Médio — nichos e empresas maiores | Caps. 3, 2.5 |
| Fundamentos profundos (atenção, KV cache, quantização) | Médio no dia a dia, alto em entrevista | Caps. 1–3 |
- Frameworks: conheça LangChain/LangGraph, LlamaIndex e SDKs de agentes — mas entrevistadores experientes valorizam quem sabe fazer sem framework (o loop do 6.4 em ~30 linhas) e escolhe frameworks por razões, não por moda.
- Habilidade transversal nº 1: avaliação. Quem chega com "eu construo o eval set antes da feature" se separa de 90% dos candidatos.
- Acompanhe a área de forma sustentável: relatórios técnicos de modelos (Llama, DeepSeek, Qwen), blogs de engenharia (Anthropic, OpenAI, vLLM, Qdrant), e reimplemente uma ideia por mês.
7.2 Portfólio: três projetos que contam uma história
- Fundamentos: seu mini-GPT (Cap. 2.7) treinado num corpus pequeno em português, com um README que explica as decisões (por que GQA, por que RoPE, gráfico de loss, ablations simples). Prova profundidade.
- RAG de produção: um assistente sobre um corpus real (legislação, docs técnicas, normas) com: ingestão robusta de PDF, híbrida + rerank, citações, conjunto de avaliação com números (recall@k antes/depois de cada melhoria — a "escada" do Cap. 5), tracing com Langfuse, Docker Compose com Qdrant/pgvector, e uma seção de custos. Prova que você entrega o que as empresas mais compram.
- Agente com MCP: um agente que resolve uma tarefa real de negócio com 3–5 tools (uma delas um servidor MCP seu), human-in-the-loop para ações de escrita, guardrails contra injection e avaliação de trajetórias. Prova que você está na fronteira aplicada.
Regras do portfólio: repositórios que rodam com um comando; READMEs com arquitetura, trade-offs e números; um post técnico por projeto (o texto é o que recrutadores leem). Profundidade em 3 > superficialidade em 10.
7.3 Entrevistas: o que esperar
- Coding: padrão de engenharia (estruturas de dados moderadas) + exercícios de LLM: implementar atenção/softmax do zero, parsear saída de modelo com robustez, consumir APIs com retry/streaming.
- System design de IA: "projete um assistente sobre os documentos internos da empresa" — percorra: ingestão → chunking → índice (e por quê) → híbrida/rerank → prompt com citações → avaliação → segurança/permissões → custo/latência → o que monitoraria. Esta apostila é o roteiro.
- Conceitual: por que √d_k; o que é KV cache e por que GQA/MLA existem; LoRA em uma equação; DPO vs. RLHF; quando fine-tuning vs. RAG; como funciona HNSW; o que é prompt injection indireta; por que decode é memory-bound.
- Comportamental: tenha 2–3 histórias com estrutura problema → decisão técnica com trade-off → número de impacto.
- Sem. 1–3: Caps. 1–2 + implementar e treinar o mini-GPT.
- Sem. 4–5: Cap. 3 + um fine-tuning LoRA/QLoRA real (ex.: classificação ou estilo) com avaliação antes/depois.
- Sem. 6–9: Caps. 4–5 + construir o RAG de produção subindo a escada de melhorias com números.
- Sem. 10–11: Cap. 6 + transformar o RAG em agente com tools/MCP, guardrails e tracing.
- Sem. 12: escrever os posts, polir READMEs, simular entrevistas com as perguntas do 7.3.
Glossário
Os termos essenciais do vocabulário de Engenharia de LLMs, em ordem alfabética. Use como revisão pré-entrevista: se você consegue explicar cada verbete em voz alta sem olhar, está pronto.
- Agentecap. 6
- LLM operando em loop: recebe um objetivo, decide chamar ferramentas, observa os resultados e itera até concluir a tarefa, com autonomia sobre o caminho.
- ALiBi
- Método posicional que dispensa embeddings: penaliza os logits de atenção linearmente pela distância entre tokens. Extrapola bem para sequências mais longas que as de treino.
- Alinhamento
- Etapa de pós-treino que ajusta o modelo a preferências humanas e políticas de comportamento (utilidade, honestidade, segurança), via RLHF, DPO e afins.
- Alucinação
- Saída fluente porém factualmente incorreta ou inventada. Mitigada com grounding (RAG com citações), avaliação de faithfulness e instruções para admitir incerteza — nunca eliminada por completo.
- ANNApproximate Nearest Neighbor
- Família de algoritmos (HNSW, IVF, PQ) que encontra vizinhos aproximadamente mais próximos em espaços vetoriais, trocando recall marginal por buscas ordens de magnitude mais rápidas que a exata.
- Atenção (self-attention)
- Mecanismo em que cada token computa pesos sobre todos os demais (via queries e keys) e agrega seus values numa média ponderada — a forma como informação circula entre posições no Transformer.
- AWQActivation-aware Weight Quantization
- Quantização pós-treino de 4 bits que identifica ~1% de canais salientes (pela magnitude das ativações) e os protege reescalando antes de quantizar.
- Bi-encoder
- Arquitetura de recuperação em que query e documento são embeddados de forma independente e comparados por produto interno. Rápido e indexável; menos preciso que um cross-encoder.
- BM25
- Algoritmo clássico de busca léxica baseado em frequência de termos (TF-IDF com saturação e normalização por tamanho). Imbatível em termos exatos: códigos, siglas, nomes. Par natural da busca densa na híbrida.
- BPEByte-Pair Encoding
- Algoritmo de tokenização que funde iterativamente os pares de símbolos mais frequentes do corpus até formar o vocabulário. Em versão byte-level, tokeniza qualquer string sem tokens desconhecidos.
- Chain-of-Thought (CoT)
- Técnica em que o modelo gera passos intermediários de raciocínio antes da resposta. Cada token gerado é compute adicional condicionando os próximos — base dos modelos de raciocínio.
- Chinchilla (scaling ótimo)
- Resultado (DeepMind, 2022) de que, para um orçamento fixo de compute, o ótimo é ~20 tokens de treino por parâmetro. Modelos modernos deliberadamente ultrapassam isso (overtraining) para baratear a inferência.
- Chunking
- Divisão de documentos em trechos para indexação em RAG. Tamanho, sobreposição e respeito à estrutura do documento afetam diretamente o recall — a decisão mais subestimada do pipeline.
- ColBERT / late interaction
- Recuperação com um vetor por token: o score é a soma dos melhores casamentos (MaxSim) entre tokens da query e do documento. Quase a precisão de um cross-encoder com índice pré-computável.
- Context engineering
- Disciplina de projetar tudo que entra na janela do modelo — instruções, memória, trechos recuperados, resultados de tools — tratando o contexto como recurso escasso a ser curado.
- Context window (janela de contexto)
- Número máximo de tokens que o modelo processa de uma vez (prompt + geração). Janelas atuais vão de 8k a 1M+; atenção e custo crescem com ela.
- Contrastive learning
- Regime de treino de embeddings que aproxima pares positivos e afasta negativos no espaço vetorial (loss InfoNCE). A qualidade dos hard negatives define a qualidade do modelo.
- Contextual retrieval
- Técnica de indexação em que um LLM prefixa cada chunk com frases que o situam no documento original antes de embeddar, reduzindo falhas de recuperação de forma expressiva.
- Continuous batching
- Estratégia de serving que insere e remove requisições do batch a cada passo de geração (em vez de esperar o batch inteiro terminar), maximizando a ocupação da GPU. Núcleo do vLLM.
- Cross-encoder
- Modelo que processa query e documento juntos, com atenção total entre eles, produzindo um score de relevância. Preciso demais para o corpus todo, ideal como reranker dos top-k recuperados.
- Decodificação especulativa
- Um modelo rascunho propõe vários tokens; o modelo grande os verifica num único forward paralelo, aceitando os que batem com sua distribuição. Acelera 2–3× sem alterar a distribuição de saída.
- Destilação
- Treinar um modelo menor (student) para imitar as saídas — ou distribuições — de um maior (teacher). Usada para comprimir capacidade, inclusive de raciocínio (ex.: destilados do DeepSeek-R1).
- DPODirect Preference Optimization
- Alinhamento por preferências sem reward model nem RL: uma loss de classificação direta sobre pares (resposta preferida vs. rejeitada), derivada da solução fechada do objetivo RLHF.
- Embedding
- Vetor denso que representa um token, sentença ou documento num espaço onde proximidade geométrica corresponde a similaridade semântica. Base da busca vetorial e do RAG.
- Faithfulness
- Métrica de avaliação de RAG: grau em que cada afirmação da resposta é sustentada pelos trechos recuperados. É a métrica que operacionaliza a medição de alucinação.
- Few-shot / zero-shot
- Uso do modelo com alguns exemplos no prompt (few-shot) ou nenhum (zero-shot), explorando o in-context learning em vez de treinar.
- FFNfeed-forward network
- A MLP aplicada por posição em cada bloco Transformer (hoje tipicamente SwiGLU). Concentra ~2/3 dos parâmetros; descrita como memória associativa onde reside conhecimento factual.
- Fine-tuning
- Continuar o treino de um modelo pré-treinado em dados específicos para adaptar comportamento, estilo ou domínio. Formas eficientes: LoRA/QLoRA. Não é a ferramenta certa para fatos atualizáveis — para isso, RAG.
- FlashAttention
- Kernel de atenção que processa em tiles na SRAM do chip com online softmax, sem materializar a matriz n×n na memória. Reduz memória de O(n²) para O(n) e evita a parede de banda.
- FSDP / ZeRO
- Técnicas de data parallelism que fragmentam pesos, gradientes e estados do otimizador entre GPUs, em vez de replicá-los — essenciais para treinar modelos que não cabem numa GPU.
- Function calling / tool use
- Capacidade do modelo de emitir chamadas estruturadas (JSON) a funções declaradas com schema; o código executa e devolve o resultado. Mecanismo base dos agentes.
- GGUF
- Formato de pesos quantizados do llama.cpp (esquemas de 2 a 8 bits) para inferência eficiente em CPU e Apple Silicon — o padrão do ecossistema local.
- GPTQ
- Quantização pós-treino camada a camada que minimiza o erro de saída usando informação de segunda ordem (aproximação da Hessiana). Clássico do 4-bit em GPU.
- GQAGrouped-Query Attention
- Variante da multi-head em que grupos de cabeças de query compartilham cabeças de K/V, encolhendo o KV cache com qualidade ≈ MHA. Padrão em Llama 3, Mistral, Qwen.
- GraphRAG
- RAG que indexa o corpus como grafo de conhecimento (entidades + relações extraídas por LLM) com resumos por comunidade, habilitando perguntas globais e multi-hop que a busca vetorial não alcança.
- GRPOGroup Relative Policy Optimization
- Algoritmo de RL sem critic: amostra G respostas por prompt e usa a reward normalizada dentro do grupo como vantagem. Barato e eficaz com recompensas verificáveis; motor do DeepSeek-R1.
- Guardrails
- Camadas de validação de entrada e saída (classificadores, regras, schemas) que bloqueiam injection, conteúdo fora de política, PII e formatos inválidos antes que causem dano.
- Hard negatives
- Exemplos negativos difíceis (parecidos com o positivo, mas errados) usados no treino contrastivo de embeddings e rerankers. São o principal fator de qualidade desses modelos.
- HNSWHierarchical Navigable Small World
- Índice ANN em grafo com camadas hierárquicas: busca desce de arestas longas para locais, com complexidade ~O(log N) e recall altíssimo. Default de Qdrant, Weaviate, Milvus e pgvector.
- HyDEHypothetical Document Embeddings
- Transformação de consulta em que o LLM gera uma resposta hipotética e a busca é feita pelo embedding dela, aproximando a query do espaço dos documentos.
- In-context learning
- Capacidade emergente de o modelo aprender uma tarefa a partir de exemplos fornecidos no próprio prompt, sem atualização de pesos.
- IVFInverted File Index
- Índice ANN que clusteriza o espaço com k-means e busca apenas nas células (nprobe) mais próximas da query. Simples, amigável a disco; base do FAISS clássico.
- KV cache
- Armazenamento das keys e values já computados durante a geração autorregressiva, evitando recomputar a atenção do prefixo a cada token. É o principal consumidor de memória no serving.
- LLM-as-judge
- Uso de um LLM com rubrica para avaliar saídas de outro (relevância, faithfulness, qualidade) em escala. Exige calibração periódica contra julgamento humano.
- Logits
- Scores brutos (pré-softmax) que o modelo atribui a cada token do vocabulário no próximo passo. Temperatura, top-p e constrained decoding operam sobre eles.
- LoRALow-Rank Adaptation
- Fine-tuning eficiente que congela os pesos e aprende correções de baixo posto (W + BA), treinando <1% dos parâmetros e permitindo fundir o adaptador sem custo de inferência.
- Lost in the middle
- Fenômeno em que modelos recuperam pior informação posicionada no meio de contextos longos do que no início ou fim — argumento para ranquear bem os trechos no prompt.
- MCPModel Context Protocol
- Protocolo aberto que padroniza como aplicações expõem ferramentas, recursos e prompts a modelos — o conector universal do ecossistema de agentes.
- MLAMulti-head Latent Attention
- Atenção que cacheia apenas uma compressão latente de baixo posto de K/V, reconstruindo-os on-the-fly. Corta o KV cache em ~10× (DeepSeek-V2/V3).
- MoEMixture of Experts
- Arquitetura em que a FFN é substituída por vários experts e um router ativa só o top-k por token — desacoplando número de parâmetros de custo por token.
- MQAMulti-Query Attention
- Todas as cabeças de query compartilham uma única cabeça de K/V, encolhendo o KV cache em h× com alguma perda de qualidade. Precursora da GQA.
- MRL / Matryoshka
- Treino de embeddings em prefixos aninhados do vetor, permitindo truncá-lo (ex.: 1024→256 dims) com perda mínima — economia direta de armazenamento e latência.
- MTEB
- Benchmark padrão para comparar modelos de embedding em dezenas de tarefas. Útil como filtro inicial; sempre valide no seu domínio.
- Multi-head attention
- Divisão da atenção em h cabeças paralelas de dimensão menor, cada uma com projeções próprias, permitindo capturar tipos distintos de relação simultaneamente.
- NF4
- Tipo de dado de 4 bits com níveis posicionados para pesos normalmente distribuídos, usado no QLoRA para manter o modelo base quantizado durante o fine-tuning.
- nDCG / MRR / Recall@k
- Métricas de recuperação: Recall@k (o item certo veio nos top-k?), MRR (posição do primeiro relevante) e nDCG (qualidade do ranking inteiro com ganhos descontados por posição).
- PagedAttention
- Gerência do KV cache como memória virtual: blocos de tamanho fixo com tabela de páginas por sequência e compartilhamento de prefixos, eliminando fragmentação. Coração do vLLM.
- Perplexidade
- Exponencial da cross-entropy média por token; mede quão "surpreso" o modelo fica com um texto. Métrica clássica de pré-treino — não substitui avaliação de tarefa.
- PPOProximal Policy Optimization
- Algoritmo de RL usado no RLHF clássico: otimiza a política com passos limitados (clipping) e penalidade KL contra o modelo de referência para evitar colapso e reward hacking.
- PQProduct Quantization
- Compressão vetorial que divide o vetor em sub-vetores quantizados por codebooks, reduzindo cada vetor a poucos bytes com distâncias aproximadas por lookup. Base do IVF-PQ bilionário.
- Prefill / Decode
- As duas fases da inferência: processar o prompt em paralelo (prefill, limitado por compute) e gerar token a token (decode, limitado por banda de memória). Definem TTFT e TPOT.
- Prompt caching
- Reuso, pelo provedor ou motor de serving, do KV cache de prefixos repetidos do prompt (system prompt, documentos), com grandes descontos de custo e latência.
- Prompt injection
- Ataque em que instruções maliciosas — digitadas pelo usuário (direta) ou embutidas em conteúdo processado (indireta) — sequestram o comportamento do modelo. A vulnerabilidade nº 1 do OWASP LLM Top 10.
- QLoRA
- LoRA sobre um modelo base quantizado em NF4 com double quantization, permitindo fine-tuning de modelos de dezenas de bilhões de parâmetros numa única GPU.
- Quantização
- Representar pesos (e às vezes ativações e KV cache) em menos bits (8, 4, até 2) para cortar memória e acelerar inferência, com perda de qualidade controlada.
- Query rewriting
- Reescrever a pergunta do usuário (resolvendo referências da conversa, expandindo termos) em consulta autocontida antes da busca — obrigatório em RAG conversacional.
- RAGRetrieval-Augmented Generation
- Padrão que recupera trechos relevantes de uma base externa e os injeta no prompt, dando ao modelo conhecimento atualizável, citável e privado sem retreinar.
- Reranking
- Reordenar os top-k recuperados com um modelo mais preciso (cross-encoder ou LLM) antes de montar o prompt. O upgrade de melhor custo-benefício de um pipeline RAG.
- Reward model
- Modelo treinado em comparações humanas para prever a qualidade de uma resposta; fornece o sinal de recompensa no RLHF clássico.
- RLHF
- Alinhamento por RL com feedback humano: coleta de preferências → reward model → otimização da política (PPO) com restrição KL. O pipeline que criou o ChatGPT.
- RLVRRL with Verifiable Rewards
- RL em que a recompensa é verificável automaticamente (teste unitário passa, resposta matemática exata) — o regime que destravou os modelos de raciocínio.
- RMSNorm
- Normalização que reescala pela raiz da média dos quadrados, sem centralização nem bias. Mais barata que LayerNorm; padrão nos modelos modernos.
- RoPERotary Position Embedding
- Codificação posicional que rotaciona pares de dimensões de q e k por ângulos proporcionais à posição, fazendo o score de atenção depender apenas da posição relativa. Padrão atual.
- RRFReciprocal Rank Fusion
- Fusão de rankings de sistemas distintos somando 1/(k + posição), robusta por ignorar escalas de score. O jeito padrão de combinar BM25 com busca densa.
- Sampling (temperatura, top-p, top-k)
- Estratégias de amostragem do próximo token: temperatura reescala logits (0 = determinístico); top-p amostra do menor conjunto com massa acumulada ≥ p; top-k limita aos k mais prováveis.
- Scaling laws
- Relações empíricas de lei de potência entre loss e parâmetros/dados/compute, que tornaram o desempenho de LLMs previsível e justificaram a corrida de escala.
- SFTSupervised Fine-Tuning
- Fine-tuning supervisionado em pares instrução→resposta de alta qualidade (com loss apenas nos tokens de resposta), que transforma um modelo base em assistente.
- Sliding window attention
- Atenção restrita a uma janela local de w tokens por camada, reduzindo custo para O(n·w); camadas empilhadas propagam informação além da janela. Frequentemente intercalada com atenção global.
- Speculative decoding
- Ver decodificação especulativa.
- SPLADE
- Modelo de recuperação esparsa aprendida: gera pesos por termo do vocabulário (com expansão de termos), unindo interpretabilidade léxica e treino neural.
- Structured output / constrained decoding
- Geração restrita por gramática ou JSON Schema, mascarando tokens inválidos a cada passo — garante saída parseável por construção.
- SwiGLU
- FFN com gate multiplicativo — (Swish(xW_g) ⊙ xW_u)W_d — que melhora perplexidade de forma consistente; padrão nos blocos modernos.
- System prompt
- Instruções do desenvolvedor que definem papel, regras e formato do assistente, colocadas antes da conversa e (idealmente) estáveis para aproveitar prompt caching.
- Test-time compute
- Escalar a qualidade gastando mais compute na inferência (cadeias longas de raciocínio, best-of-N, busca com verificadores) em vez de só no treino. O eixo de scaling da fronteira atual.
- Token
- Unidade mínima processada pelo modelo — subpalavra, palavra ou bytes — mapeada a um inteiro do vocabulário. Custos, limites e métricas de LLM são medidos em tokens.
- TTFT / TPOT
- Time To First Token (latência até o primeiro token, dominada pelo prefill) e Time Per Output Token (ritmo do decode). As duas métricas centrais de latência em serving.
- Vector database (base vetorial)
- Sistema que armazena embeddings com índices ANN, filtragem por metadados, CRUD e replicação — a infraestrutura de busca semântica do RAG.
- vLLM
- Motor de serving open-source com continuous batching, PagedAttention e prefix caching; o padrão de facto para servir LLMs open-weights em produção.
- Weight tying
- Compartilhar a matriz de embedding com a camada de saída, economizando parâmetros — comum em modelos pequenos e médios.