Phase 10 - Lesson 25

Decodificação Especulativa e EAGLE

This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.

Um LLM de fronteira gerando um único token requer um forward pass completo sobre bilhões de parâmetros. Esse forward pass é massivamente superprovisionada: na maioria das vezes, um modelo muito menor pode adivinhar os próximos 3 a 5 tokens corretamente, e o modelo grande só precisa verificar o palpite. Quando o palpite está correto, você obtém 5 tokens pelo preço de um. O speculative decoding (decodificação especulativa) (Leviathan et al. 2023) tornou isso exato, e o EAGLE-3 (2025) elevou as taxas de aceitação para cerca de 4,5 tokens por verificação — uma aceleração de 4 a 5 vezes mantendo a mesma distribuição de saída.

Tipo: Build Linguagens: Python (com numpy) Pré-requisitos: Phase 10 Lesson 12 (Inference Optimization), Phase 10 Lesson 04 (Pre-training Mini-GPT) Tempo: ~75 minutos

O Problema

O throughput de decodificação para um modelo da classe de 70B em uma H100 é tipicamente de 40 a 80 tokens/segundo. Cada token requer um forward pass completo lendo todos os pesos do modelo da HBM. Não é possível reduzir o tamanho do modelo sem alterar sua saída. Não é possível aumentar o batch size além do limite da memória. Você fica travado — a menos que consiga fazer o modelo gerar mais de um token por forward pass.

A geração autorregresiva parece inerentemente serial: x_{t+1} = sample(p(· | x_{1:t})). Mas existe uma oportunidade de concorrência. Se você tivesse um preditor de baixo custo que dissesse "os próximos 4 tokens provavelmente são [a, b, c, d]", você poderia verificar todas as 5 posições em um único forward pass do modelo grande e aceitar o prefixo correspondente mais longo.

Leviathan, Kalai, Matias (2023, "Fast Inference from Transformers via Speculative Decoding") tornaram isso exato por meio de uma regra inteligente de aceitação/rejeição que preserva a distribuição de amostragem do modelo alvo. A mesma distribuição de saída, de 2 a 4 vezes mais rápida.

O Conceito

A Configuração com Dois Modelos

  • Modelo alvo (Target model) M_p: o modelo grande, lento e de alta qualidade do qual você realmente deseja obter amostras. Distribuição: p(x).
  • Modelo de rascunho (Draft model) M_q: um modelo pequeno, rápido e de menor qualidade. Distribuição: q(x). De 5 a 30 vezes menor.

Por passo:

  1. O modelo de rascunho propõe K tokens de forma autorregresiva: x_1, x_2, ..., x_K ~ q.
  2. O modelo alvo executa UM único forward pass sobre todas as K+1 posições em paralelo, produzindo p(x_k) para cada token proposto.
  3. Aceita/rejeita cada token da esquerda para a direita através da regra modificada de amostragem por rejeição descrita abaixo. Aceita o prefixo correspondente mais longo.
  4. Se qualquer token for rejeitado, amostra o substituto a partir da distribuição corrigida e para. Caso contrário, amostra um token bônus de p(· | x_1...x_K).

Se o rascunho corresponder perfeitamente ao alvo, você obtém K+1 tokens por forward pass do alvo. Se o rascunho estiver errado na posição 1, você obtém apenas 1 token.

A Regra de Exatidão

O speculative decoding é provadamente equivalente em termos de distribuição à amostragem direta de p. A regra de rejeição:

For each drafted token x_t:
    r ~ Uniform(0, 1)
    if r < p(x_t) / q(x_t):
        accept x_t
    else:
        sample replacement from residual: (p - q)+ / ||(p - q)+||_1
        stop

onde (p - q)+ denota a parte positiva da diferença ponto a ponto. Quando o rascunho e o alvo concordam (p ≈ q), a aceitação é próxima de 1. Quando eles discordam, a distribuição residual é construída de modo que a amostra geral ainda seja exatamente p.

Caso ganancioso (Greedy case). Para amostragem com temperatura=0, basta verificar se argmax(p) == x_t. Se sim, aceita; se não, produz argmax(p) e para.

Aceleração Esperada

Se a taxa de aceitação a nível de token do modelo de rascunho for α, a quantidade esperada de tokens produzida por forward pass do alvo é:

E[tokens] = (1 - α^{K+1}) / (1 - α)        # K = draft length, α in [0, 1]

Para α = 0.8, K = 4: (1 - 0.8^5)/(1 - 0.8) = 3.36 tokens por forward pass. Um único forward pass do alvo custa aproximadamente cost_q * K + cost_p (K passos de rascunho mais uma verificação do alvo). Se cost_p >> cost_q * K, a taxa de aceleração é de 3.36× / 1 = 3.36× no throughput.

O único parâmetro real é α, que depende inteiramente do alinhamento entre o rascunho e o alvo. Um bom rascunho é tudo.

Treinando o Rascunho: Destilação

Um modelo pequeno aleatório resulta em um rascunho ruim. A receita padrão é destilar a partir do alvo:

  1. Escolha uma arquitetura pequena (~1B para um alvo de 70B, ~500M para um alvo de 7B).
  2. Execute o modelo alvo em um grande corpus de texto; armazene suas distribuições do próximo token.
  3. Treine o rascunho com divergência KL contra a distribuição do alvo (não contra os tokens reais do ground-truth).

O resultado: α é tipicamente de 0,6 a 0,8 em tarefas de programação e de 0,7 a 0,85 em chat de linguagem natural. Acelerações de 2 a 3 vezes em produção.

EAGLE: Tree Drafting + Reutilização de Features

Li, Wei, Zhang, Zhang (2024, "EAGLE: Speculative Sampling Requires Rethinking Feature Uncertainty") observaram duas ineficiências no speculative decoding padrão:

  1. O rascunho realiza K passos seriais, cada um percorrendo toda a rede. No entanto, o rascunho poderia reutilizar as features (hidden states) do alvo da verificação mais recente — o alvo já computou representações ricas que o rascunho está recalculando do zero.
  2. O rascunho produz uma cadeia linear. Se o rascunho pudesse produzir uma árvore de candidatos (cada nó com múltiplos palpites), o único forward pass do alvo poderia verificar múltiplos caminhos candidatos em paralelo por meio de uma máscara de atenção em árvore (tree attention mask) e escolher o ramo aceito mais longo.

Mudanças no EAGLE-1:

  • A entrada do rascunho = estado oculto (hidden state) final do alvo na posição t, não tokens brutos.
  • Arquitetura do rascunho = 1 camada de decodificador transformer (não um modelo menor separado).
  • Saída = árvore com K = 4-8 candidatos por profundidade, com profundidade de 4-6.

O EAGLE-2 (2024) adiciona topologia de árvore dinâmica: a árvore cresce em largura onde o rascunho é incerto e permanece estreita onde ele está confiante. Eleva a α_effective sem aumentar o custo de verificação.

O EAGLE-3 (Li et al. 2025, "EAGLE-3: Scaling up Inference Acceleration of Large Language Models via Training-Time Test") remove a dependência fixa de features da camada superior e treina o rascunho com uma nova perda de "simulação em tempo de teste" (test-time simulation loss) — o rascunho é treinado em saídas que correspondem à distribuição de tempo de teste do alvo, em vez da distribuição de treinamento com teacher forcing. A taxa de aceitação sobe de 0,75 (EAGLE-2) para 0,82 (EAGLE-3), e a média de tokens por verificação passa de 3,0 para 4,5.

Verificação de Atenção em Árvore

Quando o rascunho produz uma árvore, o modelo alvo a verifica em um único forward pass usando uma máscara de atenção em árvore (tree attention mask) — uma máscara causal que codifica a topologia da árvore em vez de uma linha pura. Cada token atende apenas aos seus ancestrais na árvore. O passo de verificação continua sendo um único forward pass, uma multiplicação de matrizes (matmul); a máscara topológica custa apenas algumas entradas KV extras.

        root
       /    \
      a      b
     / \    / \
    c  d   e   f

Se a, b forem candidatos concorrentes para o primeiro token e c, d, e, f forem candidatos para o segundo token, todas as seis posições são verificadas em um único forward pass. A saída é o prefixo mais longo ao longo de qualquer caminho aceito.

Quando Vale a Pena, Quando Não Vale

Vale a pena (Wins):

  • Chat / completamento com texto previsível (código, inglês comum, saída estruturada). O valor de α é alto.
  • Cenários com computação de GPU ociosa durante a decodificação (fase limitada por memória/memory-bound). O tree drafting aproveita as FLOPs disponíveis.

Não vale a pena / Sem ganho (Loses / no win):

  • Saídas altamente estocásticas (escrita criativa em alta temperatura). O valor de α cai em direção a 1/|vocab|.
  • Atendimento em lote (batch serving) com concorrência muito alta — o loteamento já preenche as FLOPs, restando pouco espaço para a verificação em árvore.
  • Modelos alvo muito pequenos onde o rascunho não é significativamente menor.

Ambientes de produção tipicamente relatam aceleração de 2 a 3 vezes em tempo de execução real (wall-clock) em chats, 3 a 5 vezes na geração de código e quase zero na escrita criativa.

Desenvolva

code/main.py:

  • Uma função de referência speculative_decode(target, draft, prompt, K, temperature) que implementa a regra exata de rejeição e verifica se ela preserva a distribuição do alvo (KL empírica < 0,01 vs amostragem simples do alvo).
  • Um gerador de rascunhos em árvore (tree drafter) no estilo EAGLE que constrói uma árvore de profundidade K com ramificação top-p.
  • Um construtor de máscara de atenção em árvore que gera o padrão causal correto para um verificador.
  • Um harness de taxa de aceitação que executa ambos os modelos em um LM minúsculo (destilando um GPT-2-small a partir de um alvo GPT-2-medium).
def speculative_step(p_target, q_draft, K, temperature=1.0):
    """One round of speculative decoding. Returns list of accepted tokens."""
    # 1. Draft K tokens
    draft_tokens = []
    q_probs = []
    state = draft_state_init()
    for _ in range(K):
        probs = softmax(q_draft(state) / temperature)
        t = np.random.choice(len(probs), p=probs)
        draft_tokens.append(t)
        q_probs.append(probs[t])
        state = draft_step(state, t)

    # 2. Target computes p at every drafted position + 1 extra
    p_probs_all = target_forward_batched(p_target, draft_tokens, temperature)

    # 3. Accept/reject left-to-right
    accepted = []
    for k, tok in enumerate(draft_tokens):
        r = np.random.uniform()
        if r < p_probs_all[k][tok] / q_probs[k]:
            accepted.append(tok)
        else:
            residual = np.maximum(p_probs_all[k] - q_probs[k], 0)
            residual /= residual.sum()
            accepted.append(np.random.choice(len(residual), p=residual))
            return accepted
    # 4. All K accepted → sample bonus token from target
    accepted.append(np.random.choice(len(p_probs_all[-1]), p=p_probs_all[-1]))
    return accepted

Use

  • O vLLM e o SGLang oferecem suporte nativo a speculative decoding. Flags: --speculative_model, --num_speculative_tokens. Suporte ao EAGLE-2/3 via a flag --spec_decoding_algorithm eagle.
  • O NVIDIA TensorRT-LLM suporta árvores Medusa e EAGLE nativamente.
  • Modelos de rascunho de referência: Qwen/Qwen3-0.6B-spec (rascunhos para o Qwen3-32B), meta-llama/Llama-3.2-1B-Instruct-spec (rascunhos para o 70B).
  • Medusa heads (Cai et al. 2024, "Medusa: Simple LLM Inference Acceleration Framework with Multiple Decoding Heads"): em vez de um modelo de rascunho separado, adiciona K cabeças de predição paralelas ao próprio modelo alvo. Mais simples de implantar, com taxa de aceitação ligeiramente menor que o EAGLE.

Coloque em Produção

Esta lição produz outputs/skill-speculative-tuning.md — uma skill que analisa o workload de um modelo alvo e escolhe: modelo de rascunho, K (comprimento do rascunho), largura da árvore, temperatura e quando reverter para decodificação simples.

Exercícios

  1. Implemente a regra exata de rejeição e verifique-a empiricamente. Execute 10 mil amostras via speculative_decode e via amostragem simples do alvo; calcule a distância de variação total (TV distance) entre as duas distribuições de saída. Deve ser < 0,01.

  2. Calcule a fórmula de aceleração. Com valores fixos de α e K, plote a quantidade esperada de tokens por forward pass do alvo. Encontre o K ideal para α ∈ {0.5, 0.7, 0.9}.

  3. Treine um rascunho minúsculo. Utilize um alvo GPT-2 de 124M e destile um rascunho GPT-2 de 30M em 100M de tokens com perda KL. Meça α em um conjunto de validação separado. Esperado: 0,6-0,7.

  4. Implemente o tree drafting no estilo EAGLE. Em vez de uma cadeia linear, faça o rascunho produzir os 3 melhores ramos em cada profundidade. Construa a máscara de atenção em árvore. Verifique se o alvo aceita o ramo correto mais longo.

  5. Meça modos de falha. Execute o speculative decode com temperatura=1.5 (alta estocasticidade). Mostre que α colapsa e o algoritmo se torna mais lento que a decodificação simples devido ao overhead do modelo de rascunho.

Termos-Chave

Termo O que as pessoas dizem O que realmente significa
Target model (Modelo alvo) "O modelo grande" O modelo lento e de alta qualidade do qual você deseja obter amostras (distribuição p)
Draft model (Modelo de rascunho) "O especulador" O preditor pequeno e rápido (distribuição q); 5-30x menor
K / comprimento do rascunho "Look-ahead" Número de tokens especulados por passo de verificação
α / taxa de aceitação "Taxa de acerto (Hit rate)" Probabilidade por token de que a proposta do rascunho seja aceita
Regra exata de rejeição "O teste de aceitação" Comparação r < p/q que preserva a distribuição do alvo
Distribuição residual "p-q corrigido" (p - q)+ /
Tree drafting "Especulação ramificada" O rascunho produz uma árvore de candidatos, verificada em um único passo com máscara de atenção em árvore
Máscara de atenção em árvore "Máscara topológica" Máscara causal que codifica a topologia da árvore para que cada nó atenda apenas aos seus ancestrais
Cabeças Medusa (Medusa heads) "Cabeças paralelas" K cabeças extras de predição no próprio alvo; sem modelo de rascunho separado
Reutilização de features no EAGLE "Rascunho de hidden-state" A entrada do rascunho é o último estado oculto do alvo, e não os tokens brutos, diminuindo o tamanho do rascunho
Perda de simulação em tempo de teste "Treinamento do EAGLE-3" Treina o rascunho com saídas que correspondem à distribuição de tempo de teste do alvo, e não a teacher forcing

Leituras Adicionais

0 lifetime access. Curriculum based on AI Engineering from Scratch by Rohit Ghumare (MIT, used under attribution).